mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-07-08 17:30:36 +02:00
rpc: Return fee and prevout(s) to getrawtransaction
* Add optional fee response in BTC to getrawtransaction * Add optional prevout(s) response to getrawtransaction showing utxos being spent * Add getrawtransaction_verbosity functional test to validate fields
This commit is contained in:
@ -14,6 +14,7 @@ Test the following RPCs:
|
||||
|
||||
from collections import OrderedDict
|
||||
from decimal import Decimal
|
||||
from itertools import product
|
||||
|
||||
from test_framework.blocktools import COINBASE_MATURITY
|
||||
from test_framework.messages import (
|
||||
@ -80,6 +81,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
self.generate(self.nodes[0], COINBASE_MATURITY + 1)
|
||||
|
||||
self.getrawtransaction_tests()
|
||||
self.getrawtransaction_verbosity_tests()
|
||||
self.createrawtransaction_tests()
|
||||
self.sendrawtransaction_tests()
|
||||
self.sendrawtransaction_testmempoolaccept_tests()
|
||||
@ -114,6 +116,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
# 4. valid parameters - supply txid and 1 for verbose.
|
||||
# We only check the "hex" field of the output so we don't need to update this test every time the output format changes.
|
||||
assert_equal(self.nodes[n].getrawtransaction(txId, 1)["hex"], tx['hex'])
|
||||
assert_equal(self.nodes[n].getrawtransaction(txId, 2)["hex"], tx['hex'])
|
||||
|
||||
# 5. valid parameters - supply txid and True for non-verbose
|
||||
assert_equal(self.nodes[n].getrawtransaction(txId, True)["hex"], tx['hex'])
|
||||
@ -124,13 +127,14 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
# 6. invalid parameters - supply txid and invalid boolean values (strings) for verbose
|
||||
for value in ["True", "False"]:
|
||||
assert_raises_rpc_error(-3, "not of expected type bool", self.nodes[n].getrawtransaction, txid=txId, verbose=value)
|
||||
assert_raises_rpc_error(-3, "not of expected type number", self.nodes[n].getrawtransaction, txid=txId, verbose=value)
|
||||
assert_raises_rpc_error(-3, "not of expected type number", self.nodes[n].getrawtransaction, txid=txId, verbosity=value)
|
||||
|
||||
# 7. invalid parameters - supply txid and empty array
|
||||
assert_raises_rpc_error(-3, "not of expected type bool", self.nodes[n].getrawtransaction, txId, [])
|
||||
assert_raises_rpc_error(-3, "not of expected type number", self.nodes[n].getrawtransaction, txId, [])
|
||||
|
||||
# 8. invalid parameters - supply txid and empty dict
|
||||
assert_raises_rpc_error(-3, "not of expected type bool", self.nodes[n].getrawtransaction, txId, {})
|
||||
assert_raises_rpc_error(-3, "not of expected type number", self.nodes[n].getrawtransaction, txId, {})
|
||||
|
||||
# Make a tx by sending, then generate 2 blocks; block1 has the tx in it
|
||||
tx = self.wallet.send_self_transfer(from_node=self.nodes[2])['txid']
|
||||
@ -143,9 +147,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
assert_equal(gottx['in_active_chain'], True)
|
||||
if n == 0:
|
||||
self.log.info("Test getrawtransaction with -txindex, without blockhash: 'in_active_chain' should be absent")
|
||||
gottx = self.nodes[n].getrawtransaction(txid=tx, verbose=True)
|
||||
assert_equal(gottx['txid'], tx)
|
||||
assert 'in_active_chain' not in gottx
|
||||
for v in [1,2]:
|
||||
gottx = self.nodes[n].getrawtransaction(txid=tx, verbosity=v)
|
||||
assert_equal(gottx['txid'], tx)
|
||||
assert 'in_active_chain' not in gottx
|
||||
else:
|
||||
self.log.info("Test getrawtransaction without -txindex, without blockhash: expect the call to raise")
|
||||
assert_raises_rpc_error(-5, err_msg, self.nodes[n].getrawtransaction, txid=tx, verbose=True)
|
||||
@ -170,6 +175,70 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
block = self.nodes[0].getblock(self.nodes[0].getblockhash(0))
|
||||
assert_raises_rpc_error(-5, "The genesis block coinbase is not considered an ordinary transaction", self.nodes[0].getrawtransaction, block['merkleroot'])
|
||||
|
||||
def getrawtransaction_verbosity_tests(self):
|
||||
tx = self.wallet.send_self_transfer(from_node=self.nodes[1])['txid']
|
||||
[block1] = self.generate(self.nodes[1], 1)
|
||||
fields = [
|
||||
'blockhash',
|
||||
'blocktime',
|
||||
'confirmations',
|
||||
'hash',
|
||||
'hex',
|
||||
'in_active_chain',
|
||||
'locktime',
|
||||
'size',
|
||||
'time',
|
||||
'txid',
|
||||
'vin',
|
||||
'vout',
|
||||
'vsize',
|
||||
'weight',
|
||||
]
|
||||
prevout_fields = [
|
||||
'generated',
|
||||
'height',
|
||||
'value',
|
||||
'scriptPubKey',
|
||||
]
|
||||
script_pub_key_fields = [
|
||||
'address',
|
||||
'asm',
|
||||
'hex',
|
||||
'type',
|
||||
]
|
||||
# node 0 & 2 with verbosity 1 & 2
|
||||
for n, v in product([0, 2], [1, 2]):
|
||||
self.log.info(f"Test getrawtransaction_verbosity {v} {'with' if n == 0 else 'without'} -txindex, with blockhash")
|
||||
gottx = self.nodes[n].getrawtransaction(txid=tx, verbosity=v, blockhash=block1)
|
||||
missing_fields = set(fields).difference(gottx.keys())
|
||||
if missing_fields:
|
||||
raise AssertionError(f"fields {', '.join(missing_fields)} are not in transaction")
|
||||
|
||||
assert(len(gottx['vin']) > 0)
|
||||
if v == 1:
|
||||
assert('fee' not in gottx)
|
||||
assert('prevout' not in gottx['vin'][0])
|
||||
if v == 2:
|
||||
assert(isinstance(gottx['fee'], Decimal))
|
||||
assert('prevout' in gottx['vin'][0])
|
||||
prevout = gottx['vin'][0]['prevout']
|
||||
script_pub_key = prevout['scriptPubKey']
|
||||
|
||||
missing_fields = set(prevout_fields).difference(prevout.keys())
|
||||
if missing_fields:
|
||||
raise AssertionError(f"fields {', '.join(missing_fields)} are not in transaction")
|
||||
|
||||
missing_fields = set(script_pub_key_fields).difference(script_pub_key.keys())
|
||||
if missing_fields:
|
||||
raise AssertionError(f"fields {', '.join(missing_fields)} are not in transaction")
|
||||
|
||||
# check verbosity 2 without blockhash but with txindex
|
||||
assert('fee' in self.nodes[0].getrawtransaction(txid=tx, verbosity=2))
|
||||
# check that coinbase has no fee or does not throw any errors for verbosity 2
|
||||
coin_base = self.nodes[1].getblock(block1)['tx'][0]
|
||||
gottx = self.nodes[1].getrawtransaction(txid=coin_base, verbosity=2, blockhash=block1)
|
||||
assert('fee' not in gottx)
|
||||
|
||||
def createrawtransaction_tests(self):
|
||||
self.log.info("Test createrawtransaction")
|
||||
# Test `createrawtransaction` required parameters
|
||||
|
Reference in New Issue
Block a user