mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-01-19 05:43:51 +01:00
Add invariant that doesn't allow segwit scripts to be created with uncompressed public keys
reset scalafmt for rpc/ Removing unit test that used uncompressed public key for P2WSH, removing extra debug
This commit is contained in:
parent
b0229543c9
commit
0c29c8cfda
@ -412,26 +412,6 @@ class TransactionSignatureSerializerTest extends FlatSpec with MustMatchers {
|
||||
|
||||
}
|
||||
|
||||
it must "serialize a basic p2wsh transaction correctly" in {
|
||||
val expected = "01000000ff78d7a91d1d9f2defd4b9d7e17c8b2182565453e83ceaacc78dd2ee095681f13bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e7066504490491d88b9f0dc24d271f0f67179bce5914afe1ac0f83f6cd205f8b807436d6f0000000043410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac0100000000000000ffffffffe5d196bfb21caca9dbd654cafb3b4dc0c4882c8927d2eb300d9539dd0b9342280000000001000000"
|
||||
val hex = "0100000000010190491d88b9f0dc24d271f0f67179bce5914afe1ac0f83f6cd205f8b807436d6f0000000000ffffffff010100000000000000000247304402200d461c140cfdfcf36b94961db57ae8c18d1cb80e9d95a9e47ac22470c1bf125502201c8dc1cbfef6a3ef90acbbb992ca22fe9466ee6f9d4898eda277a7ac3ab4b2510143410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac00000000"
|
||||
|
||||
val spendingTx: WitnessTransaction = WitnessTransaction(hex)
|
||||
spendingTx.hex must be(hex)
|
||||
val inputIndex = UInt32.zero
|
||||
val witnessRedeemScript = ScriptPubKey("43410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac")
|
||||
val p2wsh = P2WSHWitnessSPKV0(witnessRedeemScript)
|
||||
val amount = Satoshis(Int64(1))
|
||||
val txSigComponent = WitnessTxSigComponentRaw(
|
||||
transaction = spendingTx,
|
||||
inputIndex = inputIndex,
|
||||
output = TransactionOutput(amount, p2wsh),
|
||||
flags = Policy.standardFlags)
|
||||
val serializedForSig = TransactionSignatureSerializer.serializeForSignature(txSigComponent, HashType.sigHashAll)
|
||||
|
||||
BitcoinSUtil.encodeHex(serializedForSig) must be(expected)
|
||||
}
|
||||
|
||||
it must "serialize a p2wpkh with SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" in {
|
||||
val rawTx = "0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff05540b0000000000000151d0070000000000000151840300000000000001513c0f00000000000001512c010000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71000000000000"
|
||||
val inputIndex = UInt32(1)
|
||||
|
@ -0,0 +1,15 @@
|
||||
package org.bitcoins.core.protocol.script
|
||||
|
||||
import org.bitcoins.core.crypto.ECPrivateKey
|
||||
import org.scalatest.{ FlatSpec, MustMatchers }
|
||||
|
||||
class P2WPKHWitnessSPKV0Test extends FlatSpec with MustMatchers {
|
||||
|
||||
"P2WPKHWitnessSPKV0" must "fail to be created with an uncompressed public key" in {
|
||||
val uncompressed = ECPrivateKey(false).publicKey
|
||||
intercept[IllegalArgumentException] {
|
||||
P2WPKHWitnessSPKV0(uncompressed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package org.bitcoins.core.protocol.script
|
||||
|
||||
import org.bitcoins.core.crypto.ECPrivateKey
|
||||
import org.bitcoins.core.script.constant.ScriptNumber
|
||||
import org.scalatest.{ FlatSpec, MustMatchers }
|
||||
|
||||
class P2WSHWitnessSPKV0Test extends FlatSpec with MustMatchers {
|
||||
val uncompressed = ECPrivateKey(false).publicKey
|
||||
val p2pk = P2PKScriptPubKey(uncompressed)
|
||||
val multisig = MultiSignatureScriptPubKey(1, Vector(uncompressed))
|
||||
"P2WPKHWitnessSPKV0" must "fail to be created with an uncompressed public key" in {
|
||||
intercept[IllegalArgumentException] {
|
||||
P2WSHWitnessSPKV0(p2pk)
|
||||
}
|
||||
}
|
||||
|
||||
it must "fail for a multisig script with an uncompressed public key" in {
|
||||
|
||||
intercept[IllegalArgumentException] {
|
||||
P2WSHWitnessSPKV0(multisig)
|
||||
}
|
||||
}
|
||||
|
||||
it must "fail with a locktime script" in {
|
||||
val cltv = CLTVScriptPubKey(ScriptNumber.zero, multisig)
|
||||
intercept[IllegalArgumentException] {
|
||||
P2WSHWitnessSPKV0(cltv)
|
||||
}
|
||||
}
|
||||
}
|
@ -575,6 +575,8 @@ object P2WPKHWitnessSPKV0 extends ScriptFactory[P2WPKHWitnessSPKV0] {
|
||||
|
||||
/** Creates a P2WPKH witness script pubkey */
|
||||
def apply(pubKey: ECPublicKey): P2WPKHWitnessSPKV0 = {
|
||||
//https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#restrictions-on-public-key-type
|
||||
require(pubKey.isCompressed, s"Public key must be compressed to be used in a segwit script, see BIP143")
|
||||
val hash = CryptoUtil.sha256Hash160(pubKey.bytes)
|
||||
val pushop = BitcoinScriptUtil.calculatePushOp(hash.bytes)
|
||||
fromAsm(Seq(OP_0) ++ pushop ++ Seq(ScriptConstant(hash.bytes)))
|
||||
@ -603,6 +605,7 @@ object P2WSHWitnessSPKV0 extends ScriptFactory[P2WSHWitnessSPKV0] {
|
||||
}
|
||||
|
||||
def apply(spk: ScriptPubKey): P2WSHWitnessSPKV0 = {
|
||||
require(BitcoinScriptUtil.isOnlyCompressedPubKey(spk), s"Public key must be compressed to be used in a segwit script, see BIP143")
|
||||
val hash = CryptoUtil.sha256(spk.asmBytes)
|
||||
val pushop = BitcoinScriptUtil.calculatePushOp(hash.bytes)
|
||||
fromAsm(Seq(OP_0) ++ pushop ++ Seq(ScriptConstant(hash.bytes)))
|
||||
|
@ -391,6 +391,29 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
|
||||
else asm
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that all the [[org.bitcoins.core.crypto.ECPublicKey]] in this script
|
||||
* is compressed public keys, this is required for BIP143
|
||||
* @param spk
|
||||
* @return
|
||||
*/
|
||||
def isOnlyCompressedPubKey(spk: ScriptPubKey): Boolean = {
|
||||
spk match {
|
||||
case p2pk: P2PKScriptPubKey => p2pk.publicKey.isCompressed
|
||||
case m: MultiSignatureScriptPubKey =>
|
||||
!m.publicKeys.exists(k => !k.isCompressed)
|
||||
case l: LockTimeScriptPubKey =>
|
||||
isOnlyCompressedPubKey(l.nestedScriptPubKey)
|
||||
case e: EscrowTimeoutScriptPubKey =>
|
||||
isOnlyCompressedPubKey(e.escrow) && isOnlyCompressedPubKey(e.timeout)
|
||||
case _: P2PKHScriptPubKey | _: P2SHScriptPubKey
|
||||
| _: P2WPKHWitnessSPKV0 | _: P2WSHWitnessSPKV0 | _: UnassignedWitnessScriptPubKey
|
||||
| _: NonStandardScriptPubKey | _: WitnessCommitment | EmptyScriptPubKey =>
|
||||
true
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object BitcoinScriptUtil extends BitcoinScriptUtil
|
||||
|
Loading…
Reference in New Issue
Block a user