Skip to content

Commit 7d5cec2

Browse files
committed
refactor: separate the rpc_rawtransaction tests into functions
1 parent 409779d commit 7d5cec2

File tree

1 file changed

+136
-120
lines changed

1 file changed

+136
-120
lines changed

test/functional/rpc_rawtransaction.py

Lines changed: 136 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
"""Test the rawtransaction RPCs.
66
77
Test the following RPCs:
8+
- getrawtransaction
89
- createrawtransaction
910
- signrawtransactionwithwallet
1011
- sendrawtransaction
1112
- decoderawtransaction
12-
- getrawtransaction
1313
"""
1414

1515
from collections import OrderedDict
@@ -85,7 +85,17 @@ def run_test(self):
8585
self.nodes[0].generate(5)
8686
self.sync_all()
8787

88-
# getrawtransaction tests
88+
self.getrawtransaction_tests()
89+
self.createrawtransaction_tests()
90+
self.signrawtransactionwithwallet_tests()
91+
self.sendrawtransaction_tests()
92+
self.sendrawtransaction_testmempoolaccept_tests()
93+
self.decoderawtransaction_tests()
94+
self.transaction_version_number_tests()
95+
if not self.options.descriptors:
96+
self.raw_multisig_transaction_legacy_tests()
97+
98+
def getrawtransaction_tests(self):
8999
addr = self.nodes[1].getnewaddress()
90100
txid = self.nodes[0].sendtoaddress(addr, 10)
91101
self.nodes[0].generate(1)
@@ -168,6 +178,7 @@ def run_test(self):
168178
block = self.nodes[0].getblock(self.nodes[0].getblockhash(0))
169179
assert_raises_rpc_error(-5, "The genesis block coinbase is not considered an ordinary transaction", self.nodes[0].getrawtransaction, block['merkleroot'])
170180

181+
def createrawtransaction_tests(self):
171182
self.log.info("Test createrawtransaction")
172183
# Test `createrawtransaction` required parameters
173184
assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction)
@@ -247,6 +258,7 @@ def run_test(self):
247258
self.nodes[2].createrawtransaction(inputs=[{'txid': TXID, 'vout': 9}], outputs=[{address: 99}, {address2: 99}, {'data': '99'}]),
248259
)
249260

261+
def signrawtransactionwithwallet_tests(self):
250262
for type in ["bech32", "p2sh-segwit", "legacy"]:
251263
self.log.info(f"Test signrawtransactionwithwallet with missing prevtx info ({type})")
252264
addr = self.nodes[0].getnewaddress("", type)
@@ -259,12 +271,12 @@ def run_test(self):
259271
prevtx = dict(txid=TXID, scriptPubKey=pubkey, vout=3, amount=1)
260272
succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx])
261273
assert succ["complete"]
274+
262275
if type == "legacy":
263276
del prevtx["amount"]
264277
succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx])
265278
assert succ["complete"]
266-
267-
if type != "legacy":
279+
else:
268280
assert_raises_rpc_error(-3, "Missing amount", self.nodes[0].signrawtransactionwithwallet, rawtx, [
269281
{
270282
"txid": TXID,
@@ -295,13 +307,15 @@ def run_test(self):
295307
}
296308
])
297309

310+
def sendrawtransaction_tests(self):
298311
self.log.info("Test sendrawtransaction with missing input")
299312
inputs = [{'txid' : TXID, 'vout' : 1}] # won't exist
300313
outputs = { self.nodes[0].getnewaddress() : 4.998 }
301314
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
302315
rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx)
303316
assert_raises_rpc_error(-25, "bad-txns-inputs-missingorspent", self.nodes[2].sendrawtransaction, rawtx['hex'])
304317

318+
def sendrawtransaction_testmempoolaccept_tests(self):
305319
self.log.info("Test sendrawtransaction/testmempoolaccept with maxfeerate")
306320
# Test a transaction with a small fee.
307321
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
@@ -360,6 +374,7 @@ def run_test(self):
360374
assert_equal(testres['reject-reason'], 'txn-already-known')
361375
assert_raises_rpc_error(-27, 'Transaction already in block chain', node.sendrawtransaction, rawTxSigned['hex'])
362376

377+
def decoderawtransaction_tests(self):
363378
self.log.info("Test decoderawtransaction")
364379
# witness transaction
365380
encrawtx = "010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000102616100000000"
@@ -378,6 +393,7 @@ def run_test(self):
378393
assert_equal(decrawtx, decrawtx_wit) # the witness interpretation should be chosen
379394
assert_equal(decrawtx['vin'][0]['coinbase'], "03c68708046ff8415c622f4254432e434f4d2ffabe6d6de1965d02c68f928e5b244ab1965115a36f56eb997633c7f690124bbf43644e23080000000ca3d3af6d005a65ff0200fd00000000")
380395

396+
def transaction_version_number_tests(self):
381397
self.log.info("Test transaction version numbers")
382398

383399
# Test the minimum transaction version number that fits in a signed 32-bit integer.
@@ -395,122 +411,122 @@ def run_test(self):
395411
decrawtx = self.nodes[0].decoderawtransaction(rawtx)
396412
assert_equal(decrawtx['version'], 0x7fffffff)
397413

398-
if not self.options.descriptors:
399-
self.log.info("Test raw multisig transactions (legacy)")
400-
# The traditional multisig workflow does not work with descriptor wallets so these are legacy only.
401-
# The multisig workflow with descriptor wallets uses PSBTs and is tested elsewhere, no need to do them here.
402-
# 2of2 test
403-
addr1 = self.nodes[2].getnewaddress()
404-
addr2 = self.nodes[2].getnewaddress()
405-
406-
addr1Obj = self.nodes[2].getaddressinfo(addr1)
407-
addr2Obj = self.nodes[2].getaddressinfo(addr2)
408-
409-
# Tests for createmultisig and addmultisigaddress
410-
assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"])
411-
self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys
412-
assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here.
413-
414-
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address']
415-
416-
#use balance deltas instead of absolute values
417-
bal = self.nodes[2].getbalance()
418-
419-
# send 1.2 BTC to msig adr
420-
txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
421-
self.sync_all()
422-
self.nodes[0].generate(1)
423-
self.sync_all()
424-
assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance
425-
426-
427-
# 2of3 test from different nodes
428-
bal = self.nodes[2].getbalance()
429-
addr1 = self.nodes[1].getnewaddress()
430-
addr2 = self.nodes[2].getnewaddress()
431-
addr3 = self.nodes[2].getnewaddress()
432-
433-
addr1Obj = self.nodes[1].getaddressinfo(addr1)
434-
addr2Obj = self.nodes[2].getaddressinfo(addr2)
435-
addr3Obj = self.nodes[2].getaddressinfo(addr3)
436-
437-
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']
438-
439-
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
440-
decTx = self.nodes[0].gettransaction(txId)
441-
rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
442-
self.sync_all()
443-
self.nodes[0].generate(1)
444-
self.sync_all()
445-
446-
#THIS IS AN INCOMPLETE FEATURE
447-
#NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION
448-
assert_equal(self.nodes[2].getbalance(), bal) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable
449-
450-
txDetails = self.nodes[0].gettransaction(txId, True)
451-
rawTx = self.nodes[0].decoderawtransaction(txDetails['hex'])
452-
vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('2.20000000'))
453-
454-
bal = self.nodes[0].getbalance()
455-
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}]
456-
outputs = { self.nodes[0].getnewaddress() : 2.19 }
457-
rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
458-
rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(rawTx, inputs)
459-
assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx
460-
461-
rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx, inputs)
462-
assert_equal(rawTxSigned['complete'], True) #node2 can sign the tx compl., own two of three keys
463-
self.nodes[2].sendrawtransaction(rawTxSigned['hex'])
464-
rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex'])
465-
self.sync_all()
466-
self.nodes[0].generate(1)
467-
self.sync_all()
468-
assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
469-
470-
# 2of2 test for combining transactions
471-
bal = self.nodes[2].getbalance()
472-
addr1 = self.nodes[1].getnewaddress()
473-
addr2 = self.nodes[2].getnewaddress()
474-
475-
addr1Obj = self.nodes[1].getaddressinfo(addr1)
476-
addr2Obj = self.nodes[2].getaddressinfo(addr2)
477-
478-
self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
479-
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
480-
mSigObjValid = self.nodes[2].getaddressinfo(mSigObj)
481-
482-
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
483-
decTx = self.nodes[0].gettransaction(txId)
484-
rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex'])
485-
self.sync_all()
486-
self.nodes[0].generate(1)
487-
self.sync_all()
488-
489-
assert_equal(self.nodes[2].getbalance(), bal) # the funds of a 2of2 multisig tx should not be marked as spendable
490-
491-
txDetails = self.nodes[0].gettransaction(txId, True)
492-
rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex'])
493-
vout = next(o for o in rawTx2['vout'] if o['value'] == Decimal('2.20000000'))
494-
495-
bal = self.nodes[0].getbalance()
496-
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}]
497-
outputs = { self.nodes[0].getnewaddress() : 2.19 }
498-
rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
499-
rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs)
500-
self.log.debug(rawTxPartialSigned1)
501-
assert_equal(rawTxPartialSigned1['complete'], False) #node1 only has one key, can't comp. sign the tx
502-
503-
rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(rawTx2, inputs)
504-
self.log.debug(rawTxPartialSigned2)
505-
assert_equal(rawTxPartialSigned2['complete'], False) #node2 only has one key, can't comp. sign the tx
506-
rawTxComb = self.nodes[2].combinerawtransaction([rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']])
507-
self.log.debug(rawTxComb)
508-
self.nodes[2].sendrawtransaction(rawTxComb)
509-
rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb)
510-
self.sync_all()
511-
self.nodes[0].generate(1)
512-
self.sync_all()
513-
assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
414+
def raw_multisig_transaction_legacy_tests(self):
415+
self.log.info("Test raw multisig transactions (legacy)")
416+
# The traditional multisig workflow does not work with descriptor wallets so these are legacy only.
417+
# The multisig workflow with descriptor wallets uses PSBTs and is tested elsewhere, no need to do them here.
418+
# 2of2 test
419+
addr1 = self.nodes[2].getnewaddress()
420+
addr2 = self.nodes[2].getnewaddress()
421+
422+
addr1Obj = self.nodes[2].getaddressinfo(addr1)
423+
addr2Obj = self.nodes[2].getaddressinfo(addr2)
424+
425+
# Tests for createmultisig and addmultisigaddress
426+
assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"])
427+
self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys
428+
assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here.
429+
430+
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address']
431+
432+
#use balance deltas instead of absolute values
433+
bal = self.nodes[2].getbalance()
434+
435+
# send 1.2 BTC to msig adr
436+
txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
437+
self.sync_all()
438+
self.nodes[0].generate(1)
439+
self.sync_all()
440+
assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance
441+
442+
443+
# 2of3 test from different nodes
444+
bal = self.nodes[2].getbalance()
445+
addr1 = self.nodes[1].getnewaddress()
446+
addr2 = self.nodes[2].getnewaddress()
447+
addr3 = self.nodes[2].getnewaddress()
448+
449+
addr1Obj = self.nodes[1].getaddressinfo(addr1)
450+
addr2Obj = self.nodes[2].getaddressinfo(addr2)
451+
addr3Obj = self.nodes[2].getaddressinfo(addr3)
452+
453+
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']
454+
455+
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
456+
decTx = self.nodes[0].gettransaction(txId)
457+
rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
458+
self.sync_all()
459+
self.nodes[0].generate(1)
460+
self.sync_all()
461+
462+
#THIS IS AN INCOMPLETE FEATURE
463+
#NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION
464+
assert_equal(self.nodes[2].getbalance(), bal) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable
465+
466+
txDetails = self.nodes[0].gettransaction(txId, True)
467+
rawTx = self.nodes[0].decoderawtransaction(txDetails['hex'])
468+
vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('2.20000000'))
469+
470+
bal = self.nodes[0].getbalance()
471+
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}]
472+
outputs = { self.nodes[0].getnewaddress() : 2.19 }
473+
rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
474+
rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(rawTx, inputs)
475+
assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx
476+
477+
rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx, inputs)
478+
assert_equal(rawTxSigned['complete'], True) #node2 can sign the tx compl., own two of three keys
479+
self.nodes[2].sendrawtransaction(rawTxSigned['hex'])
480+
rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex'])
481+
self.sync_all()
482+
self.nodes[0].generate(1)
483+
self.sync_all()
484+
assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
485+
486+
# 2of2 test for combining transactions
487+
bal = self.nodes[2].getbalance()
488+
addr1 = self.nodes[1].getnewaddress()
489+
addr2 = self.nodes[2].getnewaddress()
490+
491+
addr1Obj = self.nodes[1].getaddressinfo(addr1)
492+
addr2Obj = self.nodes[2].getaddressinfo(addr2)
493+
494+
self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
495+
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
496+
mSigObjValid = self.nodes[2].getaddressinfo(mSigObj)
497+
498+
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
499+
decTx = self.nodes[0].gettransaction(txId)
500+
rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex'])
501+
self.sync_all()
502+
self.nodes[0].generate(1)
503+
self.sync_all()
504+
505+
assert_equal(self.nodes[2].getbalance(), bal) # the funds of a 2of2 multisig tx should not be marked as spendable
506+
507+
txDetails = self.nodes[0].gettransaction(txId, True)
508+
rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex'])
509+
vout = next(o for o in rawTx2['vout'] if o['value'] == Decimal('2.20000000'))
510+
511+
bal = self.nodes[0].getbalance()
512+
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}]
513+
outputs = { self.nodes[0].getnewaddress() : 2.19 }
514+
rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
515+
rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs)
516+
self.log.debug(rawTxPartialSigned1)
517+
assert_equal(rawTxPartialSigned1['complete'], False) #node1 only has one key, can't comp. sign the tx
518+
519+
rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(rawTx2, inputs)
520+
self.log.debug(rawTxPartialSigned2)
521+
assert_equal(rawTxPartialSigned2['complete'], False) #node2 only has one key, can't comp. sign the tx
522+
rawTxComb = self.nodes[2].combinerawtransaction([rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']])
523+
self.log.debug(rawTxComb)
524+
self.nodes[2].sendrawtransaction(rawTxComb)
525+
rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb)
526+
self.sync_all()
527+
self.nodes[0].generate(1)
528+
self.sync_all()
529+
assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
514530

515531

516532
if __name__ == '__main__':

0 commit comments

Comments
 (0)