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:
Chris Stewart 2018-07-22 12:55:20 -05:00
parent b0229543c9
commit 0c29c8cfda
5 changed files with 71 additions and 20 deletions

View File

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

View File

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

View File

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

View File

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

View File

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