2016-05-06 11:23:48 +02:00
#!/usr/bin/env python3
# Copyright (c) 2014-2016 The Bitcoin Core developers
2014-12-29 20:17:21 +01:00
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-08-16 00:35:19 +02:00
""" Test the rawtransaction RPCs.
2014-12-29 20:17:21 +01:00
2019-01-07 10:55:35 +01:00
Test the following RPCs :
- createrawtransaction
2018-02-20 03:29:22 +01:00
- signrawtransactionwithwallet
2019-01-07 10:55:35 +01:00
- sendrawtransaction
- decoderawtransaction
- getrawtransaction
2016-11-23 07:13:35 +01:00
"""
2014-12-29 20:17:21 +01:00
2018-03-13 17:58:52 +01:00
from collections import OrderedDict
Merge #13054: tests: Enable automatic detection of undefined names in Python tests scripts. Remove wildcard imports.
68400d8b96 tests: Use explicit imports (practicalswift)
Pull request description:
Enable automatic detection of undefined names in Python tests scripts. Remove wildcard imports.
Wildcard imports make it unclear which names are present in the namespace, confusing both readers and many automated tools.
An additional benefit of not using wildcard imports in tests scripts is that readers of a test script then can infer the rough testing scope just by looking at the imports.
Before this commit:
```
$ contrib/devtools/lint-python.sh | head -10
./test/functional/feature_rbf.py:8:1: F403 'from test_framework.util import *' used; unable to detect undefined names
./test/functional/feature_rbf.py:9:1: F403 'from test_framework.script import *' used; unable to detect undefined names
./test/functional/feature_rbf.py:10:1: F403 'from test_framework.mininode import *' used; unable to detect undefined names
./test/functional/feature_rbf.py:15:12: F405 bytes_to_hex_str may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:17:58: F405 CScript may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:25:13: F405 COIN may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:26:31: F405 satoshi_round may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:26:60: F405 COIN may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:30:41: F405 satoshi_round may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
./test/functional/feature_rbf.py:30:68: F405 COIN may be undefined, or defined from star imports: test_framework.mininode, test_framework.script, test_framework.util
$
```
After this commit:
```
$ contrib/devtools/lint-python.sh | head -10
$
```
Tree-SHA512: 3f826d39cffb6438388e5efcb20a9622ff8238247e882d68f7b38609877421b2a8e10e9229575f8eb6a8fa42dec4256986692e92922c86171f750a0e887438d9
2018-08-13 14:24:43 +02:00
from decimal import Decimal
2018-03-13 17:58:52 +01:00
from io import BytesIO
2018-04-24 11:56:32 +02:00
from test_framework . messages import CTransaction , ToHex
2015-05-02 13:58:10 +02:00
from test_framework . test_framework import BitcoinTestFramework
2021-08-27 21:03:02 +02:00
from test_framework . util import assert_equal , assert_raises_rpc_error , connect_nodes_bi , hex_str_to_bytes
2014-12-29 20:17:21 +01:00
2017-12-13 17:12:12 +01:00
class multidict ( dict ) :
""" Dictionary that allows duplicate keys.
Constructed with a list of ( key , value ) tuples . When dumped by the json module ,
will output invalid json with repeated keys , eg :
>> > json . dumps ( multidict ( [ ( 1 , 2 ) , ( 1 , 2 ) ] )
' { " 1 " : 2, " 1 " : 2} '
Used to test calls to rpc methods with repeated keys in the json object . """
def __init__ ( self , x ) :
dict . __init__ ( self , x )
self . x = x
def items ( self ) :
return self . x
2014-12-29 20:17:21 +01:00
# Create one-input, one-output, no-fee transaction:
class RawTransactionsTest ( BitcoinTestFramework ) :
2017-09-01 18:47:13 +02:00
def set_test_params ( self ) :
2016-05-20 15:16:51 +02:00
self . setup_clean_chain = True
self . num_nodes = 3
2021-08-05 17:46:17 +02:00
self . extra_args = [ [ " -txindex " ] , [ " -txindex " ] , [ " -txindex " ] ]
2014-12-29 20:17:21 +01:00
2018-12-29 20:18:43 +01:00
def setup_network ( self ) :
2017-05-02 20:02:55 +02:00
super ( ) . setup_network ( )
2018-03-13 17:58:52 +01:00
connect_nodes_bi ( self . nodes , 0 , 2 )
2015-04-01 15:08:00 +02:00
2014-12-29 20:17:21 +01:00
def run_test ( self ) :
2018-03-13 17:58:52 +01:00
self . log . info ( ' prepare some coins for multiple *rawtransaction commands ' )
2014-12-29 20:17:21 +01:00
self . nodes [ 2 ] . generate ( 1 )
2015-07-10 20:11:44 +02:00
self . sync_all ( )
2014-12-29 20:17:21 +01:00
self . nodes [ 0 ] . generate ( 101 )
self . sync_all ( )
2015-12-02 18:12:23 +01:00
self . nodes [ 0 ] . sendtoaddress ( self . nodes [ 2 ] . getnewaddress ( ) , 1.5 )
self . nodes [ 0 ] . sendtoaddress ( self . nodes [ 2 ] . getnewaddress ( ) , 1.0 )
self . nodes [ 0 ] . sendtoaddress ( self . nodes [ 2 ] . getnewaddress ( ) , 5.0 )
2014-12-29 20:17:21 +01:00
self . sync_all ( )
self . nodes [ 0 ] . generate ( 5 )
self . sync_all ( )
2018-03-13 17:58:52 +01:00
self . log . info ( ' Test getrawtransaction on genesis block coinbase returns an error ' )
2018-01-30 09:59:22 +01:00
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 ' ] )
2018-03-13 17:58:52 +01:00
self . log . info ( ' Check parameter types and required parameters of createrawtransaction ' )
2017-12-13 17:12:12 +01:00
# Test `createrawtransaction` required parameters
assert_raises_rpc_error ( - 1 , " createrawtransaction " , self . nodes [ 0 ] . createrawtransaction )
assert_raises_rpc_error ( - 1 , " createrawtransaction " , self . nodes [ 0 ] . createrawtransaction , [ ] )
# Test `createrawtransaction` invalid extra parameters
assert_raises_rpc_error ( - 1 , " createrawtransaction " , self . nodes [ 0 ] . createrawtransaction , [ ] , { } , 0 , False , ' foo ' )
# Test `createrawtransaction` invalid `inputs`
txid = ' 1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000 '
assert_raises_rpc_error ( - 3 , " Expected type array " , self . nodes [ 0 ] . createrawtransaction , ' foo ' , { } )
assert_raises_rpc_error ( - 1 , " JSON value is not an object as expected " , self . nodes [ 0 ] . createrawtransaction , [ ' foo ' ] , { } )
assert_raises_rpc_error ( - 8 , " txid must be hexadecimal string " , self . nodes [ 0 ] . createrawtransaction , [ { } ] , { } )
assert_raises_rpc_error ( - 8 , " txid must be hexadecimal string " , self . nodes [ 0 ] . createrawtransaction , [ { ' txid ' : ' foo ' } ] , { } )
assert_raises_rpc_error ( - 8 , " Invalid parameter, missing vout key " , self . nodes [ 0 ] . createrawtransaction , [ { ' txid ' : txid } ] , { } )
assert_raises_rpc_error ( - 8 , " Invalid parameter, missing vout key " , self . nodes [ 0 ] . createrawtransaction , [ { ' txid ' : txid , ' vout ' : ' foo ' } ] , { } )
assert_raises_rpc_error ( - 8 , " Invalid parameter, vout must be positive " , self . nodes [ 0 ] . createrawtransaction , [ { ' txid ' : txid , ' vout ' : - 1 } ] , { } )
assert_raises_rpc_error ( - 8 , " Invalid parameter, sequence number is out of range " , self . nodes [ 0 ] . createrawtransaction , [ { ' txid ' : txid , ' vout ' : 0 , ' sequence ' : - 1 } ] , { } )
# Test `createrawtransaction` invalid `outputs`
address = self . nodes [ 0 ] . getnewaddress ( )
2018-03-13 17:58:52 +01:00
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 = [ ] )
2017-12-13 17:12:12 +01:00
assert_raises_rpc_error ( - 8 , " Data must be hexadecimal string " , self . nodes [ 0 ] . createrawtransaction , [ ] , { ' data ' : ' foo ' } )
2020-01-31 16:38:47 +01:00
assert_raises_rpc_error ( - 5 , " Invalid Dash address " , self . nodes [ 0 ] . createrawtransaction , [ ] , { ' foo ' : 0 } )
2017-12-13 17:12:12 +01:00
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 ) ] ) )
2018-03-13 17:58:52 +01:00
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 ' ] ] )
2017-12-13 17:12:12 +01:00
# Test `createrawtransaction` invalid `locktime`
assert_raises_rpc_error ( - 3 , " Expected type number " , self . nodes [ 0 ] . createrawtransaction , [ ] , { } , ' foo ' )
assert_raises_rpc_error ( - 8 , " Invalid parameter, locktime out of range " , self . nodes [ 0 ] . createrawtransaction , [ ] , { } , - 1 )
assert_raises_rpc_error ( - 8 , " Invalid parameter, locktime out of range " , self . nodes [ 0 ] . createrawtransaction , [ ] , { } , 4294967296 )
2018-03-13 17:58:52 +01:00
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 (
2021-08-27 21:03:02 +02:00
tx . serialize ( ) . hex ( ) ,
2018-03-13 17:58:52 +01:00
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 (
2021-08-27 21:03:02 +02:00
tx . serialize ( ) . hex ( ) ,
2018-03-13 17:58:52 +01:00
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 (
2021-08-27 21:03:02 +02:00
tx . serialize ( ) . hex ( ) ,
2018-03-13 17:58:52 +01:00
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 (
2021-08-27 21:03:02 +02:00
tx . serialize ( ) . hex ( ) ,
2018-03-13 17:58:52 +01:00
self . nodes [ 2 ] . createrawtransaction ( inputs = [ { ' txid ' : txid , ' vout ' : 9 } ] , outputs = [ { address : 99 } , { ' data ' : ' 99 ' } , { ' data ' : ' 99 ' } ] ) ,
)
self . log . info ( ' sendrawtransaction with missing input ' )
2014-12-29 20:17:21 +01:00
inputs = [ { ' txid ' : " 1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000 " , ' vout ' : 1 } ] #won't exists
outputs = { self . nodes [ 0 ] . getnewaddress ( ) : 4.998 }
rawtx = self . nodes [ 2 ] . createrawtransaction ( inputs , outputs )
2018-02-20 03:29:22 +01:00
rawtx = self . nodes [ 2 ] . signrawtransactionwithwallet ( rawtx )
2015-04-01 15:08:00 +02:00
2017-03-09 10:02:13 +01:00
# This will raise an exception since there are missing inputs
2019-09-25 11:34:51 +02:00
assert_raises_rpc_error ( - 25 , " Missing inputs " , self . nodes [ 2 ] . sendrawtransaction , rawtx [ ' hex ' ] )
2015-04-01 15:08:00 +02:00
Merge #10275: [rpc] Allow fetching tx directly from specified block in getrawtransaction
434526a [test] Add tests for getrawtransaction with block hash. (Karl-Johan Alm)
b167951 [rpc] Allow getrawtransaction to take optional blockhash to fetch transaction from a block directly. (Karl-Johan Alm)
a5f5a2c [rpc] Fix fVerbose parsing (remove excess if cases). (Karl-Johan Alm)
Pull request description:
[Reviewer hint: use [?w=1](https://github.com/bitcoin/bitcoin/pull/10275/files?w=1) to avoid seeing a bunch of indentation changes.]
Presuming a user knows the block hash of the block containing a given transaction, this PR allows them to fetch the raw transaction, even without `-txindex`. It also enables support for getting transactions that are in orphaned blocks.
Note that supplying a block hash will override mempool and txindex support in `GetTransaction`. The rationale behind this is that a transaction may be in multiple places (orphaned blocks) and if the user supplies an explicit block hash it should be adhered to.
```Bash
$ # a41.. is a tx inside an orphan block ..3c6f.. -- first try getting it normally
$ ./bitcoin-cli getrawtransaction a41e66ee1341aa9fb9475b98cfdc1fe1261faa56c0a49254f33065ec90f7cd79 1
error code: -5
error message:
No such mempool transaction. Use -txindex to enable blockchain transaction queries. Use gettransaction for wallet transactions.
$ # now try with block hash
$ ./bitcoin-cli getrawtransaction a41e66ee1341aa9fb9475b98cfdc1fe1261faa56c0a49254f33065ec90f7cd79 1 0000000000000000003c6fe479122bfa4a9187493937af1734e1e5cd9f198ec7
{
"hex": "01000000014e7e81144e42f6d65550e59b715d470c9301fd7ac189[...]90488ac00000000",
"inMainChain": false,
"txid": "a41e66ee1341aa9fb9475b98cfdc1fe1261faa56c0a49254f33065ec90f7cd79",
"hash": "a41e66ee1341aa9fb9475b98cfdc1fe1261faa56c0a49254f33065ec90f7cd79",
"size": 225,
[...]
}
$ # another tx 6c66... in block 462000
$ ./bitcoin-cli getrawtransaction 6c66b98191e9d6cc671f6817142152ebf6c5cab2ef008397b5a71ac13255a735 1 00000000000000000217f2c12922e321f6d4aa933ce88005a9a493c503054a40
{
"hex": "0200000004d157[...]88acaf0c0700",
"inMainChain": true,
"txid": "6c66b98191e9d6cc671f6817142152ebf6c5cab2ef008397b5a71ac13255a735",
"hash": "6c66b98191e9d6cc671f6817142152ebf6c5cab2ef008397b5a71ac13255a735",
"size": 666,
[...]
}
$
```
Tree-SHA512: 279be3818141edd3cc194a9ee65929331920afb30297ab2d6da07293a2d7311afee5c8b00c6457477d9f1f86e86786a9b56878ea3ee19fa2629b829d042d0cda
2017-12-06 12:10:16 +01:00
#####################################
# getrawtransaction with block hash #
#####################################
# make a tx by sending then generate 2 blocks; block1 has the tx in it
tx = self . nodes [ 2 ] . sendtoaddress ( self . nodes [ 1 ] . getnewaddress ( ) , 1 )
block1 , block2 = self . nodes [ 2 ] . generate ( 2 )
self . sync_all ( )
# We should be able to get the raw transaction by providing the correct block
gottx = self . nodes [ 0 ] . getrawtransaction ( tx , True , block1 )
assert_equal ( gottx [ ' txid ' ] , tx )
assert_equal ( gottx [ ' in_active_chain ' ] , True )
# We should not have the 'in_active_chain' flag when we don't provide a block
gottx = self . nodes [ 0 ] . getrawtransaction ( tx , True )
assert_equal ( gottx [ ' txid ' ] , tx )
assert ' in_active_chain ' not in gottx
# We should not get the tx if we provide an unrelated block
assert_raises_rpc_error ( - 5 , " No such transaction found " , self . nodes [ 0 ] . getrawtransaction , tx , True , block2 )
# An invalid block hash should raise the correct errors
assert_raises_rpc_error ( - 8 , " parameter 3 must be hexadecimal " , self . nodes [ 0 ] . getrawtransaction , tx , True , True )
assert_raises_rpc_error ( - 8 , " parameter 3 must be hexadecimal " , self . nodes [ 0 ] . getrawtransaction , tx , True , " foobar " )
assert_raises_rpc_error ( - 8 , " parameter 3 must be of length 64 " , self . nodes [ 0 ] . getrawtransaction , tx , True , " abcd1234 " )
2017-12-07 17:36:46 +01:00
assert_raises_rpc_error ( - 5 , " Block hash not found " , self . nodes [ 0 ] . getrawtransaction , tx , True , " 0000000000000000000000000000000000000000000000000000000000000000 " )
# Undo the blocks and check in_active_chain
self . nodes [ 0 ] . invalidateblock ( block1 )
gottx = self . nodes [ 0 ] . getrawtransaction ( txid = tx , verbose = True , blockhash = block1 )
assert_equal ( gottx [ ' in_active_chain ' ] , False )
self . nodes [ 0 ] . reconsiderblock ( block1 )
assert_equal ( self . nodes [ 0 ] . getbestblockhash ( ) , block2 )
Merge #10275: [rpc] Allow fetching tx directly from specified block in getrawtransaction
434526a [test] Add tests for getrawtransaction with block hash. (Karl-Johan Alm)
b167951 [rpc] Allow getrawtransaction to take optional blockhash to fetch transaction from a block directly. (Karl-Johan Alm)
a5f5a2c [rpc] Fix fVerbose parsing (remove excess if cases). (Karl-Johan Alm)
Pull request description:
[Reviewer hint: use [?w=1](https://github.com/bitcoin/bitcoin/pull/10275/files?w=1) to avoid seeing a bunch of indentation changes.]
Presuming a user knows the block hash of the block containing a given transaction, this PR allows them to fetch the raw transaction, even without `-txindex`. It also enables support for getting transactions that are in orphaned blocks.
Note that supplying a block hash will override mempool and txindex support in `GetTransaction`. The rationale behind this is that a transaction may be in multiple places (orphaned blocks) and if the user supplies an explicit block hash it should be adhered to.
```Bash
$ # a41.. is a tx inside an orphan block ..3c6f.. -- first try getting it normally
$ ./bitcoin-cli getrawtransaction a41e66ee1341aa9fb9475b98cfdc1fe1261faa56c0a49254f33065ec90f7cd79 1
error code: -5
error message:
No such mempool transaction. Use -txindex to enable blockchain transaction queries. Use gettransaction for wallet transactions.
$ # now try with block hash
$ ./bitcoin-cli getrawtransaction a41e66ee1341aa9fb9475b98cfdc1fe1261faa56c0a49254f33065ec90f7cd79 1 0000000000000000003c6fe479122bfa4a9187493937af1734e1e5cd9f198ec7
{
"hex": "01000000014e7e81144e42f6d65550e59b715d470c9301fd7ac189[...]90488ac00000000",
"inMainChain": false,
"txid": "a41e66ee1341aa9fb9475b98cfdc1fe1261faa56c0a49254f33065ec90f7cd79",
"hash": "a41e66ee1341aa9fb9475b98cfdc1fe1261faa56c0a49254f33065ec90f7cd79",
"size": 225,
[...]
}
$ # another tx 6c66... in block 462000
$ ./bitcoin-cli getrawtransaction 6c66b98191e9d6cc671f6817142152ebf6c5cab2ef008397b5a71ac13255a735 1 00000000000000000217f2c12922e321f6d4aa933ce88005a9a493c503054a40
{
"hex": "0200000004d157[...]88acaf0c0700",
"inMainChain": true,
"txid": "6c66b98191e9d6cc671f6817142152ebf6c5cab2ef008397b5a71ac13255a735",
"hash": "6c66b98191e9d6cc671f6817142152ebf6c5cab2ef008397b5a71ac13255a735",
"size": 666,
[...]
}
$
```
Tree-SHA512: 279be3818141edd3cc194a9ee65929331920afb30297ab2d6da07293a2d7311afee5c8b00c6457477d9f1f86e86786a9b56878ea3ee19fa2629b829d042d0cda
2017-12-06 12:10:16 +01:00
2015-04-01 15:08:00 +02:00
#########################
# RAW TX MULTISIG TESTS #
#########################
# 2of2 test
addr1 = self . nodes [ 2 ] . getnewaddress ( )
addr2 = self . nodes [ 2 ] . getnewaddress ( )
2020-12-17 13:46:20 +01:00
addr1Obj = self . nodes [ 2 ] . getaddressinfo ( addr1 )
addr2Obj = self . nodes [ 2 ] . getaddressinfo ( addr2 )
2015-04-01 15:08:00 +02:00
2020-05-15 11:34:41 +02:00
# Tests for createmultisig and addmultisigaddress
assert_raises_rpc_error ( - 5 , " Invalid public key " , self . nodes [ 0 ] . createmultisig , 1 , [ " 01020304 " ] )
self . nodes [ 0 ] . createmultisig ( 2 , [ addr1Obj [ ' pubkey ' ] , addr2Obj [ ' pubkey ' ] ] ) # createmultisig can only take public keys
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.
mSigObj = self . nodes [ 2 ] . addmultisigaddress ( 2 , [ addr1Obj [ ' pubkey ' ] , addr1 ] ) [ ' address ' ]
2015-04-01 15:08:00 +02:00
#use balance deltas instead of absolute values
bal = self . nodes [ 2 ] . getbalance ( )
# send 1.2 BTC to msig adr
2015-12-02 18:12:23 +01:00
txId = self . nodes [ 0 ] . sendtoaddress ( mSigObj , 1.2 )
2015-04-01 15:08:00 +02:00
self . sync_all ( )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
assert_equal ( self . nodes [ 2 ] . getbalance ( ) , bal + Decimal ( ' 1.20000000 ' ) ) #node2 has both keys of the 2of2 ms addr., tx should affect the balance
# 2of3 test from different nodes
bal = self . nodes [ 2 ] . getbalance ( )
addr1 = self . nodes [ 1 ] . getnewaddress ( )
addr2 = self . nodes [ 2 ] . getnewaddress ( )
addr3 = self . nodes [ 2 ] . getnewaddress ( )
2020-12-17 13:46:20 +01:00
addr1Obj = self . nodes [ 1 ] . getaddressinfo ( addr1 )
addr2Obj = self . nodes [ 2 ] . getaddressinfo ( addr2 )
addr3Obj = self . nodes [ 2 ] . getaddressinfo ( addr3 )
2015-04-01 15:08:00 +02:00
2020-05-15 11:34:41 +02:00
mSigObj = self . nodes [ 2 ] . addmultisigaddress ( 2 , [ addr1Obj [ ' pubkey ' ] , addr2Obj [ ' pubkey ' ] , addr3Obj [ ' pubkey ' ] ] ) [ ' address ' ]
2015-04-01 15:08:00 +02:00
2015-12-02 18:12:23 +01:00
txId = self . nodes [ 0 ] . sendtoaddress ( mSigObj , 2.2 )
2015-04-01 15:08:00 +02:00
decTx = self . nodes [ 0 ] . gettransaction ( txId )
rawTx = self . nodes [ 0 ] . decoderawtransaction ( decTx [ ' hex ' ] )
self . sync_all ( )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
2018-02-12 10:47:05 +01:00
#THIS IS AN INCOMPLETE FEATURE
2015-04-01 15:08:00 +02:00
#NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION
assert_equal ( self . nodes [ 2 ] . getbalance ( ) , bal ) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable
txDetails = self . nodes [ 0 ] . gettransaction ( txId , True )
rawTx = self . nodes [ 0 ] . decoderawtransaction ( txDetails [ ' hex ' ] )
vout = False
for outpoint in rawTx [ ' vout ' ] :
if outpoint [ ' value ' ] == Decimal ( ' 2.20000000 ' ) :
vout = outpoint
2015-12-02 18:12:23 +01:00
break
2015-04-01 15:08:00 +02:00
bal = self . nodes [ 0 ] . getbalance ( )
inputs = [ { " txid " : txId , " vout " : vout [ ' n ' ] , " scriptPubKey " : vout [ ' scriptPubKey ' ] [ ' hex ' ] } ]
outputs = { self . nodes [ 0 ] . getnewaddress ( ) : 2.19 }
rawTx = self . nodes [ 2 ] . createrawtransaction ( inputs , outputs )
2018-02-20 03:29:22 +01:00
rawTxPartialSigned = self . nodes [ 1 ] . signrawtransactionwithwallet ( rawTx , inputs )
2015-04-01 15:08:00 +02:00
assert_equal ( rawTxPartialSigned [ ' complete ' ] , False ) #node1 only has one key, can't comp. sign the tx
2017-07-20 16:32:47 +02:00
2018-02-20 03:29:22 +01:00
rawTxSigned = self . nodes [ 2 ] . signrawtransactionwithwallet ( rawTx , inputs )
2015-04-01 15:08:00 +02:00
assert_equal ( rawTxSigned [ ' complete ' ] , True ) #node2 can sign the tx compl., own two of three keys
self . nodes [ 2 ] . sendrawtransaction ( rawTxSigned [ ' hex ' ] )
rawTx = self . nodes [ 0 ] . decoderawtransaction ( rawTxSigned [ ' hex ' ] )
self . sync_all ( )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
2016-03-06 16:14:39 +01:00
assert_equal ( self . nodes [ 0 ] . getbalance ( ) , bal + Decimal ( ' 500.00000000 ' ) + Decimal ( ' 2.19000000 ' ) ) #block reward + tx
2014-12-29 20:17:21 +01:00
2017-07-20 16:32:47 +02:00
# 2of2 test for combining transactions
bal = self . nodes [ 2 ] . getbalance ( )
addr1 = self . nodes [ 1 ] . getnewaddress ( )
addr2 = self . nodes [ 2 ] . getnewaddress ( )
2020-12-17 13:46:20 +01:00
addr1Obj = self . nodes [ 1 ] . getaddressinfo ( addr1 )
addr2Obj = self . nodes [ 2 ] . getaddressinfo ( addr2 )
2017-07-20 16:32:47 +02:00
2020-05-15 11:34:41 +02:00
self . nodes [ 1 ] . addmultisigaddress ( 2 , [ addr1Obj [ ' pubkey ' ] , addr2Obj [ ' pubkey ' ] ] ) [ ' address ' ]
mSigObj = self . nodes [ 2 ] . addmultisigaddress ( 2 , [ addr1Obj [ ' pubkey ' ] , addr2Obj [ ' pubkey ' ] ] ) [ ' address ' ]
2020-12-17 13:46:20 +01:00
mSigObjValid = self . nodes [ 2 ] . getaddressinfo ( mSigObj )
2017-07-20 16:32:47 +02:00
txId = self . nodes [ 0 ] . sendtoaddress ( mSigObj , 2.2 )
decTx = self . nodes [ 0 ] . gettransaction ( txId )
rawTx2 = self . nodes [ 0 ] . decoderawtransaction ( decTx [ ' hex ' ] )
self . sync_all ( )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
assert_equal ( self . nodes [ 2 ] . getbalance ( ) , bal ) # the funds of a 2of2 multisig tx should not be marked as spendable
txDetails = self . nodes [ 0 ] . gettransaction ( txId , True )
rawTx2 = self . nodes [ 0 ] . decoderawtransaction ( txDetails [ ' hex ' ] )
vout = False
for outpoint in rawTx2 [ ' vout ' ] :
if outpoint [ ' value ' ] == Decimal ( ' 2.20000000 ' ) :
vout = outpoint
break
bal = self . nodes [ 0 ] . getbalance ( )
inputs = [ { " txid " : txId , " vout " : vout [ ' n ' ] , " scriptPubKey " : vout [ ' scriptPubKey ' ] [ ' hex ' ] , " redeemScript " : mSigObjValid [ ' hex ' ] } ]
outputs = { self . nodes [ 0 ] . getnewaddress ( ) : 2.19 }
rawTx2 = self . nodes [ 2 ] . createrawtransaction ( inputs , outputs )
2018-02-20 03:29:22 +01:00
rawTxPartialSigned1 = self . nodes [ 1 ] . signrawtransactionwithwallet ( rawTx2 , inputs )
2018-03-13 17:58:52 +01:00
self . log . debug ( rawTxPartialSigned1 )
2018-04-09 13:48:24 +02:00
assert_equal ( rawTxPartialSigned1 [ ' complete ' ] , False ) #node1 only has one key, can't comp. sign the tx
2017-07-20 16:32:47 +02:00
2018-02-20 03:29:22 +01:00
rawTxPartialSigned2 = self . nodes [ 2 ] . signrawtransactionwithwallet ( rawTx2 , inputs )
2018-03-13 17:58:52 +01:00
self . log . debug ( rawTxPartialSigned2 )
2017-07-20 16:32:47 +02:00
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 ' ] ] )
2018-03-13 17:58:52 +01:00
self . log . debug ( rawTxComb )
2017-07-20 16:32:47 +02:00
self . nodes [ 2 ] . sendrawtransaction ( rawTxComb )
rawTx2 = self . nodes [ 0 ] . decoderawtransaction ( rawTxComb )
self . sync_all ( )
self . nodes [ 0 ] . generate ( 1 )
self . sync_all ( )
2019-09-22 23:01:49 +02:00
assert_equal ( self . nodes [ 0 ] . getbalance ( ) , bal + Decimal ( ' 500.00000000 ' ) + Decimal ( ' 2.19000000 ' ) ) #block reward + tx
2017-07-20 16:32:47 +02:00
2016-11-23 07:13:35 +01:00
# getrawtransaction tests
# 1. valid parameters - only supply txid
2018-01-15 08:26:15 +01:00
txHash = rawTx [ " txid " ]
2016-11-23 07:13:35 +01:00
assert_equal ( self . nodes [ 0 ] . getrawtransaction ( txHash ) , rawTxSigned [ ' hex ' ] )
# 2. valid parameters - supply txid and 0 for non-verbose
assert_equal ( self . nodes [ 0 ] . getrawtransaction ( txHash , 0 ) , rawTxSigned [ ' hex ' ] )
# 3. valid parameters - supply txid and False for non-verbose
assert_equal ( self . nodes [ 0 ] . getrawtransaction ( txHash , False ) , rawTxSigned [ ' hex ' ] )
# 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 [ 0 ] . getrawtransaction ( txHash , 1 ) [ " hex " ] , rawTxSigned [ ' hex ' ] )
# 5. valid parameters - supply txid and True for non-verbose
assert_equal ( self . nodes [ 0 ] . getrawtransaction ( txHash , True ) [ " hex " ] , rawTxSigned [ ' hex ' ] )
# 6. invalid parameters - supply txid and string "Flase"
2017-12-07 17:36:46 +01:00
assert_raises_rpc_error ( - 1 , " not a boolean " , self . nodes [ 0 ] . getrawtransaction , txHash , " Flase " )
2016-11-23 07:13:35 +01:00
# 7. invalid parameters - supply txid and empty array
2017-12-07 17:36:46 +01:00
assert_raises_rpc_error ( - 1 , " not a boolean " , self . nodes [ 0 ] . getrawtransaction , txHash , [ ] )
2016-11-23 07:13:35 +01:00
# 8. invalid parameters - supply txid and empty dict
2017-12-07 17:36:46 +01:00
assert_raises_rpc_error ( - 1 , " not a boolean " , self . nodes [ 0 ] . getrawtransaction , txHash , { } )
2016-11-23 07:13:35 +01:00
2016-06-07 18:25:10 +02:00
inputs = [ { ' txid ' : " 1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000 " , ' vout ' : 1 , ' sequence ' : 1000 } ]
outputs = { self . nodes [ 0 ] . getnewaddress ( ) : 1 }
rawtx = self . nodes [ 0 ] . createrawtransaction ( inputs , outputs )
decrawtx = self . nodes [ 0 ] . decoderawtransaction ( rawtx )
assert_equal ( decrawtx [ ' vin ' ] [ 0 ] [ ' sequence ' ] , 1000 )
2017-07-20 16:32:47 +02:00
2017-03-09 10:02:13 +01:00
# 9. invalid parameters - sequence number out of range
2016-06-16 11:05:32 +02:00
inputs = [ { ' txid ' : " 1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000 " , ' vout ' : 1 , ' sequence ' : - 1 } ]
outputs = { self . nodes [ 0 ] . getnewaddress ( ) : 1 }
2019-09-25 11:34:51 +02:00
assert_raises_rpc_error ( - 8 , ' Invalid parameter, sequence number is out of range ' , self . nodes [ 0 ] . createrawtransaction , inputs , outputs )
2017-07-20 16:32:47 +02:00
2017-03-09 10:02:13 +01:00
# 10. invalid parameters - sequence number out of range
2016-06-16 11:05:32 +02:00
inputs = [ { ' txid ' : " 1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000 " , ' vout ' : 1 , ' sequence ' : 4294967296 } ]
outputs = { self . nodes [ 0 ] . getnewaddress ( ) : 1 }
2019-09-25 11:34:51 +02:00
assert_raises_rpc_error ( - 8 , ' Invalid parameter, sequence number is out of range ' , self . nodes [ 0 ] . createrawtransaction , inputs , outputs )
2017-07-20 16:32:47 +02:00
2016-06-16 11:05:32 +02:00
inputs = [ { ' txid ' : " 1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000 " , ' vout ' : 1 , ' sequence ' : 4294967294 } ]
outputs = { self . nodes [ 0 ] . getnewaddress ( ) : 1 }
rawtx = self . nodes [ 0 ] . createrawtransaction ( inputs , outputs )
decrawtx = self . nodes [ 0 ] . decoderawtransaction ( rawtx )
assert_equal ( decrawtx [ ' vin ' ] [ 0 ] [ ' sequence ' ] , 4294967294 )
2016-06-07 18:25:10 +02:00
2018-04-24 11:56:32 +02:00
####################################
# TRANSACTION VERSION NUMBER TESTS #
####################################
2020-11-10 04:59:41 +01:00
# Test the minimum transaction version number that fits in a signed 16-bit integer.
# Note, this is different to bitcoin. Bitcoin has a 32 bit integer
# representing the version, we have 16 bits of version and 16 bits of
# type.
2018-04-24 11:56:32 +02:00
tx = CTransaction ( )
2020-11-10 04:59:41 +01:00
tx . nVersion = - 0x8000
2018-04-24 11:56:32 +02:00
rawtx = ToHex ( tx )
decrawtx = self . nodes [ 0 ] . decoderawtransaction ( rawtx )
2020-11-10 04:59:41 +01:00
assert_equal ( decrawtx [ ' version ' ] , - 0x8000 )
2018-04-24 11:56:32 +02:00
# Test the maximum transaction version number that fits in a signed 32-bit integer.
tx = CTransaction ( )
2020-11-10 04:59:41 +01:00
tx . nVersion = 0x7fff
2018-04-24 11:56:32 +02:00
rawtx = ToHex ( tx )
decrawtx = self . nodes [ 0 ] . decoderawtransaction ( rawtx )
2020-11-10 04:59:41 +01:00
assert_equal ( decrawtx [ ' version ' ] , 0x7fff )
2018-04-24 11:56:32 +02:00
2014-12-29 20:17:21 +01:00
if __name__ == ' __main__ ' :
RawTransactionsTest ( ) . main ( )