Extend getchaintips RPC test.
Add the capability to simulate network splits to the RPC test framework and use it to do more extensive testing of 'getchaintips'.
This commit is contained in:
parent
3552d4b859
commit
dcb98466b4
@ -17,31 +17,30 @@ class ForkNotifyTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
alert_filename = None # Set by setup_network
|
alert_filename = None # Set by setup_network
|
||||||
|
|
||||||
def setup_network(self, test_dir):
|
def setup_network(self):
|
||||||
nodes = []
|
self.nodes = []
|
||||||
self.alert_filename = os.path.join(test_dir, "alert.txt")
|
self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
|
||||||
with open(self.alert_filename, 'w') as f:
|
with open(self.alert_filename, 'w') as f:
|
||||||
pass # Just open then close to create zero-length file
|
pass # Just open then close to create zero-length file
|
||||||
nodes.append(start_node(0, test_dir,
|
self.nodes.append(start_node(0, self.options.tmpdir,
|
||||||
["-blockversion=2", "-alertnotify=echo %s >> '" + self.alert_filename + "'"]))
|
["-blockversion=2", "-alertnotify=echo %s >> '" + self.alert_filename + "'"]))
|
||||||
# Node1 mines block.version=211 blocks
|
# Node1 mines block.version=211 blocks
|
||||||
nodes.append(start_node(1, test_dir,
|
self.nodes.append(start_node(1, self.options.tmpdir,
|
||||||
["-blockversion=211"]))
|
["-blockversion=211"]))
|
||||||
connect_nodes(nodes[1], 0)
|
connect_nodes(self.nodes[1], 0)
|
||||||
|
|
||||||
sync_blocks(nodes)
|
self.is_network_split = False
|
||||||
return nodes
|
self.sync_all()
|
||||||
|
|
||||||
|
|
||||||
def run_test(self, nodes):
|
def run_test(self):
|
||||||
# Mine 51 up-version blocks
|
# Mine 51 up-version blocks
|
||||||
nodes[1].setgenerate(True, 51)
|
self.nodes[1].setgenerate(True, 51)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
# -alertnotify should trigger on the 51'st,
|
# -alertnotify should trigger on the 51'st,
|
||||||
# but mine and sync another to give
|
# but mine and sync another to give
|
||||||
# -alertnotify time to write
|
# -alertnotify time to write
|
||||||
nodes[1].setgenerate(True, 1)
|
self.nodes[1].setgenerate(True, 1)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
|
|
||||||
with open(self.alert_filename, 'r') as f:
|
with open(self.alert_filename, 'r') as f:
|
||||||
alert_text = f.read()
|
alert_text = f.read()
|
||||||
@ -50,10 +49,10 @@ class ForkNotifyTest(BitcoinTestFramework):
|
|||||||
raise AssertionError("-alertnotify did not warn of up-version blocks")
|
raise AssertionError("-alertnotify did not warn of up-version blocks")
|
||||||
|
|
||||||
# Mine more up-version blocks, should not get more alerts:
|
# Mine more up-version blocks, should not get more alerts:
|
||||||
nodes[1].setgenerate(True, 1)
|
self.nodes[1].setgenerate(True, 1)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
nodes[1].setgenerate(True, 1)
|
self.nodes[1].setgenerate(True, 1)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
|
|
||||||
with open(self.alert_filename, 'r') as f:
|
with open(self.alert_filename, 'r') as f:
|
||||||
alert_text2 = f.read()
|
alert_text2 = f.read()
|
||||||
|
@ -51,40 +51,40 @@ class GetBlockTemplateTest(BitcoinTestFramework):
|
|||||||
Test longpolling with getblocktemplate.
|
Test longpolling with getblocktemplate.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def run_test(self, nodes):
|
def run_test(self):
|
||||||
print "Warning: this test will take about 70 seconds in the best case. Be patient."
|
print "Warning: this test will take about 70 seconds in the best case. Be patient."
|
||||||
nodes[0].setgenerate(True, 10)
|
self.nodes[0].setgenerate(True, 10)
|
||||||
templat = nodes[0].getblocktemplate()
|
templat = self.nodes[0].getblocktemplate()
|
||||||
longpollid = templat['longpollid']
|
longpollid = templat['longpollid']
|
||||||
# longpollid should not change between successive invocations if nothing else happens
|
# longpollid should not change between successive invocations if nothing else happens
|
||||||
templat2 = nodes[0].getblocktemplate()
|
templat2 = self.nodes[0].getblocktemplate()
|
||||||
assert(templat2['longpollid'] == longpollid)
|
assert(templat2['longpollid'] == longpollid)
|
||||||
|
|
||||||
# Test 1: test that the longpolling wait if we do nothing
|
# Test 1: test that the longpolling wait if we do nothing
|
||||||
thr = LongpollThread(nodes[0])
|
thr = LongpollThread(self.nodes[0])
|
||||||
thr.start()
|
thr.start()
|
||||||
# check that thread still lives
|
# check that thread still lives
|
||||||
thr.join(5) # wait 5 seconds or until thread exits
|
thr.join(5) # wait 5 seconds or until thread exits
|
||||||
assert(thr.is_alive())
|
assert(thr.is_alive())
|
||||||
|
|
||||||
# Test 2: test that longpoll will terminate if another node generates a block
|
# Test 2: test that longpoll will terminate if another node generates a block
|
||||||
nodes[1].setgenerate(True, 1) # generate a block on another node
|
self.nodes[1].setgenerate(True, 1) # generate a block on another node
|
||||||
# check that thread will exit now that new transaction entered mempool
|
# check that thread will exit now that new transaction entered mempool
|
||||||
thr.join(5) # wait 5 seconds or until thread exits
|
thr.join(5) # wait 5 seconds or until thread exits
|
||||||
assert(not thr.is_alive())
|
assert(not thr.is_alive())
|
||||||
|
|
||||||
# Test 3: test that longpoll will terminate if we generate a block ourselves
|
# Test 3: test that longpoll will terminate if we generate a block ourselves
|
||||||
thr = LongpollThread(nodes[0])
|
thr = LongpollThread(self.nodes[0])
|
||||||
thr.start()
|
thr.start()
|
||||||
nodes[0].setgenerate(True, 1) # generate a block on another node
|
self.nodes[0].setgenerate(True, 1) # generate a block on another node
|
||||||
thr.join(5) # wait 5 seconds or until thread exits
|
thr.join(5) # wait 5 seconds or until thread exits
|
||||||
assert(not thr.is_alive())
|
assert(not thr.is_alive())
|
||||||
|
|
||||||
# Test 4: test that introducing a new transaction into the mempool will terminate the longpoll
|
# Test 4: test that introducing a new transaction into the mempool will terminate the longpoll
|
||||||
thr = LongpollThread(nodes[0])
|
thr = LongpollThread(self.nodes[0])
|
||||||
thr.start()
|
thr.start()
|
||||||
# generate a random transaction and submit it
|
# generate a random transaction and submit it
|
||||||
(txid, txhex, fee) = random_transaction(nodes, Decimal("1.1"), Decimal("0.0"), Decimal("0.001"), 20)
|
(txid, txhex, fee) = random_transaction(self.nodes, Decimal("1.1"), Decimal("0.0"), Decimal("0.001"), 20)
|
||||||
# after one minute, every 10 seconds the mempool is probed, so in 80 seconds it should have returned
|
# after one minute, every 10 seconds the mempool is probed, so in 80 seconds it should have returned
|
||||||
thr.join(60 + 20)
|
thr.join(60 + 20)
|
||||||
assert(not thr.is_alive())
|
assert(not thr.is_alive())
|
||||||
|
@ -3,22 +3,52 @@
|
|||||||
# Distributed under the MIT/X11 software license, see the accompanying
|
# Distributed under the MIT/X11 software license, see the accompanying
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
# Exercise the getchaintips API.
|
# Exercise the getchaintips API. We introduce a network split, work
|
||||||
|
# on chains of different lengths, and join the network together again.
|
||||||
# Since the test framework does not generate orphan blocks, we can
|
# This gives us two tips, verify that it works.
|
||||||
# unfortunately not check for them!
|
|
||||||
|
|
||||||
from test_framework import BitcoinTestFramework
|
from test_framework import BitcoinTestFramework
|
||||||
from util import assert_equal
|
from util import assert_equal
|
||||||
|
|
||||||
class GetChainTipsTest (BitcoinTestFramework):
|
class GetChainTipsTest (BitcoinTestFramework):
|
||||||
|
|
||||||
def run_test (self, nodes):
|
def run_test (self):
|
||||||
res = nodes[0].getchaintips ()
|
BitcoinTestFramework.run_test (self)
|
||||||
assert_equal (len (res), 1)
|
|
||||||
res = res[0]
|
tips = self.nodes[0].getchaintips ()
|
||||||
assert_equal (res['branchlen'], 0)
|
assert_equal (len (tips), 1)
|
||||||
assert_equal (res['height'], 200)
|
assert_equal (tips[0]['branchlen'], 0)
|
||||||
|
assert_equal (tips[0]['height'], 200)
|
||||||
|
|
||||||
|
# Split the network and build two chains of different lengths.
|
||||||
|
self.split_network ()
|
||||||
|
self.nodes[0].setgenerate (True, 10);
|
||||||
|
self.nodes[2].setgenerate (True, 20);
|
||||||
|
self.sync_all ()
|
||||||
|
|
||||||
|
tips = self.nodes[1].getchaintips ()
|
||||||
|
assert_equal (len (tips), 1)
|
||||||
|
shortTip = tips[0]
|
||||||
|
assert_equal (shortTip['branchlen'], 0)
|
||||||
|
assert_equal (shortTip['height'], 210)
|
||||||
|
|
||||||
|
tips = self.nodes[3].getchaintips ()
|
||||||
|
assert_equal (len (tips), 1)
|
||||||
|
longTip = tips[0]
|
||||||
|
assert_equal (longTip['branchlen'], 0)
|
||||||
|
assert_equal (longTip['height'], 220)
|
||||||
|
|
||||||
|
# Join the network halves and check that we now have two tips
|
||||||
|
# (at least at the nodes that previously had the short chain).
|
||||||
|
self.join_network ()
|
||||||
|
|
||||||
|
tips = self.nodes[0].getchaintips ()
|
||||||
|
assert_equal (len (tips), 2)
|
||||||
|
assert_equal (tips[0], longTip)
|
||||||
|
|
||||||
|
assert_equal (tips[1]['branchlen'], 10)
|
||||||
|
tips[1]['branchlen'] = 0;
|
||||||
|
assert_equal (tips[1], shortTip)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
GetChainTipsTest ().main ()
|
GetChainTipsTest ().main ()
|
||||||
|
@ -33,62 +33,64 @@ def check_array_result(object_array, to_match, expected):
|
|||||||
|
|
||||||
class ListTransactionsTest(BitcoinTestFramework):
|
class ListTransactionsTest(BitcoinTestFramework):
|
||||||
|
|
||||||
def run_test(self, nodes):
|
def run_test(self):
|
||||||
# Simple send, 0 to 1:
|
# Simple send, 0 to 1:
|
||||||
txid = nodes[0].sendtoaddress(nodes[1].getnewaddress(), 0.1)
|
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
|
||||||
sync_mempools(nodes)
|
self.sync_all()
|
||||||
check_array_result(nodes[0].listtransactions(),
|
check_array_result(self.nodes[0].listtransactions(),
|
||||||
{"txid":txid},
|
{"txid":txid},
|
||||||
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
|
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
|
||||||
check_array_result(nodes[1].listtransactions(),
|
check_array_result(self.nodes[1].listtransactions(),
|
||||||
{"txid":txid},
|
{"txid":txid},
|
||||||
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
|
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
|
||||||
# mine a block, confirmations should change:
|
# mine a block, confirmations should change:
|
||||||
nodes[0].setgenerate(True, 1)
|
self.nodes[0].setgenerate(True, 1)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
check_array_result(nodes[0].listtransactions(),
|
check_array_result(self.nodes[0].listtransactions(),
|
||||||
{"txid":txid},
|
{"txid":txid},
|
||||||
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
|
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
|
||||||
check_array_result(nodes[1].listtransactions(),
|
check_array_result(self.nodes[1].listtransactions(),
|
||||||
{"txid":txid},
|
{"txid":txid},
|
||||||
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
|
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
|
||||||
|
|
||||||
# send-to-self:
|
# send-to-self:
|
||||||
txid = nodes[0].sendtoaddress(nodes[0].getnewaddress(), 0.2)
|
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
|
||||||
check_array_result(nodes[0].listtransactions(),
|
check_array_result(self.nodes[0].listtransactions(),
|
||||||
{"txid":txid, "category":"send"},
|
{"txid":txid, "category":"send"},
|
||||||
{"amount":Decimal("-0.2")})
|
{"amount":Decimal("-0.2")})
|
||||||
check_array_result(nodes[0].listtransactions(),
|
check_array_result(self.nodes[0].listtransactions(),
|
||||||
{"txid":txid, "category":"receive"},
|
{"txid":txid, "category":"receive"},
|
||||||
{"amount":Decimal("0.2")})
|
{"amount":Decimal("0.2")})
|
||||||
|
|
||||||
# sendmany from node1: twice to self, twice to node2:
|
# sendmany from node1: twice to self, twice to node2:
|
||||||
send_to = { nodes[0].getnewaddress() : 0.11, nodes[1].getnewaddress() : 0.22,
|
send_to = { self.nodes[0].getnewaddress() : 0.11,
|
||||||
nodes[0].getaccountaddress("from1") : 0.33, nodes[1].getaccountaddress("toself") : 0.44 }
|
self.nodes[1].getnewaddress() : 0.22,
|
||||||
txid = nodes[1].sendmany("", send_to)
|
self.nodes[0].getaccountaddress("from1") : 0.33,
|
||||||
sync_mempools(nodes)
|
self.nodes[1].getaccountaddress("toself") : 0.44 }
|
||||||
check_array_result(nodes[1].listtransactions(),
|
txid = self.nodes[1].sendmany("", send_to)
|
||||||
|
self.sync_all()
|
||||||
|
check_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"send","amount":Decimal("-0.11")},
|
{"category":"send","amount":Decimal("-0.11")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(nodes[0].listtransactions(),
|
check_array_result(self.nodes[0].listtransactions(),
|
||||||
{"category":"receive","amount":Decimal("0.11")},
|
{"category":"receive","amount":Decimal("0.11")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(nodes[1].listtransactions(),
|
check_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"send","amount":Decimal("-0.22")},
|
{"category":"send","amount":Decimal("-0.22")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(nodes[1].listtransactions(),
|
check_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"receive","amount":Decimal("0.22")},
|
{"category":"receive","amount":Decimal("0.22")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(nodes[1].listtransactions(),
|
check_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"send","amount":Decimal("-0.33")},
|
{"category":"send","amount":Decimal("-0.33")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(nodes[0].listtransactions(),
|
check_array_result(self.nodes[0].listtransactions(),
|
||||||
{"category":"receive","amount":Decimal("0.33")},
|
{"category":"receive","amount":Decimal("0.33")},
|
||||||
{"txid":txid, "account" : "from1"} )
|
{"txid":txid, "account" : "from1"} )
|
||||||
check_array_result(nodes[1].listtransactions(),
|
check_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"send","amount":Decimal("-0.44")},
|
{"category":"send","amount":Decimal("-0.44")},
|
||||||
{"txid":txid, "account" : ""} )
|
{"txid":txid, "account" : ""} )
|
||||||
check_array_result(nodes[1].listtransactions(),
|
check_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"receive","amount":Decimal("0.44")},
|
{"category":"receive","amount":Decimal("0.44")},
|
||||||
{"txid":txid, "account" : "toself"} )
|
{"txid":txid, "account" : "toself"} )
|
||||||
|
|
||||||
|
@ -54,36 +54,36 @@ def check_array_result(object_array, to_match, expected, should_not_find = False
|
|||||||
|
|
||||||
class ReceivedByTest(BitcoinTestFramework):
|
class ReceivedByTest(BitcoinTestFramework):
|
||||||
|
|
||||||
def run_test(self, nodes):
|
def run_test(self):
|
||||||
'''
|
'''
|
||||||
listreceivedbyaddress Test
|
listreceivedbyaddress Test
|
||||||
'''
|
'''
|
||||||
# Send from node 0 to 1
|
# Send from node 0 to 1
|
||||||
addr = nodes[1].getnewaddress()
|
addr = self.nodes[1].getnewaddress()
|
||||||
txid = nodes[0].sendtoaddress(addr, 0.1)
|
txid = self.nodes[0].sendtoaddress(addr, 0.1)
|
||||||
sync_mempools(nodes)
|
self.sync_all()
|
||||||
|
|
||||||
#Check not listed in listreceivedbyaddress because has 0 confirmations
|
#Check not listed in listreceivedbyaddress because has 0 confirmations
|
||||||
check_array_result(nodes[1].listreceivedbyaddress(),
|
check_array_result(self.nodes[1].listreceivedbyaddress(),
|
||||||
{"address":addr},
|
{"address":addr},
|
||||||
{ },
|
{ },
|
||||||
True)
|
True)
|
||||||
#Bury Tx under 10 block so it will be returned by listreceivedbyaddress
|
#Bury Tx under 10 block so it will be returned by listreceivedbyaddress
|
||||||
nodes[1].setgenerate(True, 10)
|
self.nodes[1].setgenerate(True, 10)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
check_array_result(nodes[1].listreceivedbyaddress(),
|
check_array_result(self.nodes[1].listreceivedbyaddress(),
|
||||||
{"address":addr},
|
{"address":addr},
|
||||||
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
||||||
#With min confidence < 10
|
#With min confidence < 10
|
||||||
check_array_result(nodes[1].listreceivedbyaddress(5),
|
check_array_result(self.nodes[1].listreceivedbyaddress(5),
|
||||||
{"address":addr},
|
{"address":addr},
|
||||||
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
||||||
#With min confidence > 10, should not find Tx
|
#With min confidence > 10, should not find Tx
|
||||||
check_array_result(nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
|
check_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
|
||||||
|
|
||||||
#Empty Tx
|
#Empty Tx
|
||||||
addr = nodes[1].getnewaddress()
|
addr = self.nodes[1].getnewaddress()
|
||||||
check_array_result(nodes[1].listreceivedbyaddress(0,True),
|
check_array_result(self.nodes[1].listreceivedbyaddress(0,True),
|
||||||
{"address":addr},
|
{"address":addr},
|
||||||
{"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]})
|
{"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]})
|
||||||
|
|
||||||
@ -91,24 +91,24 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||||||
getreceivedbyaddress Test
|
getreceivedbyaddress Test
|
||||||
'''
|
'''
|
||||||
# Send from node 0 to 1
|
# Send from node 0 to 1
|
||||||
addr = nodes[1].getnewaddress()
|
addr = self.nodes[1].getnewaddress()
|
||||||
txid = nodes[0].sendtoaddress(addr, 0.1)
|
txid = self.nodes[0].sendtoaddress(addr, 0.1)
|
||||||
sync_mempools(nodes)
|
self.sync_all()
|
||||||
|
|
||||||
#Check balance is 0 because of 0 confirmations
|
#Check balance is 0 because of 0 confirmations
|
||||||
balance = nodes[1].getreceivedbyaddress(addr)
|
balance = self.nodes[1].getreceivedbyaddress(addr)
|
||||||
if balance != Decimal("0.0"):
|
if balance != Decimal("0.0"):
|
||||||
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
|
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
|
||||||
|
|
||||||
#Check balance is 0.1
|
#Check balance is 0.1
|
||||||
balance = nodes[1].getreceivedbyaddress(addr,0)
|
balance = self.nodes[1].getreceivedbyaddress(addr,0)
|
||||||
if balance != Decimal("0.1"):
|
if balance != Decimal("0.1"):
|
||||||
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
|
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
|
||||||
|
|
||||||
#Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress
|
#Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress
|
||||||
nodes[1].setgenerate(True, 10)
|
self.nodes[1].setgenerate(True, 10)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
balance = nodes[1].getreceivedbyaddress(addr)
|
balance = self.nodes[1].getreceivedbyaddress(addr)
|
||||||
if balance != Decimal("0.1"):
|
if balance != Decimal("0.1"):
|
||||||
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
|
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
|
||||||
|
|
||||||
@ -116,40 +116,40 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||||||
listreceivedbyaccount + getreceivedbyaccount Test
|
listreceivedbyaccount + getreceivedbyaccount Test
|
||||||
'''
|
'''
|
||||||
#set pre-state
|
#set pre-state
|
||||||
addrArr = nodes[1].getnewaddress()
|
addrArr = self.nodes[1].getnewaddress()
|
||||||
account = nodes[1].getaccount(addrArr)
|
account = self.nodes[1].getaccount(addrArr)
|
||||||
received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(),{"account":account})
|
received_by_account_json = get_sub_array_from_array(self.nodes[1].listreceivedbyaccount(),{"account":account})
|
||||||
if len(received_by_account_json) == 0:
|
if len(received_by_account_json) == 0:
|
||||||
raise AssertionError("No accounts found in node")
|
raise AssertionError("No accounts found in node")
|
||||||
balance_by_account = rec_by_accountArr = nodes[1].getreceivedbyaccount(account)
|
balance_by_account = rec_by_accountArr = self.nodes[1].getreceivedbyaccount(account)
|
||||||
|
|
||||||
txid = nodes[0].sendtoaddress(addr, 0.1)
|
txid = self.nodes[0].sendtoaddress(addr, 0.1)
|
||||||
|
|
||||||
# listreceivedbyaccount should return received_by_account_json because of 0 confirmations
|
# listreceivedbyaccount should return received_by_account_json because of 0 confirmations
|
||||||
check_array_result(nodes[1].listreceivedbyaccount(),
|
check_array_result(self.nodes[1].listreceivedbyaccount(),
|
||||||
{"account":account},
|
{"account":account},
|
||||||
received_by_account_json)
|
received_by_account_json)
|
||||||
|
|
||||||
# getreceivedbyaddress should return same balance because of 0 confirmations
|
# getreceivedbyaddress should return same balance because of 0 confirmations
|
||||||
balance = nodes[1].getreceivedbyaccount(account)
|
balance = self.nodes[1].getreceivedbyaccount(account)
|
||||||
if balance != balance_by_account:
|
if balance != balance_by_account:
|
||||||
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
|
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
|
||||||
|
|
||||||
nodes[1].setgenerate(True, 10)
|
self.nodes[1].setgenerate(True, 10)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
# listreceivedbyaccount should return updated account balance
|
# listreceivedbyaccount should return updated account balance
|
||||||
check_array_result(nodes[1].listreceivedbyaccount(),
|
check_array_result(self.nodes[1].listreceivedbyaccount(),
|
||||||
{"account":account},
|
{"account":account},
|
||||||
{"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))})
|
{"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))})
|
||||||
|
|
||||||
# getreceivedbyaddress should return updates balance
|
# getreceivedbyaddress should return updates balance
|
||||||
balance = nodes[1].getreceivedbyaccount(account)
|
balance = self.nodes[1].getreceivedbyaccount(account)
|
||||||
if balance != balance_by_account + Decimal("0.1"):
|
if balance != balance_by_account + Decimal("0.1"):
|
||||||
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
|
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
|
||||||
|
|
||||||
#Create a new account named "mynewaccount" that has a 0 balance
|
#Create a new account named "mynewaccount" that has a 0 balance
|
||||||
nodes[1].getaccountaddress("mynewaccount")
|
self.nodes[1].getaccountaddress("mynewaccount")
|
||||||
received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(0,True),{"account":"mynewaccount"})
|
received_by_account_json = get_sub_array_from_array(self.nodes[1].listreceivedbyaccount(0,True),{"account":"mynewaccount"})
|
||||||
if len(received_by_account_json) == 0:
|
if len(received_by_account_json) == 0:
|
||||||
raise AssertionError("No accounts found in node")
|
raise AssertionError("No accounts found in node")
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||||||
raise AssertionError("Wrong balance returned by listreceivedbyaccount, %0.2f"%(received_by_account_json["amount"]))
|
raise AssertionError("Wrong balance returned by listreceivedbyaccount, %0.2f"%(received_by_account_json["amount"]))
|
||||||
|
|
||||||
# Test getreceivedbyaccount for 0 amount accounts
|
# Test getreceivedbyaccount for 0 amount accounts
|
||||||
balance = nodes[1].getreceivedbyaccount("mynewaccount")
|
balance = self.nodes[1].getreceivedbyaccount("mynewaccount")
|
||||||
if balance != Decimal("0.0"):
|
if balance != Decimal("0.0"):
|
||||||
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
|
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
|
||||||
|
|
||||||
|
@ -10,48 +10,48 @@ from util import *
|
|||||||
|
|
||||||
class EstimateFeeTest(BitcoinTestFramework):
|
class EstimateFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
def setup_network(self, test_dir):
|
def setup_network(self):
|
||||||
nodes = []
|
self.nodes = []
|
||||||
nodes.append(start_node(0, test_dir,
|
self.nodes.append(start_node(0, self.options.tmpdir,
|
||||||
["-debug=mempool", "-debug=estimatefee"]))
|
["-debug=mempool", "-debug=estimatefee"]))
|
||||||
# Node1 mines small-but-not-tiny blocks, and allows free transactions.
|
# Node1 mines small-but-not-tiny blocks, and allows free transactions.
|
||||||
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
|
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
|
||||||
# so blockmaxsize of 2,000 is really just 1,000 bytes (room enough for
|
# so blockmaxsize of 2,000 is really just 1,000 bytes (room enough for
|
||||||
# 6 or 7 transactions)
|
# 6 or 7 transactions)
|
||||||
nodes.append(start_node(1, test_dir,
|
self.nodes.append(start_node(1, self.options.tmpdir,
|
||||||
["-blockprioritysize=1500", "-blockmaxsize=2000",
|
["-blockprioritysize=1500", "-blockmaxsize=2000",
|
||||||
"-debug=mempool", "-debug=estimatefee"]))
|
"-debug=mempool", "-debug=estimatefee"]))
|
||||||
connect_nodes(nodes[1], 0)
|
connect_nodes(self.nodes[1], 0)
|
||||||
|
|
||||||
# Node2 is a stingy miner, that
|
# Node2 is a stingy miner, that
|
||||||
# produces very small blocks (room for only 3 or so transactions)
|
# produces very small blocks (room for only 3 or so transactions)
|
||||||
node2args = [ "-blockprioritysize=0", "-blockmaxsize=1500",
|
node2args = [ "-blockprioritysize=0", "-blockmaxsize=1500",
|
||||||
"-debug=mempool", "-debug=estimatefee"]
|
"-debug=mempool", "-debug=estimatefee"]
|
||||||
nodes.append(start_node(2, test_dir, node2args))
|
self.nodes.append(start_node(2, self.options.tmpdir, node2args))
|
||||||
connect_nodes(nodes[2], 0)
|
connect_nodes(self.nodes[2], 0)
|
||||||
|
|
||||||
sync_blocks(nodes)
|
self.is_network_split = False
|
||||||
return nodes
|
self.sync_all()
|
||||||
|
|
||||||
|
|
||||||
def run_test(self, nodes):
|
def run_test(self):
|
||||||
# Prime the memory pool with pairs of transactions
|
# Prime the memory pool with pairs of transactions
|
||||||
# (high-priority, random fee and zero-priority, random fee)
|
# (high-priority, random fee and zero-priority, random fee)
|
||||||
min_fee = Decimal("0.001")
|
min_fee = Decimal("0.001")
|
||||||
fees_per_kb = [];
|
fees_per_kb = [];
|
||||||
for i in range(12):
|
for i in range(12):
|
||||||
(txid, txhex, fee) = random_zeropri_transaction(nodes, Decimal("1.1"),
|
(txid, txhex, fee) = random_zeropri_transaction(self.nodes, Decimal("1.1"),
|
||||||
min_fee, min_fee, 20)
|
min_fee, min_fee, 20)
|
||||||
tx_kbytes = (len(txhex)/2)/1000.0
|
tx_kbytes = (len(txhex)/2)/1000.0
|
||||||
fees_per_kb.append(float(fee)/tx_kbytes)
|
fees_per_kb.append(float(fee)/tx_kbytes)
|
||||||
|
|
||||||
# Mine blocks with node2 until the memory pool clears:
|
# Mine blocks with node2 until the memory pool clears:
|
||||||
count_start = nodes[2].getblockcount()
|
count_start = self.nodes[2].getblockcount()
|
||||||
while len(nodes[2].getrawmempool()) > 0:
|
while len(self.nodes[2].getrawmempool()) > 0:
|
||||||
nodes[2].setgenerate(True, 1)
|
self.nodes[2].setgenerate(True, 1)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
|
|
||||||
all_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ]
|
all_estimates = [ self.nodes[0].estimatefee(i) for i in range(1,20) ]
|
||||||
print("Fee estimates, super-stingy miner: "+str([str(e) for e in all_estimates]))
|
print("Fee estimates, super-stingy miner: "+str([str(e) for e in all_estimates]))
|
||||||
|
|
||||||
# Estimates should be within the bounds of what transactions fees actually were:
|
# Estimates should be within the bounds of what transactions fees actually were:
|
||||||
@ -63,25 +63,25 @@ class EstimateFeeTest(BitcoinTestFramework):
|
|||||||
# Generate transactions while mining 30 more blocks, this time with node1:
|
# Generate transactions while mining 30 more blocks, this time with node1:
|
||||||
for i in range(30):
|
for i in range(30):
|
||||||
for j in range(random.randrange(6-4,6+4)):
|
for j in range(random.randrange(6-4,6+4)):
|
||||||
(txid, txhex, fee) = random_transaction(nodes, Decimal("1.1"),
|
(txid, txhex, fee) = random_transaction(self.nodes, Decimal("1.1"),
|
||||||
Decimal("0.0"), min_fee, 20)
|
Decimal("0.0"), min_fee, 20)
|
||||||
tx_kbytes = (len(txhex)/2)/1000.0
|
tx_kbytes = (len(txhex)/2)/1000.0
|
||||||
fees_per_kb.append(float(fee)/tx_kbytes)
|
fees_per_kb.append(float(fee)/tx_kbytes)
|
||||||
nodes[1].setgenerate(True, 1)
|
self.nodes[1].setgenerate(True, 1)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
|
|
||||||
all_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ]
|
all_estimates = [ self.nodes[0].estimatefee(i) for i in range(1,20) ]
|
||||||
print("Fee estimates, more generous miner: "+str([ str(e) for e in all_estimates]))
|
print("Fee estimates, more generous miner: "+str([ str(e) for e in all_estimates]))
|
||||||
for e in filter(lambda x: x >= 0, all_estimates):
|
for e in filter(lambda x: x >= 0, all_estimates):
|
||||||
if float(e)+delta < min(fees_per_kb) or float(e)-delta > max(fees_per_kb):
|
if float(e)+delta < min(fees_per_kb) or float(e)-delta > max(fees_per_kb):
|
||||||
raise AssertionError("Estimated fee (%f) out of range (%f,%f)"%(float(e), min_fee_kb, max_fee_kb))
|
raise AssertionError("Estimated fee (%f) out of range (%f,%f)"%(float(e), min_fee_kb, max_fee_kb))
|
||||||
|
|
||||||
# Finish by mining a normal-sized block:
|
# Finish by mining a normal-sized block:
|
||||||
while len(nodes[0].getrawmempool()) > 0:
|
while len(self.nodes[0].getrawmempool()) > 0:
|
||||||
nodes[0].setgenerate(True, 1)
|
self.nodes[0].setgenerate(True, 1)
|
||||||
sync_blocks(nodes)
|
self.sync_all()
|
||||||
|
|
||||||
final_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ]
|
final_estimates = [ self.nodes[0].estimatefee(i) for i in range(1,20) ]
|
||||||
print("Final fee estimates: "+str([ str(e) for e in final_estimates]))
|
print("Final fee estimates: "+str([ str(e) for e in final_estimates]))
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,22 +21,64 @@ from util import *
|
|||||||
class BitcoinTestFramework(object):
|
class BitcoinTestFramework(object):
|
||||||
|
|
||||||
# These may be over-ridden by subclasses:
|
# These may be over-ridden by subclasses:
|
||||||
def run_test(self, nodes):
|
def run_test(self):
|
||||||
|
for node in self.nodes:
|
||||||
assert_equal(node.getblockcount(), 200)
|
assert_equal(node.getblockcount(), 200)
|
||||||
assert_equal(node.getbalance(), 25*50)
|
assert_equal(node.getbalance(), 25*50)
|
||||||
|
|
||||||
def add_options(self, parser):
|
def add_options(self, parser):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setup_chain(self, tmp_directory):
|
def setup_chain(self):
|
||||||
print("Initializing test directory "+tmp_directory)
|
print("Initializing test directory "+self.options.tmpdir)
|
||||||
initialize_chain(tmp_directory)
|
initialize_chain(self.options.tmpdir)
|
||||||
|
|
||||||
def setup_network(self, tmp_directory):
|
def setup_network(self, split = False):
|
||||||
nodes = start_nodes(2, tmp_directory)
|
self.nodes = start_nodes(4, self.options.tmpdir)
|
||||||
connect_nodes(nodes[1], 0)
|
|
||||||
sync_blocks(nodes)
|
# Connect the nodes as a "chain". This allows us
|
||||||
return nodes
|
# to split the network between nodes 1 and 2 to get
|
||||||
|
# two halves that can work on competing chains.
|
||||||
|
|
||||||
|
# If we joined network halves, connect the nodes from the joint
|
||||||
|
# on outward. This ensures that chains are properly reorganised.
|
||||||
|
if not split:
|
||||||
|
connect_nodes(self.nodes[2], 1)
|
||||||
|
sync_blocks(self.nodes[1:2])
|
||||||
|
sync_mempools(self.nodes[1:2])
|
||||||
|
|
||||||
|
connect_nodes(self.nodes[1], 0)
|
||||||
|
connect_nodes(self.nodes[3], 2)
|
||||||
|
self.is_network_split = split
|
||||||
|
self.sync_all()
|
||||||
|
|
||||||
|
def split_network(self):
|
||||||
|
"""
|
||||||
|
Split the network of four nodes into nodes 0/1 and 2/3.
|
||||||
|
"""
|
||||||
|
assert not self.is_network_split
|
||||||
|
stop_nodes(self.nodes)
|
||||||
|
wait_bitcoinds()
|
||||||
|
self.setup_network(True)
|
||||||
|
|
||||||
|
def sync_all(self):
|
||||||
|
if self.is_network_split:
|
||||||
|
sync_blocks(self.nodes[:1])
|
||||||
|
sync_blocks(self.nodes[2:])
|
||||||
|
sync_mempools(self.nodes[:1])
|
||||||
|
sync_mempools(self.nodes[2:])
|
||||||
|
else:
|
||||||
|
sync_blocks(self.nodes)
|
||||||
|
sync_mempools(self.nodes)
|
||||||
|
|
||||||
|
def join_network(self):
|
||||||
|
"""
|
||||||
|
Join the (previously split) network halves together.
|
||||||
|
"""
|
||||||
|
assert self.is_network_split
|
||||||
|
stop_nodes(self.nodes)
|
||||||
|
wait_bitcoinds()
|
||||||
|
self.setup_network(False)
|
||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
import optparse
|
import optparse
|
||||||
@ -56,15 +98,14 @@ class BitcoinTestFramework(object):
|
|||||||
check_json_precision()
|
check_json_precision()
|
||||||
|
|
||||||
success = False
|
success = False
|
||||||
nodes = []
|
|
||||||
try:
|
try:
|
||||||
if not os.path.isdir(self.options.tmpdir):
|
if not os.path.isdir(self.options.tmpdir):
|
||||||
os.makedirs(self.options.tmpdir)
|
os.makedirs(self.options.tmpdir)
|
||||||
self.setup_chain(self.options.tmpdir)
|
self.setup_chain()
|
||||||
|
|
||||||
nodes = self.setup_network(self.options.tmpdir)
|
self.setup_network()
|
||||||
|
|
||||||
self.run_test(nodes)
|
self.run_test()
|
||||||
|
|
||||||
success = True
|
success = True
|
||||||
|
|
||||||
@ -80,7 +121,7 @@ class BitcoinTestFramework(object):
|
|||||||
|
|
||||||
if not self.options.nocleanup:
|
if not self.options.nocleanup:
|
||||||
print("Cleaning up")
|
print("Cleaning up")
|
||||||
stop_nodes(nodes)
|
stop_nodes(self.nodes)
|
||||||
wait_bitcoinds()
|
wait_bitcoinds()
|
||||||
shutil.rmtree(self.options.tmpdir)
|
shutil.rmtree(self.options.tmpdir)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user