diff options
author | Andrew Chow <github@achow101.com> | 2023-09-20 13:43:37 -0400 |
---|---|---|
committer | Andrew Chow <github@achow101.com> | 2023-09-20 13:50:15 -0400 |
commit | 8247a8db6963d2116dc4697a3217d736c197f91d (patch) | |
tree | 41f5bbb30b99753cf63e5b30255ee1f37d286adb | |
parent | 99ce8366ed949a1e8a42c1562867b0330b78b212 (diff) | |
parent | 83d7cfd5429b0be7755bc48145032956f5f56dae (diff) |
Merge bitcoin/bitcoin#28154: test: refactor: deduplicate segwitv0 ECDSA signing for tx inputs
83d7cfd5429b0be7755bc48145032956f5f56dae test: refactor: deduplicate segwitv0 ECDSA signing for tx inputs (Sebastian Falbesoner)
Pull request description:
This PR is a simple follow-up for #28025. It introduces a `signing_input_segwitv0` helper in order to deduplicate the following steps needed to create a segwitv0 ECDSA signature:
1. calculate the `SegwitV0SignatureHash` with the desired sighash type
2. create the actual digital signature by calling ECKey.sign_ecdsa on the signature message hash calculated above
3. put the DER-encoded result (plus sighash byte) at the bottom of the witness stack
ACKs for top commit:
achow101:
ACK 83d7cfd5429b0be7755bc48145032956f5f56dae
pinheadmz:
code review ACK at 83d7cfd5429b0be7755bc48145032956f5f56dae
Tree-SHA512: b8e55409ddc9ddb14cfc06daeb4730d7750a4632f175f88dcac6ec4d216e71fd4a7eee325a64d6ebba3b33be50bcd30c2de7400f834c01abb67e52840d9823b6
-rwxr-xr-x | test/functional/p2p_segwit.py | 20 | ||||
-rw-r--r-- | test/functional/test_framework/script.py | 9 |
2 files changed, 18 insertions, 11 deletions
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index cfc177574f..b398ef51e1 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -70,9 +70,9 @@ from test_framework.script import ( SIGHASH_ANYONECANPAY, SIGHASH_NONE, SIGHASH_SINGLE, - SegwitV0SignatureHash, hash160, sign_input_legacy, + sign_input_segwitv0, ) from test_framework.script_util import ( key_to_p2pk_script, @@ -121,10 +121,8 @@ def subtest(func): def sign_p2pk_witness_input(script, tx_to, in_idx, hashtype, value, key): """Add signature for a P2PK witness script.""" - tx_hash = SegwitV0SignatureHash(script, tx_to, in_idx, hashtype, value) - signature = key.sign_ecdsa(tx_hash) + chr(hashtype).encode('latin-1') - tx_to.wit.vtxinwit[in_idx].scriptWitness.stack = [signature, script] - tx_to.rehash() + tx_to.wit.vtxinwit[in_idx].scriptWitness.stack = [script] + sign_input_segwitv0(tx_to, in_idx, script, value, key, hashtype) def test_transaction_acceptance(node, p2p, tx, with_witness, accepted, reason=None): """Send a transaction to the node and check that it's accepted to the mempool @@ -1476,11 +1474,9 @@ class SegWitTest(BitcoinTestFramework): tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_wsh)) script = keyhash_to_p2pkh_script(pubkeyhash) - sig_hash = SegwitV0SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue) - signature = key.sign_ecdsa(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL tx2.wit.vtxinwit.append(CTxInWitness()) - tx2.wit.vtxinwit[0].scriptWitness.stack = [signature, pubkey] - tx2.rehash() + tx2.wit.vtxinwit[0].scriptWitness.stack = [pubkey] + sign_input_segwitv0(tx2, 0, script, tx.vout[0].nValue, key) # Should fail policy test. test_transaction_acceptance(self.nodes[0], self.test_node, tx2, True, False, 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') @@ -1676,11 +1672,13 @@ class SegWitTest(BitcoinTestFramework): tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE]))) script = keyhash_to_p2pkh_script(pubkeyhash) - sig_hash = SegwitV0SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue) - signature = key.sign_ecdsa(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL + tx2.wit.vtxinwit.append(CTxInWitness()) + sign_input_segwitv0(tx2, 0, script, tx.vout[0].nValue, key) + signature = tx2.wit.vtxinwit[0].scriptWitness.stack.pop() # Check that we can't have a scriptSig tx2.vin[0].scriptSig = CScript([signature, pubkey]) + tx2.rehash() block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx, tx2]) test_witness_block(self.nodes[0], self.test_node, block, accepted=False, diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index 78f58cf11f..17a954cb22 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -699,6 +699,15 @@ def sign_input_legacy(tx, input_index, input_scriptpubkey, privkey, sighash_type tx.vin[input_index].scriptSig = bytes(CScript([der_sig + bytes([sighash_type])])) + tx.vin[input_index].scriptSig tx.rehash() +def sign_input_segwitv0(tx, input_index, input_scriptpubkey, input_amount, privkey, sighash_type=SIGHASH_ALL): + """Add segwitv0 ECDSA signature for a given transaction input. Note that the signature + is inserted at the bottom of the witness stack, i.e. additional witness data + needed (e.g. pubkey for P2WPKH) can already be set before.""" + sighash = SegwitV0SignatureHash(input_scriptpubkey, tx, input_index, sighash_type, input_amount) + der_sig = privkey.sign_ecdsa(sighash) + tx.wit.vtxinwit[input_index].scriptWitness.stack.insert(0, der_sig + bytes([sighash_type])) + tx.rehash() + # TODO: Allow cached hashPrevouts/hashSequence/hashOutputs to be provided. # Performance optimization probably not necessary for python tests, however. # Note that this corresponds to sigversion == 1 in EvalScript, which is used |