mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-07-09 18:00:13 +02:00
[rpc] createrawtransaction: Accept sorted outputs
This commit is contained in:
@ -12,7 +12,12 @@ Test the following RPCs:
|
||||
- getrawtransaction
|
||||
"""
|
||||
|
||||
from collections import OrderedDict
|
||||
from io import BytesIO
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.messages import (
|
||||
CTransaction,
|
||||
)
|
||||
from test_framework.util import *
|
||||
|
||||
|
||||
@ -43,11 +48,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
def setup_network(self, split=False):
|
||||
super().setup_network()
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
connect_nodes_bi(self.nodes, 0, 2)
|
||||
|
||||
def run_test(self):
|
||||
|
||||
#prepare some coins for multiple *rawtransaction commands
|
||||
self.log.info('prepare some coins for multiple *rawtransaction commands')
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(101)
|
||||
@ -59,10 +63,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
self.nodes[0].generate(5)
|
||||
self.sync_all()
|
||||
|
||||
# Test getrawtransaction on genesis block coinbase returns an error
|
||||
self.log.info('Test getrawtransaction on genesis block coinbase returns an error')
|
||||
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'])
|
||||
|
||||
self.log.info('Check parameter types and required parameters of createrawtransaction')
|
||||
# Test `createrawtransaction` required parameters
|
||||
assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction)
|
||||
assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [])
|
||||
@ -83,12 +88,18 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
# Test `createrawtransaction` invalid `outputs`
|
||||
address = self.nodes[0].getnewaddress()
|
||||
assert_raises_rpc_error(-3, "Expected type object", self.nodes[0].createrawtransaction, [], 'foo')
|
||||
address2 = self.nodes[0].getnewaddress()
|
||||
assert_raises_rpc_error(-1, "JSON value is not an array as expected", self.nodes[0].createrawtransaction, [], 'foo')
|
||||
self.nodes[0].createrawtransaction(inputs=[], outputs={}) # Should not throw for backwards compatibility
|
||||
self.nodes[0].createrawtransaction(inputs=[], outputs=[])
|
||||
assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'})
|
||||
assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].createrawtransaction, [], {'foo': 0})
|
||||
assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {address: 'foo'})
|
||||
assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {address: -1})
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)]))
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], [{address: 1}, {address: 1}])
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, key-value pair must contain exactly one key", self.nodes[0].createrawtransaction, [], [{'a': 1, 'b': 2}])
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, key-value pair not an object as expected", self.nodes[0].createrawtransaction, [], [['key-value pair1'], ['2']])
|
||||
|
||||
# Test `createrawtransaction` invalid `locktime`
|
||||
assert_raises_rpc_error(-3, "Expected type number", self.nodes[0].createrawtransaction, [], {}, 'foo')
|
||||
@ -98,9 +109,38 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
# Test `createrawtransaction` invalid `replaceable`
|
||||
assert_raises_rpc_error(-3, "Expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo')
|
||||
|
||||
#########################################
|
||||
# sendrawtransaction with missing input #
|
||||
#########################################
|
||||
self.log.info('Check that createrawtransaction accepts an array and object as outputs')
|
||||
tx = CTransaction()
|
||||
# One output
|
||||
tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs={address: 99}))))
|
||||
assert_equal(len(tx.vout), 1)
|
||||
assert_equal(
|
||||
bytes_to_hex_str(tx.serialize()),
|
||||
self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}]),
|
||||
)
|
||||
# Two outputs
|
||||
tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=OrderedDict([(address, 99), (address2, 99)])))))
|
||||
assert_equal(len(tx.vout), 2)
|
||||
assert_equal(
|
||||
bytes_to_hex_str(tx.serialize()),
|
||||
self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {address2: 99}]),
|
||||
)
|
||||
# Two data outputs
|
||||
tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=multidict([('data', '99'), ('data', '99')])))))
|
||||
assert_equal(len(tx.vout), 2)
|
||||
assert_equal(
|
||||
bytes_to_hex_str(tx.serialize()),
|
||||
self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{'data': '99'}, {'data': '99'}]),
|
||||
)
|
||||
# Multiple mixed outputs
|
||||
tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=multidict([(address, 99), ('data', '99'), ('data', '99')])))))
|
||||
assert_equal(len(tx.vout), 3)
|
||||
assert_equal(
|
||||
bytes_to_hex_str(tx.serialize()),
|
||||
self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {'data': '99'}, {'data': '99'}]),
|
||||
)
|
||||
|
||||
self.log.info('sendrawtransaction with missing input')
|
||||
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists
|
||||
outputs = { self.nodes[0].getnewaddress() : 4.998 }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
@ -248,14 +288,14 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
outputs = { self.nodes[0].getnewaddress() : 2.19 }
|
||||
rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs)
|
||||
self.log.info(rawTxPartialSigned1)
|
||||
self.log.debug(rawTxPartialSigned1)
|
||||
assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx
|
||||
|
||||
rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(rawTx2, inputs)
|
||||
self.log.info(rawTxPartialSigned2)
|
||||
self.log.debug(rawTxPartialSigned2)
|
||||
assert_equal(rawTxPartialSigned2['complete'], False) #node2 only has one key, can't comp. sign the tx
|
||||
rawTxComb = self.nodes[2].combinerawtransaction([rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']])
|
||||
self.log.info(rawTxComb)
|
||||
self.log.debug(rawTxComb)
|
||||
self.nodes[2].sendrawtransaction(rawTxComb)
|
||||
rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb)
|
||||
self.sync_all()
|
||||
@ -273,7 +313,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000"
|
||||
decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction
|
||||
assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))
|
||||
|
||||
|
||||
# getrawtransaction tests
|
||||
# 1. valid parameters - only supply txid
|
||||
txHash = rawTx["hash"]
|
||||
|
Reference in New Issue
Block a user