Skip to content
2 changes: 1 addition & 1 deletion contrib/devtools/check-doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
# list unsupported, deprecated and duplicate args as they need no documentation
SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags', '-blockminsize'])

SET_DOC_OPTIONAL.update(['-con_fpowallowmindifficultyblocks', '-con_fpownoretargeting', '-con_nsubsidyhalvinginterval', '-con_bip34height', '-con_bip65height', '-con_bip66height', '-con_npowtargettimespan', '-con_npowtargetspacing', '-con_nrulechangeactivationthreshold', '-con_nminerconfirmationwindow', '-con_powlimit', '-con_bip34hash', '-con_nminimumchainwork', '-con_defaultassumevalid', '-ndefaultport', '-npruneafterheight', '-fdefaultconsistencychecks', '-frequirestandard', '-fmineblocksondemand', '-mainchainrpccookiefile', '-testnet', '-ct_bits', '-ct_exponent', '-anyonecanspendaremine'])
SET_DOC_OPTIONAL.update(['-con_fpowallowmindifficultyblocks', '-con_fpownoretargeting', '-con_nsubsidyhalvinginterval', '-con_bip34height', '-con_bip65height', '-con_bip66height', '-con_npowtargettimespan', '-con_npowtargetspacing', '-con_nrulechangeactivationthreshold', '-con_nminerconfirmationwindow', '-con_powlimit', '-con_bip34hash', '-con_nminimumchainwork', '-con_defaultassumevalid', '-ndefaultport', '-npruneafterheight', '-fdefaultconsistencychecks', '-frequirestandard', '-fmineblocksondemand', '-mainchainrpccookiefile', '-testnet', '-ct_bits', '-ct_exponent', '-anyonecanspendaremine', '-fminingrequirespeers'])

def main():
used = check_output(CMD_GREP_ARGS, shell=True)
Expand Down
1 change: 1 addition & 0 deletions qa/pull-tester/rpc-tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
'rpcnamedargs.py',
'listsinceblock.py',
'p2p-leaktests.py',
'anyonecanspend.py',
]
if ENABLE_ZMQ:
testScripts.append('zmq_test.py')
Expand Down
36 changes: 36 additions & 0 deletions qa/rpc-tests/anyonecanspend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
# Copyright (c) 2017-2017 The Elements Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test custom -anyonecanspendaremine chainparams."""

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import start_nodes, connect_nodes_bi, assert_raises_jsonrpc

class AnyoneCanSpendTest(BitcoinTestFramework):

def __init__(self):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 2
self.extra_args = [["-anyonecanspendaremine=0"], ["-anyonecanspendaremine"]]

def setup_network(self, split=False):
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=self.extra_args)
connect_nodes_bi(self.nodes,0,1)
self.is_network_split=False
self.sync_all()

def run_test(self):
self.nodes[0].generate(100)
self.sync_all()

address = self.nodes[0].getnewaddress()
# Show error when disabled
assert_raises_jsonrpc(-6, 'Insufficient funds', self.nodes[0].sendtoaddress, address, 1)

# Using -anyonecanspendaremine bypasses the error
self.nodes[1].sendtoaddress(address, 1)

if __name__ == '__main__':
AnyoneCanSpendTest().main()
4 changes: 2 additions & 2 deletions qa/rpc-tests/pruning.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def setup_network(self):

# Create node 2 to test pruning
self.nodes.append(start_node(2, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-prune=550"], timewait=900))
self.prunedir = self.options.tmpdir+"/node2/regtest/blocks/"
self.prunedir = self.options.tmpdir+"/node2/" + self.chain + " /blocks/"

# Create nodes 3 and 4 to test manual pruning (they will be re-started with manual pruning later)
self.nodes.append(start_node(3, self.options.tmpdir, ["-debug=0","-maxreceivebuffer=20000","-blockmaxsize=999000"], timewait=900))
Expand Down Expand Up @@ -264,7 +264,7 @@ def prune(index, expected_ret=None):
assert_equal(ret, expected_ret)

def has_block(index):
return os.path.isfile(self.options.tmpdir + "/node{}/regtest/blocks/blk{:05}.dat".format(node_number, index))
return os.path.isfile(self.options.tmpdir + "/node{}/{}/blocks/blk{:05}.dat".format(node_number, self.chain, index))

# should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000)
assert_raises_message(JSONRPCException, "Blockchain is too short for pruning", node.pruneblockchain, height(500))
Expand Down
45 changes: 32 additions & 13 deletions qa/rpc-tests/replace-by-fee.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def __init__(self):
super().__init__()
self.num_nodes = 1
self.setup_clean_chain = False
self.chain = "elementsregtest"

def setup_network(self):
self.nodes = []
Expand All @@ -81,8 +82,19 @@ def setup_network(self):
]))
self.is_network_split = False

def make_utxo(self, node, amount, confirmed=True, scriptPubKey=CScript([1])):
self.sync_all()
make_utxo(self, node, amount, confirmed, scriptPubKey)
self.sync_all()

def run_test(self):
make_utxo(self.nodes[0], 1*COIN)
# Leave IBD
self.nodes[0].generate(1)

self.make_utxo(self.nodes[0], 1*COIN)

# Ensure nodes are synced
self.sync_all()

print("Running test simple doublespend...")
self.test_simple_doublespend()
Expand Down Expand Up @@ -112,14 +124,21 @@ def run_test(self):

def test_simple_doublespend(self):
"""Simple doublespend"""
tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1*COIN))

# make_utxo may have generated a bunch of blocks, so we need to sync
# before we can spend the coins generated, or else the resulting
# transactions might not be accepted by our peers.
self.sync_all()

tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
tx1a.vout = [CTxOut(1*COIN, CScript([b'a'])), CTxOut(int(0.1*COIN), b'')]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)

self.sync_all()

# Should fail because we haven't changed the fee
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
Expand Down Expand Up @@ -151,7 +170,7 @@ def test_doublespend_chain(self):
"""Doublespend of a long chain"""

initial_nValue = 50*COIN
tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
tx0_outpoint = self.make_utxo(self.nodes[0], initial_nValue)

prevout = tx0_outpoint
remaining_value = initial_nValue
Expand Down Expand Up @@ -194,7 +213,7 @@ def test_doublespend_chain(self):
def test_doublespend_tree(self):
"""Doublespend of a big tree of transactions"""
initial_nValue = 50*COIN
tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
tx0_outpoint = self.make_utxo(self.nodes[0], initial_nValue)

def branch(prevout, initial_value, max_txs, tree_width=5, fee=int(0.0001*COIN), _total_txs=None):
if _total_txs is None:
Expand Down Expand Up @@ -265,7 +284,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=int(0.0001*COIN),
# double-spent at once" anti-DoS limit.
for n in (MAX_REPLACEMENT_LIMIT+1, MAX_REPLACEMENT_LIMIT*2):
fee = int(0.0001*COIN)
tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
tx0_outpoint = self.make_utxo(self.nodes[0], initial_nValue)
tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
assert_equal(len(tree_txs), n)

Expand All @@ -287,7 +306,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=int(0.0001*COIN),

def test_replacement_feeperkb(self):
"""Replacement requires fee-per-KB to be higher"""
tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1*COIN))

tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
Expand All @@ -311,8 +330,8 @@ def test_replacement_feeperkb(self):

def test_spends_of_conflicting_outputs(self):
"""Replacements that spend conflicting tx outputs are rejected"""
utxo1 = make_utxo(self.nodes[0], int(1.2*COIN))
utxo2 = make_utxo(self.nodes[0], 3*COIN)
utxo1 = self.make_utxo(self.nodes[0], int(1.2*COIN))
utxo2 = self.make_utxo(self.nodes[0], 3*COIN)

tx1a = CTransaction()
tx1a.vin = [CTxIn(utxo1, nSequence=0)]
Expand Down Expand Up @@ -360,8 +379,8 @@ def test_spends_of_conflicting_outputs(self):

def test_new_unconfirmed_inputs(self):
"""Replacements that add new unconfirmed inputs are rejected"""
confirmed_utxo = make_utxo(self.nodes[0], int(1.1*COIN))
unconfirmed_utxo = make_utxo(self.nodes[0], int(0.1*COIN), False)
confirmed_utxo = self.make_utxo(self.nodes[0], int(1.1*COIN))
unconfirmed_utxo = self.make_utxo(self.nodes[0], int(0.1*COIN), False)

tx1 = CTransaction()
tx1.vin = [CTxIn(confirmed_utxo)]
Expand Down Expand Up @@ -389,7 +408,7 @@ def test_too_many_replacements(self):

# Start by creating a single transaction with many outputs
initial_nValue = 10*COIN
utxo = make_utxo(self.nodes[0], initial_nValue)
utxo = self.make_utxo(self.nodes[0], initial_nValue)
fee = int(0.0001*COIN)
split_value = int((initial_nValue-fee)/(MAX_REPLACEMENT_LIMIT+1))
fee += int((initial_nValue-fee)%(MAX_REPLACEMENT_LIMIT+1))
Expand Down Expand Up @@ -449,7 +468,7 @@ def test_prioritised_transactions(self):
# correctly used by replacement logic

# 1. Check that feeperkb uses modified fees
tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1*COIN))

tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
Expand Down Expand Up @@ -480,7 +499,7 @@ def test_prioritised_transactions(self):
assert(tx1b_txid in self.nodes[0].getrawmempool())

# 2. Check that absolute fee checks use modified fee.
tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
tx1_outpoint = self.make_utxo(self.nodes[0], int(1.1*COIN))

tx2a = CTransaction()
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
Expand Down
7 changes: 4 additions & 3 deletions qa/rpc-tests/test_framework/test_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self):
self.num_nodes = 4
self.setup_clean_chain = False
self.nodes = None
self.chain = "custom"

def run_test(self):
raise NotImplementedError
Expand All @@ -45,9 +46,9 @@ def add_options(self, parser):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
if self.setup_clean_chain:
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
initialize_chain_clean(self.chain, self.options.tmpdir, self.num_nodes)
else:
initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir)
initialize_chain(self.chain, self.options.tmpdir, self.num_nodes, self.options.cachedir)

def stop_node(self, num_node):
stop_node(self.nodes[num_node], num_node)
Expand Down Expand Up @@ -176,7 +177,7 @@ def main(self):
# Dump the end of the debug logs, to aid in debugging rare
# travis failures.
import glob
filenames = glob.glob(self.options.tmpdir + "/node*/regtest/debug.log")
filenames = glob.glob(self.options.tmpdir + "/node*/" + self.chain + "/debug.log")
MAX_LINES_TO_PRINT = 1000
for f in filenames:
print("From" , f, ":")
Expand Down
26 changes: 13 additions & 13 deletions qa/rpc-tests/test_framework/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,13 @@ def sync_mempools(rpc_connections, *, wait=1, timeout=60):

bitcoind_processes = {}

def initialize_datadir(dirname, n):
def initialize_datadir(chain, dirname, n):
datadir = os.path.join(dirname, "node"+str(n))
if not os.path.isdir(datadir):
os.makedirs(datadir)
rpc_u, rpc_p = rpc_auth_pair(n)
with open(os.path.join(datadir, "elements.conf"), 'w', encoding='utf8') as f:
f.write("regtest=1\n")
f.write("chain=" + chain + "\n")
f.write("rpcuser=" + rpc_u + "\n")
f.write("rpcpassword=" + rpc_p + "\n")
f.write("port="+str(p2p_port(n))+"\n")
Expand Down Expand Up @@ -230,7 +230,7 @@ def wait_for_bitcoind_start(process, url, i):
raise # unknown JSON RPC exception
time.sleep(0.25)

def initialize_chain(test_dir, num_nodes, cachedir):
def initialize_chain(chain, test_dir, num_nodes, cachedir):
"""
Create a cache of a 200-block-long chain (with wallet) for MAX_NODES
Afterward, create num_nodes copies from the cache
Expand All @@ -252,7 +252,7 @@ def initialize_chain(test_dir, num_nodes, cachedir):

# Create cache directories, run bitcoinds:
for i in range(MAX_NODES):
datadir=initialize_datadir(cachedir, i)
datadir=initialize_datadir(chain, cachedir, i)
args = [ os.getenv("ELEMENTSD", "elementsd"), "-server", "-keypool=1", "-datadir="+datadir, "-discover=0" ]
if i > 0:
args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
Expand Down Expand Up @@ -293,24 +293,24 @@ def initialize_chain(test_dir, num_nodes, cachedir):
stop_nodes(rpcs)
disable_mocktime()
for i in range(MAX_NODES):
os.remove(log_filename(cachedir, i, "debug.log"))
os.remove(log_filename(cachedir, i, "db.log"))
os.remove(log_filename(cachedir, i, "peers.dat"))
os.remove(log_filename(cachedir, i, "fee_estimates.dat"))
os.remove(log_filename(chain, cachedir, i, "debug.log"))
os.remove(log_filename(chain, cachedir, i, "db.log"))
os.remove(log_filename(chain, cachedir, i, "peers.dat"))
os.remove(log_filename(chain, cachedir, i, "fee_estimates.dat"))

for i in range(num_nodes):
from_dir = os.path.join(cachedir, "node"+str(i))
to_dir = os.path.join(test_dir, "node"+str(i))
shutil.copytree(from_dir, to_dir)
initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf
initialize_datadir(chain, test_dir, i) # Overwrite port/rpcport in bitcoin.conf

def initialize_chain_clean(test_dir, num_nodes):
def initialize_chain_clean(chain, test_dir, num_nodes):
"""
Create an empty blockchain and num_nodes wallets.
Useful if a test case wants complete control over initialization.
"""
for i in range(num_nodes):
datadir=initialize_datadir(test_dir, i)
datadir=initialize_datadir(chain, test_dir, i)


def _rpchost_to_args(rpchost):
Expand Down Expand Up @@ -371,8 +371,8 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None
raise
return rpcs

def log_filename(dirname, n_node, logname):
return os.path.join(dirname, "node"+str(n_node), "elementsregtest", logname)
def log_filename(chain, dirname, n_node, logname):
return os.path.join(dirname, "node"+str(n_node), chain, logname)

def stop_node(node, i):
try:
Expand Down
4 changes: 2 additions & 2 deletions qa/rpc-tests/wallet-hd.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ def run_test (self):

print("Restore backup ...")
self.stop_node(1)
os.remove(self.options.tmpdir + "/node1/elementsregtest/wallet.dat")
shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/elementsregtest/wallet.dat")
os.remove(self.options.tmpdir + "/node1/" + self.chain + "/wallet.dat")
shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/" + self.chain + "/wallet.dat")
self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1])
#connect_nodes_bi(self.nodes, 0, 1)

Expand Down
20 changes: 10 additions & 10 deletions qa/rpc-tests/walletbackup.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ def stop_three(self):
stop_node(self.nodes[2], 2)

def erase_three(self):
os.remove(self.options.tmpdir + "/node0/regtest/wallet.dat")
os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat")
os.remove(self.options.tmpdir + "/node2/regtest/wallet.dat")
os.remove(self.options.tmpdir + "/node0/" + self.chain + " /wallet.dat")
os.remove(self.options.tmpdir + "/node1/" + self.chain + " /wallet.dat")
os.remove(self.options.tmpdir + "/node2/" + self.chain + " /wallet.dat")

def run_test(self):
return #TODO
Expand Down Expand Up @@ -158,13 +158,13 @@ def run_test(self):
self.erase_three()

# Start node2 with no chain
shutil.rmtree(self.options.tmpdir + "/node2/regtest/blocks")
shutil.rmtree(self.options.tmpdir + "/node2/regtest/chainstate")
shutil.rmtree(self.options.tmpdir + "/node2/" + self.chain + " /blocks")
shutil.rmtree(self.options.tmpdir + "/node2/" + self.chain + " /chainstate")

# Restore wallets from backup
shutil.copyfile(tmpdir + "/node0/wallet.bak", tmpdir + "/node0/regtest/wallet.dat")
shutil.copyfile(tmpdir + "/node1/wallet.bak", tmpdir + "/node1/regtest/wallet.dat")
shutil.copyfile(tmpdir + "/node2/wallet.bak", tmpdir + "/node2/regtest/wallet.dat")
shutil.copyfile(tmpdir + "/node0/wallet.bak", tmpdir + "/node0/" + self.chain + " /wallet.dat")
shutil.copyfile(tmpdir + "/node1/wallet.bak", tmpdir + "/node1/" + self.chain + " /wallet.dat")
shutil.copyfile(tmpdir + "/node2/wallet.bak", tmpdir + "/node2/" + self.chain + " /wallet.dat")

logging.info("Re-starting nodes")
self.start_three()
Expand All @@ -179,8 +179,8 @@ def run_test(self):
self.erase_three()

#start node2 with no chain
shutil.rmtree(self.options.tmpdir + "/node2/regtest/blocks")
shutil.rmtree(self.options.tmpdir + "/node2/regtest/chainstate")
shutil.rmtree(self.options.tmpdir + "/node2/" + self.chain + " /blocks")
shutil.rmtree(self.options.tmpdir + "/node2/" + self.chain + " /chainstate")

self.start_three()

Expand Down
Loading