Changeset View
Changeset View
Standalone View
Standalone View
test/functional/mempool_packages.py
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
# MAX_ANCESTORS transactions off a confirmed tx should be fine | # MAX_ANCESTORS transactions off a confirmed tx should be fine | ||||
chain = [] | chain = [] | ||||
for i in range(MAX_ANCESTORS): | for i in range(MAX_ANCESTORS): | ||||
(txid, sent_value) = self.chain_transaction( | (txid, sent_value) = self.chain_transaction( | ||||
self.nodes[0], txid, 0, value, fee, 1) | self.nodes[0], txid, 0, value, fee, 1) | ||||
value = sent_value | value = sent_value | ||||
chain.append(txid) | chain.append(txid) | ||||
# Check mempool has MAX_ANCESTORS transactions in it, and descendant | # Check mempool has MAX_ANCESTORS transactions in it, and descendant and ancestor | ||||
# count and fees should look correct | # count and fees should look correct | ||||
mempool = self.nodes[0].getrawmempool(True) | mempool = self.nodes[0].getrawmempool(True) | ||||
assert_equal(len(mempool), MAX_ANCESTORS) | assert_equal(len(mempool), MAX_ANCESTORS) | ||||
descendant_count = 1 | descendant_count = 1 | ||||
descendant_fees = 0 | descendant_fees = 0 | ||||
descendant_size = 0 | descendant_size = 0 | ||||
ancestor_size = sum([mempool[tx]['size'] for tx in mempool]) | |||||
ancestor_count = MAX_ANCESTORS | |||||
ancestor_fees = sum([mempool[tx]['fee'] for tx in mempool]) | |||||
descendants = [] | descendants = [] | ||||
ancestors = list(chain) | ancestors = list(chain) | ||||
for x in reversed(chain): | for x in reversed(chain): | ||||
# Check that getmempoolentry is consistent with getrawmempool | # Check that getmempoolentry is consistent with getrawmempool | ||||
entry = self.nodes[0].getmempoolentry(x) | entry = self.nodes[0].getmempoolentry(x) | ||||
assert_equal(entry, mempool[x]) | assert_equal(entry, mempool[x]) | ||||
# Check that the descendant calculations are correct | # Check that the descendant calculations are correct | ||||
assert_equal(mempool[x]['descendantcount'], descendant_count) | assert_equal(mempool[x]['descendantcount'], descendant_count) | ||||
descendant_fees += mempool[x]['fee'] | descendant_fees += mempool[x]['fee'] | ||||
assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee']) | assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee']) | ||||
assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN) | assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN) | ||||
descendant_size += mempool[x]['size'] | descendant_size += mempool[x]['size'] | ||||
assert_equal(mempool[x]['descendantsize'], descendant_size) | assert_equal(mempool[x]['descendantsize'], descendant_size) | ||||
descendant_count += 1 | descendant_count += 1 | ||||
# Check that ancestor calculations are correct | |||||
assert_equal(mempool[x]['ancestorcount'], ancestor_count) | |||||
assert_equal(mempool[x]['ancestorfees'], ancestor_fees * COIN) | |||||
assert_equal(mempool[x]['ancestorsize'], ancestor_size) | |||||
ancestor_size -= mempool[x]['size'] | |||||
ancestor_fees -= mempool[x]['fee'] | |||||
ancestor_count -= 1 | |||||
# Check that parent/child list is correct | |||||
assert_equal(mempool[x]['spentby'], descendants[-1:]) | |||||
assert_equal(mempool[x]['depends'], ancestors[-2:-1]) | |||||
# Check that getmempooldescendants is correct | # Check that getmempooldescendants is correct | ||||
assert_equal(sorted(descendants), sorted( | assert_equal(sorted(descendants), sorted( | ||||
self.nodes[0].getmempooldescendants(x))) | self.nodes[0].getmempooldescendants(x))) | ||||
# Check getmempooldescendants verbose output is correct | |||||
for descendant, dinfo in self.nodes[0].getmempooldescendants(x, True).items(): | |||||
assert_equal(dinfo['depends'], [ | |||||
chain[chain.index(descendant) - 1]]) | |||||
if dinfo['descendantcount'] > 1: | |||||
assert_equal(dinfo['spentby'], [ | |||||
chain[chain.index(descendant) + 1]]) | |||||
else: | |||||
assert_equal(dinfo['spentby'], []) | |||||
descendants.append(x) | descendants.append(x) | ||||
# Check that getmempoolancestors is correct | # Check that getmempoolancestors is correct | ||||
ancestors.remove(x) | ancestors.remove(x) | ||||
assert_equal(sorted(ancestors), sorted( | assert_equal(sorted(ancestors), sorted( | ||||
self.nodes[0].getmempoolancestors(x))) | self.nodes[0].getmempoolancestors(x))) | ||||
# Check that getmempoolancestors verbose output is correct | |||||
for ancestor, ainfo in self.nodes[0].getmempoolancestors(x, True).items(): | |||||
assert_equal(ainfo['spentby'], [ | |||||
chain[chain.index(ancestor) + 1]]) | |||||
if ainfo['ancestorcount'] > 1: | |||||
assert_equal(ainfo['depends'], [ | |||||
chain[chain.index(ancestor) - 1]]) | |||||
else: | |||||
assert_equal(ainfo['depends'], []) | |||||
# Check that getmempoolancestors/getmempooldescendants correctly handle verbose=true | # Check that getmempoolancestors/getmempooldescendants correctly handle verbose=true | ||||
v_ancestors = self.nodes[0].getmempoolancestors(chain[-1], True) | v_ancestors = self.nodes[0].getmempoolancestors(chain[-1], True) | ||||
assert_equal(len(v_ancestors), len(chain) - 1) | assert_equal(len(v_ancestors), len(chain) - 1) | ||||
for x in v_ancestors.keys(): | for x in v_ancestors.keys(): | ||||
assert_equal(mempool[x], v_ancestors[x]) | assert_equal(mempool[x], v_ancestors[x]) | ||||
assert(chain[-1] not in v_ancestors.keys()) | assert(chain[-1] not in v_ancestors.keys()) | ||||
v_descendants = self.nodes[0].getmempooldescendants(chain[0], True) | v_descendants = self.nodes[0].getmempooldescendants(chain[0], True) | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
# TODO: test ancestor size limits | # TODO: test ancestor size limits | ||||
# Now test descendant chain limits | # Now test descendant chain limits | ||||
txid = utxo[1]['txid'] | txid = utxo[1]['txid'] | ||||
value = utxo[1]['amount'] | value = utxo[1]['amount'] | ||||
vout = utxo[1]['vout'] | vout = utxo[1]['vout'] | ||||
transaction_package = [] | transaction_package = [] | ||||
tx_children = [] | |||||
# First create one parent tx with 10 children | # First create one parent tx with 10 children | ||||
(txid, sent_value) = self.chain_transaction( | (txid, sent_value) = self.chain_transaction( | ||||
self.nodes[0], txid, vout, value, fee, 10) | self.nodes[0], txid, vout, value, fee, 10) | ||||
parent_transaction = txid | parent_transaction = txid | ||||
for i in range(10): | for i in range(10): | ||||
transaction_package.append( | transaction_package.append( | ||||
{'txid': txid, 'vout': i, 'amount': sent_value}) | {'txid': txid, 'vout': i, 'amount': sent_value}) | ||||
# Sign and send up to MAX_DESCENDANT transactions chained off the parent tx | # Sign and send up to MAX_DESCENDANT transactions chained off the parent tx | ||||
for i in range(MAX_DESCENDANTS - 1): | for i in range(MAX_DESCENDANTS - 1): | ||||
utxo = transaction_package.pop(0) | utxo = transaction_package.pop(0) | ||||
(txid, sent_value) = self.chain_transaction( | (txid, sent_value) = self.chain_transaction( | ||||
self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) | self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) | ||||
if utxo['txid'] is parent_transaction: | |||||
tx_children.append(txid) | |||||
for j in range(10): | for j in range(10): | ||||
transaction_package.append( | transaction_package.append( | ||||
{'txid': txid, 'vout': j, 'amount': sent_value}) | {'txid': txid, 'vout': j, 'amount': sent_value}) | ||||
mempool = self.nodes[0].getrawmempool(True) | mempool = self.nodes[0].getrawmempool(True) | ||||
assert_equal(mempool[parent_transaction] | assert_equal(mempool[parent_transaction] | ||||
['descendantcount'], MAX_DESCENDANTS) | ['descendantcount'], MAX_DESCENDANTS) | ||||
assert_equal(sorted(mempool[parent_transaction] | |||||
['spentby']), sorted(tx_children)) | |||||
for child in tx_children: | |||||
assert_equal(mempool[child]['depends'], [parent_transaction]) | |||||
# Sending one more chained transaction will fail | # Sending one more chained transaction will fail | ||||
utxo = transaction_package.pop(0) | utxo = transaction_package.pop(0) | ||||
assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, | assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, | ||||
self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) | self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) | ||||
# TODO: check that node1's mempool is as expected | # TODO: check that node1's mempool is as expected | ||||
▲ Show 20 Lines • Show All 72 Lines • Show Last 20 Lines |