Changeset View
Changeset View
Standalone View
Standalone View
test/functional/relay_zero_fee_transaction.py
- This file was added.
Property | Old Value | New Value |
---|---|---|
File Mode | null | 100755 |
#!/usr/bin/env python3 | |||||
# Copyright (c) 2017 The Bitcoin developers | |||||
# Distributed under the MIT software license, see the accompanying | |||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | |||||
# | |||||
# Test HighPriorityTransaction code | |||||
# | |||||
from test_framework.test_framework import BitcoinTestFramework | |||||
from test_framework.util import * | |||||
from datetime import datetime | |||||
class RelayZeroFeeTransactionTest(BitcoinTestFramework): | |||||
def __init__(self): | |||||
super().__init__() | |||||
self.setup_clean_chain = True | |||||
self.is_network_split = False | |||||
self.num_nodes = 2 | |||||
# limitfreerelay = X means that we can't relay more than X * 1000 bytes of 0 fee txns per minute | |||||
# but for some reasons involving a 10 minutes exponentially decay window the limit is X * 10 * 1000 | |||||
# see validation.cpp#L917 | |||||
self.extra_args = [ | |||||
["-limitfreerelay=1", "-minrelaytxfee=0.0001"], | |||||
["-limitfreerelay=1", "-minrelaytxfee=0.0001"] | |||||
] | |||||
def setup_network(self): | |||||
self.setup_nodes() | |||||
connect_nodes(self.nodes[0], 1) | |||||
self.sync_all() | |||||
def create_transactions(self, node, utxos, num, fee): | |||||
addr = node.getnewaddress() | |||||
txids = [] | |||||
for _ in range(num): | |||||
t = utxos.pop() | |||||
inputs = [{"txid": t["txid"], "vout": t["vout"]}] | |||||
outputs = {} | |||||
change = t['amount'] - fee | |||||
outputs[addr] = satoshi_round(change) | |||||
rawtx = node.createrawtransaction(inputs, outputs) | |||||
signresult = node.signrawtransaction( | |||||
rawtx, None, None, "NONE|FORKID") | |||||
txid = node.sendrawtransaction(signresult["hex"], True) | |||||
txids.append(txid) | |||||
return txids | |||||
def generate_zerofee_transactions(self, node, count, fee): | |||||
# be sure to make this utxo aged enough | |||||
# and with enough fees | |||||
txns = create_confirmed_utxos( | |||||
Decimal('0.00015'), node, count) | |||||
txids = [] | |||||
# Create txns_count number of txns with 0 fee | |||||
range_size = [0, count] | |||||
start_range = range_size[0] | |||||
end_range = range_size[1] | |||||
txids = self.create_transactions( | |||||
node, txns[start_range:end_range], end_range - start_range, fee) | |||||
return txids | |||||
def run_test(self): | |||||
# self.relayfee0 = self.nodes[0].getnetworkinfo()['relayfee'] | |||||
# self.relayfee1 = self.nodes[1].getnetworkinfo()['relayfee'] | |||||
# self.log.info("minRelayTxFee node0 set to: %s" % str(self.relayfee0)) | |||||
# self.log.info("minRelayTxFee node1 set to: %s" % str(self.relayfee1)) | |||||
# self.log.info("Fee set to: %d" % self.relayfee0) | |||||
# first test: verify that 0 fee transactions generated locally are rate | |||||
# rate limited. So we are going to generate 200 simple txns (~35K) in a very | |||||
# short period. We should get rate limited at around 10K | |||||
try: | |||||
txids = self.generate_zerofee_transactions(self.nodes[0], 200, 0) | |||||
except JSONRPCException as e: | |||||
# mempool should be around 10K (using 2% tolerance) | |||||
self.log.info("Error message is: %s" % e.error['message']) | |||||
self.log.info("mem pool size is: %d" % | |||||
self.nodes[0].getmempoolinfo()['bytes']) | |||||
assert(self.nodes[0].getmempoolinfo()['bytes'] <= 10200) | |||||
# 2nd test: verify that only 10K 0 fee txns are realyed from | |||||
# node0 to node1 if minrelayfee is set to 0.0001 and limiterfreerelay is set to 1 | |||||
# (the mempool size is about 35K) | |||||
stop_nodes(self.nodes) | |||||
os.remove(self.options.tmpdir + "/node0/regtest/mempool.dat") | |||||
os.remove(self.options.tmpdir + "/node1/regtest/mempool.dat") | |||||
self.extra_args = [ | |||||
["-limitfreerelay=10", "-minrelaytxfee=0.0001"], | |||||
["-limitfreerelay=1", "-minrelaytxfee=0.0001"] | |||||
] | |||||
self.nodes = start_nodes( | |||||
self.num_nodes, self.options.tmpdir, self.extra_args) | |||||
connect_nodes_bi(self.nodes, 0, 1) | |||||
txids = self.generate_zerofee_transactions(self.nodes[0], 200, 0) | |||||
mempool_size_pre = self.nodes[0].getmempoolinfo()['bytes'] | |||||
self.log.info("Current mempool size n bytes is: %d" % | |||||
mempool_size_pre) | |||||
try: | |||||
# wait for 1 minute for the sync to happen | |||||
# node1 mempool should be lower than 10K | |||||
sync_mempools(self.nodes, wait=1, timeout=60) | |||||
except AssertionError: | |||||
self.log.debug("memp 0 %d, memp 1 %d" % | |||||
(self.nodes[0].getmempoolinfo()['bytes'], self.nodes[1].getmempoolinfo()['bytes'])) | |||||
self.log.info( | |||||
"Assert that only 10K worth of zero fee transactions will be relayed") | |||||
assert(self.nodes[1].getmempoolinfo()['bytes'] <= 10200) | |||||
if __name__ == '__main__': | |||||
RelayZeroFeeTransactionTest().main() |