test: refactor: deduplicate legacy ECDSA signing for tx inputs

There are several instances in functional tests and the framework
(MiniWallet, feature_block.py, p2p_segwit.py) where we create a legacy
ECDSA signature for a certain transaction's input by doing the following
steps:
    1) calculate the `LegacySignatureHash` 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 as CScript data push into
       tx input's scriptSig

Create a new helper `sign_input_legacy` which hides those details and
takes only the necessary parameters (tx, input index, relevant
scriptPubKey, private key, sighash type [SIGHASH_ALL by default]). For
further convenience, the signature is prepended to already existing
data-pushes in scriptSig, in order to avoid rehashing the transaction
after calling the new signing function.
This commit is contained in:
Sebastian Falbesoner
2023-07-03 02:05:13 +02:00
parent 61d59fed74
commit 5cf44275c8
4 changed files with 24 additions and 25 deletions

View File

@@ -36,12 +36,11 @@ from test_framework.messages import (
)
from test_framework.script import (
CScript,
LegacySignatureHash,
LEAF_VERSION_TAPSCRIPT,
OP_NOP,
OP_RETURN,
OP_TRUE,
SIGHASH_ALL,
sign_input_legacy,
taproot_construct,
)
from test_framework.script_util import (
@@ -166,18 +165,16 @@ class MiniWallet:
def sign_tx(self, tx, fixed_length=True):
if self._mode == MiniWalletMode.RAW_P2PK:
(sighash, err) = LegacySignatureHash(CScript(self._scriptPubKey), tx, 0, SIGHASH_ALL)
assert err is None
# for exact fee calculation, create only signatures with fixed size by default (>49.89% probability):
# 65 bytes: high-R val (33 bytes) + low-S val (32 bytes)
# with the DER header/skeleton data of 6 bytes added, this leads to a target size of 71 bytes
der_sig = b''
while not len(der_sig) == 71:
der_sig = self._priv_key.sign_ecdsa(sighash)
# with the DER header/skeleton data of 6 bytes added, plus 2 bytes scriptSig overhead
# (OP_PUSHn and SIGHASH_ALL), this leads to a scriptSig target size of 73 bytes
tx.vin[0].scriptSig = b''
while not len(tx.vin[0].scriptSig) == 73:
tx.vin[0].scriptSig = b''
sign_input_legacy(tx, 0, self._scriptPubKey, self._priv_key)
if not fixed_length:
break
tx.vin[0].scriptSig = CScript([der_sig + bytes(bytearray([SIGHASH_ALL]))])
tx.rehash()
elif self._mode == MiniWalletMode.RAW_OP_TRUE:
for i in tx.vin:
i.scriptSig = CScript([OP_NOP] * 43) # pad to identical size