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
|
||||
|
||||
def setup_network(self, test_dir):
|
||||
nodes = []
|
||||
self.alert_filename = os.path.join(test_dir, "alert.txt")
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
|
||||
with open(self.alert_filename, 'w') as f:
|
||||
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 + "'"]))
|
||||
# Node1 mines block.version=211 blocks
|
||||
nodes.append(start_node(1, test_dir,
|
||||
self.nodes.append(start_node(1, self.options.tmpdir,
|
||||
["-blockversion=211"]))
|
||||
connect_nodes(nodes[1], 0)
|
||||
connect_nodes(self.nodes[1], 0)
|
||||
|
||||
sync_blocks(nodes)
|
||||
return nodes
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
|
||||
|
||||
def run_test(self, nodes):
|
||||
def run_test(self):
|
||||
# Mine 51 up-version blocks
|
||||
nodes[1].setgenerate(True, 51)
|
||||
sync_blocks(nodes)
|
||||
self.nodes[1].setgenerate(True, 51)
|
||||
self.sync_all()
|
||||
# -alertnotify should trigger on the 51'st,
|
||||
# but mine and sync another to give
|
||||
# -alertnotify time to write
|
||||
nodes[1].setgenerate(True, 1)
|
||||
sync_blocks(nodes)
|
||||
self.nodes[1].setgenerate(True, 1)
|
||||
self.sync_all()
|
||||
|
||||
with open(self.alert_filename, 'r') as f:
|
||||
alert_text = f.read()
|
||||
@ -50,10 +49,10 @@ class ForkNotifyTest(BitcoinTestFramework):
|
||||
raise AssertionError("-alertnotify did not warn of up-version blocks")
|
||||
|
||||
# Mine more up-version blocks, should not get more alerts:
|
||||
nodes[1].setgenerate(True, 1)
|
||||
sync_blocks(nodes)
|
||||
nodes[1].setgenerate(True, 1)
|
||||
sync_blocks(nodes)
|
||||
self.nodes[1].setgenerate(True, 1)
|
||||
self.sync_all()
|
||||
self.nodes[1].setgenerate(True, 1)
|
||||
self.sync_all()
|
||||
|
||||
with open(self.alert_filename, 'r') as f:
|
||||
alert_text2 = f.read()
|
||||
|
@ -51,40 +51,40 @@ class GetBlockTemplateTest(BitcoinTestFramework):
|
||||
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."
|
||||
nodes[0].setgenerate(True, 10)
|
||||
templat = nodes[0].getblocktemplate()
|
||||
self.nodes[0].setgenerate(True, 10)
|
||||
templat = self.nodes[0].getblocktemplate()
|
||||
longpollid = templat['longpollid']
|
||||
# longpollid should not change between successive invocations if nothing else happens
|
||||
templat2 = nodes[0].getblocktemplate()
|
||||
templat2 = self.nodes[0].getblocktemplate()
|
||||
assert(templat2['longpollid'] == longpollid)
|
||||
|
||||
# Test 1: test that the longpolling wait if we do nothing
|
||||
thr = LongpollThread(nodes[0])
|
||||
thr = LongpollThread(self.nodes[0])
|
||||
thr.start()
|
||||
# check that thread still lives
|
||||
thr.join(5) # wait 5 seconds or until thread exits
|
||||
assert(thr.is_alive())
|
||||
|
||||
# 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
|
||||
thr.join(5) # wait 5 seconds or until thread exits
|
||||
assert(not thr.is_alive())
|
||||
|
||||
# Test 3: test that longpoll will terminate if we generate a block ourselves
|
||||
thr = LongpollThread(nodes[0])
|
||||
thr = LongpollThread(self.nodes[0])
|
||||
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
|
||||
assert(not thr.is_alive())
|
||||
|
||||
# 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()
|
||||
# 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
|
||||
thr.join(60 + 20)
|
||||
assert(not thr.is_alive())
|
||||
|
@ -3,22 +3,52 @@
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
# Exercise the getchaintips API.
|
||||
|
||||
# Since the test framework does not generate orphan blocks, we can
|
||||
# unfortunately not check for them!
|
||||
# Exercise the getchaintips API. We introduce a network split, work
|
||||
# on chains of different lengths, and join the network together again.
|
||||
# This gives us two tips, verify that it works.
|
||||
|
||||
from test_framework import BitcoinTestFramework
|
||||
from util import assert_equal
|
||||
|
||||
class GetChainTipsTest (BitcoinTestFramework):
|
||||
|
||||
def run_test (self, nodes):
|
||||
res = nodes[0].getchaintips ()
|
||||
assert_equal (len (res), 1)
|
||||
res = res[0]
|
||||
assert_equal (res['branchlen'], 0)
|
||||
assert_equal (res['height'], 200)
|
||||
def run_test (self):
|
||||
BitcoinTestFramework.run_test (self)
|
||||
|
||||
tips = self.nodes[0].getchaintips ()
|
||||
assert_equal (len (tips), 1)
|
||||
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__':
|
||||
GetChainTipsTest ().main ()
|
||||
|
@ -33,62 +33,64 @@ def check_array_result(object_array, to_match, expected):
|
||||
|
||||
class ListTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
def run_test(self, nodes):
|
||||
def run_test(self):
|
||||
# Simple send, 0 to 1:
|
||||
txid = nodes[0].sendtoaddress(nodes[1].getnewaddress(), 0.1)
|
||||
sync_mempools(nodes)
|
||||
check_array_result(nodes[0].listtransactions(),
|
||||
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
|
||||
self.sync_all()
|
||||
check_array_result(self.nodes[0].listtransactions(),
|
||||
{"txid":txid},
|
||||
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
|
||||
check_array_result(nodes[1].listtransactions(),
|
||||
check_array_result(self.nodes[1].listtransactions(),
|
||||
{"txid":txid},
|
||||
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
|
||||
# mine a block, confirmations should change:
|
||||
nodes[0].setgenerate(True, 1)
|
||||
sync_blocks(nodes)
|
||||
check_array_result(nodes[0].listtransactions(),
|
||||
self.nodes[0].setgenerate(True, 1)
|
||||
self.sync_all()
|
||||
check_array_result(self.nodes[0].listtransactions(),
|
||||
{"txid":txid},
|
||||
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
|
||||
check_array_result(nodes[1].listtransactions(),
|
||||
check_array_result(self.nodes[1].listtransactions(),
|
||||
{"txid":txid},
|
||||
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
|
||||
|
||||
# send-to-self:
|
||||
txid = nodes[0].sendtoaddress(nodes[0].getnewaddress(), 0.2)
|
||||
check_array_result(nodes[0].listtransactions(),
|
||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
|
||||
check_array_result(self.nodes[0].listtransactions(),
|
||||
{"txid":txid, "category":"send"},
|
||||
{"amount":Decimal("-0.2")})
|
||||
check_array_result(nodes[0].listtransactions(),
|
||||
check_array_result(self.nodes[0].listtransactions(),
|
||||
{"txid":txid, "category":"receive"},
|
||||
{"amount":Decimal("0.2")})
|
||||
|
||||
# sendmany from node1: twice to self, twice to node2:
|
||||
send_to = { nodes[0].getnewaddress() : 0.11, nodes[1].getnewaddress() : 0.22,
|
||||
nodes[0].getaccountaddress("from1") : 0.33, nodes[1].getaccountaddress("toself") : 0.44 }
|
||||
txid = nodes[1].sendmany("", send_to)
|
||||
sync_mempools(nodes)
|
||||
check_array_result(nodes[1].listtransactions(),
|
||||
send_to = { self.nodes[0].getnewaddress() : 0.11,
|
||||
self.nodes[1].getnewaddress() : 0.22,
|
||||
self.nodes[0].getaccountaddress("from1") : 0.33,
|
||||
self.nodes[1].getaccountaddress("toself") : 0.44 }
|
||||
txid = self.nodes[1].sendmany("", send_to)
|
||||
self.sync_all()
|
||||
check_array_result(self.nodes[1].listtransactions(),
|
||||
{"category":"send","amount":Decimal("-0.11")},
|
||||
{"txid":txid} )
|
||||
check_array_result(nodes[0].listtransactions(),
|
||||
check_array_result(self.nodes[0].listtransactions(),
|
||||
{"category":"receive","amount":Decimal("0.11")},
|
||||
{"txid":txid} )
|
||||
check_array_result(nodes[1].listtransactions(),
|
||||
check_array_result(self.nodes[1].listtransactions(),
|
||||
{"category":"send","amount":Decimal("-0.22")},
|
||||
{"txid":txid} )
|
||||
check_array_result(nodes[1].listtransactions(),
|
||||
check_array_result(self.nodes[1].listtransactions(),
|
||||
{"category":"receive","amount":Decimal("0.22")},
|
||||
{"txid":txid} )
|
||||
check_array_result(nodes[1].listtransactions(),
|
||||
check_array_result(self.nodes[1].listtransactions(),
|
||||
{"category":"send","amount":Decimal("-0.33")},
|
||||
{"txid":txid} )
|
||||
check_array_result(nodes[0].listtransactions(),
|
||||
check_array_result(self.nodes[0].listtransactions(),
|
||||
{"category":"receive","amount":Decimal("0.33")},
|
||||
{"txid":txid, "account" : "from1"} )
|
||||
check_array_result(nodes[1].listtransactions(),
|
||||
check_array_result(self.nodes[1].listtransactions(),
|
||||
{"category":"send","amount":Decimal("-0.44")},
|
||||
{"txid":txid, "account" : ""} )
|
||||
check_array_result(nodes[1].listtransactions(),
|
||||
check_array_result(self.nodes[1].listtransactions(),
|
||||
{"category":"receive","amount":Decimal("0.44")},
|
||||
{"txid":txid, "account" : "toself"} )
|
||||
|
||||
|
@ -54,36 +54,36 @@ def check_array_result(object_array, to_match, expected, should_not_find = False
|
||||
|
||||
class ReceivedByTest(BitcoinTestFramework):
|
||||
|
||||
def run_test(self, nodes):
|
||||
def run_test(self):
|
||||
'''
|
||||
listreceivedbyaddress Test
|
||||
'''
|
||||
# Send from node 0 to 1
|
||||
addr = nodes[1].getnewaddress()
|
||||
txid = nodes[0].sendtoaddress(addr, 0.1)
|
||||
sync_mempools(nodes)
|
||||
addr = self.nodes[1].getnewaddress()
|
||||
txid = self.nodes[0].sendtoaddress(addr, 0.1)
|
||||
self.sync_all()
|
||||
|
||||
#Check not listed in listreceivedbyaddress because has 0 confirmations
|
||||
check_array_result(nodes[1].listreceivedbyaddress(),
|
||||
check_array_result(self.nodes[1].listreceivedbyaddress(),
|
||||
{"address":addr},
|
||||
{ },
|
||||
True)
|
||||
#Bury Tx under 10 block so it will be returned by listreceivedbyaddress
|
||||
nodes[1].setgenerate(True, 10)
|
||||
sync_blocks(nodes)
|
||||
check_array_result(nodes[1].listreceivedbyaddress(),
|
||||
self.nodes[1].setgenerate(True, 10)
|
||||
self.sync_all()
|
||||
check_array_result(self.nodes[1].listreceivedbyaddress(),
|
||||
{"address":addr},
|
||||
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
||||
#With min confidence < 10
|
||||
check_array_result(nodes[1].listreceivedbyaddress(5),
|
||||
check_array_result(self.nodes[1].listreceivedbyaddress(5),
|
||||
{"address":addr},
|
||||
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
||||
#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
|
||||
addr = nodes[1].getnewaddress()
|
||||
check_array_result(nodes[1].listreceivedbyaddress(0,True),
|
||||
addr = self.nodes[1].getnewaddress()
|
||||
check_array_result(self.nodes[1].listreceivedbyaddress(0,True),
|
||||
{"address":addr},
|
||||
{"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]})
|
||||
|
||||
@ -91,24 +91,24 @@ class ReceivedByTest(BitcoinTestFramework):
|
||||
getreceivedbyaddress Test
|
||||
'''
|
||||
# Send from node 0 to 1
|
||||
addr = nodes[1].getnewaddress()
|
||||
txid = nodes[0].sendtoaddress(addr, 0.1)
|
||||
sync_mempools(nodes)
|
||||
addr = self.nodes[1].getnewaddress()
|
||||
txid = self.nodes[0].sendtoaddress(addr, 0.1)
|
||||
self.sync_all()
|
||||
|
||||
#Check balance is 0 because of 0 confirmations
|
||||
balance = nodes[1].getreceivedbyaddress(addr)
|
||||
balance = self.nodes[1].getreceivedbyaddress(addr)
|
||||
if balance != Decimal("0.0"):
|
||||
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
|
||||
|
||||
#Check balance is 0.1
|
||||
balance = nodes[1].getreceivedbyaddress(addr,0)
|
||||
balance = self.nodes[1].getreceivedbyaddress(addr,0)
|
||||
if balance != Decimal("0.1"):
|
||||
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
|
||||
|
||||
#Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress
|
||||
nodes[1].setgenerate(True, 10)
|
||||
sync_blocks(nodes)
|
||||
balance = nodes[1].getreceivedbyaddress(addr)
|
||||
self.nodes[1].setgenerate(True, 10)
|
||||
self.sync_all()
|
||||
balance = self.nodes[1].getreceivedbyaddress(addr)
|
||||
if balance != Decimal("0.1"):
|
||||
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
|
||||
|
||||
@ -116,40 +116,40 @@ class ReceivedByTest(BitcoinTestFramework):
|
||||
listreceivedbyaccount + getreceivedbyaccount Test
|
||||
'''
|
||||
#set pre-state
|
||||
addrArr = nodes[1].getnewaddress()
|
||||
account = nodes[1].getaccount(addrArr)
|
||||
received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(),{"account":account})
|
||||
addrArr = self.nodes[1].getnewaddress()
|
||||
account = self.nodes[1].getaccount(addrArr)
|
||||
received_by_account_json = get_sub_array_from_array(self.nodes[1].listreceivedbyaccount(),{"account":account})
|
||||
if len(received_by_account_json) == 0:
|
||||
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
|
||||
check_array_result(nodes[1].listreceivedbyaccount(),
|
||||
check_array_result(self.nodes[1].listreceivedbyaccount(),
|
||||
{"account":account},
|
||||
received_by_account_json)
|
||||
|
||||
# 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:
|
||||
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
|
||||
|
||||
nodes[1].setgenerate(True, 10)
|
||||
sync_blocks(nodes)
|
||||
self.nodes[1].setgenerate(True, 10)
|
||||
self.sync_all()
|
||||
# listreceivedbyaccount should return updated account balance
|
||||
check_array_result(nodes[1].listreceivedbyaccount(),
|
||||
check_array_result(self.nodes[1].listreceivedbyaccount(),
|
||||
{"account":account},
|
||||
{"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))})
|
||||
|
||||
# getreceivedbyaddress should return updates balance
|
||||
balance = nodes[1].getreceivedbyaccount(account)
|
||||
balance = self.nodes[1].getreceivedbyaccount(account)
|
||||
if balance != balance_by_account + Decimal("0.1"):
|
||||
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
|
||||
|
||||
#Create a new account named "mynewaccount" that has a 0 balance
|
||||
nodes[1].getaccountaddress("mynewaccount")
|
||||
received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(0,True),{"account":"mynewaccount"})
|
||||
self.nodes[1].getaccountaddress("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:
|
||||
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"]))
|
||||
|
||||
# Test getreceivedbyaccount for 0 amount accounts
|
||||
balance = nodes[1].getreceivedbyaccount("mynewaccount")
|
||||
balance = self.nodes[1].getreceivedbyaccount("mynewaccount")
|
||||
if balance != Decimal("0.0"):
|
||||
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
|
||||
|
||||
|
@ -10,48 +10,48 @@ from util import *
|
||||
|
||||
class EstimateFeeTest(BitcoinTestFramework):
|
||||
|
||||
def setup_network(self, test_dir):
|
||||
nodes = []
|
||||
nodes.append(start_node(0, test_dir,
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.nodes.append(start_node(0, self.options.tmpdir,
|
||||
["-debug=mempool", "-debug=estimatefee"]))
|
||||
# Node1 mines small-but-not-tiny blocks, and allows free transactions.
|
||||
# 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
|
||||
# 6 or 7 transactions)
|
||||
nodes.append(start_node(1, test_dir,
|
||||
self.nodes.append(start_node(1, self.options.tmpdir,
|
||||
["-blockprioritysize=1500", "-blockmaxsize=2000",
|
||||
"-debug=mempool", "-debug=estimatefee"]))
|
||||
connect_nodes(nodes[1], 0)
|
||||
connect_nodes(self.nodes[1], 0)
|
||||
|
||||
# Node2 is a stingy miner, that
|
||||
# produces very small blocks (room for only 3 or so transactions)
|
||||
node2args = [ "-blockprioritysize=0", "-blockmaxsize=1500",
|
||||
"-debug=mempool", "-debug=estimatefee"]
|
||||
nodes.append(start_node(2, test_dir, node2args))
|
||||
connect_nodes(nodes[2], 0)
|
||||
self.nodes.append(start_node(2, self.options.tmpdir, node2args))
|
||||
connect_nodes(self.nodes[2], 0)
|
||||
|
||||
sync_blocks(nodes)
|
||||
return nodes
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
|
||||
|
||||
def run_test(self, nodes):
|
||||
def run_test(self):
|
||||
# Prime the memory pool with pairs of transactions
|
||||
# (high-priority, random fee and zero-priority, random fee)
|
||||
min_fee = Decimal("0.001")
|
||||
fees_per_kb = [];
|
||||
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)
|
||||
tx_kbytes = (len(txhex)/2)/1000.0
|
||||
fees_per_kb.append(float(fee)/tx_kbytes)
|
||||
|
||||
# Mine blocks with node2 until the memory pool clears:
|
||||
count_start = nodes[2].getblockcount()
|
||||
while len(nodes[2].getrawmempool()) > 0:
|
||||
nodes[2].setgenerate(True, 1)
|
||||
sync_blocks(nodes)
|
||||
count_start = self.nodes[2].getblockcount()
|
||||
while len(self.nodes[2].getrawmempool()) > 0:
|
||||
self.nodes[2].setgenerate(True, 1)
|
||||
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]))
|
||||
|
||||
# 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:
|
||||
for i in range(30):
|
||||
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)
|
||||
tx_kbytes = (len(txhex)/2)/1000.0
|
||||
fees_per_kb.append(float(fee)/tx_kbytes)
|
||||
nodes[1].setgenerate(True, 1)
|
||||
sync_blocks(nodes)
|
||||
self.nodes[1].setgenerate(True, 1)
|
||||
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]))
|
||||
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):
|
||||
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:
|
||||
while len(nodes[0].getrawmempool()) > 0:
|
||||
nodes[0].setgenerate(True, 1)
|
||||
sync_blocks(nodes)
|
||||
while len(self.nodes[0].getrawmempool()) > 0:
|
||||
self.nodes[0].setgenerate(True, 1)
|
||||
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]))
|
||||
|
||||
|
||||
|
@ -21,22 +21,64 @@ from util import *
|
||||
class BitcoinTestFramework(object):
|
||||
|
||||
# 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.getbalance(), 25*50)
|
||||
|
||||
def add_options(self, parser):
|
||||
pass
|
||||
|
||||
def setup_chain(self, tmp_directory):
|
||||
print("Initializing test directory "+tmp_directory)
|
||||
initialize_chain(tmp_directory)
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain(self.options.tmpdir)
|
||||
|
||||
def setup_network(self, tmp_directory):
|
||||
nodes = start_nodes(2, tmp_directory)
|
||||
connect_nodes(nodes[1], 0)
|
||||
sync_blocks(nodes)
|
||||
return nodes
|
||||
def setup_network(self, split = False):
|
||||
self.nodes = start_nodes(4, self.options.tmpdir)
|
||||
|
||||
# Connect the nodes as a "chain". This allows us
|
||||
# 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):
|
||||
import optparse
|
||||
@ -56,15 +98,14 @@ class BitcoinTestFramework(object):
|
||||
check_json_precision()
|
||||
|
||||
success = False
|
||||
nodes = []
|
||||
try:
|
||||
if not os.path.isdir(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
|
||||
|
||||
@ -80,7 +121,7 @@ class BitcoinTestFramework(object):
|
||||
|
||||
if not self.options.nocleanup:
|
||||
print("Cleaning up")
|
||||
stop_nodes(nodes)
|
||||
stop_nodes(self.nodes)
|
||||
wait_bitcoinds()
|
||||
shutil.rmtree(self.options.tmpdir)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user