|
|
|
@ -361,54 +361,29 @@ def sync_blocks(rpc_connections, *, wait=1, timeout=60):
|
|
|
|
|
one node already synced to the latest, stable tip, otherwise there's a
|
|
|
|
|
chance it might return before all nodes are stably synced.
|
|
|
|
|
"""
|
|
|
|
|
# Use getblockcount() instead of waitforblockheight() to determine the
|
|
|
|
|
# initial max height because the two RPCs look at different internal global
|
|
|
|
|
# variables (chainActive vs latestBlock) and the former gets updated
|
|
|
|
|
# earlier.
|
|
|
|
|
maxheight = max(x.getblockcount() for x in rpc_connections)
|
|
|
|
|
start_time = cur_time = time.time()
|
|
|
|
|
while cur_time <= start_time + timeout:
|
|
|
|
|
tips = [r.waitforblockheight(maxheight, int(wait * 1000)) for r in rpc_connections]
|
|
|
|
|
if all(t["height"] == maxheight for t in tips):
|
|
|
|
|
if all(t["hash"] == tips[0]["hash"] for t in tips):
|
|
|
|
|
return
|
|
|
|
|
raise AssertionError("Block sync failed, mismatched block hashes:{}".format(
|
|
|
|
|
"".join("\n {!r}".format(tip) for tip in tips)))
|
|
|
|
|
cur_time = time.time()
|
|
|
|
|
raise AssertionError("Block sync to height {} timed out:{}".format(
|
|
|
|
|
maxheight, "".join("\n {!r}".format(tip) for tip in tips)))
|
|
|
|
|
|
|
|
|
|
def sync_chain(rpc_connections, *, wait=1, timeout=60):
|
|
|
|
|
"""
|
|
|
|
|
Wait until everybody has the same best block
|
|
|
|
|
"""
|
|
|
|
|
while timeout > 0:
|
|
|
|
|
stop_time = time.time() + timeout
|
|
|
|
|
while time.time() <= stop_time:
|
|
|
|
|
best_hash = [x.getbestblockhash() for x in rpc_connections]
|
|
|
|
|
if best_hash == [best_hash[0]] * len(best_hash):
|
|
|
|
|
if best_hash.count(best_hash[0]) == len(rpc_connections):
|
|
|
|
|
return
|
|
|
|
|
time.sleep(wait)
|
|
|
|
|
timeout -= wait
|
|
|
|
|
raise AssertionError("Chain sync failed: Best block hashes don't match")
|
|
|
|
|
raise AssertionError("Block sync timed out:{}".format("".join("\n {!r}".format(b) for b in best_hash)))
|
|
|
|
|
|
|
|
|
|
def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True):
|
|
|
|
|
"""
|
|
|
|
|
Wait until everybody has the same transactions in their memory
|
|
|
|
|
pools
|
|
|
|
|
"""
|
|
|
|
|
while timeout > 0:
|
|
|
|
|
pool = set(rpc_connections[0].getrawmempool())
|
|
|
|
|
num_match = 1
|
|
|
|
|
for i in range(1, len(rpc_connections)):
|
|
|
|
|
if set(rpc_connections[i].getrawmempool()) == pool:
|
|
|
|
|
num_match = num_match + 1
|
|
|
|
|
if num_match == len(rpc_connections):
|
|
|
|
|
stop_time = time.time() + timeout
|
|
|
|
|
while time.time() <= stop_time:
|
|
|
|
|
pool = [set(r.getrawmempool()) for r in rpc_connections]
|
|
|
|
|
if pool.count(pool[0]) == len(rpc_connections):
|
|
|
|
|
if flush_scheduler:
|
|
|
|
|
for r in rpc_connections:
|
|
|
|
|
r.syncwithvalidationinterfacequeue()
|
|
|
|
|
return
|
|
|
|
|
time.sleep(wait)
|
|
|
|
|
timeout -= wait
|
|
|
|
|
raise AssertionError("Mempool sync failed")
|
|
|
|
|
raise AssertionError("Mempool sync timed out:{}".format("".join("\n {!r}".format(m) for m in pool)))
|
|
|
|
|
|
|
|
|
|
# Transaction/Block functions
|
|
|
|
|
#############################
|
|
|
|
|