aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chow <github@achow101.com>2023-09-20 13:43:37 -0400
committerAndrew Chow <github@achow101.com>2023-09-20 13:50:15 -0400
commit8247a8db6963d2116dc4697a3217d736c197f91d (patch)
tree41f5bbb30b99753cf63e5b30255ee1f37d286adb
parent99ce8366ed949a1e8a42c1562867b0330b78b212 (diff)
parent83d7cfd5429b0be7755bc48145032956f5f56dae (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-xtest/functional/p2p_segwit.py20
-rw-r--r--test/functional/test_framework/script.py9
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