Skip to content

Commit 1a572ce

Browse files
committed
test: refactor: introduce generate_keypair helper with WIF support
In functional tests it is a quite common scenario to generate fresh elliptic curve keypairs, which is currently a bit cumbersome as it involves multiple steps, e.g.: privkey = ECKey() privkey.generate() privkey_wif = bytes_to_wif(privkey.get_bytes()) pubkey = privkey.get_pubkey().get_bytes() Simplify this by providing a new `generate_keypair` helper function that returns the private key either as `ECKey` object or as WIF-string (depending on the boolean `wif` parameter) and the public key as byte-string; these formats are what we mostly need (currently we don't use `ECPubKey` objects from generated keypairs anywhere). With this, most of the affected code blocks following the pattern above can be replaced by one-liners, e.g.: privkey, pubkey = generate_keypair(wif=True) Note that after this commit, the only direct uses of `ECKey` remain in situations where we want to set the private key explicitly, e.g. in MiniWallet (test/functional/test_framework/wallet.py) or the test for the signet miner script (test/functional/tool_signet_miner.py).
1 parent 7f0b79e commit 1a572ce

18 files changed

+79
-130
lines changed

test/functional/feature_assumevalid.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
create_block,
3636
create_coinbase,
3737
)
38-
from test_framework.key import ECKey
3938
from test_framework.messages import (
4039
CBlockHeader,
4140
COutPoint,
@@ -46,9 +45,13 @@
4645
msg_headers,
4746
)
4847
from test_framework.p2p import P2PInterface
49-
from test_framework.script import (CScript, OP_TRUE)
48+
from test_framework.script import (
49+
CScript,
50+
OP_TRUE,
51+
)
5052
from test_framework.test_framework import BitcoinTestFramework
5153
from test_framework.util import assert_equal
54+
from test_framework.wallet_util import generate_keypair
5255

5356

5457
class BaseNode(P2PInterface):
@@ -90,9 +93,7 @@ def run_test(self):
9093
self.blocks = []
9194

9295
# Get a pubkey for the coinbase TXO
93-
coinbase_key = ECKey()
94-
coinbase_key.generate()
95-
coinbase_pubkey = coinbase_key.get_pubkey().get_bytes()
96+
_, coinbase_pubkey = generate_keypair()
9697

9798
# Create the first block with a coinbase output to our key
9899
height = 1

test/functional/feature_block.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
get_legacy_sigopcount_block,
1515
MAX_BLOCK_SIGOPS,
1616
)
17-
from test_framework.key import ECKey
1817
from test_framework.messages import (
1918
CBlock,
2019
COIN,
@@ -55,6 +54,7 @@
5554
assert_equal,
5655
assert_greater_than,
5756
)
57+
from test_framework.wallet_util import generate_keypair
5858
from data import invalid_txs
5959

6060

@@ -98,9 +98,7 @@ def run_test(self):
9898
self.bootstrap_p2p() # Add one p2p connection to the node
9999

100100
self.block_heights = {}
101-
self.coinbase_key = ECKey()
102-
self.coinbase_key.generate()
103-
self.coinbase_pubkey = self.coinbase_key.get_pubkey().get_bytes()
101+
self.coinbase_key, self.coinbase_pubkey = generate_keypair()
104102
self.tip = None
105103
self.blocks = {}
106104
self.genesis_hash = int(self.nodes[0].getbestblockhash(), 16)

test/functional/feature_nulldummy.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
assert_raises_rpc_error,
3636
)
3737
from test_framework.wallet import getnewdestination
38-
from test_framework.key import ECKey
39-
from test_framework.wallet_util import bytes_to_wif
38+
from test_framework.wallet_util import generate_keypair
4039

4140
NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)"
4241

@@ -71,12 +70,9 @@ def create_transaction(self, *, txid, input_details=None, addr, amount, privkey)
7170
return tx_from_hex(signedtx["hex"])
7271

7372
def run_test(self):
74-
eckey = ECKey()
75-
eckey.generate()
76-
self.privkey = bytes_to_wif(eckey.get_bytes())
77-
self.pubkey = eckey.get_pubkey().get_bytes().hex()
78-
cms = self.nodes[0].createmultisig(1, [self.pubkey])
79-
wms = self.nodes[0].createmultisig(1, [self.pubkey], 'p2sh-segwit')
73+
self.privkey, self.pubkey = generate_keypair(wif=True)
74+
cms = self.nodes[0].createmultisig(1, [self.pubkey.hex()])
75+
wms = self.nodes[0].createmultisig(1, [self.pubkey.hex()], 'p2sh-segwit')
8076
self.ms_address = cms["address"]
8177
ms_unlock_details = {"scriptPubKey": address_to_scriptpubkey(self.ms_address).hex(),
8278
"redeemScript": cms["redeemScript"]}

test/functional/feature_taproot.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
assert_equal,
9898
random_bytes,
9999
)
100+
from test_framework.wallet_util import generate_keypair
100101
from test_framework.key import (
101102
generate_privkey,
102103
compute_xonly_pubkey,
@@ -1186,11 +1187,8 @@ def predict_sigops_ratio(n, dummy_size):
11861187

11871188
# Also add a few legacy spends into the mix, so that transactions which combine taproot and pre-taproot spends get tested too.
11881189
for compressed in [False, True]:
1189-
eckey1 = ECKey()
1190-
eckey1.set(generate_privkey(), compressed)
1191-
pubkey1 = eckey1.get_pubkey().get_bytes()
1192-
eckey2 = ECKey()
1193-
eckey2.set(generate_privkey(), compressed)
1190+
eckey1, pubkey1 = generate_keypair(compressed=compressed)
1191+
eckey2, _ = generate_keypair(compressed=compressed)
11941192
for p2sh in [False, True]:
11951193
for witv0 in [False, True]:
11961194
for hashtype in VALID_SIGHASHES_ECDSA + [random.randrange(0x04, 0x80), random.randrange(0x84, 0x100)]:

test/functional/mempool_accept.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import math
1010

1111
from test_framework.test_framework import BitcoinTestFramework
12-
from test_framework.key import ECKey
1312
from test_framework.messages import (
1413
MAX_BIP125_RBF_SEQUENCE,
1514
COIN,
@@ -44,6 +43,7 @@
4443
assert_raises_rpc_error,
4544
)
4645
from test_framework.wallet import MiniWallet
46+
from test_framework.wallet_util import generate_keypair
4747

4848

4949
class MempoolAcceptanceTest(BitcoinTestFramework):
@@ -283,9 +283,7 @@ def run_test(self):
283283
rawtxs=[tx.serialize().hex()],
284284
)
285285
tx = tx_from_hex(raw_tx_reference)
286-
key = ECKey()
287-
key.generate()
288-
pubkey = key.get_pubkey().get_bytes()
286+
_, pubkey = generate_keypair()
289287
tx.vout[0].scriptPubKey = keys_to_multisig_script([pubkey] * 3, k=2) # Some bare multisig script (2-of-3)
290288
self.check_mempool_result(
291289
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bare-multisig'}],

test/functional/mempool_dust.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"""Test dust limit mempool policy (`-dustrelayfee` parameter)"""
66
from decimal import Decimal
77

8-
from test_framework.key import ECKey
98
from test_framework.messages import (
109
COIN,
1110
CTxOut,
@@ -32,6 +31,7 @@
3231
get_fee,
3332
)
3433
from test_framework.wallet import MiniWallet
34+
from test_framework.wallet_util import generate_keypair
3535

3636

3737
DUST_RELAY_TX_FEE = 3000 # default setting [sat/kvB]
@@ -74,11 +74,8 @@ def run_test(self):
7474
self.wallet = MiniWallet(self.nodes[0])
7575

7676
# prepare output scripts of each standard type
77-
key = ECKey()
78-
key.generate(compressed=False)
79-
uncompressed_pubkey = key.get_pubkey().get_bytes()
80-
key.generate(compressed=True)
81-
pubkey = key.get_pubkey().get_bytes()
77+
_, uncompressed_pubkey = generate_keypair(compressed=False)
78+
_, pubkey = generate_keypair(compressed=True)
8279

8380
output_scripts = (
8481
(key_to_p2pk_script(uncompressed_pubkey), "P2PK (uncompressed)"),

test/functional/p2p_segwit.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
create_block,
1515
create_coinbase,
1616
)
17-
from test_framework.key import ECKey
1817
from test_framework.messages import (
1918
MAX_BIP125_RBF_SEQUENCE,
2019
CBlockHeader,
@@ -89,6 +88,7 @@
8988
assert_raises_rpc_error,
9089
)
9190
from test_framework.wallet import MiniWallet
91+
from test_framework.wallet_util import generate_keypair
9292

9393

9494
MAX_SIGOP_COST = 80000
@@ -1448,9 +1448,7 @@ def test_uncompressed_pubkey(self):
14481448

14491449
# Segwit transactions using uncompressed pubkeys are not accepted
14501450
# under default policy, but should still pass consensus.
1451-
key = ECKey()
1452-
key.generate(False)
1453-
pubkey = key.get_pubkey().get_bytes()
1451+
key, pubkey = generate_keypair(compressed=False)
14541452
assert_equal(len(pubkey), 65) # This should be an uncompressed pubkey
14551453

14561454
utxo = self.utxo.pop(0)
@@ -1544,11 +1542,7 @@ def test_uncompressed_pubkey(self):
15441542

15451543
@subtest
15461544
def test_signature_version_1(self):
1547-
1548-
key = ECKey()
1549-
key.generate()
1550-
pubkey = key.get_pubkey().get_bytes()
1551-
1545+
key, pubkey = generate_keypair()
15521546
witness_script = key_to_p2pk_script(pubkey)
15531547
script_pubkey = script_to_p2wsh_script(witness_script)
15541548

test/functional/rpc_createmultisig.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
from test_framework.blocktools import COINBASE_MATURITY
1313
from test_framework.authproxy import JSONRPCException
1414
from test_framework.descriptors import descsum_create, drop_origins
15-
from test_framework.key import ECPubKey, ECKey
15+
from test_framework.key import ECPubKey
1616
from test_framework.test_framework import BitcoinTestFramework
1717
from test_framework.util import (
1818
assert_raises_rpc_error,
1919
assert_equal,
2020
)
21-
from test_framework.wallet_util import bytes_to_wif
21+
from test_framework.wallet_util import generate_keypair
2222
from test_framework.wallet import (
2323
MiniWallet,
2424
getnewdestination,
@@ -38,10 +38,9 @@ def get_keys(self):
3838
self.priv = []
3939
node0, node1, node2 = self.nodes
4040
for _ in range(self.nkeys):
41-
k = ECKey()
42-
k.generate()
43-
self.pub.append(k.get_pubkey().get_bytes().hex())
44-
self.priv.append(bytes_to_wif(k.get_bytes(), k.is_compressed))
41+
privkey, pubkey = generate_keypair(wif=True)
42+
self.pub.append(pubkey.hex())
43+
self.priv.append(privkey)
4544
if self.is_bdb_compiled():
4645
self.final = node2.getnewaddress()
4746
else:

test/functional/rpc_psbt.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from itertools import product
99

1010
from test_framework.descriptors import descsum_create
11-
from test_framework.key import ECKey, H_POINT
11+
from test_framework.key import H_POINT
1212
from test_framework.messages import (
1313
COutPoint,
1414
CTransaction,
@@ -43,8 +43,8 @@
4343
random_bytes,
4444
)
4545
from test_framework.wallet_util import (
46-
bytes_to_wif,
47-
get_generate_key
46+
generate_keypair,
47+
get_generate_key,
4848
)
4949

5050
import json
@@ -710,9 +710,7 @@ def test_psbt_input_keys(psbt_input, keys):
710710

711711
self.log.info("Test that we can fund psbts with external inputs specified")
712712

713-
eckey = ECKey()
714-
eckey.generate()
715-
privkey = bytes_to_wif(eckey.get_bytes())
713+
privkey, _ = generate_keypair(wif=True)
716714

717715
self.nodes[1].createwallet("extfund")
718716
wallet = self.nodes[1].get_wallet_rpc("extfund")
@@ -825,11 +823,9 @@ def test_psbt_input_keys(psbt_input, keys):
825823
self.nodes[1].createwallet(wallet_name="scriptwatchonly", disable_private_keys=True)
826824
watchonly = self.nodes[1].get_wallet_rpc("scriptwatchonly")
827825

828-
eckey = ECKey()
829-
eckey.generate()
830-
privkey = bytes_to_wif(eckey.get_bytes())
826+
privkey, pubkey = generate_keypair(wif=True)
831827

832-
desc = descsum_create("wsh(pkh({}))".format(eckey.get_pubkey().get_bytes().hex()))
828+
desc = descsum_create("wsh(pkh({}))".format(pubkey.hex()))
833829
if self.options.descriptors:
834830
res = watchonly.importdescriptors([{"desc": desc, "timestamp": "now"}])
835831
else:
@@ -846,11 +842,9 @@ def test_psbt_input_keys(psbt_input, keys):
846842

847843
# Same test but for taproot
848844
if self.options.descriptors:
849-
eckey = ECKey()
850-
eckey.generate()
851-
privkey = bytes_to_wif(eckey.get_bytes())
845+
privkey, pubkey = generate_keypair(wif=True)
852846

853-
desc = descsum_create("tr({},pk({}))".format(H_POINT, eckey.get_pubkey().get_bytes().hex()))
847+
desc = descsum_create("tr({},pk({}))".format(H_POINT, pubkey.hex()))
854848
res = watchonly.importdescriptors([{"desc": desc, "timestamp": "now"}])
855849
assert res[0]["success"]
856850
addr = self.nodes[0].deriveaddresses(desc)[0]

test/functional/rpc_signrawtransactionwithkey.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
address_to_scriptpubkey,
1212
script_to_p2sh,
1313
)
14-
from test_framework.key import ECKey
1514
from test_framework.test_framework import BitcoinTestFramework
1615
from test_framework.util import (
1716
assert_equal,
@@ -23,16 +22,16 @@
2322
script_to_p2sh_p2wsh_script,
2423
script_to_p2wsh_script,
2524
)
25+
from test_framework.wallet import (
26+
getnewdestination,
27+
)
2628
from test_framework.wallet_util import (
27-
bytes_to_wif,
29+
generate_keypair,
2830
)
2931

3032
from decimal import (
3133
Decimal,
3234
)
33-
from test_framework.wallet import (
34-
getnewdestination,
35-
)
3635

3736

3837
class SignRawTransactionWithKeyTest(BitcoinTestFramework):
@@ -80,11 +79,8 @@ def successful_signing_test(self):
8079
def witness_script_test(self):
8180
self.log.info("Test signing transaction to P2SH-P2WSH addresses without wallet")
8281
# Create a new P2SH-P2WSH 1-of-1 multisig address:
83-
eckey = ECKey()
84-
eckey.generate()
85-
embedded_privkey = bytes_to_wif(eckey.get_bytes())
86-
embedded_pubkey = eckey.get_pubkey().get_bytes().hex()
87-
p2sh_p2wsh_address = self.nodes[1].createmultisig(1, [embedded_pubkey], "p2sh-segwit")
82+
embedded_privkey, embedded_pubkey = generate_keypair(wif=True)
83+
p2sh_p2wsh_address = self.nodes[1].createmultisig(1, [embedded_pubkey.hex()], "p2sh-segwit")
8884
# send transaction to P2SH-P2WSH 1-of-1 multisig address
8985
self.block_hash = self.generate(self.nodes[0], COINBASE_MATURITY + 1)
9086
self.blk_idx = 0
@@ -109,10 +105,7 @@ def witness_script_test(self):
109105

110106
def verify_txn_with_witness_script(self, tx_type):
111107
self.log.info("Test with a {} script as the witnessScript".format(tx_type))
112-
eckey = ECKey()
113-
eckey.generate()
114-
embedded_privkey = bytes_to_wif(eckey.get_bytes())
115-
embedded_pubkey = eckey.get_pubkey().get_bytes().hex()
108+
embedded_privkey, embedded_pubkey = generate_keypair(wif=True)
116109
witness_script = {
117110
'P2PKH': key_to_p2pkh_script(embedded_pubkey).hex(),
118111
'P2PK': key_to_p2pk_script(embedded_pubkey).hex()

0 commit comments

Comments
 (0)