You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wallet.py 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #!/usr/bin/env python2
  2. # Copyright (c) 2014-2015 The Bitcoin Core developers
  3. # Distributed under the MIT software license, see the accompanying
  4. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. #
  6. # Exercise the wallet. Ported from wallet.sh.
  7. # Does the following:
  8. # a) creates 3 nodes, with an empty chain (no blocks).
  9. # b) node0 mines a block
  10. # c) node1 mines 101 blocks, so now nodes 0 and 1 have 50btc, node2 has none.
  11. # d) node0 sends 21 btc to node2, in two transactions (11 btc, then 10 btc).
  12. # e) node0 mines a block, collects the fee on the second transaction
  13. # f) node1 mines 100 blocks, to mature node0's just-mined block
  14. # g) check that node0 has 100-21, node2 has 21
  15. # h) node0 should now have 2 unspent outputs; send these to node2 via raw tx broadcast by node1
  16. # i) have node1 mine a block
  17. # j) check balances - node0 should have 0, node2 should have 100
  18. # k) test ResendWalletTransactions - create transactions, startup fourth node, make sure it syncs
  19. #
  20. from test_framework.test_framework import BitcoinTestFramework
  21. from test_framework.util import *
  22. class WalletTest (BitcoinTestFramework):
  23. def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size):
  24. """Return curr_balance after asserting the fee was in range"""
  25. fee = balance_with_fee - curr_balance
  26. target_fee = fee_per_byte * tx_size
  27. if fee < target_fee:
  28. raise AssertionError("Fee of %s BTC too low! (Should be %s BTC)"%(str(fee), str(target_fee)))
  29. # allow the node's estimation to be at most 2 bytes off
  30. if fee > fee_per_byte * (tx_size + 2):
  31. raise AssertionError("Fee of %s BTC too high! (Should be %s BTC)"%(str(fee), str(target_fee)))
  32. return curr_balance
  33. def setup_chain(self):
  34. print("Initializing test directory "+self.options.tmpdir)
  35. initialize_chain_clean(self.options.tmpdir, 4)
  36. def setup_network(self, split=False):
  37. self.nodes = start_nodes(3, self.options.tmpdir)
  38. connect_nodes_bi(self.nodes,0,1)
  39. connect_nodes_bi(self.nodes,1,2)
  40. connect_nodes_bi(self.nodes,0,2)
  41. self.is_network_split=False
  42. self.sync_all()
  43. def run_test (self):
  44. print "Mining blocks..."
  45. self.nodes[0].generate(1)
  46. walletinfo = self.nodes[0].getwalletinfo()
  47. assert_equal(walletinfo['immature_balance'], 50)
  48. assert_equal(walletinfo['balance'], 0)
  49. self.sync_all()
  50. self.nodes[1].generate(101)
  51. self.sync_all()
  52. assert_equal(self.nodes[0].getbalance(), 50)
  53. assert_equal(self.nodes[1].getbalance(), 50)
  54. assert_equal(self.nodes[2].getbalance(), 0)
  55. # Send 21 BTC from 0 to 2 using sendtoaddress call.
  56. # Second transaction will be child of first, and will require a fee
  57. self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
  58. self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
  59. walletinfo = self.nodes[0].getwalletinfo()
  60. assert_equal(walletinfo['immature_balance'], 0)
  61. # Have node0 mine a block, thus it will collect its own fee.
  62. self.nodes[0].generate(1)
  63. self.sync_all()
  64. # Have node1 generate 100 blocks (so node0 can recover the fee)
  65. self.nodes[1].generate(100)
  66. self.sync_all()
  67. # node0 should end up with 100 btc in block rewards plus fees, but
  68. # minus the 21 plus fees sent to node2
  69. assert_equal(self.nodes[0].getbalance(), 100-21)
  70. assert_equal(self.nodes[2].getbalance(), 21)
  71. # Node0 should have two unspent outputs.
  72. # Create a couple of transactions to send them to node2, submit them through
  73. # node1, and make sure both node0 and node2 pick them up properly:
  74. node0utxos = self.nodes[0].listunspent(1)
  75. assert_equal(len(node0utxos), 2)
  76. # create both transactions
  77. txns_to_send = []
  78. for utxo in node0utxos:
  79. inputs = []
  80. outputs = {}
  81. inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
  82. outputs[self.nodes[2].getnewaddress("from1")] = utxo["amount"]
  83. raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
  84. txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))
  85. # Have node 1 (miner) send the transactions
  86. self.nodes[1].sendrawtransaction(txns_to_send[0]["hex"], True)
  87. self.nodes[1].sendrawtransaction(txns_to_send[1]["hex"], True)
  88. # Have node1 mine a block to confirm transactions:
  89. self.nodes[1].generate(1)
  90. self.sync_all()
  91. assert_equal(self.nodes[0].getbalance(), 0)
  92. assert_equal(self.nodes[2].getbalance(), 100)
  93. assert_equal(self.nodes[2].getbalance("from1"), 100-21)
  94. # Send 10 BTC normal
  95. address = self.nodes[0].getnewaddress("test")
  96. fee_per_byte = Decimal('0.001') / 1000
  97. self.nodes[2].settxfee(fee_per_byte * 1000)
  98. txid = self.nodes[2].sendtoaddress(address, 10, "", "", False)
  99. self.nodes[2].generate(1)
  100. self.sync_all()
  101. node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('90'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
  102. assert_equal(self.nodes[0].getbalance(), Decimal('10'))
  103. # Send 10 BTC with subtract fee from amount
  104. txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
  105. self.nodes[2].generate(1)
  106. self.sync_all()
  107. node_2_bal -= Decimal('10')
  108. assert_equal(self.nodes[2].getbalance(), node_2_bal)
  109. node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
  110. # Sendmany 10 BTC
  111. txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [])
  112. self.nodes[2].generate(1)
  113. self.sync_all()
  114. node_0_bal += Decimal('10')
  115. node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
  116. assert_equal(self.nodes[0].getbalance(), node_0_bal)
  117. # Sendmany 10 BTC with subtract fee from amount
  118. txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [address])
  119. self.nodes[2].generate(1)
  120. self.sync_all()
  121. node_2_bal -= Decimal('10')
  122. assert_equal(self.nodes[2].getbalance(), node_2_bal)
  123. node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
  124. # Test ResendWalletTransactions:
  125. # Create a couple of transactions, then start up a fourth
  126. # node (nodes[3]) and ask nodes[0] to rebroadcast.
  127. # EXPECT: nodes[3] should have those transactions in its mempool.
  128. txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
  129. txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
  130. sync_mempools(self.nodes)
  131. self.nodes.append(start_node(3, self.options.tmpdir))
  132. connect_nodes_bi(self.nodes, 0, 3)
  133. sync_blocks(self.nodes)
  134. relayed = self.nodes[0].resendwallettransactions()
  135. assert_equal(set(relayed), set([txid1, txid2]))
  136. sync_mempools(self.nodes)
  137. assert(txid1 in self.nodes[3].getrawmempool())
  138. #check if we can list zero value tx as available coins
  139. #1. create rawtx
  140. #2. hex-changed one output to 0.0
  141. #3. sign and send
  142. #4. check if recipient (node0) can list the zero value tx
  143. usp = self.nodes[1].listunspent()
  144. inputs = [{"txid":usp[0]['txid'], "vout":usp[0]['vout']}]
  145. outputs = {self.nodes[1].getnewaddress(): 49.998, self.nodes[0].getnewaddress(): 11.11}
  146. rawTx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") #replace 11.11 with 0.0 (int32)
  147. decRawTx = self.nodes[1].decoderawtransaction(rawTx)
  148. signedRawTx = self.nodes[1].signrawtransaction(rawTx)
  149. decRawTx = self.nodes[1].decoderawtransaction(signedRawTx['hex'])
  150. zeroValueTxid= decRawTx['txid']
  151. sendResp = self.nodes[1].sendrawtransaction(signedRawTx['hex'])
  152. self.sync_all()
  153. self.nodes[1].generate(1) #mine a block
  154. self.sync_all()
  155. unspentTxs = self.nodes[0].listunspent() #zero value tx must be in listunspents output
  156. found = False
  157. for uTx in unspentTxs:
  158. if uTx['txid'] == zeroValueTxid:
  159. found = True
  160. assert_equal(uTx['amount'], Decimal('0.00000000'));
  161. assert(found)
  162. #do some -walletbroadcast tests
  163. stop_nodes(self.nodes)
  164. wait_bitcoinds()
  165. self.nodes = start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"],["-walletbroadcast=0"],["-walletbroadcast=0"]])
  166. connect_nodes_bi(self.nodes,0,1)
  167. connect_nodes_bi(self.nodes,1,2)
  168. connect_nodes_bi(self.nodes,0,2)
  169. self.sync_all()
  170. txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2);
  171. txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
  172. self.nodes[1].generate(1) #mine a block, tx should not be in there
  173. self.sync_all()
  174. assert_equal(self.nodes[2].getbalance(), node_2_bal); #should not be changed because tx was not broadcasted
  175. #now broadcast from another node, mine a block, sync, and check the balance
  176. self.nodes[1].sendrawtransaction(txObjNotBroadcasted['hex'])
  177. self.nodes[1].generate(1)
  178. self.sync_all()
  179. txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
  180. assert_equal(self.nodes[2].getbalance(), node_2_bal + Decimal('2')); #should not be
  181. #create another tx
  182. txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2);
  183. #restart the nodes with -walletbroadcast=1
  184. stop_nodes(self.nodes)
  185. wait_bitcoinds()
  186. self.nodes = start_nodes(3, self.options.tmpdir)
  187. connect_nodes_bi(self.nodes,0,1)
  188. connect_nodes_bi(self.nodes,1,2)
  189. connect_nodes_bi(self.nodes,0,2)
  190. sync_blocks(self.nodes)
  191. self.nodes[0].generate(1)
  192. sync_blocks(self.nodes)
  193. #tx should be added to balance because after restarting the nodes tx should be broadcastet
  194. assert_equal(self.nodes[2].getbalance(), node_2_bal + Decimal('4')); #should not be
  195. #send a tx with value in a string (PR#6380 +)
  196. txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
  197. txObj = self.nodes[0].gettransaction(txId)
  198. assert_equal(txObj['amount'], Decimal('-2.00000000'))
  199. txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
  200. txObj = self.nodes[0].gettransaction(txId)
  201. assert_equal(txObj['amount'], Decimal('-0.00010000'))
  202. #check if JSON parser can handle scientific notation in strings
  203. txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
  204. txObj = self.nodes[0].gettransaction(txId)
  205. assert_equal(txObj['amount'], Decimal('-0.00010000'))
  206. #this should fail
  207. errorString = ""
  208. try:
  209. txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1f-4")
  210. except JSONRPCException,e:
  211. errorString = e.error['message']
  212. assert_equal("Invalid amount" in errorString, True);
  213. errorString = ""
  214. try:
  215. self.nodes[0].generate("2") #use a string to as block amount parameter must fail because it's not interpreted as amount
  216. except JSONRPCException,e:
  217. errorString = e.error['message']
  218. assert_equal("not an integer" in errorString, True);
  219. if __name__ == '__main__':
  220. WalletTest ().main ()