mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 18:47:38 +01:00
Limit bech32 addresses to segwitv0 (#2471)
* Limit bech32 addresses to segwitv0 * extend ScriptFactory, make check exhuastive
This commit is contained in:
parent
f2f41bfb58
commit
6b441631f3
5 changed files with 34 additions and 10 deletions
|
@ -28,7 +28,7 @@ class Bech32Spec extends Properties("Bech32Spec") {
|
||||||
}
|
}
|
||||||
|
|
||||||
property("serialization symmetry") = {
|
property("serialization symmetry") = {
|
||||||
Prop.forAll(ScriptGenerators.witnessScriptPubKey,
|
Prop.forAll(ScriptGenerators.witnessScriptPubKeyV0,
|
||||||
ChainParamsGenerator.networkParams) {
|
ChainParamsGenerator.networkParams) {
|
||||||
case ((witSPK, _), network) =>
|
case ((witSPK, _), network) =>
|
||||||
val addr = Bech32Address(witSPK, network)
|
val addr = Bech32Address(witSPK, network)
|
||||||
|
|
|
@ -240,4 +240,18 @@ class Bech32Test extends BitcoinSUnitTest {
|
||||||
.checkDataValidity("bcrt1qq6w6pu6zq90az9krn53zlkvgyzkyeglzukyepf")
|
.checkDataValidity("bcrt1qq6w6pu6zq90az9krn53zlkvgyzkyeglzukyepf")
|
||||||
.isFailure)
|
.isFailure)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it must "fail to read a segwitV1 bech32 address" in {
|
||||||
|
assert(
|
||||||
|
Bech32Address
|
||||||
|
.fromStringT(
|
||||||
|
"tb1prp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7")
|
||||||
|
.isFailure)
|
||||||
|
|
||||||
|
assert(
|
||||||
|
Bech32Address
|
||||||
|
.fromStringT(
|
||||||
|
"bc1prp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7")
|
||||||
|
.isFailure)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ sealed abstract class Bech32Address extends BitcoinAddress {
|
||||||
|
|
||||||
def checksum: Vector[UInt5] = Bech32Address.createChecksum(hrp, data)
|
def checksum: Vector[UInt5] = Bech32Address.createChecksum(hrp, data)
|
||||||
|
|
||||||
override def scriptPubKey: WitnessScriptPubKey = {
|
override def scriptPubKey: WitnessScriptPubKeyV0 = {
|
||||||
Bech32Address.fromStringToWitSPK(value).get
|
Bech32Address.fromStringToWitSPK(value).get
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,9 +99,6 @@ sealed abstract class Bech32Address extends BitcoinAddress {
|
||||||
Sha256Hash160Digest(byteVector)
|
Sha256Hash160Digest(byteVector)
|
||||||
case _: P2WSHWitnessSPKV0 =>
|
case _: P2WSHWitnessSPKV0 =>
|
||||||
Sha256Digest(byteVector)
|
Sha256Digest(byteVector)
|
||||||
case _: UnassignedWitnessScriptPubKey =>
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
s"Cannot parse the hash of an unassigned witness scriptpubkey for bech32 address")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +146,7 @@ object Bech32Address extends AddressFactory[Bech32Address] {
|
||||||
/** Tries to convert the given string a to a
|
/** Tries to convert the given string a to a
|
||||||
* [[org.bitcoins.core.protocol.script.WitnessScriptPubKey WitnessScriptPubKey]]
|
* [[org.bitcoins.core.protocol.script.WitnessScriptPubKey WitnessScriptPubKey]]
|
||||||
*/
|
*/
|
||||||
def fromStringToWitSPK(string: String): Try[WitnessScriptPubKey] = {
|
def fromStringToWitSPK(string: String): Try[WitnessScriptPubKeyV0] = {
|
||||||
val decoded = fromStringT(string)
|
val decoded = fromStringT(string)
|
||||||
decoded.flatMap { bech32Addr =>
|
decoded.flatMap { bech32Addr =>
|
||||||
val bytes = bech32Addr.data
|
val bytes = bech32Addr.data
|
||||||
|
@ -161,7 +158,7 @@ object Bech32Address extends AddressFactory[Bech32Address] {
|
||||||
witVersion match {
|
witVersion match {
|
||||||
case Some(v) =>
|
case Some(v) =>
|
||||||
val witSPK = Try(
|
val witSPK = Try(
|
||||||
WitnessScriptPubKey(
|
WitnessScriptPubKeyV0(
|
||||||
List(v.version) ++ pushOp ++ List(ScriptConstant(progBytes))))
|
List(v.version) ++ pushOp ++ List(ScriptConstant(progBytes))))
|
||||||
witSPK match {
|
witSPK match {
|
||||||
case Success(spk) => Success(spk)
|
case Success(spk) => Success(spk)
|
||||||
|
|
|
@ -1212,7 +1212,7 @@ sealed abstract class WitnessScriptPubKeyV0 extends WitnessScriptPubKey {
|
||||||
override def witnessProgram: Seq[ScriptToken] = asm.tail.tail
|
override def witnessProgram: Seq[ScriptToken] = asm.tail.tail
|
||||||
}
|
}
|
||||||
|
|
||||||
object WitnessScriptPubKeyV0 {
|
object WitnessScriptPubKeyV0 extends ScriptFactory[WitnessScriptPubKeyV0] {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mimics the function to determine if a
|
* Mimics the function to determine if a
|
||||||
|
@ -1227,6 +1227,19 @@ object WitnessScriptPubKeyV0 {
|
||||||
WitnessScriptPubKey.isWitnessScriptPubKey(asm) && asm.headOption.contains(
|
WitnessScriptPubKey.isWitnessScriptPubKey(asm) && asm.headOption.contains(
|
||||||
OP_0)
|
OP_0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def apply(asm: Seq[ScriptToken]): WitnessScriptPubKeyV0 = fromAsm(asm)
|
||||||
|
|
||||||
|
override def fromAsm(asm: Seq[ScriptToken]): WitnessScriptPubKeyV0 =
|
||||||
|
asm match {
|
||||||
|
case _ if P2WPKHWitnessSPKV0.isValid(asm) =>
|
||||||
|
P2WPKHWitnessSPKV0.fromAsm(asm)
|
||||||
|
case _ if P2WSHWitnessSPKV0.isValid(asm) =>
|
||||||
|
P2WSHWitnessSPKV0.fromAsm(asm)
|
||||||
|
case _ =>
|
||||||
|
sys.error(
|
||||||
|
s"The given asm was not a valid WitnessScriptPubKeyV0, got asm=$asm")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,9 +24,9 @@ sealed trait AddressGenerator {
|
||||||
|
|
||||||
def bech32Address: Gen[Bech32Address] =
|
def bech32Address: Gen[Bech32Address] =
|
||||||
for {
|
for {
|
||||||
(witSPK, _) <- ScriptGenerators.assignedWitnessScriptPubKey
|
(witSPKV0, _) <- ScriptGenerators.witnessScriptPubKeyV0
|
||||||
network <- ChainParamsGenerator.networkParams
|
network <- ChainParamsGenerator.networkParams
|
||||||
addr = Bech32Address(witSPK, network)
|
addr = Bech32Address(witSPKV0, network)
|
||||||
} yield addr
|
} yield addr
|
||||||
|
|
||||||
def bitcoinAddress: Gen[BitcoinAddress] =
|
def bitcoinAddress: Gen[BitcoinAddress] =
|
||||||
|
|
Loading…
Add table
Reference in a new issue