def setup_chain(self): super().setup_chain() #Append rpcauth to bitcoin.conf before initialization rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" rpcuser = "******" rpcpassword = "******" with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "bitcoin.conf"), 'a', encoding='utf8') as f: f.write(rpcauth+"\n") f.write(rpcauth2+"\n") with open(os.path.join(get_datadir_path(self.options.tmpdir, 1), "bitcoin.conf"), 'a', encoding='utf8') as f: f.write(rpcuser+"\n") f.write(rpcpassword+"\n")
def run_test(self): self.stop_node(0) # Remove the -datadir argument so it doesn't override the config file self.nodes[0].args = [arg for arg in self.nodes[0].args if not arg.startswith("-datadir")] default_data_dir = get_datadir_path(self.options.tmpdir, 0) new_data_dir = os.path.join(default_data_dir, 'newdatadir') new_data_dir_2 = os.path.join(default_data_dir, 'newdatadir2') # Check that using -datadir argument on non-existent directory fails self.nodes[0].datadir = new_data_dir self.assert_start_raises_init_error(0, ['-datadir='+new_data_dir], 'Error: Specified data directory "' + new_data_dir + '" does not exist.') # Check that using non-existent datadir in conf file fails conf_file = os.path.join(default_data_dir, "titcoin.conf") with open(conf_file, 'a', encoding='utf8') as f: f.write("datadir=" + new_data_dir + "\n") self.assert_start_raises_init_error(0, ['-conf='+conf_file], 'Error reading configuration file: specified data directory "' + new_data_dir + '" does not exist.') # Create the directory and ensure the config file now works os.mkdir(new_data_dir) self.start_node(0, ['-conf='+conf_file, '-wallet=w1']) self.stop_node(0) assert os.path.isfile(os.path.join(new_data_dir, 'regtest', 'wallets', 'w1')) # Ensure command line argument overrides datadir in conf os.mkdir(new_data_dir_2) self.nodes[0].datadir = new_data_dir_2 self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2']) assert os.path.isfile(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2'))
def setup_chain(self): super().setup_chain() #Append rpcauth to digibyte.conf before initialization rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" rpcuser = "******" rpcpassword = "******" self.user = ''.join(SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10)) config = configparser.ConfigParser() config.read_file(open(self.options.configfile)) gen_rpcauth = config['environment']['RPCAUTH'] p = subprocess.Popen([sys.executable, gen_rpcauth, self.user], stdout=subprocess.PIPE, universal_newlines=True) lines = p.stdout.read().splitlines() rpcauth3 = lines[1] self.password = lines[3] with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "digibyte.conf"), 'a', encoding='utf8') as f: f.write(rpcauth+"\n") f.write(rpcauth2+"\n") f.write(rpcauth3+"\n") with open(os.path.join(get_datadir_path(self.options.tmpdir, 1), "digibyte.conf"), 'a', encoding='utf8') as f: f.write(rpcuser+"\n") f.write(rpcpassword+"\n")
def run_test(self): self.log.info('Check correctness of the rpcauth config option') url = urllib.parse.urlparse(self.nodes[0].url) self.test_auth(self.nodes[0], url.username, url.password) self.test_auth(self.nodes[0], 'rt', self.rtpassword) self.test_auth(self.nodes[0], 'rt2', self.rt2password) self.test_auth(self.nodes[0], self.user, self.password) self.log.info( 'Check correctness of the rpcuser/rpcpassword config options') url = urllib.parse.urlparse(self.nodes[1].url) self.test_auth(self.nodes[1], self.rpcuser, self.rpcpassword) self.log.info( 'Check that failure to write cookie file will abort the node gracefully' ) self.stop_node(0) cookie_file = os.path.join(get_datadir_path(self.options.tmpdir, 0), self.chain, '.cookie.tmp') os.mkdir(cookie_file) init_error = 'Error: Unable to start HTTP server. See debug log for details.' self.nodes[0].assert_start_raises_init_error(expected_msg=init_error)
def _test_getblock(self): node = self.nodes[0] fee_per_byte = Decimal('0.00000010') fee_per_kb = 1000 * fee_per_byte self.wallet.send_self_transfer(fee_rate=fee_per_kb, from_node=node) blockhash = self.generate(node, 1)[0] def assert_fee_not_in_block(verbosity): block = node.getblock(blockhash, verbosity) assert 'fee' not in block['tx'][1] def assert_fee_in_block(verbosity): block = node.getblock(blockhash, verbosity) tx = block['tx'][1] assert 'fee' in tx assert_equal(tx['fee'], tx['vsize'] * fee_per_byte) def assert_vin_contains_prevout(verbosity): block = node.getblock(blockhash, verbosity) tx = block["tx"][1] total_vin = Decimal("0.00000000") total_vout = Decimal("0.00000000") for vin in tx["vin"]: assert "prevout" in vin assert_equal(set(vin["prevout"].keys()), set(("value", "height", "generated", "scriptPubKey"))) assert_equal(vin["prevout"]["generated"], True) total_vin += vin["prevout"]["value"] for vout in tx["vout"]: total_vout += vout["value"] assert_equal(total_vin, total_vout + tx["fee"]) def assert_vin_does_not_contain_prevout(verbosity): block = node.getblock(blockhash, verbosity) tx = block["tx"][1] if isinstance(tx, str): # In verbosity level 1, only the transaction hashes are written pass else: for vin in tx["vin"]: assert "prevout" not in vin self.log.info("Test that getblock with verbosity 1 doesn't include fee") assert_fee_not_in_block(1) self.log.info('Test that getblock with verbosity 2 and 3 includes expected fee') assert_fee_in_block(2) assert_fee_in_block(3) self.log.info("Test that getblock with verbosity 1 and 2 does not include prevout") assert_vin_does_not_contain_prevout(1) assert_vin_does_not_contain_prevout(2) self.log.info("Test that getblock with verbosity 3 includes prevout") assert_vin_contains_prevout(3) self.log.info("Test that getblock with verbosity 2 and 3 still works with pruned Undo data") datadir = get_datadir_path(self.options.tmpdir, 0) self.log.info("Test getblock with invalid verbosity type returns proper error message") assert_raises_rpc_error(-1, "JSON value is not an integer as expected", node.getblock, blockhash, "2") def move_block_file(old, new): old_path = os.path.join(datadir, self.chain, 'blocks', old) new_path = os.path.join(datadir, self.chain, 'blocks', new) os.rename(old_path, new_path) # Move instead of deleting so we can restore chain state afterwards move_block_file('rev00000.dat', 'rev_wrong') assert_fee_not_in_block(2) assert_fee_not_in_block(3) assert_vin_does_not_contain_prevout(2) assert_vin_does_not_contain_prevout(3) # Restore chain state move_block_file('rev_wrong', 'rev00000.dat') assert 'previousblockhash' not in node.getblock(node.getblockhash(0)) assert 'nextblockhash' not in node.getblock(node.getbestblockhash())
def setup_network(self, split=False): if self.options.parent_bitcoin and self.options.parent_binpath == "": raise Exception( "Can't run with --parent_bitcoin without specifying --parent_binpath" ) self.nodes = [] # Setup parent nodes parent_chain = "parent" if not self.options.parent_bitcoin else "regtest" parent_binary = [self.options.parent_binpath ] if self.options.parent_binpath != "" else None for n in range(2): extra_args = [ "-port=" + str(p2p_port(n)), "-rpcport=" + str(rpc_port(n)) ] if self.options.parent_bitcoin: # bitcoind can't read elements.conf config files extra_args.extend([ "-regtest=1", "-printtoconsole=0", "-server=1", "-discover=0", "-keypool=1", "-listenonion=0", "-addresstype=legacy", # To make sure bitcoind gives back p2pkh no matter version ]) else: extra_args.extend([ "-validatepegin=0", "-initialfreecoins=0", "-anyonecanspendaremine", "-signblockscript=51", # OP_TRUE '-con_blocksubsidy=5000000000', ]) self.add_nodes(1, [extra_args], chain=[parent_chain], binary=parent_binary, chain_in_args=[not self.options.parent_bitcoin]) self.start_node(n) print("Node {} started".format(n)) connect_nodes_bi(self.nodes, 0, 1) self.parentgenesisblockhash = self.nodes[0].getblockhash(0) if not self.options.parent_bitcoin: parent_pegged_asset = self.nodes[0].getsidechaininfo( )['pegged_asset'] # Setup sidechain nodes self.fedpeg_script = "512103dff4923d778550cc13ce0d887d737553b4b58f4e8e886507fc39f5e447b2186451ae" for n in range(2): extra_args = [ "-printtoconsole=0", "-port=" + str(p2p_port(2 + n)), "-rpcport=" + str(rpc_port(2 + n)), '-parentgenesisblockhash=%s' % self.parentgenesisblockhash, '-validatepegin=1', '-fedpegscript=%s' % self.fedpeg_script, '-anyonecanspendaremine=0', '-minrelaytxfee=0', '-blockmintxfee=0', '-initialfreecoins=0', '-peginconfirmationdepth=10', '-mainchainrpchost=127.0.0.1', '-mainchainrpcport=%s' % rpc_port(n), '-recheckpeginblockinterval=15', # Long enough to allow failure and repair before timeout '-parentpubkeyprefix=111', '-parentscriptprefix=196', ] if not self.options.parent_bitcoin: extra_args.extend([ '-parentpubkeyprefix=111', '-parentscriptprefix=196', '-con_parent_chain_signblockscript=51', '-con_parent_pegged_asset=%s' % parent_pegged_asset, ]) # Use rpcuser auth only for first parent. if n == 0: # Extract username and password from cookie file and use directly. datadir = get_datadir_path(self.options.tmpdir, n) rpc_u, rpc_p = get_auth_cookie(datadir, parent_chain) extra_args.extend([ '-mainchainrpcuser=%s' % rpc_u, '-mainchainrpcpassword=%s' % rpc_p, ]) else: # Need to specify where to find parent cookie file datadir = get_datadir_path(self.options.tmpdir, n) extra_args.append('-mainchainrpccookiefile=' + datadir + "/" + parent_chain + "/.cookie") self.add_nodes(1, [extra_args], chain=["sidechain"]) self.start_node(2 + n) print("Node {} started".format(2 + n)) # We only connect the same-chain nodes, so sync_all works correctly connect_nodes_bi(self.nodes, 2, 3) self.node_groups = [[self.nodes[0], self.nodes[1]], [self.nodes[2], self.nodes[3]]] self.sync_all(self.node_groups) print("Setting up network done")
def setup_chain(self): super().setup_chain() # 0 => Username # 1 => Password (Hashed) # 2 => Permissions # 3 => Password Plaintext self.users = [ [ "user1", "50358aa884c841648e0700b073c32b2e$b73e95fff0748cc0b517859d2ca47d9bac1aa78231f3e48fa9222b612bd2083e", "getbestblockhash,getblockcount,", "12345" ], [ "user2", "8650ba41296f62092377a38547f361de$4620db7ba063ef4e2f7249853e9f3c5c3592a9619a759e3e6f1c63f2e22f1d21", "getblockcount", "54321" ] ] # For exceptions self.strange_users = [ # Test empty [ "strangedude", "62d67dffec03836edd698314f1b2be62$c2fb4be29bb0e3646298661123cf2d8629640979cabc268ef05ea613ab54068d", ":", "s7R4nG3R7H1nGZ" ], [ "strangedude2", "575c012c7fe4b1e83b9d809412da3ef7$09f448d0acfc19924dd62ecb96004d3c2d4b91f471030dfe43c6ea64a8f658c1", "", "s7R4nG3R7H1nGZ" ], # Test trailing comma [ "strangedude3", "23189c561b5975a56f4cf94030495d61$3a2f6aac26351e2257428550a553c4c1979594e36675bbd3db692442387728c0", ":getblockcount,", "s7R4nG3R7H1nGZ" ], # Test overwrite [ "strangedude4", "990c895760a70df83949e8278665e19a$8f0906f20431ff24cb9e7f5b5041e4943bdf2a5c02a19ef4960dcf45e72cde1c", ":getblockcount, getbestblockhash", "s7R4nG3R7H1nGZ" ], [ "strangedude4", "990c895760a70df83949e8278665e19a$8f0906f20431ff24cb9e7f5b5041e4943bdf2a5c02a19ef4960dcf45e72cde1c", ":getblockcount", "s7R4nG3R7H1nGZ" ], # Testing the same permission twice [ "strangedude5", "d12c6e962d47a454f962eb41225e6ec8$2dd39635b155536d3c1a2e95d05feff87d5ba55f2d5ff975e6e997a836b717c9", ":getblockcount,getblockcount", "s7R4nG3R7H1nGZ" ] ] # These commands shouldn't be allowed for any user to test failures self.never_allowed = ["getnetworkinfo"] with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "readercoin.conf"), 'a', encoding='utf8') as f: f.write("\nrpcwhitelistdefault=0\n") for user in self.users: f.write("rpcauth=" + user[0] + ":" + user[1] + "\n") f.write("rpcwhitelist=" + user[0] + ":" + user[2] + "\n") # Special cases for strangedude in self.strange_users: f.write("rpcauth=" + strangedude[0] + ":" + strangedude[1] + "\n") f.write("rpcwhitelist=" + strangedude[0] + strangedude[2] + "\n")
def setup_network(self, split=False): if self.options.parent_bitcoin and self.options.parent_binpath == "": raise Exception( "Can't run with --parent_bitcoin without specifying --parent_binpath" ) self.nodes = [] # Setup parent nodes parent_chain = "elementsregtest" if not self.options.parent_bitcoin else "regtest" parent_binary = [self.options.parent_binpath ] if self.options.parent_binpath != "" else None for n in range(2): extra_args = [ "-port=" + str(p2p_port(n)), "-rpcport=" + str(rpc_port(n)) ] if self.options.parent_bitcoin: # bitcoind can't read elements.conf config files extra_args.extend([ "-regtest=1", "-printtoconsole=0", "-server=1", "-discover=0", "-keypool=1", "-listenonion=0", "-addresstype=legacy", # To make sure bitcoind gives back p2pkh no matter version "-fallbackfee=0.0002" ]) else: extra_args.extend([ "-validatepegin=0", "-initialfreecoins=0", "-anyonecanspendaremine=1", "-signblockscript=51", # OP_TRUE ]) self.add_nodes(1, [extra_args], chain=[parent_chain], binary=parent_binary, chain_in_args=[not self.options.parent_bitcoin]) self.start_node(n) print("Node {} started".format(n)) # set hard-coded mining keys for non-Elements chains if self.options.parent_bitcoin: self.nodes[0].set_deterministic_priv_key( '2Mysp7FKKe52eoC2JmU46irt1dt58TpCvhQ', 'cTNbtVJmhx75RXomhYWSZAafuNNNKPd1cr2ZiUcAeukLNGrHWjvJ') self.nodes[1].set_deterministic_priv_key( '2N19ZHF3nEzBXzkaZ3N5sVBJXQ8jZ7Udpg5', 'cRnDSw1JsjmYYEN6xxQvf5pqMENsRE584z6MdWfJ7v85c4ciitkk') connect_nodes_bi(self.nodes, 0, 1) self.parentgenesisblockhash = self.nodes[0].getblockhash(0) if not self.options.parent_bitcoin: parent_pegged_asset = self.nodes[0].getsidechaininfo( )['pegged_asset'] # Setup sidechain nodes self.fedpeg_script = "512103dff4923d778550cc13ce0d887d737553b4b58f4e8e886507fc39f5e447b2186451ae" for n in range(2): extra_args = [ "-printtoconsole=0", "-port=" + str(p2p_port(2 + n)), "-rpcport=" + str(rpc_port(2 + n)), '-validatepegin=1', '-fedpegscript=%s' % self.fedpeg_script, '-minrelaytxfee=0', '-blockmintxfee=0', '-initialfreecoins=0', '-peginconfirmationdepth=10', '-mainchainrpchost=127.0.0.1', '-mainchainrpcport=%s' % rpc_port(n), '-recheckpeginblockinterval=15', # Long enough to allow failure and repair before timeout '-parentgenesisblockhash=%s' % self.parentgenesisblockhash, '-parentpubkeyprefix=111', '-parentscriptprefix=196', '-parent_bech32_hrp=bcrt', # Turn of consistency checks that can cause assert when parent node stops # and a peg-in transaction fails this belt-and-suspenders check. '-checkmempool=0', ] if not self.options.parent_bitcoin: extra_args.extend([ '-parentpubkeyprefix=235', '-parentscriptprefix=75', '-parent_bech32_hrp=ert', '-con_parent_chain_signblockscript=51', '-con_parent_pegged_asset=%s' % parent_pegged_asset, ]) # Immediate activation of dynafed when requested versus "never" from conf if self.options.pre_transition or self.options.post_transition: extra_args.extend(["-con_dyna_deploy_start=-1"]) # Use rpcuser auth only for first parent. if n == 0: # Extract username and password from cookie file and use directly. datadir = get_datadir_path(self.options.tmpdir, n) rpc_u, rpc_p = get_auth_cookie(datadir, parent_chain) extra_args.extend([ '-mainchainrpcuser=%s' % rpc_u, '-mainchainrpcpassword=%s' % rpc_p, ]) else: # Need to specify where to find parent cookie file datadir = get_datadir_path(self.options.tmpdir, n) extra_args.append('-mainchainrpccookiefile=' + datadir + "/" + parent_chain + "/.cookie") self.add_nodes(1, [extra_args], chain=["elementsregtest"]) self.start_node(2 + n) print("Node {} started".format(2 + n)) # We only connect the same-chain nodes, so sync_all works correctly connect_nodes_bi(self.nodes, 2, 3) self.node_groups = [[self.nodes[0], self.nodes[1]], [self.nodes[2], self.nodes[3]]] self.sync_all(self.node_groups) print("Setting up network done")
def run_test(self): self.enable_mocktime() self.setup_3_masternodes_network() txHashSet = set([ self.mnOneCollateral.hash, self.mnTwoCollateral.hash, self.proRegTx1 ]) # check mn list from miner self.check_mn_list(self.miner, txHashSet) # check status of masternodes self.check_mns_status_legacy(self.remoteOne, self.mnOneCollateral.hash) self.log.info("MN1 active") self.check_mns_status_legacy(self.remoteTwo, self.mnTwoCollateral.hash) self.log.info("MN2 active") self.check_mns_status(self.remoteDMN1, self.proRegTx1) self.log.info("DMN1 active") # activate sporks self.activate_spork(self.minerPos, "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") self.activate_spork(self.minerPos, "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") self.activate_spork(self.minerPos, "SPORK_13_ENABLE_SUPERBLOCKS") nextSuperBlockHeight = self.miner.getnextsuperblock() # Submit first proposal self.log.info("preparing budget proposal..") firstProposal = Proposal("super-cool", "https://forum.pivx.org/t/test-proposal", 2, self.miner.getnewaddress(), 300) self.submit_proposals([firstProposal]) # Create 15 more proposals to have a higher tier two net gossip movement props = [] for i in range(15): props.append( Proposal("prop_" + str(i), "https://link_" + str(i) + ".com", 3, self.miner.getnewaddress(), 11 * (i + 1))) self.submit_proposals(props) # Proposals are established after 5 minutes. Mine 7 blocks # Proposal needs to be on the chain > 5 min. self.stake(7, [self.remoteOne, self.remoteTwo]) # Check proposals existence for i in range(self.num_nodes): assert_equal(len(self.nodes[i].getbudgetinfo()), 16) # now let's vote for the proposal with the first MN self.log.info("Voting with MN1...") voteResult = self.ownerOne.mnbudgetvote("alias", firstProposal.proposalHash, "yes", self.masternodeOneAlias, True) assert_equal(voteResult["detail"][0]["result"], "success") # check that the vote was accepted everywhere self.stake(1, [self.remoteOne, self.remoteTwo]) self.check_vote_existence(firstProposal.name, self.mnOneCollateral.hash, "YES", True) self.log.info("all good, MN1 vote accepted everywhere!") # now let's vote for the proposal with the second MN self.log.info("Voting with MN2...") voteResult = self.ownerTwo.mnbudgetvote("alias", firstProposal.proposalHash, "yes", self.masternodeTwoAlias, True) assert_equal(voteResult["detail"][0]["result"], "success") # check that the vote was accepted everywhere self.stake(1, [self.remoteOne, self.remoteTwo]) self.check_vote_existence(firstProposal.name, self.mnTwoCollateral.hash, "YES", True) self.log.info("all good, MN2 vote accepted everywhere!") # now let's vote for the proposal with the first DMN self.log.info("Voting with DMN1...") voteResult = self.ownerOne.mnbudgetvote("alias", firstProposal.proposalHash, "yes", self.proRegTx1) assert_equal(voteResult["detail"][0]["result"], "success") # check that the vote was accepted everywhere self.stake(1, [self.remoteOne, self.remoteTwo]) self.check_vote_existence(firstProposal.name, self.proRegTx1, "YES", True) self.log.info("all good, DMN1 vote accepted everywhere!") # Now check the budget blockStart = nextSuperBlockHeight blockEnd = blockStart + firstProposal.cycles * 145 TotalPayment = firstProposal.amountPerCycle * firstProposal.cycles Allotted = firstProposal.amountPerCycle RemainingPaymentCount = firstProposal.cycles expected_budget = [ self.get_proposal_obj(firstProposal.name, firstProposal.link, firstProposal.proposalHash, firstProposal.feeTxId, blockStart, blockEnd, firstProposal.cycles, RemainingPaymentCount, firstProposal.paymentAddr, 1, 3, 0, 0, satoshi_round(TotalPayment), satoshi_round(firstProposal.amountPerCycle), True, True, satoshi_round(Allotted), satoshi_round(Allotted)) ] self.check_budgetprojection(expected_budget) # Quick block count check. assert_equal(self.ownerOne.getblockcount(), 279) self.log.info("starting budget finalization sync test..") self.stake(2, [self.remoteOne, self.remoteTwo]) # assert that there is no budget finalization first. assert_equal(len(self.ownerOne.mnfinalbudget("show")), 0) # suggest the budget finalization and confirm the tx (+4 blocks). budgetFinHash = self.broadcastbudgetfinalization( self.miner, with_ping_mns=[self.remoteOne, self.remoteTwo]) assert (budgetFinHash != "") time.sleep(2) self.log.info("checking budget finalization sync..") self.check_budget_finalization_sync(0, "OK") self.log.info( "budget finalization synced!, now voting for the budget finalization.." ) voteResult = self.ownerOne.mnfinalbudget("vote-many", budgetFinHash, True) assert_equal(voteResult["detail"][0]["result"], "success") self.log.info("Remote One voted successfully.") voteResult = self.ownerTwo.mnfinalbudget("vote-many", budgetFinHash, True) assert_equal(voteResult["detail"][0]["result"], "success") self.log.info("Remote Two voted successfully.") voteResult = self.remoteDMN1.mnfinalbudget("vote", budgetFinHash) assert_equal(voteResult["detail"][0]["result"], "success") self.log.info("DMN voted successfully.") self.stake(2, [self.remoteOne, self.remoteTwo]) self.log.info("checking finalization votes..") self.check_budget_finalization_sync(3, "OK") self.stake(8, [self.remoteOne, self.remoteTwo]) addrInfo = self.miner.listreceivedbyaddress(0, False, False, firstProposal.paymentAddr) assert_equal(addrInfo[0]["amount"], firstProposal.amountPerCycle) self.log.info("budget proposal paid!, all good") # Check that the proposal info returns updated payment count expected_budget[0]["RemainingPaymentCount"] -= 1 self.check_budgetprojection(expected_budget) self.stake(1, [self.remoteOne, self.remoteTwo]) self.log.info("checking resync (1): cleaning budget data only..") # now let's drop budget data and try to re-sync it. self.remoteOne.cleanbudget(True) assert_equal( self.remoteOne.mnsync("status")["RequestedMasternodeAssets"], 0) assert_equal(self.remoteOne.getbudgetprojection(), []) # empty assert_equal(self.remoteOne.getbudgetinfo(), []) self.log.info("budget cleaned, starting resync") self.wait_until_mnsync_finished() self.check_budgetprojection(expected_budget) for i in range(self.num_nodes): assert_equal(len(self.nodes[i].getbudgetinfo()), 16) self.log.info("resync (1): budget data resynchronized successfully!") self.log.info( "checking resync (2): stop node, delete chain data and resync from scratch.." ) # stop and remove everything self.stop_node(self.ownerTwoPos) ownerTwoDir = os.path.join( get_datadir_path(self.options.tmpdir, self.ownerTwoPos), "regtest") for entry in [ 'chainstate', 'blocks', 'sporks', 'evodb', 'zerocoin', "mncache.dat", "budget.dat", "mnpayments.dat", "peers.dat" ]: rem_path = os.path.join(ownerTwoDir, entry) shutil.rmtree(rem_path) if os.path.isdir(rem_path) else os.remove( rem_path) self.log.info("restarting node..") self.start_node(self.ownerTwoPos) self.ownerTwo.setmocktime(self.mocktime) for i in range(self.num_nodes): if i is not self.ownerTwoPos: self.connect_nodes_bi(self.nodes, self.ownerTwoPos, i) self.stake(2, [self.remoteOne, self.remoteTwo]) self.log.info("syncing node..") self.wait_until_mnsync_finished() for i in range(self.num_nodes): assert_equal(len(self.nodes[i].getbudgetinfo()), 16) self.log.info("resync (2): budget data resynchronized successfully!") # now let's verify that votes expire properly. # Drop one MN and one DMN self.log.info("expiring MN1..") self.spend_collateral(self.ownerOne, self.mnOneCollateral, self.miner) self.wait_until_mn_vinspent(self.mnOneCollateral.hash, 30, [self.remoteTwo]) self.stake(15, [self.remoteTwo]) # create blocks to remove staled votes time.sleep(2) # wait a little bit self.check_vote_existence(firstProposal.name, self.mnOneCollateral.hash, "YES", False) self.log.info("MN1 vote expired after collateral spend, all good") self.log.info("expiring DMN1..") lm = self.ownerOne.listmasternodes(self.proRegTx1)[0] self.spend_collateral( self.ownerOne, COutPoint(lm["collateralHash"], lm["collateralIndex"]), self.miner) self.wait_until_mn_vinspent(self.proRegTx1, 30, [self.remoteTwo]) self.stake(15, [self.remoteTwo]) # create blocks to remove staled votes time.sleep(2) # wait a little bit self.check_vote_existence(firstProposal.name, self.proRegTx1, "YES", False) self.log.info("DMN vote expired after collateral spend, all good") # Check that the budget is removed 200 blocks after the last payment assert_equal(len(self.miner.mnfinalbudget("show")), 1) blocks_to_mine = nextSuperBlockHeight + 200 - self.miner.getblockcount( ) self.log.info( "Mining %d more blocks to check expired budget removal..." % blocks_to_mine) self.stake(blocks_to_mine - 1, [self.remoteTwo]) # finalized budget must still be there self.miner.checkbudgets() assert_equal(len(self.miner.mnfinalbudget("show")), 1) # after one more block it must be removed self.stake(1, [self.remoteTwo]) self.miner.checkbudgets() assert_equal(len(self.miner.mnfinalbudget("show")), 0) self.log.info("All good.")
def setup_chain(self): super().setup_chain() self.authinfo = [] #Append rpcauth to bitcoin.conf before initialization self.rtpassword = "******" rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" self.rpcuser = "******" self.rpcpassword = "******" config = configparser.ConfigParser() config.read_file(open(self.options.configfile)) gen_rpcauth = config['environment']['RPCAUTH'] # Generate RPCAUTH with specified password self.rt2password = "******" p = subprocess.Popen([sys.executable, gen_rpcauth, 'rt2', self.rt2password], stdout=subprocess.PIPE, universal_newlines=True) lines = p.stdout.read().splitlines() rpcauth2 = lines[1] # Generate RPCAUTH without specifying password self.user = ''.join(SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10)) p = subprocess.Popen([sys.executable, gen_rpcauth, self.user], stdout=subprocess.PIPE, universal_newlines=True) lines = p.stdout.read().splitlines() rpcauth3 = lines[1] self.password = lines[3] # Generate rpcauthfile with one entry username = '******' + ''.join(SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10)) p = subprocess.Popen([sys.executable, gen_rpcauth, "--output", os.path.join(self.options.tmpdir, "rpcauth_single"), username], stdout=subprocess.PIPE, universal_newlines=True) lines = p.stdout.read().splitlines() self.authinfo.append( (username, lines[1]) ) # Generate rpcauthfile with two entries username = '******' + ''.join(SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10)) p = subprocess.Popen([sys.executable, gen_rpcauth, "--output", os.path.join(self.options.tmpdir, "rpcauth_multi"), username], stdout=subprocess.PIPE, universal_newlines=True) lines = p.stdout.read().splitlines() self.authinfo.append( (username, lines[1]) ) # Blank lines in between should get ignored with open(os.path.join(self.options.tmpdir, "rpcauth_multi"), "a", encoding='utf8') as f: f.write("\n\n") username = '******' + ''.join(SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10)) p = subprocess.Popen([sys.executable, gen_rpcauth, "--output", os.path.join(self.options.tmpdir, "rpcauth_multi"), username], stdout=subprocess.PIPE, universal_newlines=True) lines = p.stdout.read().splitlines() self.authinfo.append( (username, lines[1]) ) # Hand-generated rpcauthfile with one entry and no newline username = '******' + ''.join(SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10)) p = subprocess.Popen([sys.executable, gen_rpcauth, username], stdout=subprocess.PIPE, universal_newlines=True) lines = p.stdout.read().splitlines() assert "\n" not in lines[1] assert lines[1][:8] == 'rpcauth=' with open(os.path.join(self.options.tmpdir, "rpcauth_nonewline"), "a", encoding='utf8') as f: f.write(lines[1][8:]) self.authinfo.append( (username, lines[3]) ) with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "bitcoin.conf"), 'a', encoding='utf8') as f: f.write(rpcauth + "\n") f.write(rpcauth2 + "\n") f.write(rpcauth3 + "\n") f.write("rpcauthfile=rpcauth_single\n") f.write("rpcauthfile=rpcauth_multi\n") f.write("rpcauthfile=rpcauth_nonewline\n") with open(os.path.join(get_datadir_path(self.options.tmpdir, 1), "bitcoin.conf"), 'a', encoding='utf8') as f: f.write("rpcuser={}\n".format(self.rpcuser)) f.write("rpcpassword={}\n".format(self.rpcpassword))
def run_test(self): block_count = 0 # Create a P2P connections node0 = NodeConnCB() connection0 = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0) node0.add_connection(connection0) node1 = NodeConnCB() connection1 = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node1) node1.add_connection(connection1) # *** Prepare node connection for early announcements testing node2 = NodeConnCB() node2.add_connection( NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node2)) NetworkThread().start() # wait_for_verack ensures that the P2P connection is fully up. node0.wait_for_verack() node1.wait_for_verack() # *** Activate early announcement functionality for this connection # After this point the early announcements are not received yet - # we still need to set latest announced block (CNode::pindexBestKnownBlock) # which is set for e.g. by calling best headers message with locator # set to non-null node2.wait_for_verack() node2.send_message(msg_sendcmpct(announce=True)) self.chain.set_genesis_hash(int(self.nodes[0].getbestblockhash(), 16)) _, outs, block_count = prepare_init_chain(self.chain, 101, 1, block_0=False, start_block=0, node=node0) out = outs[0] self.log.info("waiting for block height 101 via rpc") self.nodes[0].waitforblockheight(101) tip_block_num = block_count - 1 # adding extra transactions to get different block hashes block2_hard = self.chain.next_block(block_count, spend=out, extra_txns=8) block_count += 1 self.chain.set_tip(tip_block_num) block3_easier = self.chain.next_block(block_count, spend=out, extra_txns=2) block_count += 1 self.chain.set_tip(tip_block_num) block4_hard = self.chain.next_block(block_count, spend=out, extra_txns=10) block_count += 1 # send three "hard" blocks, with waitaftervalidatingblock we artificially # extend validation time. self.log.info(f"hard block2 hash: {block2_hard.hash}") self.nodes[0].waitaftervalidatingblock(block2_hard.hash, "add") self.log.info(f"hard block4 hash: {block4_hard.hash}") self.nodes[0].waitaftervalidatingblock(block4_hard.hash, "add") # make sure block hashes are in waiting list wait_for_waiting_blocks({block2_hard.hash, block4_hard.hash}, self.nodes[0], self.log) # *** Complete early announcement setup by sending getheaders message # with a non-null locator (pointing to the last block that we know # of on python side - we claim that we know of all the blocks that # bitcoind node knows of) # # We also set on_cmpctblock handler as early announced blocks are # announced via compact block messages instead of inv messages node2.send_and_ping( msg_getheaders( locator_have=[int(self.nodes[0].getbestblockhash(), 16)])) receivedAnnouncement = False waiting_for_announcement_block_hash = block2_hard.sha256 def on_cmpctblock(conn, message): nonlocal receivedAnnouncement message.header_and_shortids.header.calc_sha256() if message.header_and_shortids.header.sha256 == waiting_for_announcement_block_hash: receivedAnnouncement = True node2.on_cmpctblock = on_cmpctblock # send one block via p2p and one via rpc node0.send_message(msg_block(block2_hard)) # *** make sure that we receive announcement of the block before it has # been validated wait_until(lambda: receivedAnnouncement) # making rpc call submitblock in a separate thread because waitaftervalidation is blocking # the return of submitblock submitblock_thread = threading.Thread(target=self.nodes[0].submitblock, args=(ToHex(block4_hard), )) submitblock_thread.start() # because self.nodes[0] rpc is blocked we use another rpc client rpc_client = get_rpc_proxy(rpc_url( get_datadir_path(self.options.tmpdir, 0), 0), 0, coveragedir=self.options.coveragedir) wait_for_validating_blocks({block2_hard.hash, block4_hard.hash}, rpc_client, self.log) # *** prepare to intercept block3_easier announcement - it will not be # announced before validation is complete as early announcement is # limited to announcing one block per height (siblings are ignored) # but after validation is complete we should still get the announcing # compact block message receivedAnnouncement = False waiting_for_announcement_block_hash = block3_easier.sha256 self.log.info(f"easy block3 hash: {block3_easier.hash}") node1.send_message(msg_block(block3_easier)) # *** Make sure that we receive compact block announcement of the block # after the validation is complete even though it was not the first # block that was received by bitcoind node. # # Also make sure that we receive inv announcement of the block after # the validation is complete by the nodes that are not using early # announcement functionality. wait_until(lambda: receivedAnnouncement) node0.wait_for_inv([CInv(CInv.BLOCK, block3_easier.sha256)]) # node 1 was the sender but receives inv for block non the less # (with early announcement that's not the case - sender does not receive the announcement) node1.wait_for_inv([CInv(CInv.BLOCK, block3_easier.sha256)]) rpc_client.waitforblockheight(102) assert_equal(block3_easier.hash, rpc_client.getbestblockhash()) # now we can remove waiting status from blocks and finish their validation rpc_client.waitaftervalidatingblock(block2_hard.hash, "remove") rpc_client.waitaftervalidatingblock(block4_hard.hash, "remove") submitblock_thread.join() # wait till validation of block or blocks finishes node0.sync_with_ping() # easier block should still be on tip assert_equal(block3_easier.hash, self.nodes[0].getbestblockhash())
def run_test(self): block_count = 0 # Create a P2P connections node0 = NodeConnCB() connection = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0) node0.add_connection(connection) node1 = NodeConnCB() connection = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node1) node1.add_connection(connection) NetworkThread().start() # wait_for_verack ensures that the P2P connection is fully up. node0.wait_for_verack() node1.wait_for_verack() self.chain.set_genesis_hash(int(self.nodes[0].getbestblockhash(), 16)) _, outs, block_count = prepare_init_chain(self.chain, 101, 1, block_0=False, start_block=0, node=node0) out = outs[0] self.log.info("waiting for block height 101 via rpc") self.nodes[0].waitforblockheight(101) tip_block_num = block_count - 1 # adding extra transactions to get different block hashes block2_hard = self.chain.next_block(block_count, spend=out, extra_txns=8) block_count += 1 self.chain.set_tip(tip_block_num) block3_easier = self.chain.next_block(block_count, spend=out, extra_txns=2) block_count += 1 mining_candidate = self.nodes[0].getminingcandidate() block4_hard = self.chain.next_block(block_count) block4_hard.hashPrevBlock = int(mining_candidate["prevhash"], 16) block4_hard.nTime = mining_candidate["time"] block4_hard.nVersion = mining_candidate["version"] block4_hard.solve() mining_solution = {"id": mining_candidate["id"], "nonce": block4_hard.nNonce, "coinbase": ToHex(block4_hard.vtx[0]), "time": mining_candidate["time"], "version": mining_candidate["version"]} # send three "hard" blocks, with waitaftervalidatingblock we artificially # extend validation time. self.log.info(f"hard block2 hash: {block2_hard.hash}") self.nodes[0].waitaftervalidatingblock(block2_hard.hash, "add") self.log.info(f"hard block4 hash: {block4_hard.hash}") self.nodes[0].waitaftervalidatingblock(block4_hard.hash, "add") # make sure block hashes are in waiting list wait_for_waiting_blocks({block2_hard.hash, block4_hard.hash}, self.nodes[0], self.log) # send one block via p2p and one via rpc node0.send_message(msg_block(block2_hard)) # making rpc call submitminingsolution in a separate thread because waitaftervalidation is blocking # the return of submitminingsolution submitminingsolution_thread = threading.Thread(target=self.nodes[0].submitminingsolution, args=(mining_solution,)) submitminingsolution_thread.start() # because self.nodes[0] rpc is blocked we use another rpc client rpc_client = get_rpc_proxy(rpc_url(get_datadir_path(self.options.tmpdir, 0), 0), 0, coveragedir=self.options.coveragedir) wait_for_validating_blocks({block2_hard.hash, block4_hard.hash}, rpc_client, self.log) self.log.info(f"easy block3 hash: {block3_easier.hash}") node1.send_message(msg_block(block3_easier)) rpc_client.waitforblockheight(102) assert_equal(block3_easier.hash, rpc_client.getbestblockhash()) # now we can remove waiting status from blocks and finish their validation rpc_client.waitaftervalidatingblock(block2_hard.hash, "remove") rpc_client.waitaftervalidatingblock(block4_hard.hash, "remove") submitminingsolution_thread.join() # wait till validation of block or blocks finishes node0.sync_with_ping() # easier block should still be on tip assert_equal(block3_easier.hash, self.nodes[0].getbestblockhash())
def setup_network(self, split=False): if self.options.parent_bitcoin and self.options.parent_binpath == "": raise Exception("Can't run with --parent_bitcoin without specifying --parent_binpath") self.nodes = [] # Setup parent nodes parent_chain = "parent" if not self.options.parent_bitcoin else "regtest" parent_binary = [self.options.parent_binpath] if self.options.parent_binpath != "" else None for n in range(2): extra_args = [ "-port="+str(p2p_port(n)), "-rpcport="+str(rpc_port(n)) ] if self.options.parent_bitcoin: # bitcoind can't read elements.conf config files extra_args.extend([ "-regtest=1", "-printtoconsole=0", "-server=1", "-discover=0", "-keypool=1", "-listenonion=0", "-addresstype=legacy", # To make sure bitcoind gives back p2pkh no matter version ]) else: extra_args.extend([ "-validatepegin=0", "-initialfreecoins=0", "-anyonecanspendaremine", "-signblockscript=51", # OP_TRUE '-con_blocksubsidy=5000000000', "-pubkeyprefix=111", "-scriptprefix=196", ]) self.add_nodes(1, [extra_args], chain=[parent_chain], binary=parent_binary, chain_in_args=[not self.options.parent_bitcoin]) self.start_node(n) print("Node {} started".format(n)) connect_nodes_bi(self.nodes, 0, 1) self.parentgenesisblockhash = self.nodes[0].getblockhash(0) if not self.options.parent_bitcoin: parent_pegged_asset = self.nodes[0].getsidechaininfo()['pegged_asset'] # Setup sidechain nodes self.fedpeg_script = "512103dff4923d778550cc13ce0d887d737553b4b58f4e8e886507fc39f5e447b2186451ae" for n in range(2): extra_args = [ "-printtoconsole=0", "-port="+str(p2p_port(2+n)), "-rpcport="+str(rpc_port(2+n)), '-parentgenesisblockhash=%s' % self.parentgenesisblockhash, '-validatepegin=1', '-fedpegscript=%s' % self.fedpeg_script, '-anyonecanspendaremine=0', '-minrelaytxfee=0', '-blockmintxfee=0', '-initialfreecoins=0', '-peginconfirmationdepth=10', '-mainchainrpchost=127.0.0.1', '-mainchainrpcport=%s' % rpc_port(n), '-recheckpeginblockinterval=15', # Long enough to allow failure and repair before timeout '-parentpubkeyprefix=111', '-parentscriptprefix=196', # Turn of consistency checks that can cause assert when parent node stops # and a peg-in transaction fails this belt-and-suspenders check. '-checkmempool=0', ] if not self.options.parent_bitcoin: extra_args.extend([ '-parentpubkeyprefix=111', '-parentscriptprefix=196', "-parent_bech32_hrp=ert", '-con_parent_chain_signblockscript=51', '-con_parent_pegged_asset=%s' % parent_pegged_asset, ]) # Use rpcuser auth only for first parent. if n==0: # Extract username and password from cookie file and use directly. datadir = get_datadir_path(self.options.tmpdir, n) rpc_u, rpc_p = get_auth_cookie(datadir, parent_chain) extra_args.extend([ '-mainchainrpcuser=%s' % rpc_u, '-mainchainrpcpassword=%s' % rpc_p, ]) else: # Need to specify where to find parent cookie file datadir = get_datadir_path(self.options.tmpdir, n) extra_args.append('-mainchainrpccookiefile='+datadir+"/" + parent_chain + "/.cookie") self.add_nodes(1, [extra_args], chain=["sidechain"]) self.start_node(2+n) print("Node {} started".format(2+n)) # We only connect the same-chain nodes, so sync_all works correctly connect_nodes_bi(self.nodes, 2, 3) self.node_groups = [[self.nodes[0], self.nodes[1]], [self.nodes[2], self.nodes[3]]] self.sync_all(self.node_groups) print("Setting up network done")
# Generate RPCAUTH with specified password self.rt2password = "******" p = subprocess.Popen([sys.executable, gen_rpcauth, 'rt2', self.rt2password], stdout=subprocess.PIPE, universal_newlines=True) lines = p.stdout.read().splitlines() rpcauth2 = lines[1] # Generate RPCAUTH without specifying password self.user = ''.join(SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10)) p = subprocess.Popen([sys.executable, gen_rpcauth, self.user], stdout=subprocess.PIPE, universal_newlines=True) lines = p.stdout.read().splitlines() rpcauth3 = lines[1] self.password = lines[3] <<<<<<< HEAD with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "Actinium.conf"), 'a', encoding='utf8') as f: f.write(rpcauth+"\n") f.write(rpcauth2+"\n") f.write(rpcauth3+"\n") ======= with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "bitcoin.conf"), 'a', encoding='utf8') as f: f.write(rpcauth + "\n") f.write(rpcauth2 + "\n") f.write(rpcauth3 + "\n") >>>>>>> b5c423c48e094bd098e11c3d1f57acae7502a4da with open(os.path.join(get_datadir_path(self.options.tmpdir, 1), "bitcoin.conf"), 'a', encoding='utf8') as f: f.write("rpcuser={}\n".format(self.rpcuser)) f.write("rpcpassword={}\n".format(self.rpcpassword)) def test_auth(self, node, user, password): self.log.info('Correct...')