Limit bech32 addresses to segwitv0 (#2471)

* Limit bech32 addresses to segwitv0

* extend ScriptFactory, make check exhuastive
This commit is contained in:
benthecarman 2021-01-07 08:13:31 -06:00 committed by GitHub
parent f2f41bfb58
commit 6b441631f3
5 changed files with 34 additions and 10 deletions

View file

@ -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)

View file

@ -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)
}
} }

View file

@ -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)

View file

@ -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")
}
} }
/** /**

View file

@ -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] =