示例#1
0
    def run_test(self):
        assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
        assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2)

        self.nodes[0].setnetworkactive(False)
        assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], False)
        timeout = 3
        while self.nodes[0].getnetworkinfo()['connections'] != 0:
            # Wait a bit for all sockets to close
            assert timeout > 0, 'not all connections closed in time'
            timeout -= 0.1
            time.sleep(0.1)

        self.nodes[0].setnetworkactive(True)
        connect_nodes_bi(self.nodes, 0, 1)
        assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
        assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2)

        # test getaddednodeinfo
        assert_equal(self.nodes[0].getaddednodeinfo(), [])
        # add a node (node2) to node0
        ip_port = "127.0.0.1:{}".format(p2p_port(2))
        self.nodes[0].addnode(ip_port, 'add')
        # check that the node has indeed been added
        added_nodes = self.nodes[0].getaddednodeinfo(ip_port)
        assert_equal(len(added_nodes), 1)
        assert_equal(added_nodes[0]['addednode'], ip_port)
        # check that a non-existant node returns an error
        assert_raises_jsonrpc(-24, "Node has not been added",
                              self.nodes[0].getaddednodeinfo, '1.1.1.1')
示例#2
0
    def run_test (self):
        tmpdir = self.options.tmpdir

        # Make sure can't switch off usehd after wallet creation
        self.stop_node(1)
        assert_start_raises_init_error(1, self.options.tmpdir, ['-usehd=0'], 'already existing HD wallet')
        self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1])
        connect_nodes_bi(self.nodes, 0, 1)

        # Make sure we use hd, keep masterkeyid
        masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
        assert_equal(len(masterkeyid), 40)

        # Import a non-HD private key in the HD wallet
        non_hd_add = self.nodes[0].getnewaddress()
        self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add))

        # This should be enough to keep the master key and the non-HD key 
        self.nodes[1].backupwallet(tmpdir + "/hd.bak")
        #self.nodes[1].dumpwallet(tmpdir + "/hd.dump")

        # Derive some HD addresses and remember the last
        # Also send funds to each add
        self.nodes[0].generate(101)
        hd_add = None
        num_hd_adds = 300
        for i in range(num_hd_adds):
            hd_add = self.nodes[1].getnewaddress()
            hd_info = self.nodes[1].validateaddress(hd_add)
            assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i+1)+"'")
            assert_equal(hd_info["hdmasterkeyid"], masterkeyid)
            self.nodes[0].sendtoaddress(hd_add, 1)
            self.nodes[0].generate(1)
        self.nodes[0].sendtoaddress(non_hd_add, 1)
        self.nodes[0].generate(1)

        self.sync_all()
        assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)

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

        # Assert that derivation is deterministic
        hd_add_2 = None
        for _ in range(num_hd_adds):
            hd_add_2 = self.nodes[1].getnewaddress()
            hd_info_2 = self.nodes[1].validateaddress(hd_add_2)
            assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(_+1)+"'")
            assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid)
        assert_equal(hd_add, hd_add_2)

        # Needs rescan
        self.stop_node(1)
        self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1] + ['-rescan'])
        #connect_nodes_bi(self.nodes, 0, 1)
        assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
示例#3
0
 def restart_second_node(self, extra_args=[]):
     self.nodes[1].stop()
     bitcoind_processes[1].wait()
     self.nodes[1] = start_node(1, self.options.tmpdir, extra_args=['-regtestprotectcoinbase','-debug=zrpc'] + extra_args)
     self.nodes[1].setmocktime(starttime + 9000)
     connect_nodes_bi(self.nodes, 0, 1)
     self.sync_all()
示例#4
0
文件: turnstile.py 项目: zcash/zcash
 def setup_network(self, split=False):
     self.nodes = start_nodes(3, self.options.tmpdir,
         extra_args=[NUPARAMS_ARGS] * 3)
     connect_nodes_bi(self.nodes,0,1)
     connect_nodes_bi(self.nodes,1,2)
     self.is_network_split=False
     self.sync_all()
    def run_test(self):
        self.log.info("test -blocknotify")
        block_count = 10
        blocks = self.nodes[1].generatetoaddress(block_count, self.nodes[1].getnewaddress() if self.is_wallet_compiled() else ADDRESS_BCRT1_UNSPENDABLE)

        # wait at most 10 seconds for expected number of files before reading the content
        wait_until(lambda: len(os.listdir(self.blocknotify_dir)) == block_count, timeout=10)

        # directory content should equal the generated blocks hashes
        assert_equal(sorted(blocks), sorted(os.listdir(self.blocknotify_dir)))

        if self.is_wallet_compiled():
            self.log.info("test -walletnotify")
            # wait at most 10 seconds for expected number of files before reading the content
            wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)

            # directory content should equal the generated transaction hashes
            txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
            assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
            self.stop_node(1)
            for tx_file in os.listdir(self.walletnotify_dir):
                os.remove(os.path.join(self.walletnotify_dir, tx_file))

            self.log.info("test -walletnotify after rescan")
            # restart node to rescan to force wallet notifications
            self.start_node(1)
            connect_nodes_bi(self.nodes, 0, 1)

            wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)

            # directory content should equal the generated transaction hashes
            txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
            assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
    def setup_network(self):
        self.setup_nodes()

        # Fully mesh-connect nodes for faster mempool sync
        for i, j in itertools.product(range(self.num_nodes), repeat=2):
            if i > j:
                connect_nodes_bi(self.nodes, i, j)
        self.sync_all()
示例#7
0
 def setup_network(self, split=False):
     self.nodes = start_nodes(5, self.options.tmpdir )
     connect_nodes_bi(self.nodes,0,1)
     connect_nodes_bi(self.nodes,1,2)
     connect_nodes_bi(self.nodes,0,2)
     connect_nodes_bi(self.nodes,0,3)
     connect_nodes_bi(self.nodes,0,4)
     self.is_network_split=False
     self.sync_all()
示例#8
0
    def run_test(self):
        ###########################
        # setban/listbanned tests #
        ###########################
        assert_equal(len(self.nodes[1].getpeerinfo()), 2)  # node1 should have 2 connections to node0 at this point
        self.nodes[1].setban("127.0.0.1", "add")
        assert wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0, timeout=10)
        assert_equal(len(self.nodes[1].getpeerinfo()), 0)  # all nodes must be disconnected at this point
        assert_equal(len(self.nodes[1].listbanned()), 1)
        self.nodes[1].clearbanned()
        assert_equal(len(self.nodes[1].listbanned()), 0)
        self.nodes[1].setban("127.0.0.0/24", "add")
        assert_equal(len(self.nodes[1].listbanned()), 1)
        # This will throw an exception because 127.0.0.1 is within range 127.0.0.0/24
        assert_raises_jsonrpc(-23, "IP/Subnet already banned", self.nodes[1].setban, "127.0.0.1", "add")
        # This will throw an exception because 127.0.0.1/42 is not a real subnet
        assert_raises_jsonrpc(-30, "Error: Invalid IP/Subnet", self.nodes[1].setban, "127.0.0.1/42", "add")
        assert_equal(len(self.nodes[1].listbanned()), 1)  # still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24
        # This will throw an exception because 127.0.0.1 was not added above
        assert_raises_jsonrpc(-30, "Error: Unban failed", self.nodes[1].setban, "127.0.0.1", "remove")
        assert_equal(len(self.nodes[1].listbanned()), 1)
        self.nodes[1].setban("127.0.0.0/24", "remove")
        assert_equal(len(self.nodes[1].listbanned()), 0)
        self.nodes[1].clearbanned()
        assert_equal(len(self.nodes[1].listbanned()), 0)

        # test persisted banlist
        self.nodes[1].setban("127.0.0.0/32", "add")
        self.nodes[1].setban("127.0.0.0/24", "add")
        self.nodes[1].setban("192.168.0.1", "add", 1)  # ban for 1 seconds
        self.nodes[1].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000)  # ban for 1000 seconds
        listBeforeShutdown = self.nodes[1].listbanned()
        assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address'])
        assert wait_until(lambda: len(self.nodes[1].listbanned()) == 3, timeout=10)

        stop_node(self.nodes[1], 1)

        self.nodes[1] = start_node(1, self.options.tmpdir)
        listAfterShutdown = self.nodes[1].listbanned()
        assert_equal("127.0.0.0/24", listAfterShutdown[0]['address'])
        assert_equal("127.0.0.0/32", listAfterShutdown[1]['address'])
        assert_equal("/19" in listAfterShutdown[2]['address'], True)

        # Clear ban lists
        self.nodes[1].clearbanned()
        connect_nodes_bi(self.nodes, 0, 1)

        ###########################
        # RPC disconnectnode test #
        ###########################
        address1 = self.nodes[0].getpeerinfo()[0]['addr']
        self.nodes[0].disconnectnode(address=address1)
        assert wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10)
        assert not [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]

        connect_nodes_bi(self.nodes, 0, 1)  # reconnect the node
        assert [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
示例#9
0
 def setup_network(self):
     ''' Can't rely on syncing all the nodes when staking=1
     :param:
     :return:
     '''
     self.setup_nodes()
     for i in range(self.num_nodes - 1):
         for j in range(i+1, self.num_nodes):
             connect_nodes_bi(self.nodes, i, j)
示例#10
0
 def setup_network(self, split=False):
     self.nodes = start_nodes(3, self.options.tmpdir,
         extra_args=[[
             '-nuparams=5ba81b19:100', # Overwinter
             '-nuparams=76b809bb:201', # Sapling
         ]] * 3)
     connect_nodes_bi(self.nodes,0,1)
     connect_nodes_bi(self.nodes,1,2)
     self.is_network_split=False
     self.sync_all()
    def run_test(self):
        self.log.info("test -blocknotify")
        block_count = 10
        blocks = self.nodes[1].generate(block_count)

        # wait at most 10 seconds for expected file size before reading the content
        wait_until(lambda: os.path.isfile(self.block_filename) and os.stat(self.block_filename).st_size >= (block_count * 65), timeout=10)

        # file content should equal the generated blocks hashes
        with open(self.block_filename, 'r', encoding="utf-8") as f:
            assert_equal(sorted(blocks), sorted(l.strip() for l in f.read().splitlines()))

        self.log.info("test -walletnotify")
        # wait at most 10 seconds for expected file size before reading the content
        wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat(self.tx_filename).st_size >= (block_count * 65), timeout=10)

        # file content should equal the generated transaction hashes
        txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
        with open(self.tx_filename, 'r', encoding="ascii") as f:
            assert_equal(sorted(txids_rpc), sorted(l.strip() for l in f.read().splitlines()))
        os.remove(self.tx_filename)

        self.log.info("test -walletnotify after rescan")
        # restart node to rescan to force wallet notifications
        self.restart_node(1)
        connect_nodes_bi(self.nodes, 0, 1)

        wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat(self.tx_filename).st_size >= (block_count * 65), timeout=10)

        # file content should equal the generated transaction hashes
        txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
        with open(self.tx_filename, 'r', encoding="ascii") as f:
            assert_equal(sorted(txids_rpc), sorted(l.strip() for l in f.read().splitlines()))

        # Mine another 41 up-version blocks. -alertnotify should trigger on the 51st.
        self.log.info("test -alertnotify")
        self.nodes[1].generate(41)
        self.sync_all()

        # Give bitcoind 10 seconds to write the alert notification
        wait_until(lambda: os.path.isfile(self.alert_filename) and os.path.getsize(self.alert_filename), timeout=10)

        with open(self.alert_filename, 'r', encoding='utf8') as f:
            alert_text = f.read()

        # Mine more up-version blocks, should not get more alerts:
        self.nodes[1].generate(2)
        self.sync_all()

        with open(self.alert_filename, 'r', encoding='utf8') as f:
            alert_text2 = f.read()

        self.log.info("-alertnotify should not continue notifying for more unknown version blocks")
        assert_equal(alert_text, alert_text2)
示例#12
0
 def mine_chain(self):
     self.log.info('Create some old blocks')
     for t in range(TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK + 200 * 600, 600):
         self.nodes[0].setmocktime(t)
         self.nodes[0].generate(1)
     mining_info = self.nodes[0].getmininginfo()
     assert_equal(mining_info['blocks'], 200)
     assert_equal(mining_info['currentblocktx'], 0)
     assert_equal(mining_info['currentblockweight'], 4000)
     self.restart_node(0)
     connect_nodes_bi(self.nodes, 0, 1)
示例#13
0
    def _test_getnetworkinginfo(self):
        assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
        assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2)

        self.nodes[0].setnetworkactive(False)
        assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], False)
        # Wait a bit for all sockets to close
        wait_until(lambda: self.nodes[0].getnetworkinfo()['connections'] == 0, timeout=3)

        self.nodes[0].setnetworkactive(True)
        connect_nodes_bi(self.nodes, 0, 1)
        assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
        assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2)
示例#14
0
    def run_test(self):
        assert(self.nodes[0].getblockcount() == 200)
        assert(self.nodes[2].getblockcount() == 200)

        self.split_network()

        print "Test the maximum-allowed reorg:"
        print "Mine 99 blocks on Node 0"
        self.nodes[0].generate(99)
        assert(self.nodes[0].getblockcount() == 299)
        assert(self.nodes[2].getblockcount() == 200)

        print "Mine competing 100 blocks on Node 2"
        self.nodes[2].generate(100)
        assert(self.nodes[0].getblockcount() == 299)
        assert(self.nodes[2].getblockcount() == 300)

        print "Connect nodes to force a reorg"
        connect_nodes_bi(self.nodes, 0, 2)
        self.is_network_split = False
        sync_blocks(self.nodes)

        print "Check Node 0 is still running and on the correct chain"
        assert(self.nodes[0].getblockcount() == 300)

        self.split_network()

        print "Test the minimum-rejected reorg:"
        print "Mine 100 blocks on Node 0"
        self.nodes[0].generate(100)
        assert(self.nodes[0].getblockcount() == 400)
        assert(self.nodes[2].getblockcount() == 300)

        print "Mine competing 101 blocks on Node 2"
        self.nodes[2].generate(101)
        assert(self.nodes[0].getblockcount() == 400)
        assert(self.nodes[2].getblockcount() == 401)

        print "Sync nodes to force a reorg"
        connect_nodes_bi(self.nodes, 0, 2)
        self.is_network_split = False
        # sync_blocks uses RPC calls to wait for nodes to be synced, so don't
        # call it here, because it will have a non-specific connection error
        # when Node 0 stops. Instead, we explicitly check for the process itself
        # to stop.

        print "Check Node 0 is no longer running"
        assert(check_stopped(0))

        # Dummy stop to enable the test to tear down
        self.nodes[0].stop = lambda: True
    def run_test(self):
        self.log.info("test -blocknotify")
        block_count = 10
        blocks = self.nodes[1].generatetoaddress(block_count, self.nodes[1].getnewaddress() if self.is_wallet_compiled() else ADDRESS_BCRT1_UNSPENDABLE)

        # wait at most 10 seconds for expected number of files before reading the content
        wait_until(lambda: len(os.listdir(self.blocknotify_dir)) == block_count, timeout=10)

        # directory content should equal the generated blocks hashes
        assert_equal(sorted(blocks), sorted(os.listdir(self.blocknotify_dir)))

        if self.is_wallet_compiled():
            self.log.info("test -walletnotify")
            # wait at most 10 seconds for expected number of files before reading the content
            wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)

            # directory content should equal the generated transaction hashes
            txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
            assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
            self.stop_node(1)
            for tx_file in os.listdir(self.walletnotify_dir):
                os.remove(os.path.join(self.walletnotify_dir, tx_file))

            self.log.info("test -walletnotify after rescan")
            # restart node to rescan to force wallet notifications
            self.start_node(1)
            connect_nodes_bi(self.nodes, 0, 1)

            wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)

            # directory content should equal the generated transaction hashes
            txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
            assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))

        # Mine another 41 up-version blocks. -alertnotify should trigger on the 51st.
        self.log.info("test -alertnotify")
        self.nodes[1].generatetoaddress(41, ADDRESS_BCRT1_UNSPENDABLE)
        self.sync_all()

        # Give bitcoind 10 seconds to write the alert notification
        wait_until(lambda: len(os.listdir(self.alertnotify_dir)), timeout=10)

        for notify_file in os.listdir(self.alertnotify_dir):
            os.remove(os.path.join(self.alertnotify_dir, notify_file))

        # Mine more up-version blocks, should not get more alerts:
        self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_UNSPENDABLE)
        self.sync_all()

        self.log.info("-alertnotify should not continue notifying for more unknown version blocks")
        assert_equal(len(os.listdir(self.alertnotify_dir)), 0)
示例#16
0
    def setup_network(self, split=False):
        self.setup_nodes()

        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 0, 2)
        connect_nodes_bi(self.nodes, 0, 3)
    def setup_network(self):
        self.setup_nodes()

        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 0, 2)
        connect_nodes_bi(self.nodes, 0, 3)
示例#18
0
 def setup_network(self, split=False):
     self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[['-regtestprotectcoinbase', '-debug=zrpcunsafe']] * 4 )
     connect_nodes_bi(self.nodes,0,1)
     connect_nodes_bi(self.nodes,1,2)
     connect_nodes_bi(self.nodes,0,2)
     connect_nodes_bi(self.nodes,0,3)
     self.is_network_split=False
     self.sync_all()
示例#19
0
 def setup_network(self, split=False):
     self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[["-nuparams=5ba81b19:200", "-debug=zrpcunsafe", "-txindex"]] * 4 )
     connect_nodes_bi(self.nodes,0,1)
     connect_nodes_bi(self.nodes,1,2)
     connect_nodes_bi(self.nodes,0,2)
     connect_nodes_bi(self.nodes,0,3)
     self.is_network_split=False
     self.sync_all()
示例#20
0
文件: net.py 项目: Airche/wificoin
    def _test_getnetworkinginfo(self):
        assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
        assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2)

        self.nodes[0].setnetworkactive(False)
        assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], False)
        timeout = 3
        while self.nodes[0].getnetworkinfo()['connections'] != 0:
            # Wait a bit for all sockets to close
            assert timeout > 0, 'not all connections closed in time'
            timeout -= 0.1
            time.sleep(0.1)

        self.nodes[0].setnetworkactive(True)
        connect_nodes_bi(self.nodes, 0, 1)
        assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
        assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2)
示例#21
0
    def run_test(self):
        print "Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:"
        print "Mine 4 blocks on Node 0"
        self.nodes[0].generate(4)
        assert(self.nodes[0].getblockcount() == 4)
        besthash = self.nodes[0].getbestblockhash()

        print "Mine competing 6 blocks on Node 1"
        self.nodes[1].generate(6)
        assert(self.nodes[1].getblockcount() == 6)

        print "Connect nodes to force a reorg"
        connect_nodes_bi(self.nodes,0,1)
        sync_blocks(self.nodes[0:2])
        assert(self.nodes[0].getblockcount() == 6)
        badhash = self.nodes[1].getblockhash(2)

        print "Invalidate block 2 on node 0 and verify we reorg to node 0's original chain"
        self.nodes[0].invalidateblock(badhash)
        newheight = self.nodes[0].getblockcount()
        newhash = self.nodes[0].getbestblockhash()
        if (newheight != 4 or newhash != besthash):
            raise AssertionError("Wrong tip for node0, hash %s, height %d"%(newhash,newheight))

        print "\nMake sure we won't reorg to a lower work chain:"
        connect_nodes_bi(self.nodes,1,2)
        print "Sync node 2 to node 1 so both have 6 blocks"
        sync_blocks(self.nodes[1:3])
        assert(self.nodes[2].getblockcount() == 6)
        print "Invalidate block 5 on node 1 so its tip is now at 4"
        self.nodes[1].invalidateblock(self.nodes[1].getblockhash(5))
        assert(self.nodes[1].getblockcount() == 4)
        print "Invalidate block 3 on node 2, so its tip is now 2"
        self.nodes[2].invalidateblock(self.nodes[2].getblockhash(3))
        assert(self.nodes[2].getblockcount() == 2)
        print "..and then mine a block"
        self.nodes[2].generate(1)
        print "Verify all nodes are at the right height"
        time.sleep(5)
        for i in xrange(3):
            print i,self.nodes[i].getblockcount()
        assert(self.nodes[2].getblockcount() == 3)
        assert(self.nodes[0].getblockcount() == 4)
        node1height = self.nodes[1].getblockcount()
        if node1height < 4:
            raise AssertionError("Node 1 reorged to a lower height: %d"%node1height)
    def set_test_params(self):
        self.log.info("Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:")
        self.log.info("Mine 4 blocks on Node 0")
        self.nodes[0].generate(4)
        assert(self.nodes[0].getblockcount() == 4)
        besthash = self.nodes[0].getbestblockhash()

        self.log.info("Mine competing 6 blocks on Node 1")
        self.nodes[1].generate(6)
        assert(self.nodes[1].getblockcount() == 6)

        self.log.info("Connect nodes to force a reorg")
        connect_nodes_bi(self.nodes,0,1)
        sync_blocks(self.nodes[0:2])
        assert(self.nodes[0].getblockcount() == 6)
        badhash = self.nodes[1].getblockhash(2)

        self.log.info("Invalidate block 2 on node 0 and verify we reorg to node 0's original chain")
        self.nodes[0].invalidateblock(badhash)
        newheight = self.nodes[0].getblockcount()
        newhash = self.nodes[0].getbestblockhash()
        if (newheight != 4 or newhash != besthash):
            raise AssertionError("Wrong tip for node0, hash %s, height %d"%(newhash,newheight))

        self.log.info("Make sure we won't reorg to a lower work chain:")
        connect_nodes_bi(self.nodes,1,2)
        self.log.info("Sync node 2 to node 1 so both have 6 blocks")
        sync_blocks(self.nodes[1:3])
        assert(self.nodes[2].getblockcount() == 6)
        self.log.info("Invalidate block 5 on node 1 so its tip is now at 4")
        self.nodes[1].invalidateblock(self.nodes[1].getblockhash(5))
        assert(self.nodes[1].getblockcount() == 4)
        self.log.info("Invalidate block 3 on node 2, so its tip is now 2")
        self.nodes[2].invalidateblock(self.nodes[2].getblockhash(3))
        assert(self.nodes[2].getblockcount() == 2)
        self.log.info("..and then mine a block")
        self.nodes[2].generate(1)
        self.log.info("Verify all nodes are at the right height")
        time.sleep(5)
        assert_equal(self.nodes[2].getblockcount(), 3)
        assert_equal(self.nodes[0].getblockcount(), 4)
        node1height = self.nodes[1].getblockcount()
        if node1height < 4:
            raise AssertionError("Node 1 reorged to a lower height: %d"%node1height)
示例#23
0
    def run_test(self):
        self.tmpdir = self.options.tmpdir
        self.nodes[0].generate(101)

        self.log.info("Make backup of wallet")

        self.stop_node(1)

        shutil.copyfile(self.tmpdir + "/node1/regtest/wallet.dat", self.tmpdir + "/wallet.bak")
        self.start_node(1, self.extra_args[1])
        connect_nodes_bi(self.nodes, 0, 1)

        self.log.info("Generate keys for wallet")

        for _ in range(90):
            addr_oldpool = self.nodes[1].getnewaddress()
        for _ in range(20):
            addr_extpool = self.nodes[1].getnewaddress()

        self.log.info("Send funds to wallet")

        self.nodes[0].sendtoaddress(addr_oldpool, 10)
        self.nodes[0].generate(1)
        self.nodes[0].sendtoaddress(addr_extpool, 5)
        self.nodes[0].generate(1)
        sync_blocks(self.nodes)

        self.log.info("Restart node with wallet backup")

        self.stop_node(1)

        shutil.copyfile(self.tmpdir + "/wallet.bak", self.tmpdir + "/node1/regtest/wallet.dat")

        self.log.info("Verify keypool is restored and balance is correct")

        self.start_node(1, self.extra_args[1])
        connect_nodes_bi(self.nodes, 0, 1)
        self.sync_all()

        assert_equal(self.nodes[1].getbalance(), 15)
        assert_equal(self.nodes[1].listtransactions()[0]['category'], "receive")

        # Check that we have marked all keys up to the used keypool key as used
        assert_equal(self.nodes[1].validateaddress(self.nodes[1].getnewaddress())['hdkeypath'], "m/0'/0'/110'")
示例#24
0
 def setup_network(self, split=False):
     self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[
         '-nuparams=5ba81b19:100', # Overwinter
         '-nuparams=76b809bb:200', # Sapling
         '-txindex'                # Avoid JSONRPC error: No information available about transaction
         ]] * 4 )
     connect_nodes_bi(self.nodes,0,1)
     connect_nodes_bi(self.nodes,1,2)
     connect_nodes_bi(self.nodes,0,2)
     connect_nodes_bi(self.nodes,0,3)
     self.is_network_split=False
     self.sync_all()
示例#25
0
    def run_test(self):
        ###########################
        # setban/listbanned tests #
        ###########################
        assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point
        self.nodes[2].setban("127.0.0.1", "add")
        time.sleep(3) #wait till the nodes are disconected
        assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point
        assert_equal(len(self.nodes[2].listbanned()), 1)
        self.nodes[2].clearbanned()
        assert_equal(len(self.nodes[2].listbanned()), 0)
        self.nodes[2].setban("127.0.0.0/24", "add")
        assert_equal(len(self.nodes[2].listbanned()), 1)
        try:
            self.nodes[2].setban("127.0.0.1", "add") #throws exception because 127.0.0.1 is within range 127.0.0.0/24
        except:
            pass
        assert_equal(len(self.nodes[2].listbanned()), 1) #still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24
        try:
            self.nodes[2].setban("127.0.0.1", "remove")
        except:
            pass
        assert_equal(len(self.nodes[2].listbanned()), 1)
        self.nodes[2].setban("127.0.0.0/24", "remove")
        assert_equal(len(self.nodes[2].listbanned()), 0)
        self.nodes[2].clearbanned()
        assert_equal(len(self.nodes[2].listbanned()), 0)
        
        ###########################
        # RPC disconnectnode test #
        ###########################
        url = urlparse.urlparse(self.nodes[1].url)
        self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))
        time.sleep(2) #disconnecting a node needs a little bit of time
        for node in self.nodes[0].getpeerinfo():
            assert(node['addr'] != url.hostname+":"+str(p2p_port(1)))

        connect_nodes_bi(self.nodes,0,1) #reconnect the node
        found = False
        for node in self.nodes[0].getpeerinfo():
            if node['addr'] == url.hostname+":"+str(p2p_port(1)):
                found = True
        assert(found)
示例#26
0
    def run_test(self):
        # Encrypt wallet for test_locked_wallet_fails test
        self.nodes[1].encryptwallet(WALLET_PASSPHRASE)
        self.nodes[1].walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)

        connect_nodes_bi(self.nodes, 0, 1)
        self.sync_all()

        peer_node, rbf_node = self.nodes
        rbf_node_address = rbf_node.getnewaddress()

        # fund rbf node with 10 coins of 0.001 btc (100,000 satoshis)
        self.log.info("Mining blocks...")
        peer_node.generate(110)
        self.sync_all()
        for i in range(25):
            peer_node.sendtoaddress(rbf_node_address, 0.001)
        self.sync_all()
        peer_node.generate(1)
        self.sync_all()
        assert_equal(rbf_node.getbalance(), Decimal("0.025"))

        self.log.info("Running tests")
        dest_address = peer_node.getnewaddress()
        test_simple_bumpfee_succeeds(self, rbf_node, peer_node, dest_address)
        test_segwit_bumpfee_succeeds(rbf_node, dest_address)
        test_nonrbf_bumpfee_fails(peer_node, dest_address)
        test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address)
        test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
        test_small_output_fails(rbf_node, dest_address)
        test_dust_to_fee(rbf_node, dest_address)
        test_settxfee(rbf_node, dest_address)
        test_rebumping(rbf_node, dest_address)
        test_rebumping_not_replaceable(rbf_node, dest_address)
        test_unconfirmed_not_spendable(rbf_node, rbf_node_address)
        test_bumpfee_metadata(rbf_node, dest_address)
        test_locked_wallet_fails(rbf_node, dest_address)
        test_change_script_match(rbf_node, dest_address)
        # These tests wipe out a number of utxos that are expected in other tests
        test_small_output_with_feerate_succeeds(rbf_node, dest_address)
        test_no_more_inputs_fails(rbf_node, dest_address)
        self.log.info("Success")
示例#27
0
    def run_test(self):
        raise SkipTest("Litecoin doesn't support RBF.")

        # Encrypt wallet for test_locked_wallet_fails test
        self.nodes[1].node_encrypt_wallet(WALLET_PASSPHRASE)
        self.start_node(1)
        self.nodes[1].walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)

        connect_nodes_bi(self.nodes, 0, 1)
        self.sync_all()

        peer_node, rbf_node = self.nodes
        rbf_node_address = rbf_node.getnewaddress()

        # fund rbf node with 10 coins of 0.001 btc (100,000 satoshis)
        self.log.info("Mining blocks...")
        peer_node.generate(110)
        self.sync_all()
        for i in range(25):
            peer_node.sendtoaddress(rbf_node_address, 0.001)
        self.sync_all()
        peer_node.generate(1)
        self.sync_all()
        assert_equal(rbf_node.getbalance(), Decimal("0.025"))

        self.log.info("Running tests")
        dest_address = peer_node.getnewaddress()
        test_simple_bumpfee_succeeds(rbf_node, peer_node, dest_address)
        test_segwit_bumpfee_succeeds(rbf_node, dest_address)
        test_nonrbf_bumpfee_fails(peer_node, dest_address)
        test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address)
        test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address)
        test_small_output_fails(rbf_node, dest_address)
        test_dust_to_fee(rbf_node, dest_address)
        test_settxfee(rbf_node, dest_address)
        test_rebumping(rbf_node, dest_address)
        test_rebumping_not_replaceable(rbf_node, dest_address)
        test_unconfirmed_not_spendable(rbf_node, rbf_node_address)
        test_bumpfee_metadata(rbf_node, dest_address)
        test_locked_wallet_fails(rbf_node, dest_address)
        self.log.info("Success")
示例#28
0
    def run_test(self):
        wallet_path = os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")
        wallet_backup_path = os.path.join(self.nodes[1].datadir, "wallet.bak")
        self.nodes[0].generate(101)

        self.log.info("Make backup of wallet")
        self.stop_node(1)
        shutil.copyfile(wallet_path, wallet_backup_path)
        self.start_node(1, self.extra_args[1])
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 0, 2)
        connect_nodes_bi(self.nodes, 0, 3)

        for i, output_type in enumerate(["legacy", "p2sh-segwit", "bech32"]):

            self.log.info("Generate keys for wallet with address type: {}".format(output_type))
            idx = i+1
            for _ in range(90):
                addr_oldpool = self.nodes[idx].getnewaddress(address_type=output_type)
            for _ in range(20):
                addr_extpool = self.nodes[idx].getnewaddress(address_type=output_type)

            # Make sure we're creating the outputs we expect
            address_details = self.nodes[idx].validateaddress(addr_extpool)
            if i == 0:
                assert(not address_details["isscript"] and not address_details["iswitness"])
            elif i == 1:
                assert(address_details["isscript"] and not address_details["iswitness"])
            else:
                assert(not address_details["isscript"] and address_details["iswitness"])


            self.log.info("Send funds to wallet")
            self.nodes[0].sendtoaddress(addr_oldpool, 10)
            self.nodes[0].generate(1)
            self.nodes[0].sendtoaddress(addr_extpool, 5)
            self.nodes[0].generate(1)
            sync_blocks(self.nodes)

            self.log.info("Restart node with wallet backup")
            self.stop_node(idx)
            shutil.copyfile(wallet_backup_path, wallet_path)
            self.start_node(idx, self.extra_args[idx])
            connect_nodes_bi(self.nodes, 0, idx)
            self.sync_all()

            self.log.info("Verify keypool is restored and balance is correct")
            assert_equal(self.nodes[idx].getbalance(), 15)
            assert_equal(self.nodes[idx].listtransactions()[0]['category'], "receive")
            # Check that we have marked all keys up to the used keypool key as used
            assert_equal(self.nodes[idx].getaddressinfo(self.nodes[idx].getnewaddress())['hdkeypath'], "m/0'/0'/110'")
 def setup_network(self, split=False):
     self.setup_nodes()
     connect_nodes_bi(self.nodes, 0, 1)
     connect_nodes_bi(self.nodes, 1, 2)
     connect_nodes_bi(self.nodes, 0, 2)
     self.is_network_split = False
     self.sync_all()
示例#30
0
 def setup_network(self):
     self.setup_nodes()
     # Only need nodes 0-2 running at start of test
     self.stop_node(3)
     connect_nodes_bi(self.nodes, 0, 1)
     connect_nodes_bi(self.nodes, 1, 2)
     connect_nodes_bi(self.nodes, 0, 2)
     self.sync_all(self.nodes[0:3])
    def run_test(self):
        min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']*100
        # This test is not meant to test fee estimation and we'd like
        # to be sure all txs are sent at a consistent desired feerate
        for node in self.nodes:
            node.settxfee(min_relay_tx_fee)

        # if the fee's positive delta is higher than this value tests will fail,
        # neg. delta always fail the tests.
        # The size of the signature of every input may be at most 2 bytes larger
        # than a minimum sized signature.

        #            = 2 bytes * minRelayTxFeePerByte
        feeTolerance = 2 * min_relay_tx_fee/1000

        self.nodes[2].generate(1)
        self.sync_all()
        self.nodes[0].generate(121)
        self.sync_all()

        # ensure that setting changePosition in fundraw with an exact match is handled properly
        rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():50})
        rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition":1, "subtractFeeFromOutputs":[0]})
        assert_equal(rawmatch["changepos"], -1)

        watchonly_address = self.nodes[0].getnewaddress()
        watchonly_pubkey = self.nodes[0].getaddressinfo(watchonly_address)["pubkey"]
        watchonly_amount = Decimal(200)
        self.nodes[3].importpubkey(watchonly_pubkey, "", True)
        watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)

        # Lock UTXO so nodes[0] doesn't accidentally spend it
        watchonly_vout = find_vout_for_address(self.nodes[0], watchonly_txid, watchonly_address)
        self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])

        self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)

        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0)

        self.nodes[0].generate(1)
        self.sync_all()

        ###############
        # simple test #
        ###############
        inputs  = [ ]
        outputs = { self.nodes[0].getnewaddress() : 1.0 }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)
        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        assert(len(dec_tx['vin']) > 0) #test that we have enough inputs

        ##############################
        # simple test with two coins #
        ##############################
        inputs  = [ ]
        outputs = { self.nodes[0].getnewaddress() : 2.2 }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        assert(len(dec_tx['vin']) > 0) #test if we have enough inputs

        ##############################
        # simple test with two coins #
        ##############################
        inputs  = [ ]
        outputs = { self.nodes[0].getnewaddress() : 2.6 }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        assert(len(dec_tx['vin']) > 0)
        assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')


        ################################
        # simple test with two outputs #
        ################################
        inputs  = [ ]
        outputs = { self.nodes[0].getnewaddress() : 2.6, self.nodes[1].getnewaddress() : 2.5 }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        for out in dec_tx['vout']:
            totalOut += out['value']

        assert(len(dec_tx['vin']) > 0)
        assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')


        #########################################################################
        # test a fundrawtransaction with a VIN greater than the required amount #
        #########################################################################
        utx = get_unspent(self.nodes[2].listunspent(), 5)

        inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
        outputs = { self.nodes[0].getnewaddress() : 1.0 }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        for out in dec_tx['vout']:
            totalOut += out['value']

        assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee


        #####################################################################
        # test a fundrawtransaction with which will not get a change output #
        #####################################################################
        utx = get_unspent(self.nodes[2].listunspent(), 5)

        inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
        outputs = { self.nodes[0].getnewaddress() : Decimal(5.0) - fee - feeTolerance }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        for out in dec_tx['vout']:
            totalOut += out['value']

        assert_equal(rawtxfund['changepos'], -1)
        assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee


        ####################################################
        # test a fundrawtransaction with an invalid option #
        ####################################################
        utx = get_unspent(self.nodes[2].listunspent(), 5)

        inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
        outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        assert_raises_rpc_error(-3, "Unexpected key foo", self.nodes[2].fundrawtransaction, rawtx, {'foo':'bar'})

        # reserveChangeKey was deprecated and is now removed
        assert_raises_rpc_error(-3, "Unexpected key reserveChangeKey", lambda: self.nodes[2].fundrawtransaction(hexstring=rawtx, options={'reserveChangeKey': True}))

        ############################################################
        # test a fundrawtransaction with an invalid change address #
        ############################################################
        utx = get_unspent(self.nodes[2].listunspent(), 5)

        inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
        outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        assert_raises_rpc_error(-5, "changeAddress must be a valid DeepOnion address", self.nodes[2].fundrawtransaction, rawtx, {'changeAddress':'foobar'})

        ############################################################
        # test a fundrawtransaction with a provided change address #
        ############################################################
        utx = get_unspent(self.nodes[2].listunspent(), 5)

        inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
        outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        change = self.nodes[2].getnewaddress()
        assert_raises_rpc_error(-8, "changePosition out of bounds", self.nodes[2].fundrawtransaction, rawtx, {'changeAddress':change, 'changePosition':2})
        rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 0})
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        out = dec_tx['vout'][0]
        assert_equal(change, out['scriptPubKey']['addresses'][0])

        #########################################################
        # test a fundrawtransaction with a provided change type #
        #########################################################
        utx = get_unspent(self.nodes[2].listunspent(), 5)

        inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
        outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None})
        assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''})
        rawtx = self.nodes[2].fundrawtransaction(rawtx, {'change_type': 'bech32'})
        dec_tx = self.nodes[2].decoderawtransaction(rawtx['hex'])
        assert_equal('witness_v0_keyhash', dec_tx['vout'][rawtx['changepos']]['scriptPubKey']['type'])

        #########################################################################
        # test a fundrawtransaction with a VIN smaller than the required amount #
        #########################################################################
        utx = get_unspent(self.nodes[2].listunspent(), 1)

        inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
        outputs = { self.nodes[0].getnewaddress() : 1.0 }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)

        # 4-byte version + 1-byte vin count + 36-byte prevout then script_len
        rawtx = rawtx[:82] + "0100" + rawtx[84:]

        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
        assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        matchingOuts = 0
        for i, out in enumerate(dec_tx['vout']):
            totalOut += out['value']
            if out['scriptPubKey']['addresses'][0] in outputs:
                matchingOuts+=1
            else:
                assert_equal(i, rawtxfund['changepos'])

        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
        assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex'])

        assert_equal(matchingOuts, 1)
        assert_equal(len(dec_tx['vout']), 2)


        ###########################################
        # test a fundrawtransaction with two VINs #
        ###########################################
        utx = get_unspent(self.nodes[2].listunspent(), 1)
        utx2 = get_unspent(self.nodes[2].listunspent(), 5)

        inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
        outputs = { self.nodes[0].getnewaddress() : 6.0 }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        matchingOuts = 0
        for out in dec_tx['vout']:
            totalOut += out['value']
            if out['scriptPubKey']['addresses'][0] in outputs:
                matchingOuts+=1

        assert_equal(matchingOuts, 1)
        assert_equal(len(dec_tx['vout']), 2)

        matchingIns = 0
        for vinOut in dec_tx['vin']:
            for vinIn in inputs:
                if vinIn['txid'] == vinOut['txid']:
                    matchingIns+=1

        assert_equal(matchingIns, 2) #we now must see two vins identical to vins given as params

        #########################################################
        # test a fundrawtransaction with two VINs and two vOUTs #
        #########################################################
        utx = get_unspent(self.nodes[2].listunspent(), 1)
        utx2 = get_unspent(self.nodes[2].listunspent(), 5)

        inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
        outputs = { self.nodes[0].getnewaddress() : 6.0, self.nodes[0].getnewaddress() : 1.0 }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        matchingOuts = 0
        for out in dec_tx['vout']:
            totalOut += out['value']
            if out['scriptPubKey']['addresses'][0] in outputs:
                matchingOuts+=1

        assert_equal(matchingOuts, 2)
        assert_equal(len(dec_tx['vout']), 3)

        ##############################################
        # test a fundrawtransaction with invalid vin #
        ##############################################
        inputs  = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin!
        outputs = { self.nodes[0].getnewaddress() : 1.0}
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)

        assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx)

        ############################################################
        #compare fee of a standard pubkeyhash transaction
        inputs = []
        outputs = {self.nodes[1].getnewaddress():1.1}
        rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[0].fundrawtransaction(rawtx)

        #create same transaction over sendtoaddress
        txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1)
        signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert(feeDelta >= 0 and feeDelta <= feeTolerance)
        ############################################################

        ############################################################
        #compare fee of a standard pubkeyhash transaction with multiple outputs
        inputs = []
        outputs = {self.nodes[1].getnewaddress():1.1,self.nodes[1].getnewaddress():1.2,self.nodes[1].getnewaddress():0.1,self.nodes[1].getnewaddress():1.3,self.nodes[1].getnewaddress():0.2,self.nodes[1].getnewaddress():0.3}
        rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[0].fundrawtransaction(rawtx)
        #create same transaction over sendtoaddress
        txId = self.nodes[0].sendmany("", outputs)
        signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert(feeDelta >= 0 and feeDelta <= feeTolerance)
        ############################################################


        ############################################################
        #compare fee of a 2of2 multisig p2sh transaction

        # create 2of2 addr
        addr1 = self.nodes[1].getnewaddress()
        addr2 = self.nodes[1].getnewaddress()

        addr1Obj = self.nodes[1].getaddressinfo(addr1)
        addr2Obj = self.nodes[1].getaddressinfo(addr2)

        mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']

        inputs = []
        outputs = {mSigObj:1.1}
        rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[0].fundrawtransaction(rawtx)

        #create same transaction over sendtoaddress
        txId = self.nodes[0].sendtoaddress(mSigObj, 1.1)
        signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert(feeDelta >= 0 and feeDelta <= feeTolerance)
        ############################################################


        ############################################################
        #compare fee of a standard pubkeyhash transaction

        # create 4of5 addr
        addr1 = self.nodes[1].getnewaddress()
        addr2 = self.nodes[1].getnewaddress()
        addr3 = self.nodes[1].getnewaddress()
        addr4 = self.nodes[1].getnewaddress()
        addr5 = self.nodes[1].getnewaddress()

        addr1Obj = self.nodes[1].getaddressinfo(addr1)
        addr2Obj = self.nodes[1].getaddressinfo(addr2)
        addr3Obj = self.nodes[1].getaddressinfo(addr3)
        addr4Obj = self.nodes[1].getaddressinfo(addr4)
        addr5Obj = self.nodes[1].getaddressinfo(addr5)

        mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])['address']

        inputs = []
        outputs = {mSigObj:1.1}
        rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[0].fundrawtransaction(rawtx)

        #create same transaction over sendtoaddress
        txId = self.nodes[0].sendtoaddress(mSigObj, 1.1)
        signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert(feeDelta >= 0 and feeDelta <= feeTolerance)
        ############################################################


        ############################################################
        # spend a 2of2 multisig transaction over fundraw

        # create 2of2 addr
        addr1 = self.nodes[2].getnewaddress()
        addr2 = self.nodes[2].getnewaddress()

        addr1Obj = self.nodes[2].getaddressinfo(addr1)
        addr2Obj = self.nodes[2].getaddressinfo(addr2)

        mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']


        # send 1.2 BTC to msig addr
        txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()

        oldBalance = self.nodes[1].getbalance()
        inputs = []
        outputs = {self.nodes[1].getnewaddress():1.1}
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[2].fundrawtransaction(rawtx)

        signedTx = self.nodes[2].signrawtransactionwithwallet(fundedTx['hex'])
        txId = self.nodes[2].sendrawtransaction(signedTx['hex'])
        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()

        # make sure funds are received at node1
        assert_equal(oldBalance+Decimal('1.10000000'), self.nodes[1].getbalance())

        ############################################################
        # locked wallet test
        self.nodes[1].encryptwallet("test")
        self.stop_nodes()

        self.start_nodes()
        # This test is not meant to test fee estimation and we'd like
        # to be sure all txs are sent at a consistent desired feerate
        for node in self.nodes:
            node.settxfee(min_relay_tx_fee)

        connect_nodes_bi(self.nodes,0,1)
        connect_nodes_bi(self.nodes,1,2)
        connect_nodes_bi(self.nodes,0,2)
        connect_nodes_bi(self.nodes,0,3)
        # Again lock the watchonly UTXO or nodes[0] may spend it, because
        # lockunspent is memory-only and thus lost on restart
        self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
        self.sync_all()

        # drain the keypool
        self.nodes[1].getnewaddress()
        self.nodes[1].getrawchangeaddress()
        inputs = []
        outputs = {self.nodes[0].getnewaddress():1.1}
        rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
        # fund a transaction that requires a new key for the change output
        # creating the key must be impossible because the wallet is locked
        assert_raises_rpc_error(-4, "Keypool ran out, please call keypoolrefill first", self.nodes[1].fundrawtransaction, rawtx)

        #refill the keypool
        self.nodes[1].walletpassphrase("test", 100)
        self.nodes[1].keypoolrefill(8) #need to refill the keypool to get an internal change address
        self.nodes[1].walletlock()

        assert_raises_rpc_error(-13, "walletpassphrase", self.nodes[1].sendtoaddress, self.nodes[0].getnewaddress(), 1.2)

        oldBalance = self.nodes[0].getbalance()

        inputs = []
        outputs = {self.nodes[0].getnewaddress():1.1}
        rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[1].fundrawtransaction(rawtx)

        #now we need to unlock
        self.nodes[1].walletpassphrase("test", 600)
        signedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex'])
        txId = self.nodes[1].sendrawtransaction(signedTx['hex'])
        self.nodes[1].generate(1)
        self.sync_all()

        # make sure funds are received at node1
        assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance())


        ###############################################
        # multiple (~19) inputs tx test | Compare fee #
        ###############################################

        #empty node1, send some small coins from node0 to node1
        self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        for i in range(0,20):
            self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
        self.nodes[0].generate(1)
        self.sync_all()

        #fund a tx with ~20 small inputs
        inputs = []
        outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
        rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[1].fundrawtransaction(rawtx)

        #create same transaction over sendtoaddress
        txId = self.nodes[1].sendmany("", outputs)
        signedFee = self.nodes[1].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert(feeDelta >= 0 and feeDelta <= feeTolerance*19) #~19 inputs


        #############################################
        # multiple (~19) inputs tx test | sign/send #
        #############################################

        #again, empty node1, send some small coins from node0 to node1
        self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        for i in range(0,20):
            self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
        self.nodes[0].generate(1)
        self.sync_all()

        #fund a tx with ~20 small inputs
        oldBalance = self.nodes[0].getbalance()

        inputs = []
        outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
        rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[1].fundrawtransaction(rawtx)
        fundedAndSignedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex'])
        txId = self.nodes[1].sendrawtransaction(fundedAndSignedTx['hex'])
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()
        assert_equal(oldBalance+Decimal('50.19000000'), self.nodes[0].getbalance()) #0.19+block reward

        #####################################################
        # test fundrawtransaction with OP_RETURN and no vin #
        #####################################################

        rawtx   = "0100000000010000000000000000066a047465737400000000"
        dec_tx  = self.nodes[2].decoderawtransaction(rawtx)

        assert_equal(len(dec_tx['vin']), 0)
        assert_equal(len(dec_tx['vout']), 1)

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        dec_tx  = self.nodes[2].decoderawtransaction(rawtxfund['hex'])

        assert_greater_than(len(dec_tx['vin']), 0) # at least one vin
        assert_equal(len(dec_tx['vout']), 2) # one change output added


        ##################################################
        # test a fundrawtransaction using only watchonly #
        ##################################################

        inputs = []
        outputs = {self.nodes[2].getnewaddress() : watchonly_amount / 2}
        rawtx = self.nodes[3].createrawtransaction(inputs, outputs)

        result = self.nodes[3].fundrawtransaction(rawtx, {'includeWatching': True })
        res_dec = self.nodes[0].decoderawtransaction(result["hex"])
        assert_equal(len(res_dec["vin"]), 1)
        assert_equal(res_dec["vin"][0]["txid"], watchonly_txid)

        assert("fee" in result.keys())
        assert_greater_than(result["changepos"], -1)

        ###############################################################
        # test fundrawtransaction using the entirety of watched funds #
        ###############################################################

        inputs = []
        outputs = {self.nodes[2].getnewaddress() : watchonly_amount}
        rawtx = self.nodes[3].createrawtransaction(inputs, outputs)

        # Backward compatibility test (2nd param is includeWatching)
        result = self.nodes[3].fundrawtransaction(rawtx, True)
        res_dec = self.nodes[0].decoderawtransaction(result["hex"])
        assert_equal(len(res_dec["vin"]), 2)
        assert(res_dec["vin"][0]["txid"] == watchonly_txid or res_dec["vin"][1]["txid"] == watchonly_txid)

        assert_greater_than(result["fee"], 0)
        assert_greater_than(result["changepos"], -1)
        assert_equal(result["fee"] + res_dec["vout"][result["changepos"]]["value"], watchonly_amount / 10)

        signedtx = self.nodes[3].signrawtransactionwithwallet(result["hex"])
        assert(not signedtx["complete"])
        signedtx = self.nodes[0].signrawtransactionwithwallet(signedtx["hex"])
        assert(signedtx["complete"])
        self.nodes[0].sendrawtransaction(signedtx["hex"])
        self.nodes[0].generate(1)
        self.sync_all()

        #######################
        # Test feeRate option #
        #######################

        # Make sure there is exactly one input so coin selection can't skew the result
        assert_equal(len(self.nodes[3].listunspent(1)), 1)

        inputs = []
        outputs = {self.nodes[3].getnewaddress() : 1}
        rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
        result = self.nodes[3].fundrawtransaction(rawtx) # uses min_relay_tx_fee (set by settxfee)
        result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee})
        result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10*min_relay_tx_fee})
        assert_raises_rpc_error(-4, "Fee exceeds maximum configured by -maxtxfee", self.nodes[3].fundrawtransaction, rawtx, {"feeRate": 1})
        result_fee_rate = result['fee'] * 1000 / count_bytes(result['hex'])
        assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate)
        assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate)

        ################################
        # Test no address reuse occurs #
        ################################

        result3 = self.nodes[3].fundrawtransaction(rawtx)
        res_dec = self.nodes[0].decoderawtransaction(result3["hex"])
        changeaddress = ""
        for out in res_dec['vout']:
            if out['value'] > 1.0:
                changeaddress += out['scriptPubKey']['addresses'][0]
        assert(changeaddress != "")
        nextaddr = self.nodes[3].getnewaddress()
        # Now the change address key should be removed from the keypool
        assert(changeaddress != nextaddr)

        ######################################
        # Test subtractFeeFromOutputs option #
        ######################################

        # Make sure there is exactly one input so coin selection can't skew the result
        assert_equal(len(self.nodes[3].listunspent(1)), 1)

        inputs = []
        outputs = {self.nodes[2].getnewaddress(): 1}
        rawtx = self.nodes[3].createrawtransaction(inputs, outputs)

        result = [self.nodes[3].fundrawtransaction(rawtx), # uses min_relay_tx_fee (set by settxfee)
                  self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": []}), # empty subtraction list
                  self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0]}), # uses min_relay_tx_fee (set by settxfee)
                  self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee}),
                  self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee, "subtractFeeFromOutputs": [0]})]

        dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result]
        output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)]
        change = [d['vout'][r['changepos']]['value'] for d, r in zip(dec_tx, result)]

        assert_equal(result[0]['fee'], result[1]['fee'], result[2]['fee'])
        assert_equal(result[3]['fee'], result[4]['fee'])
        assert_equal(change[0], change[1])
        assert_equal(output[0], output[1])
        assert_equal(output[0], output[2] + result[2]['fee'])
        assert_equal(change[0] + result[0]['fee'], change[2])
        assert_equal(output[3], output[4] + result[4]['fee'])
        assert_equal(change[3] + result[3]['fee'], change[4])

        inputs = []
        outputs = {self.nodes[2].getnewaddress(): value for value in (1.0, 1.1, 1.2, 1.3)}
        rawtx = self.nodes[3].createrawtransaction(inputs, outputs)

        result = [self.nodes[3].fundrawtransaction(rawtx),
                  # split the fee between outputs 0, 2, and 3, but not output 1
                  self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0, 2, 3]})]

        dec_tx = [self.nodes[3].decoderawtransaction(result[0]['hex']),
                  self.nodes[3].decoderawtransaction(result[1]['hex'])]

        # Nested list of non-change output amounts for each transaction
        output = [[out['value'] for i, out in enumerate(d['vout']) if i != r['changepos']]
                  for d, r in zip(dec_tx, result)]

        # List of differences in output amounts between normal and subtractFee transactions
        share = [o0 - o1 for o0, o1 in zip(output[0], output[1])]

        # output 1 is the same in both transactions
        assert_equal(share[1], 0)

        # the other 3 outputs are smaller as a result of subtractFeeFromOutputs
        assert_greater_than(share[0], 0)
        assert_greater_than(share[2], 0)
        assert_greater_than(share[3], 0)

        # outputs 2 and 3 take the same share of the fee
        assert_equal(share[2], share[3])

        # output 0 takes at least as much share of the fee, and no more than 2 satoshis more, than outputs 2 and 3
        assert_greater_than_or_equal(share[0], share[2])
        assert_greater_than_or_equal(share[2] + Decimal(2e-8), share[0])

        # the fee is the same in both transactions
        assert_equal(result[0]['fee'], result[1]['fee'])

        # the total subtracted from the outputs is equal to the fee
        assert_equal(share[0] + share[2] + share[3], result[0]['fee'])
示例#32
0
    def run_test(self):
        def wait_for_tip(node, tip):
            def check_tip():
                return node.getbestblockhash() == tip

            wait_until(check_tip)

        node = self.nodes[0]
        parking_node = self.nodes[1]

        self.log.info("Test chain parking...")
        node.generate(10)
        tip = node.getbestblockhash()
        node.generate(1)
        block_to_park = node.getbestblockhash()
        node.generate(10)
        parked_tip = node.getbestblockhash()

        # get parking_node caught up.
        # (probably not needed, but just in case parking can have race
        # condition like invalidateblock below)
        wait_for_tip(parking_node, parked_tip)

        # Let's park the chain.
        assert parked_tip != tip
        assert block_to_park != tip
        assert block_to_park != parked_tip
        node.parkblock(block_to_park)
        assert_equal(node.getbestblockhash(), tip)

        # When the chain is unparked, the node reorg into its original chain.
        node.unparkblock(parked_tip)
        assert_equal(node.getbestblockhash(), parked_tip)

        # Parking and then unparking a block should not change its validity,
        # and invaliding and reconsidering a block should not change its
        # parked state.  See the following test cases:
        self.log.info("Test invalidate, park, unpark, reconsider...")
        node.generate(1)
        tip = node.getbestblockhash()
        node.generate(1)
        bad_tip = node.getbestblockhash()
        # Generate an extra block to check that children are invalidated as
        # expected and do not produce dangling chaintips
        node.generate(1)
        good_tip = node.getbestblockhash()

        # avoid race condition from parking_node requesting block when invalid
        wait_for_tip(parking_node, good_tip)

        node.invalidateblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="invalid")
        node.parkblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="invalid")
        node.unparkblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="invalid")
        node.reconsiderblock(bad_tip)
        self.only_valid_tip(good_tip)

        self.log.info("Test park, invalidate, reconsider, unpark")
        node.generate(1)
        tip = node.getbestblockhash()
        node.generate(1)
        bad_tip = node.getbestblockhash()
        node.generate(1)
        good_tip = node.getbestblockhash()

        # avoid race condition from parking_node requesting block when invalid
        wait_for_tip(parking_node, good_tip)

        node.parkblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="parked")
        node.invalidateblock(bad_tip)
        # NOTE: Intuitively, other_tip_status would be "invalid", but because
        # only valid (unparked) chains are walked, child blocks' statuses are
        # not updated, so the "parked" state remains.
        self.only_valid_tip(tip, other_tip_status="parked")
        node.reconsiderblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="parked")
        node.unparkblock(bad_tip)
        self.only_valid_tip(good_tip)

        self.log.info("Test invalidate, park, reconsider, unpark...")
        node.generate(1)
        tip = node.getbestblockhash()
        node.generate(1)
        bad_tip = node.getbestblockhash()
        node.generate(1)
        good_tip = node.getbestblockhash()

        # avoid race condition from parking_node requesting block when invalid
        wait_for_tip(parking_node, good_tip)

        node.invalidateblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="invalid")
        node.parkblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="invalid")
        node.reconsiderblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="parked")
        node.unparkblock(bad_tip)
        self.only_valid_tip(good_tip)

        self.log.info("Test park, invalidate, unpark, reconsider")
        node.generate(1)
        tip = node.getbestblockhash()
        node.generate(1)
        bad_tip = node.getbestblockhash()
        node.generate(1)
        good_tip = node.getbestblockhash()

        # avoid race condition from parking_node requesting block when invalid
        wait_for_tip(parking_node, good_tip)

        node.parkblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="parked")
        node.invalidateblock(bad_tip)
        # NOTE: Intuitively, other_tip_status would be "invalid", but because
        # only valid (unparked) chains are walked, child blocks' statuses are
        # not updated, so the "parked" state remains.
        self.only_valid_tip(tip, other_tip_status="parked")
        node.unparkblock(bad_tip)
        self.only_valid_tip(tip, other_tip_status="invalid")
        node.reconsiderblock(bad_tip)
        self.only_valid_tip(good_tip)

        # To get ready for next testset, make sure both nodes are in sync.
        wait_for_tip(parking_node, good_tip)
        assert_equal(node.getbestblockhash(), parking_node.getbestblockhash())

        # Wait for node 1 to park the chain.
        def wait_for_parked_block(block):
            def check_block():
                for tip in parking_node.getchaintips():
                    if tip["hash"] == block:
                        assert tip["status"] != "active"
                        return tip["status"] == "parked"
                return False

            wait_until(check_block)

        def check_reorg_protection(depth, extra_blocks):
            self.log.info(
                "Test deep reorg parking, {} block deep".format(depth))

            # Invalidate the tip on node 0, so it doesn't follow node 1.
            node.invalidateblock(node.getbestblockhash())
            # Mine block to create a fork of proper depth
            parking_node.generatetoaddress(
                nblocks=depth - 1,
                address=parking_node.getnewaddress(label='coinbase'))
            node.generatetoaddress(
                nblocks=depth, address=node.getnewaddress(label='coinbase'))
            # extra block should now find themselves parked
            for i in range(extra_blocks):
                node.generate(1)
                wait_for_parked_block(node.getbestblockhash())

            # If we mine one more block, the node reorgs.
            node.generate(1)
            wait_until(lambda: parking_node.getbestblockhash() == node.
                       getbestblockhash())

        check_reorg_protection(1, 0)
        check_reorg_protection(2, 0)
        check_reorg_protection(3, 1)
        check_reorg_protection(4, 4)
        check_reorg_protection(5, 5)
        check_reorg_protection(6, 6)
        check_reorg_protection(100, 100)

        # try deep reorg with a log check.
        with parking_node.assert_debug_log(["Park block"]):
            check_reorg_protection(3, 1)

        self.log.info(
            "Accepting many blocks at once (possibly out of order) should not park if there is no reorg."
        )
        # rewind one block to make a reorg that is shallow.
        node.invalidateblock(parking_node.getbestblockhash())
        # generate a ton of blocks at once.
        try:
            with parking_node.assert_debug_log(["Park block"]):
                node.generatetoaddress(
                    nblocks=20, address=node.getnewaddress(label='coinbase'))
                wait_until(lambda: parking_node.getbestblockhash() == node.
                           getbestblockhash())
        except AssertionError as exc:
            # good, we want an absence of "Park block" messages
            assert "does not partially match log" in exc.args[0]
        else:
            raise AssertionError("Parked block when there was no deep reorg")

        self.log.info("Test that unparking works when -parkdeepreorg=0")
        # Set up parking node height = fork + 4, node height = fork + 5
        node.invalidateblock(node.getbestblockhash())
        parking_node.generate(3)
        node.generatetoaddress(nblocks=5,
                               address=node.getnewaddress(label='coinbase'))
        wait_for_parked_block(node.getbestblockhash())
        # Restart the parking node without parkdeepreorg.
        self.restart_node(1, ["-parkdeepreorg=0"])
        parking_node = self.nodes[1]
        connect_nodes_bi(node, parking_node)
        # The other chain should still be marked 'parked'.
        wait_for_parked_block(node.getbestblockhash())
        # Three more blocks is not enough to unpark. Even though its PoW is
        # larger, we are still following the delayed-unparking rules.
        node.generate(3)
        wait_for_parked_block(node.getbestblockhash())
        # Final block pushes over the edge, and should unpark.
        node.generate(1)
        wait_until(
            lambda: parking_node.getbestblockhash() == node.getbestblockhash(),
            timeout=5)
示例#33
0
 def setup_network(self):
     self.nodes = start_nodes(3,
                              self.options.tmpdir,
                              extra_args=[['-nuparams=5ba81b19:10']] * 3)
     connect_nodes_bi(self.nodes, 0, 1)
    def test_mix_contract_transaction_fork(self, gen_blocks=False):
        '''
        在2条分叉链中,混合执行各种交易,然后:
        1.不产生块,合并网络
        2.产生块,合并网络

        :return:
        '''
        self.sync_all()
        self.node1.generate(2)
        assert_equal(self.node1.getrawmempool(), [])  # make sure mempool empty
        assert_equal(self.node0.getrawmempool(), [])  # make sure mempool empty
        ct = Contract(self.node0, self.options.tmpdir, debug=False)
        ct2 = Contract(self.node0, self.options.tmpdir, debug=False)
        ct2.call_payable(amount=1000)
        print(ct.publish_txid)
        self.sync_all()
        self.node0.generate(2)
        self.sync_all()
        blocks_num = self.node0.getblockcount()

        # split mgc network
        self.split_network()
        self.node0.generate(2)  # fork
        self.node2.generate(8)  # fork
        balances = [n.getbalance() for n in self.nodes]

        # in group 1
        # normal transaction
        sendtxs_a = [
            self.node0.sendtoaddress(self.node3.getnewaddress(), 1000)
            for i in range(5)
        ]

        # publish contract transaction
        ccontracts_a = [
            Contract(self.node0, self.options.tmpdir, debug=False)
            for i in range(5)
        ]

        # call contract transaction
        call_contract_txs_a = [
            ct.call_payable(amount=1000).txid for ct in ccontracts_a
        ]
        call_contract_txs_a1 = [
            ct.call_callOtherContractTest(ccontracts_a[0].contract_id,
                                          'callOtherContractTest',
                                          ccontracts_a[-1].contract_id,
                                          "contractDataTest").txid
            for ct in ccontracts_a
        ]

        # long mempool chain transaction
        for i in range(8):
            result = ccontracts_a[1].call_reentrancyTest(throw_exception=False)

        ccontracts_a[2].call_maxContractCallTest(2).txid
        self.sync_all([self.nodes[:2], self.nodes[2:]])

        # in group 2
        sendtxs_b = [
            self.node2.sendtoaddress(self.node1.getnewaddress(), 1000)
            for i in range(5)
        ]

        # publish contract transaction
        ccontracts_b = [
            Contract(self.node2, self.options.tmpdir, debug=False)
            for i in range(5)
        ]

        # call contract transaction
        call_contract_txs_b = [
            ct.call_payable(amount=1000).txid for ct in ccontracts_b
        ]
        call_contract_txs_b1 = [
            ct.call_callOtherContractTest(ccontracts_b[0].contract_id,
                                          'callOtherContractTest',
                                          ccontracts_b[-1].contract_id,
                                          "contractDataTest").txid
            for ct in ccontracts_b
        ]

        # long mempool chain transaction

        for i in range(8):
            result = ccontracts_b[1].call_reentrancyTest(throw_exception=False)

        ccontracts_b[2].call_maxContractCallTest(2).txid
        self.sync_all([self.nodes[:2], self.nodes[2:]])

        # join network
        if gen_blocks:
            blocks_a = self.node0.generate(2)
            blocks_b = self.node2.generate(6)
            more_work_blocks = self.make_more_work_than(2, 0)

            for i in range(4):
                print("before join:", i, self.nodes[i].getblockcount(),
                      int(self.nodes[i].getchaintipwork(), 16))
                print("mempool:", self.nodes[i].getrawmempool())

        print("join network")
        connect_nodes_bi(self.nodes, 1, 2)
        try:
            print("sync_mempools.......")
            # sync_mempools(self.nodes, timeout=30)
            print("sync_mempools done")
        except Exception as e:
            print("sync mempool failed,ignore!")

        sync_blocks(self.nodes)

        if gen_blocks:
            for i in range(4):
                print("mempool:", self.nodes[i].getrawmempool())
        for i in range(4):
            print(i, self.nodes[i].getblockcount(),
                  int(self.nodes[i].getchaintipwork(), 16))
        tips = self.nodes[0].getchaintips()
        print("tips:", tips)
        assert_equal(len(tips), self.tips_num + 1)
        self.tips_num += 1

        # 合并后,节点再次调用合约,该交易应该回被不同组的节点抛弃,因为合约不存在
        result = ccontracts_a[2].call_reentrancyTest()
        if not result.reason():
            tx1 = result.txid
        result = ccontracts_b[2].call_reentrancyTest()
        if not result.reason():
            tx2 = result.txid
        # tx1 = ccontracts_a[2].call_reentrancyTest().txid
        # tx2 = ccontracts_b[2].call_reentrancyTest().txid
        try:
            sync_mempools(self.nodes, timeout=30)
        except Exception as e:
            print("sync_mempools(self.nodes,timeout = 30) not done")
        # wait_until(lambda: tx1 not in self.node2.getrawmempool(), timeout=10)
        # wait_until(lambda: tx1 in self.node1.getrawmempool(), timeout=10)
        # wait_until(lambda: tx2 not in self.node1.getrawmempool(), timeout=10)
        # wait_until(lambda: tx2 in self.node3.getrawmempool(), timeout=10)

        for i, n in enumerate(self.nodes):
            n.generate(2)
            print("node{} generate done".format(i))
            sync_blocks(self.nodes)
    def test_double_publish(self):
        '''
        同一个合约交易,在主链与分叉上发布
        合并后,确认数为2(bb-bb4),而不是3(a1-a2-a3)
        txid同时存在于listsinceblock的transactions和removed
        只消耗一份utxo,合约余额也只有一份
              ab0
          /       \
        aa1 [ca1]   bb1
         |           |
        aa2         bb2
         |           |
        aa3         bb3 [ca1]
                     |
                    bb4
        :return:
        '''
        self.sync_all()
        self.node0.generate(2)
        self.sync_all()
        assert_equal(self.node0.getrawmempool(), [])

        hex_content = get_contract_hex(self.contract_file)
        coster = self.node0.getnewaddress()
        sendtx = self.node0.sendtoaddress(coster, 1000)
        self.node0.generate(1)
        self.sync_all()
        sender_pub = self.node0.validateaddress(coster)['pubkey']
        sender_pri = self.node0.dumpprivkey(coster)
        amount = 100
        changeaddress = self.node0.getnewaddress()

        balance = self.node0.getbalance()
        signed_tx = self.publish_contract(self.node0,
                                          hex_content,
                                          coster,
                                          sender_pub,
                                          sender_pri,
                                          amount,
                                          changeaddress,
                                          send_flag=False)
        blocks_num = self.node0.getblockcount()

        self.split_network()

        txid1 = self.node0.sendrawtransaction(signed_tx['hex'])
        # generate bb1-bb2 on right side
        self.node2.generate(2)
        txid2 = self.node2.sendrawtransaction(signed_tx['hex'])
        print(txid1, txid2)
        assert_equal(txid1, txid2)

        lastblockhash = self.node0.generate(3)[-1]
        block_hash = self.node2.generate(2)[-1]
        blocks = self.make_more_work_than(2, 0)
        gen_blocks = len(blocks)

        # join network
        for i in range(4):
            print("before join:", i, self.nodes[i].getblockcount(),
                  int(self.nodes[i].getchaintipwork(), 16))
            print("mempool:", self.nodes[i].getrawmempool())

        print("join network")
        connect_nodes_bi(self.nodes, 1, 2)
        sync_blocks(self.nodes)

        for i in range(4):
            print("mempool:", self.nodes[i].getrawmempool())
        # 确认存在分叉存在
        tips = self.nodes[1].getchaintips()
        print(tips)
        assert_equal(len(tips), self.tips_num + 1)
        self.tips_num += 1
        assert_equal(self.node1.getblockcount(), blocks_num + 4 + gen_blocks)
        assert_equal(self.node1.getbestblockhash(),
                     blocks[-1] if gen_blocks > 0 else block_hash)

        # assert
        assert_equal(
            self.node0.getbalance() - MINER_REWARD + 100 -
            self.get_txfee(txid1['txid']) + self.get_txfee(sendtx), balance)
        assert_equal(self.node2.getbalanceof(txid1['contractaddress']), 100)

        # listsinceblock(lastblockhash) should now include txid1 in transactions
        # as well as in removed
        lsbres = self.node0.listsinceblock(lastblockhash)
        assert any(tx['txid'] == txid1['txid']
                   for tx in lsbres['transactions'])
        assert any(tx['txid'] == txid1['txid'] for tx in lsbres['removed'])

        # find transaction and ensure confirmations is valid
        for tx in lsbres['transactions']:
            if tx['txid'] == txid1['txid']:
                assert_equal(tx['confirmations'], 2 + gen_blocks)

        # the same check for the removed array; confirmations should STILL be 2
        for tx in lsbres['removed']:
            if tx['txid'] == txid1['txid']:
                assert_equal(tx['confirmations'], 2 + gen_blocks)
 def setup_network(self, split=False):
     self.add_nodes(self.num_nodes, extra_args=self.extra_args)
     self.start_nodes()
     connect_nodes_bi(self.nodes, 0, 1)
 def setup_network(self):
     super().setup_network()
     connect_nodes_bi(self.nodes, 0, 2)
示例#38
0
    def run_test(self):
        # NLAST_POW_BLOCK = 250 - so mine 125 blocks each node (25 consecutive blocks for 5 times)
        NMATURITY = 100
        self.log.info("Mining 250 blocks (125 with node 0 and 125 with node 1)...")
        for i in range(5):
            self.generateBatchBlocks(0, 25)
            sync_blocks(self.nodes)
            self.generateBatchBlocks(1, 25)
            sync_blocks(self.nodes)
        sync_mempools(self.nodes)

        # Check balances
        balance0 = 250.0 * (125 - 50)
        balance1 = 250.0 * (125 - 50)
        # Last two 25-blocks bursts (for each node) are not mature: NMATURITY = 2 * (2 * 25)
        immature_balance0 = 250.0 * 50
        immature_balance1 = 250.0 * 50
        w_info = self.nodes[0].getwalletinfo()
        assert_equal(w_info["balance"], balance0)
        assert_equal(w_info["immature_balance"], immature_balance0)
        self.log.info("Balance for node 0 checks out: %f [%f]" % (balance0, immature_balance0))
        w_info = self.nodes[1].getwalletinfo()
        assert_equal(w_info["balance"], balance1)
        assert_equal(w_info["immature_balance"], immature_balance1)
        self.log.info("Balance for node 1 checks out: %f [%f]" % (balance1, immature_balance1))
        initial_balance = balance0
        initial_immature_balance = immature_balance0
        initial_unspent = self.nodes[0].listunspent()

        # PoS start reached (block 250) - disconnect nodes
        self.nodes[0].disconnectnode(urllib.parse.urlparse(self.nodes[1].url).hostname + ":" + str(p2p_port(1)))
        self.nodes[1].disconnectnode(urllib.parse.urlparse(self.nodes[0].url).hostname + ":" + str(p2p_port(0)))
        self.log.info("Nodes disconnected")

        # Stake one block with node-0 and save the stake input
        self.log.info("Staking 1 block with node 0...")
        self.nodes[0].generate(1)
        last_block = self.nodes[0].getblock(self.nodes[0].getbestblockhash())
        assert(len(last_block["tx"]) > 1)                                       # a PoS block has at least two txes
        coinstake_txid = last_block["tx"][1]
        coinstake_tx = self.nodes[0].getrawtransaction(coinstake_txid, True)
        assert(coinstake_tx["vout"][0]["scriptPubKey"]["hex"] == "")            # first output of coinstake is empty
        stakeinput = coinstake_tx["vin"][0]

        # The stake input was unspent 1 block ago, now it's not
        res, utxo = self.findUtxoInList(stakeinput["txid"], stakeinput["vout"], initial_unspent)
        assert (res and utxo["spendable"])
        res, utxo = self.findUtxoInList(stakeinput["txid"], stakeinput["vout"], self.nodes[0].listunspent())
        assert (not res or not utxo["spendable"])
        self.log.info("Coinstake input %s...%s-%d is no longer spendable." % (
            stakeinput["txid"][:9], stakeinput["txid"][-4:], stakeinput["vout"]))

        # Stake 10 more blocks with node-0 and check balances
        self.log.info("Staking 10 more blocks with node 0...")
        self.generateBatchBlocks(0, 10)
        balance0 = initial_balance + 0          # mined blocks matured (250*11) - staked blocks inputs (250*11)
        immature_balance0 += 250 * 11           # -mined blocks matured (250*11) + staked blocks (500*11)
        w_info = self.nodes[0].getwalletinfo()
        assert_equal(w_info["balance"], balance0)
        assert_equal(w_info["immature_balance"], immature_balance0)
        self.log.info("Balance for node 0 checks out: %f [%f]" % (balance0, immature_balance0))

        # verify that the stakeinput can't be spent
        rawtx_unsigned = self.nodes[0].createrawtransaction(
            [{"txid": str(stakeinput["txid"]), "vout": int(stakeinput["vout"])}],
            {"xxncEuJK27ygNh7imNfaX8JV6ZQUnoBqzN": 249.99})
        rawtx = self.nodes[0].signrawtransaction(rawtx_unsigned)
        assert(rawtx["complete"])
        assert_raises_rpc_error(-25, "Missing inputs",self.nodes[0].sendrawtransaction, rawtx["hex"])

        # Stake 12 blocks with node-1
        self.log.info("Staking 12 blocks with node 1...")
        self.generateBatchBlocks(1, 12)
        balance1 -= 250 * 12                       # 0 - staked blocks inputs (250*12)
        immature_balance1 += 500 * 12              # + staked blocks (500 * 12)
        w_info = self.nodes[1].getwalletinfo()
        assert_equal(w_info["balance"], balance1)
        assert_equal(w_info["immature_balance"], immature_balance1)
        self.log.info("Balance for node 1 checks out: %f [%f]" % (balance1, immature_balance1))
        new_best_hash = self.nodes[1].getbestblockhash()

        # re-connect and sync nodes and check that node-0 gets on the other chain
        self.log.info("Connecting and syncing nodes...")
        connect_nodes_bi(self.nodes, 0, 1)
        sync_blocks(self.nodes)
        assert_equal(self.nodes[0].getbestblockhash(), new_best_hash)

        # check balance of node-0
        balance0 = initial_balance + 250 * 12                       # + mined blocks matured (250*12)
        immature_balance0 = initial_immature_balance - 250 * 12     # - mined blocks matured (250*12)
        w_info = self.nodes[0].getwalletinfo()
        assert_equal(w_info["balance"], balance0)                   # <--- !!! THIS FAILS before PR #1043
        assert_equal(w_info["immature_balance"], immature_balance0)
        self.log.info("Balance for node 0 checks out: %f [%f]" % (balance0, immature_balance0))

        # check that NOW the original stakeinput is present and spendable
        res, utxo = self.findUtxoInList(stakeinput["txid"], stakeinput["vout"], self.nodes[0].listunspent())
        assert (res and utxo["spendable"])                          # <--- !!! THIS FAILS before PR #1043
        self.log.info("Coinstake input %s...%s-%d is spendable again." % (
            stakeinput["txid"][:9], stakeinput["txid"][-4:], stakeinput["vout"]))
        self.nodes[0].sendrawtransaction(rawtx["hex"])
        self.nodes[1].generate(1)
        sync_blocks(self.nodes)
        res, utxo = self.findUtxoInList(stakeinput["txid"], stakeinput["vout"], self.nodes[0].listunspent())
        assert (not res or not utxo["spendable"])
示例#39
0
    def run_test (self):
        tmpdir = self.options.tmpdir

        # Make sure can't switch off usehd after wallet creation
        self.stop_node(1)
        self.assert_start_raises_init_error(1, ['-usehd=0'], 'already existing HD wallet')
        self.start_node(1)
        connect_nodes_bi(self.nodes, 0, 1)

        # Make sure we use hd, keep masterkeyid
        masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
        assert_equal(masterkeyid, self.nodes[1].getwalletinfo()['hdmasterkeyid'])
        assert_equal(len(masterkeyid), 40)

        # create an internal key
        change_addr = self.nodes[1].getrawchangeaddress()
        change_addrV= self.nodes[1].validateaddress(change_addr)
        assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") #first internal child key

        # Import a non-HD private key in the HD wallet
        non_hd_add = self.nodes[0].getnewaddress()
        self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add))

        # This should be enough to keep the master key and the non-HD key
        self.nodes[1].backupwallet(tmpdir + "/hd.bak")
        #self.nodes[1].dumpwallet(tmpdir + "/hd.dump")

        # Derive some HD addresses and remember the last
        # Also send funds to each add
        self.nodes[0].generate(101)
        hd_add = None
        num_hd_adds = 300
        for i in range(num_hd_adds):
            hd_add = self.nodes[1].getnewaddress()
            hd_info = self.nodes[1].validateaddress(hd_add)
            assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i)+"'")
            assert_equal(hd_info["hdseedid"], masterkeyid)
            self.nodes[0].sendtoaddress(hd_add, 1)
            self.nodes[0].generate(1)
        self.nodes[0].sendtoaddress(non_hd_add, 1)
        self.nodes[0].generate(1)

        # create an internal key (again)
        change_addr = self.nodes[1].getrawchangeaddress()
        change_addrV= self.nodes[1].validateaddress(change_addr)
        assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") #second internal child key

        self.sync_all()
        assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)

        self.log.info("Restore backup ...")
        self.stop_node(1)
        # we need to delete the complete regtest directory
        # otherwise node1 would auto-recover all funds in flag the keypool keys as used
        shutil.rmtree(os.path.join(tmpdir, "node1/regtest/blocks"))
        shutil.rmtree(os.path.join(tmpdir, "node1/regtest/chainstate"))
        shutil.copyfile(os.path.join(tmpdir, "hd.bak"), os.path.join(tmpdir, "node1/regtest/wallet.dat"))
        self.start_node(1)

        # Assert that derivation is deterministic
        hd_add_2 = None
        for _ in range(num_hd_adds):
            hd_add_2 = self.nodes[1].getnewaddress()
            hd_info_2 = self.nodes[1].validateaddress(hd_add_2)
            assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(_)+"'")
            assert_equal(hd_info_2["hdseedid"], masterkeyid)
        assert_equal(hd_add, hd_add_2)
        connect_nodes_bi(self.nodes, 0, 1)
        self.sync_all()

        # Needs rescan
        self.stop_node(1)
        self.start_node(1, extra_args=self.extra_args[1] + ['-rescan'])
        assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)

        # Try a RPC based rescan
        self.stop_node(1)
        shutil.rmtree(os.path.join(tmpdir, "node1/regtest/blocks"))
        shutil.rmtree(os.path.join(tmpdir, "node1/regtest/chainstate"))
        shutil.copyfile(os.path.join(tmpdir, "hd.bak"), os.path.join(tmpdir, "node1/regtest/wallet.dat"))
        self.start_node(1, extra_args=self.extra_args[1])
        connect_nodes_bi(self.nodes, 0, 1)
        self.sync_all()
        out = self.nodes[1].rescanblockchain(0, 1)
        assert_equal(out['start_height'], 0)
        assert_equal(out['stop_height'], 1)
        out = self.nodes[1].rescanblockchain()
        assert_equal(out['start_height'], 0)
        assert_equal(out['stop_height'], self.nodes[1].getblockcount())
        assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)

        # send a tx and make sure its using the internal chain for the changeoutput
        txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
        outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout']
        keypath = ""
        for out in outs:
            if out['value'] != 1:
                keypath = self.nodes[1].validateaddress(out['scriptPubKey']['addresses'][0])['hdkeypath']

        assert_equal(keypath[0:7], "m/0'/1'")
示例#40
0
    def run_test(self):
        pp = pprint.PrettyPrinter(indent=4)

        self.num_nodes = 4
        self.start_nodes()
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 2, 3)
        connect_nodes_bi(self.nodes, 3, 0)

        print "Announce nodes"
        self.mns = [
            Mn(self.nodes[i], "node" + str(i)) for i in range(self.num_nodes)
        ]
        for i in range(self.num_nodes):
            self.announce_mn(i)

        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        for i in range(self.num_nodes):
            assert_equal(self.dump_mn(i)['status'], "announced")

        print "Nodes announced, restarting nodes (node #3 disconnected)"
        self.stop_nodes()
        self.num_nodes = 3
        self.start_nodes([["-masternode_operator=" + self.mns[i].operator]
                          for i in range(self.num_nodes)])
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 2, 0)

        # Generate blocks for activation height
        self.nodes[0].generate(9)
        sync_blocks([self.nodes[0], self.nodes[1]])
        sync_blocks([self.nodes[0], self.nodes[2]])
        time.sleep(4)

        # Autoactivation should happen here
        self.nodes[0].generate(1)
        sync_blocks([self.nodes[0], self.nodes[1]])
        sync_blocks([self.nodes[0], self.nodes[1]])
        time.sleep(4)

        for i in range(self.num_nodes):
            assert_equal(self.dump_mn(i)['status'], "activated")

        print "Nodes activated. Waiting for node #3 became outdated (30 sec)"
        time.sleep(30)
        # Here, nodes should deside to kick off node #3
        self.nodes[0].generate(1)
        time.sleep(4)
        print "Here should be autovoting"
        self.nodes[0].generate(1)
        time.sleep(4)
        #        pp.pprint(self.nodes[0].mn_list([], True))

        print "Waiting for autofinalize"
        i = 0
        while i < 10 and self.nodes[0].mn_list([self.mns[3].id
                                                ])[0]['status'] == "announced":
            self.nodes[0].generate(1)
            time.sleep(1)
            i = i + 1
            print i

        assert_equal(self.nodes[0].mn_list([self.mns[3].id])[0]['status'],
                     "announced, dismissed")

        #        pp.pprint(self.nodes[0].mn_list([], True))

        print "Done"
示例#41
0
 def setup_network(self):
     self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
                              self.node_args)
     self.is_network_split = False
     connect_nodes_bi(self.nodes, 0, 1)
示例#42
0
 def setup_network(self, split=False):
     # Setup nodes and connect them
     self.nodes = self.setup_nodes()
     connect_nodes_bi(self.nodes, 0, 1)
     self.sync_all()
示例#43
0
    def run_test(self):
        # Check that there's no UTXO on none of the nodes
        assert_equal(len(self.nodes[0].listunspent()), 0)
        assert_equal(len(self.nodes[1].listunspent()), 0)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        self.log.info("Mining blocks...")

        self.nodes[0].generate(1)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 50)
        assert_equal(walletinfo['balance'], 0)

        self.sync_all([self.nodes[0:3]])
        self.nodes[1].generate(101)
        self.sync_all([self.nodes[0:3]])

        assert_equal(self.nodes[0].getbalance(), 50)
        assert_equal(self.nodes[1].getbalance(), 50)
        assert_equal(self.nodes[2].getbalance(), 0)

        # Check that only first and second nodes have UTXOs
        utxos = self.nodes[0].listunspent()
        assert_equal(len(utxos), 1)
        assert_equal(len(self.nodes[1].listunspent()), 1)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        self.log.info("test gettxout")
        confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[0]["vout"]
        # First, outputs that are unspent both in the chain and in the
        # mempool should appear with or without include_mempool
        txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=False)
        assert_equal(txout['value'], 50)
        txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True)
        assert_equal(txout['value'], 50)

        # Send 21 BTC from 0 to 2 using sendtoaddress call.
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
        mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)

        self.log.info("test gettxout (second part)")
        # utxo spent in mempool should be visible if you exclude mempool
        # but invisible if you include mempool
        txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False)
        assert_equal(txout['value'], 50)
        txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, True)
        assert txout is None
        # new utxo from mempool should be invisible if you exclude mempool
        # but visible if you include mempool
        txout = self.nodes[0].gettxout(mempool_txid, 0, False)
        assert txout is None
        txout1 = self.nodes[0].gettxout(mempool_txid, 0, True)
        txout2 = self.nodes[0].gettxout(mempool_txid, 1, True)
        # note the mempool tx will have randomly assigned indices
        # but 10 will go to node2 and the rest will go to node0
        balance = self.nodes[0].getbalance()
        assert_equal(set([txout1['value'], txout2['value']]), set([10, balance]))
        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 0)

        # Have node0 mine a block, thus it will collect its own fee.
        self.nodes[0].generate(1)
        self.sync_all([self.nodes[0:3]])

        # Exercise locking of unspent outputs
        unspent_0 = self.nodes[2].listunspent()[0]
        unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]}
        assert_raises_rpc_error(-8, "Invalid parameter, expected locked output", self.nodes[2].lockunspent, True, [unspent_0])
        self.nodes[2].lockunspent(False, [unspent_0])
        assert_raises_rpc_error(-8, "Invalid parameter, output already locked", self.nodes[2].lockunspent, False, [unspent_0])
        assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20)
        assert_equal([unspent_0], self.nodes[2].listlockunspent())
        self.nodes[2].lockunspent(True, [unspent_0])
        assert_equal(len(self.nodes[2].listlockunspent()), 0)
        assert_raises_rpc_error(-8, "txid must be of length 64 (not 34, for '0000000000000000000000000000000000')",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "0000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "ZZZ0000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "0000000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds",
                                self.nodes[2].lockunspent, False,
                                [{"txid": unspent_0["txid"], "vout": 999}])

        # An output should be unlocked when spent
        unspent_0 = self.nodes[1].listunspent()[0]
        self.nodes[1].lockunspent(False, [unspent_0])
        tx = self.nodes[1].createrawtransaction([unspent_0], { self.nodes[1].getnewaddress() : 1 })
        tx = self.nodes[1].fundrawtransaction(tx)['hex']
        tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"]
        self.nodes[1].sendrawtransaction(tx)
        assert_equal(len(self.nodes[1].listlockunspent()), 0)

        # Have node1 generate 100 blocks (so node0 can recover the fee)
        self.nodes[1].generate(100)
        self.sync_all([self.nodes[0:3]])

        # node0 should end up with 100 btc in block rewards plus fees, but
        # minus the 21 plus fees sent to node2
        assert_equal(self.nodes[0].getbalance(), 100 - 21)
        assert_equal(self.nodes[2].getbalance(), 21)

        # Node0 should have two unspent outputs.
        # Create a couple of transactions to send them to node2, submit them through
        # node1, and make sure both node0 and node2 pick them up properly:
        node0utxos = self.nodes[0].listunspent(1)
        assert_equal(len(node0utxos), 2)

        # create both transactions
        txns_to_send = []
        for utxo in node0utxos:
            inputs = []
            outputs = {}
            inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
            outputs[self.nodes[2].getnewaddress()] = utxo["amount"] - 3
            raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
            txns_to_send.append(self.nodes[0].signrawtransactionwithwallet(raw_tx))

        # Have node 1 (miner) send the transactions
        self.nodes[1].sendrawtransaction(txns_to_send[0]["hex"], True)
        self.nodes[1].sendrawtransaction(txns_to_send[1]["hex"], True)

        # Have node1 mine a block to confirm transactions:
        self.nodes[1].generate(1)
        self.sync_all([self.nodes[0:3]])

        assert_equal(self.nodes[0].getbalance(), 0)
        assert_equal(self.nodes[2].getbalance(), 94)

        # Verify that a spent output cannot be locked anymore
        spent_0 = {"txid": node0utxos[0]["txid"], "vout": node0utxos[0]["vout"]}
        assert_raises_rpc_error(-8, "Invalid parameter, expected unspent output", self.nodes[0].lockunspent, False, [spent_0])

        # Send 10 BTC normal
        address = self.nodes[0].getnewaddress("test")
        fee_per_byte = Decimal('0.001') / 1000
        self.nodes[2].settxfee(fee_per_byte * 1000)
        txid = self.nodes[2].sendtoaddress(address, 10, "", "", False)
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
        assert_equal(self.nodes[0].getbalance(), Decimal('10'))

        # Send 10 BTC with subtract fee from amount
        txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal -= Decimal('10')
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))

        # Sendmany 10 BTC
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [])
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_0_bal += Decimal('10')
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        # Sendmany 10 BTC with subtract fee from amount
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address])
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal -= Decimal('10')
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))

        # Test ResendWalletTransactions:
        # Create a couple of transactions, then start up a fourth
        # node (nodes[3]) and ask nodes[0] to rebroadcast.
        # EXPECT: nodes[3] should have those transactions in its mempool.
        txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
        txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
        sync_mempools(self.nodes[0:2])

        self.start_node(3)
        connect_nodes_bi(self.nodes, 0, 3)
        sync_blocks(self.nodes)

        relayed = self.nodes[0].resendwallettransactions()
        assert_equal(set(relayed), {txid1, txid2})
        sync_mempools(self.nodes)

        assert txid1 in self.nodes[3].getrawmempool()

        # check if we can list zero value tx as available coins
        # 1. create raw_tx
        # 2. hex-changed one output to 0.0
        # 3. sign and send
        # 4. check if recipient (node0) can list the zero value tx
        usp = self.nodes[1].listunspent(query_options={'minimumAmount': '49.998'})[0]
        inputs = [{"txid": usp['txid'], "vout": usp['vout']}]
        outputs = {self.nodes[1].getnewaddress(): 49.998, self.nodes[0].getnewaddress(): 11.11}

        raw_tx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000")  # replace 11.11 with 0.0 (int32)
        signed_raw_tx = self.nodes[1].signrawtransactionwithwallet(raw_tx)
        decoded_raw_tx = self.nodes[1].decoderawtransaction(signed_raw_tx['hex'])
        zero_value_txid = decoded_raw_tx['txid']
        self.nodes[1].sendrawtransaction(signed_raw_tx['hex'])

        self.sync_all()
        self.nodes[1].generate(1)  # mine a block
        self.sync_all()

        unspent_txs = self.nodes[0].listunspent()  # zero value tx must be in listunspents output
        found = False
        for uTx in unspent_txs:
            if uTx['txid'] == zero_value_txid:
                found = True
                assert_equal(uTx['amount'], Decimal('0'))
        assert found

        # do some -walletbroadcast tests
        self.stop_nodes()
        self.start_node(0, ["-walletbroadcast=0"])
        self.start_node(1, ["-walletbroadcast=0"])
        self.start_node(2, ["-walletbroadcast=0"])
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 0, 2)
        self.sync_all([self.nodes[0:3]])

        txid_not_broadcast = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
        tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
        self.nodes[1].generate(1)  # mine a block, tx should not be in there
        self.sync_all([self.nodes[0:3]])
        assert_equal(self.nodes[2].getbalance(), node_2_bal)  # should not be changed because tx was not broadcasted

        # now broadcast from another node, mine a block, sync, and check the balance
        self.nodes[1].sendrawtransaction(tx_obj_not_broadcast['hex'])
        self.nodes[1].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal += 2
        tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
        assert_equal(self.nodes[2].getbalance(), node_2_bal)

        # create another tx
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)

        # restart the nodes with -walletbroadcast=1
        self.stop_nodes()
        self.start_node(0)
        self.start_node(1)
        self.start_node(2)
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 0, 2)
        sync_blocks(self.nodes[0:3])

        self.nodes[0].generate(1)
        sync_blocks(self.nodes[0:3])
        node_2_bal += 2

        # tx should be added to balance because after restarting the nodes tx should be broadcast
        assert_equal(self.nodes[2].getbalance(), node_2_bal)

        # send a tx with value in a string (PR#6380 +)
        txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
        tx_obj = self.nodes[0].gettransaction(txid)
        assert_equal(tx_obj['amount'], Decimal('-2'))

        txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
        tx_obj = self.nodes[0].gettransaction(txid)
        assert_equal(tx_obj['amount'], Decimal('-0.0001'))

        # check if JSON parser can handle scientific notation in strings
        txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
        tx_obj = self.nodes[0].gettransaction(txid)
        assert_equal(tx_obj['amount'], Decimal('-0.0001'))

        # General checks for errors from incorrect inputs
        # This will raise an exception because the amount type is wrong
        assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4")

        # This will raise an exception since generate does not accept a string
        assert_raises_rpc_error(-1, "not an integer", self.nodes[0].generate, "2")

        # This will raise an exception for the invalid private key format
        assert_raises_rpc_error(-5, "Invalid private key encoding", self.nodes[0].importprivkey, "invalid")

        # This will raise an exception for importing an address with the PS2H flag
        temp_address = self.nodes[1].getnewaddress()
        assert_raises_rpc_error(-5, "Cannot use the p2sh flag with an address - use a script instead", self.nodes[0].importaddress, temp_address, "label", False, True)

        # This will raise an exception for attempting to dump the private key of an address you do not own
        assert_raises_rpc_error(-3, "Address does not refer to a key", self.nodes[0].dumpprivkey, temp_address)

        # This will raise an exception for attempting to get the private key of an invalid Bitcoin address
        assert_raises_rpc_error(-5, "Invalid Goldcoin address", self.nodes[0].dumpprivkey, "invalid")

        # This will raise an exception for attempting to set a label for an invalid Bitcoin address
        assert_raises_rpc_error(-5, "Invalid Goldcoin address", self.nodes[0].setlabel, "invalid address", "label")

        # This will raise an exception for importing an invalid address
        assert_raises_rpc_error(-5, "Invalid Goldcoin address or script", self.nodes[0].importaddress, "invalid")

        # This will raise an exception for attempting to import a pubkey that isn't in hex
        assert_raises_rpc_error(-5, "Pubkey must be a hex string", self.nodes[0].importpubkey, "not hex")

        # This will raise an exception for importing an invalid pubkey
        assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f")

        # Import address and private key to check correct behavior of spendable unspents
        # 1. Send some coins to generate new UTXO
        address_to_import = self.nodes[2].getnewaddress()
        txid = self.nodes[0].sendtoaddress(address_to_import, 1)
        self.nodes[0].generate(1)
        self.sync_all([self.nodes[0:3]])

        # 2. Import address from node2 to node1
        self.nodes[1].importaddress(address_to_import)

        # 3. Validate that the imported address is watch-only on node1
        assert self.nodes[1].getaddressinfo(address_to_import)["iswatchonly"]

        # 4. Check that the unspents after import are not spendable
        assert_array_result(self.nodes[1].listunspent(),
                            {"address": address_to_import},
                            {"spendable": False})

        # 5. Import private key of the previously imported address on node1
        priv_key = self.nodes[2].dumpprivkey(address_to_import)
        self.nodes[1].importprivkey(priv_key)

        # 6. Check that the unspents are now spendable on node1
        assert_array_result(self.nodes[1].listunspent(),
                            {"address": address_to_import},
                            {"spendable": True})

        # Mine a block from node0 to an address from node1
        coinbase_addr = self.nodes[1].getnewaddress()
        block_hash = self.nodes[0].generatetoaddress(1, coinbase_addr)[0]
        coinbase_txid = self.nodes[0].getblock(block_hash)['tx'][0]
        self.sync_all([self.nodes[0:3]])

        # Check that the txid and balance is found by node1
        self.nodes[1].gettransaction(coinbase_txid)

        # check if wallet or blockchain maintenance changes the balance
        self.sync_all([self.nodes[0:3]])
        blocks = self.nodes[0].generate(2)
        self.sync_all([self.nodes[0:3]])
        balance_nodes = [self.nodes[i].getbalance() for i in range(3)]
        block_count = self.nodes[0].getblockcount()

        # Check modes:
        #   - True: unicode escaped as \u....
        #   - False: unicode directly as UTF-8
        for mode in [True, False]:
            self.nodes[0].rpc.ensure_ascii = mode
            # unicode check: Basic Multilingual Plane, Supplementary Plane respectively
            for label in [u'б€б‹аБаА', u'№…Ё']:
                addr = self.nodes[0].getnewaddress()
                self.nodes[0].setlabel(addr, label)
                assert_equal(self.nodes[0].getaddressinfo(addr)['label'], label)
                assert label in self.nodes[0].listlabels()
        self.nodes[0].rpc.ensure_ascii = True  # restore to default

        # maintenance tests
        maintenance = [
            '-rescan',
            '-reindex',
            '-zapwallettxes=1',
            '-zapwallettxes=2',
            # disabled until issue is fixed: https://github.com/bitcoin/bitcoin/issues/7463
            # '-salvagewallet',
        ]
        chainlimit = 6
        for m in maintenance:
            self.log.info("check " + m)
            self.stop_nodes()
            # set lower ancestor limit for later
            self.start_node(0, [m, "-limitancestorcount=" + str(chainlimit)])
            self.start_node(1, [m, "-limitancestorcount=" + str(chainlimit)])
            self.start_node(2, [m, "-limitancestorcount=" + str(chainlimit)])
            if m == '-reindex':
                # reindex will leave rpc warm up "early"; Wait for it to finish
                wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)])
            assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)])

        # Exercise listsinceblock with the last two blocks
        coinbase_tx_1 = self.nodes[0].listsinceblock(blocks[0])
        assert_equal(coinbase_tx_1["lastblock"], blocks[1])
        assert_equal(len(coinbase_tx_1["transactions"]), 1)
        assert_equal(coinbase_tx_1["transactions"][0]["blockhash"], blocks[1])
        assert_equal(len(self.nodes[0].listsinceblock(blocks[1])["transactions"]), 0)

        # ==Check that wallet prefers to use coins that don't exceed mempool limits =====

        # Get all non-zero utxos together
        chain_addrs = [self.nodes[0].getnewaddress(), self.nodes[0].getnewaddress()]
        singletxid = self.nodes[0].sendtoaddress(chain_addrs[0], self.nodes[0].getbalance(), "", "", True)
        self.nodes[0].generate(1)
        node0_balance = self.nodes[0].getbalance()
        # Split into two chains
        rawtx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], {chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')})
        signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx)
        singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"])
        self.nodes[0].generate(1)

        # Make a long chain of unconfirmed payments without hitting mempool limit
        # Each tx we make leaves only one output of change on a chain 1 longer
        # Since the amount to send is always much less than the outputs, we only ever need one output
        # So we should be able to generate exactly chainlimit txs for each original output
        sending_addr = self.nodes[1].getnewaddress()
        txid_list = []
        for i in range(chainlimit * 2):
            txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
        assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2)
        assert_equal(len(txid_list), chainlimit * 2)

        # Without walletrejectlongchains, we will still generate a txid
        # The tx will be stored in the wallet but not accepted to the mempool
        extra_txid = self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001'))
        assert extra_txid not in self.nodes[0].getrawmempool()
        assert extra_txid in [tx["txid"] for tx in self.nodes[0].listtransactions()]
        self.nodes[0].abandontransaction(extra_txid)
        total_txs = len(self.nodes[0].listtransactions("*", 99999))

        # Try with walletrejectlongchains
        # Double chain limit but require combining inputs, so we pass SelectCoinsMinConf
        self.stop_node(0)
        self.start_node(0, extra_args=["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)])

        # wait for loadmempool
        timeout = 10
        while (timeout > 0 and len(self.nodes[0].getrawmempool()) < chainlimit * 2):
            time.sleep(0.5)
            timeout -= 0.5
        assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2)

        node0_balance = self.nodes[0].getbalance()
        # With walletrejectlongchains we will not create the tx and store it in our wallet.
        assert_raises_rpc_error(-4, "Transaction has too long of a mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01'))

        # Verify nothing new in wallet
        assert_equal(total_txs, len(self.nodes[0].listtransactions("*", 99999)))

        # Test getaddressinfo on external address. Note that these addresses are taken from disablewallet.py
        assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy")
        address_info = self.nodes[0].getaddressinfo("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
        assert_equal(address_info['address'], "mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
        assert_equal(address_info["scriptPubKey"], "76a9144e3854046c7bd1594ac904e4793b6a45b36dea0988ac")
        assert not address_info["ismine"]
        assert not address_info["iswatchonly"]
        assert not address_info["isscript"]
        assert not address_info["ischange"]

        # Test getaddressinfo 'ischange' field on change address.
        self.nodes[0].generate(1)
        destination = self.nodes[1].getnewaddress()
        txid = self.nodes[0].sendtoaddress(destination, 0.123)
        tx = self.nodes[0].decoderawtransaction(self.nodes[0].gettransaction(txid)['hex'])
        output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]]
        assert len(output_addresses) > 1
        for address in output_addresses:
            ischange = self.nodes[0].getaddressinfo(address)['ischange']
            assert_equal(ischange, address != destination)
            if ischange:
                change = address
        self.nodes[0].setlabel(change, 'foobar')
        assert_equal(self.nodes[0].getaddressinfo(change)['ischange'], False)
    def run_test(self):
        self.log.info("test -blocknotify")
        block_count = 10
        blocks = self.nodes[1].generate(block_count)

        # wait at most 10 seconds for expected file size before reading the content
        wait_until(lambda: os.path.isfile(self.block_filename) and os.stat(
            self.block_filename).st_size >= (block_count * 65),
                   timeout=10)

        # file content should equal the generated blocks hashes
        with open(self.block_filename, 'r') as f:
            assert_equal(sorted(blocks), sorted(f.read().splitlines()))

        self.log.info("test -walletnotify")
        # wait at most 10 seconds for expected file size before reading the content
        wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat(
            self.tx_filename).st_size >= (block_count * 65),
                   timeout=10)

        # file content should equal the generated transaction hashes
        txids_rpc = list(
            map(lambda t: t['txid'],
                self.nodes[1].listtransactions("*", block_count)))
        with open(self.tx_filename, 'r') as f:
            assert_equal(sorted(txids_rpc), sorted(f.read().splitlines()))
        os.remove(self.tx_filename)

        self.log.info("test -walletnotify after rescan")
        # restart node to rescan to force wallet notifications
        self.restart_node(1)
        connect_nodes_bi(self.nodes, 0, 1)

        wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat(
            self.tx_filename).st_size >= (block_count * 65),
                   timeout=10)

        # file content should equal the generated transaction hashes
        txids_rpc = list(
            map(lambda t: t['txid'],
                self.nodes[1].listtransactions("*", block_count)))
        with open(self.tx_filename, 'r') as f:
            assert_equal(sorted(txids_rpc), sorted(f.read().splitlines()))

        # Mine another 41 up-version blocks. -alertnotify should trigger on the 51st.
        self.log.info("test -alertnotify")
        self.nodes[1].generate(51)
        self.sync_all()

        # Give kabberryd 10 seconds to write the alert notification
        wait_until(lambda: os.path.isfile(self.alert_filename) and os.path.
                   getsize(self.alert_filename),
                   timeout=10)

        with open(self.alert_filename, 'r', encoding='utf8') as f:
            alert_text = f.read()

        # Mine more up-version blocks, should not get more alerts:
        self.nodes[1].generate(2)
        self.sync_all()

        with open(self.alert_filename, 'r', encoding='utf8') as f:
            alert_text2 = f.read()

        self.log.info(
            "-alertnotify should not continue notifying for more unknown version blocks"
        )
        assert_equal(alert_text, alert_text2)
示例#45
0
    def run_test(self):
        assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI

        print("Generating initial chain...")

        self.nodes[0].generate(100)
        owner = self.nodes[0].getnewaddress("", "legacy")
        self.nodes[0].generate(1)
        self.sync_blocks()

        # START
        #========================
        print("Generating accounts...")
        self.generate_accounts()
        assert_equal(len(self.accounts), self.COUNT_ACCOUNT)
        print("Generate " + str(self.COUNT_ACCOUNT) + " accounts")

        print("Generating pools...")
        self.create_pools(owner)
        assert_equal(len(self.nodes[0].listtokens({}, False)), (3 * self.COUNT_POOLS) + 1)
        assert_equal(len(self.nodes[0].listpoolpairs({}, False)), self.COUNT_POOLS)
        print("Generate " + str(self.COUNT_POOLS) + " pools and " + str(self.COUNT_POOLS * 2) + " tokens")

        print("Minting tokens...")
        mint_amount = self.mint_tokens(owner)
        assert_equal(len(self.nodes[0].getaccount(owner, {}, True)), self.COUNT_POOLS * 2)
        print("Minted " + mint_amount + " of every coin")

        print("Sending tokens...")
        self.send_tokens(owner)
        for account in self.accounts:
            assert_equal(self.nodes[0].getaccount(account, {}, True)[self.get_id_token(self.tokens[0])], self.AMOUNT_TOKEN)
        print("Tokens sent out")

        print("Adding liquidity...")
        self.add_pools_liquidity(owner)
        for pool in self.pools:
            idPool = list(self.nodes[0].getpoolpair(pool, True).keys())[0]

            idTokenA = self.nodes[0].getpoolpair(pool, True)[idPool]['idTokenA']
            idTokenB = self.nodes[0].getpoolpair(pool, True)[idPool]['idTokenB']

            reserveA = self.nodes[0].getpoolpair(pool, True)[idPool]['reserveA']
            reserveB = self.nodes[0].getpoolpair(pool, True)[idPool]['reserveB']
            assert_equal(self.liquidity[idTokenA], reserveA)
            assert_equal(self.liquidity[idTokenB], reserveB)

            reserveAB = self.nodes[0].getpoolpair(pool, True)[idPool]['reserveA/reserveB']
            reserveBA = self.nodes[0].getpoolpair(pool, True)[idPool]['reserveB/reserveA']
            resAB = int((self.liquidity[idTokenA] * self.DECIMAL) / (self.liquidity[idTokenB] * self.DECIMAL) * self.DECIMAL)
            resBA = int((self.liquidity[idTokenB] * self.DECIMAL) / (self.liquidity[idTokenA] * self.DECIMAL) * self.DECIMAL)
            assert_equal(reserveAB * self.DECIMAL, resAB)
            assert_equal(reserveBA * self.DECIMAL, resBA)
        print("Liquidity added")

        print("Setting governance variables...")
        obj = {}
        for i in range(self.COUNT_POOLS):
            obj[str(i + 1)] = 1 / self.COUNT_POOLS

        self.nodes[0].setgov({ "LP_SPLITS": obj })
        self.nodes[0].setgov({ "LP_DAILY_DFI_REWARD": self.LP_DAILY_DFI_REWARD })
        self.nodes[0].generate(1)
        self.sync_blocks()

        g1 = self.nodes[0].getgov("LP_SPLITS")
        for i in range(self.COUNT_POOLS):
            assert_equal(g1['LP_SPLITS'][str(i + 1)], 1 / self.COUNT_POOLS)

        g2 = self.nodes[0].getgov("LP_DAILY_DFI_REWARD")
        assert(g2 == {'LP_DAILY_DFI_REWARD': Decimal(self.LP_DAILY_DFI_REWARD)} )
        print("Set governance variables")

        # Stop node #2 for future revert
        self.stop_node(2)

        print("Swapping tokens...")
        start_time = time.time()
        nodes = self.nodes[0:2]
        self.poolswap(nodes)
        end_time = time.time() - start_time
        print("Tokens exchanged")
        print("Elapsed time: {} s".format(end_time))

        # REVERTING:
        #========================
        print ("Reverting...")
        self.start_node(2)
        self.nodes[2].generate(5)

        connect_nodes_bi(self.nodes, 1, 2)
        self.sync_blocks()

        # Wipe mempool
        self.nodes[0].clearmempool()
        self.nodes[1].clearmempool()
        self.nodes[2].clearmempool()

        assert(self.nodes[0].getblockcount() == 120) # eunos

        self.LP_DAILY_DFI_REWARD = self.nodes[0].getgov("LP_DAILY_DFI_REWARD")['LP_DAILY_DFI_REWARD']
        assert_equal(self.LP_DAILY_DFI_REWARD, Decimal('14843.90592000')) # 144 blocks a day times 103.08268000

        print("Swapping tokens after eunos height...")
        self.poolswap(self.nodes)
示例#46
0
 def setup_network(self):
     self.node_args[1].append('-backupdir=' + self.options.tmpdir)
     self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
                              self.node_args)
     self.is_network_split = False
     connect_nodes_bi(self.nodes, 0, 1)
示例#47
0
 def setup_network(self, split=False):
     self.nodes = start_nodes(2, self.options.tmpdir)
     connect_nodes_bi(self.nodes, 0, 1)
     self.is_network_split = False
     self.sync_all()
    def run_test(self):
        self.log.info("Ensure submitblock can in principle reorg to a competing chain")
        self.nodes[0].generate(1)
        assert_equal(self.nodes[0].getblockcount(), 1)
        hashZ = self.nodes[1].generate(2)[-1]
        assert_equal(self.nodes[1].getblockcount(), 2)
        node_sync_via_rpc(self.nodes[0:3])
        assert_equal(self.nodes[0].getbestblockhash(), hashZ)

        self.log.info("Mine blocks A-B-C on Node 0")
        hashC = self.nodes[0].generate(3)[-1]
        assert_equal(self.nodes[0].getblockcount(), 5)
        self.log.info("Mine competing blocks E-F-G on Node 1")
        hashG = self.nodes[1].generate(3)[-1]
        assert_equal(self.nodes[1].getblockcount(), 5)
        assert(hashC != hashG)
        self.log.info("Connect nodes and check no reorg occurs")
        # Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync)
        node_sync_via_rpc(self.nodes[0:2])
        connect_nodes_bi(self.nodes,0,1)
        assert_equal(self.nodes[0].getbestblockhash(), hashC)
        assert_equal(self.nodes[1].getbestblockhash(), hashG)
        self.log.info("Make Node0 prefer block G")
        self.nodes[0].preciousblock(hashG)
        assert_equal(self.nodes[0].getbestblockhash(), hashG)
        self.log.info("Make Node0 prefer block C again")
        self.nodes[0].preciousblock(hashC)
        assert_equal(self.nodes[0].getbestblockhash(), hashC)
        self.log.info("Make Node1 prefer block C")
        self.nodes[1].preciousblock(hashC)
        sync_chain(self.nodes[0:2]) # wait because node 1 may not have downloaded hashC
        assert_equal(self.nodes[1].getbestblockhash(), hashC)
        self.log.info("Make Node1 prefer block G again")
        self.nodes[1].preciousblock(hashG)
        assert_equal(self.nodes[1].getbestblockhash(), hashG)
        self.log.info("Make Node0 prefer block G again")
        self.nodes[0].preciousblock(hashG)
        assert_equal(self.nodes[0].getbestblockhash(), hashG)
        self.log.info("Make Node1 prefer block C again")
        self.nodes[1].preciousblock(hashC)
        assert_equal(self.nodes[1].getbestblockhash(), hashC)
        self.log.info("Mine another block (E-F-G-)H on Node 0 and reorg Node 1")
        self.nodes[0].generate(1)
        assert_equal(self.nodes[0].getblockcount(), 6)
        sync_blocks(self.nodes[0:2])
        hashH = self.nodes[0].getbestblockhash()
        assert_equal(self.nodes[1].getbestblockhash(), hashH)
        self.log.info("Node1 should not be able to prefer block C anymore")
        self.nodes[1].preciousblock(hashC)
        assert_equal(self.nodes[1].getbestblockhash(), hashH)
        self.log.info("Mine competing blocks I-J-K-L on Node 2")
        self.nodes[2].generate(4)
        assert_equal(self.nodes[2].getblockcount(), 6)
        hashL = self.nodes[2].getbestblockhash()
        self.log.info("Connect nodes and check no reorg occurs")
        node_sync_via_rpc(self.nodes[1:3])
        connect_nodes_bi(self.nodes,1,2)
        connect_nodes_bi(self.nodes,0,2)
        assert_equal(self.nodes[0].getbestblockhash(), hashH)
        assert_equal(self.nodes[1].getbestblockhash(), hashH)
        assert_equal(self.nodes[2].getbestblockhash(), hashL)
        self.log.info("Make Node1 prefer block L")
        self.nodes[1].preciousblock(hashL)
        assert_equal(self.nodes[1].getbestblockhash(), hashL)
        self.log.info("Make Node2 prefer block H")
        self.nodes[2].preciousblock(hashH)
        assert_equal(self.nodes[2].getbestblockhash(), hashH)
    def test_callcontract_fork(self, with_send=False, crash_point=1):
        '''
        调用同一合约,不含send操作与含send操作
        ab0[contract_ab]
          /         \
        aa1 [cca1]   bb1 [ccb1]
         |           |
        aa2         bb2
         |           |
        aa3         bb3
                     |
                    bb4
                     |
                    ...
        :param with_send:
        :return:
        '''
        self.sync_all()
        self.node0.generate(2)
        assert_equal(self.node0.getrawmempool(), [])  # make sure mempool empty
        assert_equal(self.node1.getrawmempool(), [])  # make sure mempool empty
        ct = Contract(self.node1, self.options.tmpdir, debug=False)
        ct2 = Contract(self.node1, self.options.tmpdir, debug=False)
        ct2.call_payable(amount=1000)
        print(ct.publish_txid)
        self.sync_all()
        self.node0.generate(2)
        self.sync_all()
        blocks_num = self.node1.getblockcount()

        # split mgc network
        self.split_network()
        self.node1.generate(2)  # fork
        self.node3.generate(8)  # fork

        # in group 1
        balance = self.node1.getbalance()

        # tx_ai,tx_a11,tx_a12这3个交易,在合并网络后,应该都会被重新打回内存池中,毕竟是短链
        tx_a1 = ct.call_payable(amount=2000)['txid']
        tx_a11 = ct.call_contractDataTest(amount=0)['txid']
        tx_a12 = ct.call_contractDataTest(amount=0)['txid']
        if with_send:
            tmp_ct = Contract(self.node1, debug=False)
            print(tmp_ct.publish_txid)
            tx_a13 = ct.call_callOtherContractTest(ct2.contract_id,
                                                   'callOtherContractTest',
                                                   tmp_ct.contract_id,
                                                   "contractDataTest",
                                                   amount=0)
            print("ct balance:", ct.get_balance())
            print(tx_a13)
        print(tx_a1, tx_a11, tx_a12)
        self.sync_all([self.nodes[:2], self.nodes[2:]])
        last_block_hash = self.node1.generate(2)[-1]
        assert self.node1.getrawmempool() == []
        self.sync_all([self.nodes[:2], self.nodes[2:]])

        # in group 2
        tx_b1 = ct.call_payable(amount=2000,
                                exec_node=self.node3,
                                sender=self.node3.getnewaddress())['txid']
        print(tx_b1)
        self.sync_all([self.nodes[:2], self.nodes[2:]])
        self.node3.generate(2)
        self.sync_all([self.nodes[:2], self.nodes[2:]])
        assert tx_b1 not in self.node3.getrawmempool()
        tx_b11 = ct.call_contractDataTest(amount=0,
                                          exec_node=self.node3)['txid']
        print("ct balance:", ct.get_balance(exec_node=self.node3))
        if with_send:
            # 这里有两个crash point,下面代码分别对应不同的CP
            if crash_point == 1:
                tx_b12 = ct.call_callOtherContractTest(ct2.contract_id,
                                                       'callOtherContractTest',
                                                       ct.contract_id,
                                                       "contractDataTest",
                                                       exec_node=self.node3,
                                                       amount=0)
                print("ct balance:", ct.get_balance(exec_node=self.node3))

            else:
                tx_b12 = ct.call_callOtherContractTest(ct2.contract_id,
                                                       'callOtherContractTest',
                                                       ct.contract_id,
                                                       "contractDataTest",
                                                       amount=0)
                ct.call_reentrancyTest()
                print("ct balance:", ct.get_balance(exec_node=self.node1))
            print("ct balance:", ct.get_balance(exec_node=self.node3))
            print("tx_b12:", tx_b12.txid)
        print(tx_b11)
        block_b16 = self.node3.generate(6)[-1]
        assert_equal(self.node3.getrawmempool(), [])
        if with_send and crash_point == 1:
            assert_equal(self.node1.getrawmempool(), [])
        elif with_send and crash_point == 2:
            pass
            # assert_equal(self.node1.getrawmempool(), [tx_b12.txid])
        self.sync_all([self.nodes[:2], self.nodes[2:]])

        # join network
        more_work_blocks = self.make_more_work_than(3, 1)
        for i in range(4):
            print("before join:", i, self.nodes[i].getblockcount(),
                  int(self.nodes[i].getchaintipwork(), 16))
            print("mempool:", self.nodes[i].getrawmempool())

        print("ct balance:", ct.get_balance(exec_node=self.node3))
        print("ct balance:", ct.get_balance(exec_node=self.node1))
        print("join network")
        connect_nodes_bi(self.nodes, 1, 2)
        sync_blocks(self.nodes)

        print("ct balance:", ct.get_balance(exec_node=self.node1))
        print("ct balance:", ct.get_balance(exec_node=self.node3))

        for i in range(4):
            print("mempool:", self.nodes[i].getrawmempool())
        if with_send:
            print(
                "assert_equal(len(self.node1.getrawmempool()), 5),should {} == 5"
                .format(len(self.node1.getrawmempool())))
            # assert_equal(len(self.node1.getrawmempool()), 5)  # 短链的块内交易必须是打回内存池的,否则可能有bug了
        else:
            print(
                " assert_equal(len(self.node1.getrawmempool()), 3),should {} == 5"
                .format(len(self.node1.getrawmempool())))
            # assert_equal(len(self.node1.getrawmempool()), 3)  # 短链的块内交易必须是打回内存池的,否则可能有bug了
        assert (balance - MINER_REWARD * 2 -
                2000) - self.node1.getbalance() < 100
        print("node2 ct get_balance:", ct.get_balance(exec_node=self.node2))
        bal = 2000
        if with_send and crash_point == 1:
            bal = 2000 - 20  #应该是2000-10的
        assert_equal(self.node1.getbalanceof(ct.contract_id),
                     bal)  # 减去合约的send调用
        assert_equal(self.node0.getbalanceof(ct.contract_id),
                     bal)  # 减去合约的send调用
        # assert_equal(ct.call_get('counter', broadcasting=False,amount = 0)['return'][0], 4)  # 因为本节点mempool有合约交易,所以应该为4
        assert_equal(
            ct.call_get('counter',
                        broadcasting=False,
                        exec_node=self.node2,
                        amount=0)['return'][0], 2)  # 该节点内存池中没有交易哦,所以应该为2
        for i in range(4):
            print("node{} ct2 get_balance:{}".format(
                i, ct2.get_balance(exec_node=self.nodes[i])))
        # assert_equal(self.node0.getbalanceof(ct2.contract_id), 1000 if with_send else 1000)  # 减去合约的send调用
        # assert_equal(self.node1.getbalanceof(ct2.contract_id), 1000 if with_send else 1000)  # 减去合约的send调用
        # # assert_equal(self.node2.getbalanceof(ct2.contract_id), 1000 - 10 if with_send else 1000)  # 减去合约的send调用
        # assert_equal(self.node2.getbalanceof(ct2.contract_id), 1000 - 0 if with_send else 1000)  # 减去合约的send调用

        for i in range(4):
            print(i, self.nodes[i].getblockcount(),
                  int(self.nodes[i].getchaintipwork(), 16))
        tips = self.nodes[0].getchaintips()
        print(tips)
        assert_equal(len(tips), self.tips_num + 1)
        self.tips_num += 1
        assert_equal(self.node2.getblockcount(),
                     blocks_num + 16 + len(more_work_blocks))
        assert_equal(
            self.node2.getbestblockhash(),
            block_b16 if not more_work_blocks else more_work_blocks[-1])
        print(self.node1.gettransaction(tx_a1))
        print(self.node1.gettransaction(tx_a11))

        # clear node0's and node1's mempool and check balance
        self.node1.generate(4)
        sync_blocks(self.nodes)
        assert_equal(self.node0.getrawmempool(), [])
        assert_equal(self.node1.getrawmempool(), [])
        # assert_equal(self.node1.getbalanceof(ct.contract_id), 4000 - 20 if with_send else 4000)
        bal = 4000
        if with_send and crash_point == 1:
            bal = 4000 - 40  #应该是4000- 20 的
        elif with_send and crash_point == 2:
            bal = 4000 - 20
        # assert_equal(self.node1.getbalanceof(ct.contract_id), bal)
        assert (balance - MINER_REWARD * 2 -
                2000) - self.node1.getbalance() < 100

        # In bestchain,ensure contract data is correct
        # for i in range(4):
        #     assert_equal(
        #         ct.call_get('counter', exec_node=self.nodes[i], sender=self.nodes[i].getnewaddress(),amount = 0)['return'][0], 4)

        # 未完成的用例,下面的有问题,先屏蔽
        # '''
        # listsinceblock(lastblockhash) should now include txid_a1, as seen from nodes[0]
        # 这里只有node1节点才成功,换成其他节点时失败的,这不应该
        lsbres = self.nodes[1].listsinceblock(last_block_hash)
        assert any(
            tx['txid'] == tx_a1
            for tx in lsbres['transactions'])  # 这里只有node1节点才成功,换成其他节点时失败的,这不应该

        # but it should not include 'removed' if include_removed=false
        lsbres2 = self.nodes[1].listsinceblock(blockhash=last_block_hash,
                                               include_removed=False)
        assert 'removed' not in lsbres2
    def run_test(self):
        self.nodes[0].importaddress(ADDRESS_WATCHONLY)
        # Check that nodes don't own any UTXOs
        assert_equal(len(self.nodes[0].listunspent()), 0)
        assert_equal(len(self.nodes[1].listunspent()), 0)

        self.log.info("Check that only node 0 is watching an address")
        assert 'watchonly' in self.nodes[0].getbalances()
        assert 'watchonly' not in self.nodes[1].getbalances()

        self.log.info("Mining blocks ...")
        self.nodes[0].generate(1)
        self.sync_all()
        self.nodes[1].generate(1)
        self.nodes[1].generatetoaddress(101, ADDRESS_WATCHONLY)
        self.sync_all()

        assert_equal(self.nodes[0].getbalances()['mine']['trusted'], 50)
        assert_equal(self.nodes[0].getwalletinfo()['balance'], 50)
        assert_equal(self.nodes[1].getbalances()['mine']['trusted'], 50)

        assert_equal(self.nodes[0].getbalances()['watchonly']['immature'],
                     5000)
        assert 'watchonly' not in self.nodes[1].getbalances()

        assert_equal(self.nodes[0].getbalance(), 50)
        assert_equal(self.nodes[1].getbalance(), 50)

        self.log.info("Test getbalance with different arguments")
        assert_equal(self.nodes[0].getbalance("*"), 50)
        assert_equal(self.nodes[0].getbalance("*", 1), 50)
        assert_equal(self.nodes[0].getbalance("*", 1, True), 100)
        assert_equal(self.nodes[0].getbalance(minconf=1), 50)
        assert_equal(
            self.nodes[0].getbalance(minconf=0, include_watchonly=True), 100)
        assert_equal(
            self.nodes[1].getbalance(minconf=0, include_watchonly=True), 50)

        # Send 40 CRT from 0 to 1 and 60 CRT from 1 to 0.
        txs = create_transactions(self.nodes[0], self.nodes[1].getnewaddress(),
                                  40, [Decimal('0.01')])
        self.nodes[0].sendrawtransaction(txs[0]['hex'])
        self.nodes[1].sendrawtransaction(
            txs[0]['hex']
        )  # sending on both nodes is faster than waiting for propagation

        self.sync_all()
        txs = create_transactions(
            self.nodes[1], self.nodes[0].getnewaddress(), 60,
            [Decimal('0.01'), Decimal('0.02')])
        self.nodes[1].sendrawtransaction(txs[0]['hex'])
        self.nodes[0].sendrawtransaction(
            txs[0]['hex']
        )  # sending on both nodes is faster than waiting for propagation
        self.sync_all()

        # First argument of getbalance must be set to "*"
        assert_raises_rpc_error(
            -32, "dummy first argument must be excluded or set to \"*\"",
            self.nodes[1].getbalance, "")

        self.log.info(
            "Test getbalance and getunconfirmedbalance with unconfirmed inputs"
        )

        def test_balances(*, fee_node_1=0):
            # getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions
            assert_equal(self.nodes[0].getbalance(),
                         Decimal('9.99'))  # change from node 0's send
            assert_equal(self.nodes[1].getbalance(),
                         Decimal('30') -
                         fee_node_1)  # change from node 1's send
            # Same with minconf=0
            assert_equal(self.nodes[0].getbalance(minconf=0), Decimal('9.99'))
            assert_equal(self.nodes[1].getbalance(minconf=0),
                         Decimal('30') - fee_node_1)
            # getbalance with a minconf incorrectly excludes coins that have been spent more recently than the minconf blocks ago
            # TODO: fix getbalance tracking of coin spentness depth
            assert_equal(self.nodes[0].getbalance(minconf=1), Decimal('0'))
            assert_equal(self.nodes[1].getbalance(minconf=1), Decimal('0'))
            # getunconfirmedbalance
            assert_equal(self.nodes[0].getunconfirmedbalance(),
                         Decimal('60'))  # output of node 1's spend
            assert_equal(
                self.nodes[0].getbalances()['mine']['untrusted_pending'],
                Decimal('60'))
            assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"],
                         Decimal('60'))

            assert_equal(
                self.nodes[1].getunconfirmedbalance(), Decimal('0')
            )  # Doesn't include output of node 0's send since it was spent
            assert_equal(
                self.nodes[1].getbalances()['mine']['untrusted_pending'],
                Decimal('0'))
            assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"],
                         Decimal('0'))

        test_balances(fee_node_1=Decimal('0.01'))

        # Node 1 bumps the transaction fee and resends
        self.nodes[1].sendrawtransaction(txs[1]['hex'])
        self.nodes[0].sendrawtransaction(
            txs[1]['hex']
        )  # sending on both nodes is faster than waiting for propagation
        self.sync_all()

        self.log.info(
            "Test getbalance and getunconfirmedbalance with conflicted unconfirmed inputs"
        )
        test_balances(fee_node_1=Decimal('0.02'))

        self.nodes[1].generatetoaddress(1, ADDRESS_WATCHONLY)
        self.sync_all()

        # balances are correct after the transactions are confirmed
        assert_equal(
            self.nodes[0].getbalance(),
            Decimal('69.99'))  # node 1's send plus change from node 0's send
        assert_equal(self.nodes[1].getbalance(),
                     Decimal('29.98'))  # change from node 0's send

        # Send total balance away from node 1
        txs = create_transactions(self.nodes[1], self.nodes[0].getnewaddress(),
                                  Decimal('29.97'), [Decimal('0.01')])
        self.nodes[1].sendrawtransaction(txs[0]['hex'])
        self.nodes[1].generatetoaddress(2, ADDRESS_WATCHONLY)
        self.sync_all()

        # getbalance with a minconf incorrectly excludes coins that have been spent more recently than the minconf blocks ago
        # TODO: fix getbalance tracking of coin spentness depth
        # getbalance with minconf=3 should still show the old balance
        assert_equal(self.nodes[1].getbalance(minconf=3), Decimal('0'))

        # getbalance with minconf=2 will show the new balance.
        assert_equal(self.nodes[1].getbalance(minconf=2), Decimal('0'))

        # check mempool transactions count for wallet unconfirmed balance after
        # dynamically loading the wallet.
        before = self.nodes[1].getunconfirmedbalance()
        dst = self.nodes[1].getnewaddress()
        self.nodes[1].unloadwallet('')
        self.nodes[0].sendtoaddress(dst, 0.1)
        self.sync_all()
        self.nodes[1].loadwallet('')
        after = self.nodes[1].getunconfirmedbalance()
        assert_equal(before + Decimal('0.1'), after)

        # Create 3 more wallet txs, where the last is not accepted to the
        # mempool because it is the third descendant of the tx above
        for _ in range(3):
            # Set amount high enough such that all coins are spent by each tx
            txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(),
                                               99)

        self.log.info('Check that wallet txs not in the mempool are untrusted')
        assert txid not in self.nodes[0].getrawmempool()
        assert_equal(self.nodes[0].gettransaction(txid)['trusted'], False)
        assert_equal(self.nodes[0].getbalance(minconf=0), 0)

        self.log.info("Test replacement and reorg of non-mempool tx")
        tx_orig = self.nodes[0].gettransaction(txid)['hex']
        # Increase fee by 1 coin
        tx_replace = tx_orig.replace(
            struct.pack("<q", 99 * 10**8).hex(),
            struct.pack("<q", 98 * 10**8).hex(),
        )
        tx_replace = self.nodes[0].signrawtransactionwithwallet(
            tx_replace)['hex']
        # Total balance is given by the sum of outputs of the tx
        total_amount = sum([
            o['value']
            for o in self.nodes[0].decoderawtransaction(tx_replace)['vout']
        ])
        self.sync_all()
        self.nodes[1].sendrawtransaction(hexstring=tx_replace, maxfeerate=0)

        # Now confirm tx_replace
        block_reorg = self.nodes[1].generatetoaddress(1, ADDRESS_WATCHONLY)[0]
        self.sync_all()
        assert_equal(self.nodes[0].getbalance(minconf=0), total_amount)

        self.log.info('Put txs back into mempool of node 1 (not node 0)')
        self.nodes[0].invalidateblock(block_reorg)
        self.nodes[1].invalidateblock(block_reorg)
        assert_equal(self.nodes[0].getbalance(minconf=0),
                     0)  # wallet txs not in the mempool are untrusted
        self.nodes[0].generatetoaddress(1, ADDRESS_WATCHONLY)
        assert_equal(self.nodes[0].getbalance(minconf=0),
                     0)  # wallet txs not in the mempool are untrusted

        # Now confirm tx_orig
        self.restart_node(1, ['-persistmempool=0'])
        connect_nodes_bi(self.nodes, 0, 1)
        sync_blocks(self.nodes)
        self.nodes[1].sendrawtransaction(tx_orig)
        self.nodes[1].generatetoaddress(1, ADDRESS_WATCHONLY)
        self.sync_all()
        assert_equal(self.nodes[0].getbalance(minconf=0),
                     total_amount + 1)  # The reorg recovered our fee of 1 coin
    def run_test(self):
        node = self.nodes[0].add_p2p_connection(P2PIgnoreInv())
        network_thread_start()
        node.wait_for_verack()

        expected_services = NODE_BLOOM | NODE_WITNESS | NODE_NETWORK_LIMITED

        self.log.info("Check that node has signalled expected services.")
        assert_equal(node.nServices, expected_services)

        self.log.info("Check that the localservices is as expected.")
        assert_equal(int(self.nodes[0].getnetworkinfo()['localservices'], 16),
                     expected_services)

        self.log.info(
            "Mine enough blocks to reach the NODE_NETWORK_LIMITED range.")
        connect_nodes_bi(self.nodes, 0, 1)
        blocks = self.nodes[1].generate(292)
        sync_blocks([self.nodes[0], self.nodes[1]])

        self.log.info("Make sure we can max retrieve block at tip-288.")
        node.send_getdata_for_block(blocks[1])  # last block in valid range
        node.wait_for_block(int(blocks[1], 16), timeout=3)

        self.log.info(
            "Requesting block at height 2 (tip-289) must fail (ignored).")
        node.send_getdata_for_block(
            blocks[0])  # first block outside of the 288+2 limit
        node.wait_for_disconnect(5)

        self.log.info("Check local address relay, do a fresh connection.")
        self.nodes[0].disconnect_p2ps()
        network_thread_join()
        node1 = self.nodes[0].add_p2p_connection(P2PIgnoreInv())
        network_thread_start()
        node1.wait_for_verack()
        node1.send_message(msg_verack())

        node1.wait_for_addr()
        #must relay address with NODE_NETWORK_LIMITED
        assert_equal(node1.firstAddrnServices, 1036)

        self.nodes[0].disconnect_p2ps()
        node1.wait_for_disconnect()

        # connect unsynced node 2 with pruned NODE_NETWORK_LIMITED peer
        # because node 2 is in IBD and node 0 is a NODE_NETWORK_LIMITED peer, sync must not be possible
        connect_nodes_bi(self.nodes, 0, 2)
        try:
            sync_blocks([self.nodes[0], self.nodes[2]], timeout=5)
        except:
            pass
        # node2 must remain at heigh 0
        assert_equal(
            self.nodes[2].getblockheader(
                self.nodes[2].getbestblockhash())['height'], 0)

        # now connect also to node 1 (non pruned)
        connect_nodes_bi(self.nodes, 1, 2)

        # sync must be possible
        sync_blocks(self.nodes)

        # disconnect all peers
        self.disconnect_all()

        # mine 10 blocks on node 0 (pruned node)
        self.nodes[0].generate(10)

        # connect node1 (non pruned) with node0 (pruned) and check if the can sync
        connect_nodes_bi(self.nodes, 0, 1)

        # sync must be possible, node 1 is no longer in IBD and should therefore connect to node 0 (NODE_NETWORK_LIMITED)
        sync_blocks([self.nodes[0], self.nodes[1]])
 def setup_network(self, split=False):
     super().setup_network()
     connect_nodes_bi(self.nodes, 0, 2)
示例#53
0
    def run_test(self):
        assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI

        self.nodes[0].generate(100)
        self.sync_all()

        # Stop node #3 for future revert
        self.stop_node(3)

        # CREATION:
        #========================
        collateral0 = self.nodes[0].getnewaddress("", "legacy")

        self.nodes[0].generate(1)

        # 1 Creating DAT token
        self.nodes[0].createtoken({
            "symbol": "PT",
            "name": "Platinum",
            "isDAT": True,
            "collateralAddress": collateral0
        })

        self.nodes[0].generate(1)
        self.sync_blocks([self.nodes[0], self.nodes[2]])

        # At this point, token was created
        tokens = self.nodes[0].listtokens()
        assert_equal(len(tokens), 2)
        assert_equal(tokens['1']["symbol"], "PT")

        # check sync:
        tokens = self.nodes[2].listtokens()
        assert_equal(len(tokens), 2)
        assert_equal(tokens['1']["symbol"], "PT")

        # 3 Trying to make regular token
        self.nodes[0].generate(1)
        createTokenTx = self.nodes[0].createtoken({
            "symbol": "GOLD",
            "name": "shiny gold",
            "isDAT": False,
            "collateralAddress": collateral0
        })
        self.nodes[0].generate(1)
        # Checks
        tokens = self.nodes[0].listtokens()
        assert_equal(len(tokens), 3)
        assert_equal(tokens['128']["symbol"], "GOLD")
        assert_equal(tokens['128']["creationTx"], createTokenTx)

        # 7 Creating PoolPair from Foundation -> OK
        self.nodes[0].createpoolpair({
            "tokenA": "PT",
            "tokenB": "GOLD#128",
            "comission": 0.001,
            "status": True,
            "ownerAddress": collateral0,
            "pairSymbol": "PTGOLD"
        }, [])

        self.nodes[0].generate(1)
        # Trying to create the same again and fail
        try:
            self.nodes[0].createpoolpair({
            "tokenA": "PT",
            "tokenB": "GOLD#128",
            "comission": 0.001,
            "status": True,
            "ownerAddress": collateral0,
            "pairSymbol": "PTGD"
        }, [])
        except JSONRPCException as e:
            errorString = e.error['message']
        assert("Error, there is already a poolpairwith same tokens, but different poolId" in errorString)

        # Creating another one
        trPP = self.nodes[0].createpoolpair({
            "tokenA": "DFI",
            "tokenB": "GOLD#128",
            "comission": 0.001,
            "status": True,
            "ownerAddress": collateral0,
            "pairSymbol": "DFGLD"
        }, [])

        # 7+ Checking if it's an automatically created token (collateral unlocked, user's token has collateral locked)
        tx = self.nodes[0].getrawtransaction(trPP)
        decodeTx = self.nodes[0].decoderawtransaction(tx)
        assert_equal(len(decodeTx['vout']), 2)
        #print(decodeTx['vout'][1]['scriptPubKey']['hex'])

        spendTx = self.nodes[0].createrawtransaction([{'txid':decodeTx['txid'], 'vout':1}],[{collateral0:9.999}])
        signedTx = self.nodes[0].signrawtransactionwithwallet(spendTx)
        assert_equal(signedTx['complete'], True)

        self.nodes[0].generate(1)
        # 8 Creating PoolPair not from Foundation -> Error
        try:
            self.nodes[2].createpoolpair({
            "tokenA": "DFI",
            "tokenB": "GOLD#128",
            "comission": 0.001,
            "status": True,
            "ownerAddress": collateral0,
            "pairSymbol": "DFIGOLD"
        }, [])
        except JSONRPCException as e:
            errorString = e.error['message']
        assert("Need foundation member authorization" in errorString)

        # 9 Checking pool existence
        p0 = self.nodes[0].getpoolpair("PTGOLD")
        assert_equal(p0['2']['symbol'], "PTGOLD")

        #10 Checking nonexistent pool
        try:
            self.nodes[0].getpoolpair("DFIGOLD")
        except JSONRPCException as e:
            errorString = e.error['message']
        assert("Pool not found" in errorString)

        try:
            self.nodes[2].getpoolpair("PTGOLD")
        except JSONRPCException as e:
            errorString = e.error['message']
        assert("Pool not found" in errorString)

        #11 Checking listpoolpairs
        poolpairsn0 = self.nodes[0].listpoolpairs()
        assert_equal(len(poolpairsn0), 2)

        self.sync_blocks([self.nodes[0], self.nodes[2]])

        poolpairsn2 = self.nodes[2].listpoolpairs()
        #print (poolpairsn2)
        assert_equal(len(poolpairsn2), 2)

        # 12 Checking pool existence after sync
        p1 = self.nodes[2].getpoolpair("PTGOLD")
        #print(p1)
        assert_equal(p1['2']['symbol'], "PTGOLD")
        assert(p1['2']['idTokenA'] == '1')
        assert(p1['2']['idTokenB'] == '128')

        # 13 Change pool status
        assert_equal(self.nodes[0].getpoolpair("PTGOLD")['2']['status'], True)
        self.nodes[0].updatepoolpair({
            "pool": "PTGOLD",
            "status": False,
            "commission": 0.01
        }, [])
        self.nodes[0].generate(1)

        assert_equal(self.nodes[0].getpoolpair("PTGOLD")['2']['status'], False)
        assert_equal(str(self.nodes[0].getpoolpair("PTGOLD")['2']['commission']), "0.01000000")
        self.sync_blocks([self.nodes[0], self.nodes[2]])
        assert_equal(self.nodes[2].getpoolpair("PTGOLD")['2']['status'], False)
        assert_equal(str(self.nodes[2].getpoolpair("PTGOLD")['2']['commission']), "0.01000000")

        self.nodes[0].updatepoolpair({"pool": "PTGOLD", "commission": 0.1}, [])
        self.nodes[0].generate(1)
        assert_equal(self.nodes[0].getpoolpair("PTGOLD")['2']['status'], False)
        assert_equal(str(self.nodes[0].getpoolpair("PTGOLD")['2']['commission']), "0.10000000")

        try:
            self.nodes[0].updatepoolpair({"pool": "PTGOLD", "commission": 2})
        except JSONRPCException as e:
            errorString = e.error['message']
        assert("commission > 100%" in errorString)

        self.nodes[0].updatepoolpair({"pool": "PTGOLD", "status": True}, [])
        self.nodes[0].generate(1)
        assert_equal(self.nodes[0].getpoolpair("PTGOLD")['2']['status'], True)
        assert_equal(str(self.nodes[0].getpoolpair("PTGOLD")['2']['commission']), "0.10000000")

        ownerAddress = self.nodes[0].getpoolpair("PTGOLD")['2']['ownerAddress']
        collateral1 = self.nodes[1].getnewaddress("", "legacy")
        self.nodes[0].updatepoolpair({"pool": "PTGOLD", "ownerAddress": collateral1}, [])
        self.nodes[0].generate(1)
        assert_equal(self.nodes[0].getpoolpair("PTGOLD")['2']['status'], True)
        assert_equal(str(self.nodes[0].getpoolpair("PTGOLD")['2']['commission']), "0.10000000")
        assert(self.nodes[0].getpoolpair("PTGOLD")['2']['ownerAddress'] != ownerAddress)

        self.nodes[0].updatepoolpair({"pool": "PTGOLD", "ownerAddress": collateral0}, [])
        self.nodes[0].generate(1)
        assert_equal(self.nodes[0].getpoolpair("PTGOLD")['2']['ownerAddress'], ownerAddress)

        # REVERTING:
        #========================
        print ("Reverting...")
        # Reverting creation!
        self.start_node(3)
        self.nodes[3].generate(30)

        connect_nodes_bi(self.nodes, 0, 3)
        self.sync_blocks()
        assert_equal(len(self.nodes[0].listpoolpairs()), 0)
示例#54
0
    def run_test(self):
        self.log.info("Test setban and listbanned RPCs")

        self.log.info("setban: successfully ban single IP address")
        assert_equal(
            len(self.nodes[1].getpeerinfo()),
            2)  # node1 should have 2 connections to node0 at this point
        self.nodes[1].setban("127.0.0.1", "add")
        wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0, timeout=10)
        assert_equal(len(self.nodes[1].getpeerinfo()),
                     0)  # all nodes must be disconnected at this point
        assert_equal(len(self.nodes[1].listbanned()), 1)

        self.log.info("clearbanned: successfully clear ban list")
        self.nodes[1].clearbanned()
        assert_equal(len(self.nodes[1].listbanned()), 0)
        self.nodes[1].setban("127.0.0.0/24", "add")

        self.log.info("setban: fail to ban an already banned subnet")
        assert_equal(len(self.nodes[1].listbanned()), 1)
        assert_raises_rpc_error(-23, "IP/Subnet already banned",
                                self.nodes[1].setban, "127.0.0.1", "add")

        self.log.info("setban: fail to ban an invalid subnet")
        assert_raises_rpc_error(-30, "Error: Invalid IP/Subnet",
                                self.nodes[1].setban, "127.0.0.1/42", "add")
        assert_equal(
            len(self.nodes[1].listbanned()), 1
        )  # still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24

        self.log.info("setban remove: fail to unban a non-banned subnet")
        assert_raises_rpc_error(-30, "Error: Unban failed",
                                self.nodes[1].setban, "127.0.0.1", "remove")
        assert_equal(len(self.nodes[1].listbanned()), 1)

        self.log.info("setban remove: successfully unban subnet")
        self.nodes[1].setban("127.0.0.0/24", "remove")
        assert_equal(len(self.nodes[1].listbanned()), 0)
        self.nodes[1].clearbanned()
        assert_equal(len(self.nodes[1].listbanned()), 0)

        self.log.info("setban: test persistence across node restart")
        self.nodes[1].setban("127.0.0.0/32", "add")
        self.nodes[1].setban("127.0.0.0/24", "add")
        # Set the mocktime so we can control when bans expire
        old_time = int(time.time())
        self.nodes[1].setmocktime(old_time)
        self.nodes[1].setban("192.168.0.1", "add", 1)  # ban for 1 seconds
        self.nodes[1].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19",
                             "add", 1000)  # ban for 1000 seconds
        listBeforeShutdown = self.nodes[1].listbanned()
        assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address'])
        # Move time forward by 3 seconds so the third ban has expired
        self.nodes[1].setmocktime(old_time + 3)
        assert_equal(len(self.nodes[1].listbanned()), 3)

        self.stop_node(1)
        self.start_node(1)

        listAfterShutdown = self.nodes[1].listbanned()
        assert_equal("127.0.0.0/24", listAfterShutdown[0]['address'])
        assert_equal("127.0.0.0/32", listAfterShutdown[1]['address'])
        assert_equal("/19" in listAfterShutdown[2]['address'], True)

        # Clear ban lists
        self.nodes[1].clearbanned()
        connect_nodes_bi(self.nodes, 0, 1)

        self.log.info("Test disconnectnode RPCs")

        self.log.info(
            "disconnectnode: fail to disconnect when calling with address and nodeid"
        )
        address1 = self.nodes[0].getpeerinfo()[0]['addr']
        node1 = self.nodes[0].getpeerinfo()[0]['addr']
        assert_raises_rpc_error(
            -32602,
            "Only one of address and nodeid should be provided.",
            self.nodes[0].disconnectnode,
            address=address1,
            nodeid=node1)

        self.log.info(
            "disconnectnode: fail to disconnect when calling with junk address"
        )
        assert_raises_rpc_error(-29,
                                "Node not found in connected nodes",
                                self.nodes[0].disconnectnode,
                                address="221B Baker Street")

        self.log.info(
            "disconnectnode: successfully disconnect node by address")
        address1 = self.nodes[0].getpeerinfo()[0]['addr']
        self.nodes[0].disconnectnode(address=address1)
        wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10)
        assert not [
            node
            for node in self.nodes[0].getpeerinfo() if node['addr'] == address1
        ]

        self.log.info("disconnectnode: successfully reconnect node")
        connect_nodes_bi(self.nodes, 0, 1)  # reconnect the node
        assert_equal(len(self.nodes[0].getpeerinfo()), 2)
        assert [
            node for node in self.nodes[0].getpeerinfo()
            if node['addr'] == address1
        ]

        self.log.info(
            "disconnectnode: successfully disconnect node by node id")
        id1 = self.nodes[0].getpeerinfo()[0]['id']
        self.nodes[0].disconnectnode(nodeid=id1)
        wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10)
        assert not [
            node for node in self.nodes[0].getpeerinfo() if node['id'] == id1
        ]
示例#55
0
    def run_test(self):
        wallet_path = os.path.join(self.nodes[1].datadir, "regtest", "wallets",
                                   "wallet.dat")
        wallet_backup_path = os.path.join(self.nodes[1].datadir, "wallet.bak")
        self.nodes[0].generate(101)

        self.log.info("Make backup of wallet")
        self.stop_node(1)
        shutil.copyfile(wallet_path, wallet_backup_path)
        self.start_node(1, self.extra_args[1])
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 0, 2)
        connect_nodes_bi(self.nodes, 0, 3)

        for i, output_type in enumerate(["legacy", "p2sh-segwit", "bech32"]):

            self.log.info(
                "Generate keys for wallet with address type: {}".format(
                    output_type))
            idx = i + 1
            for _ in range(90):
                addr_oldpool = self.nodes[idx].getnewaddress(
                    address_type=output_type)
            for _ in range(20):
                addr_extpool = self.nodes[idx].getnewaddress(
                    address_type=output_type)

            # Make sure we're creating the outputs we expect
            address_details = self.nodes[idx].validateaddress(addr_extpool)
            if i == 0:
                assert not address_details["isscript"] and not address_details[
                    "iswitness"]
            elif i == 1:
                assert address_details[
                    "isscript"] and not address_details["iswitness"]
            else:
                assert not address_details["isscript"] and address_details[
                    "iswitness"]

            self.log.info("Send funds to wallet")
            self.nodes[0].sendtoaddress(addr_oldpool, 10)
            self.nodes[0].generate(1)
            self.nodes[0].sendtoaddress(addr_extpool, 5)
            self.nodes[0].generate(1)
            self.sync_blocks()

            self.log.info("Restart node with wallet backup")
            self.stop_node(idx)
            shutil.copyfile(wallet_backup_path, wallet_path)
            self.start_node(idx, self.extra_args[idx])
            connect_nodes_bi(self.nodes, 0, idx)
            self.sync_all()

            self.log.info("Verify keypool is restored and balance is correct")
            assert_equal(self.nodes[idx].getbalance(), 15)
            assert_equal(self.nodes[idx].listtransactions()[0]['category'],
                         "receive")
            # Check that we have marked all keys up to the used keypool key as used
            assert_equal(
                self.nodes[idx].getaddressinfo(
                    self.nodes[idx].getnewaddress())['hdkeypath'],
                "m/0'/0'/110'")
示例#56
0
    def run_test(self):
        # add zaddr to node 0
        myzaddr0 = self.nodes[0].z_getnewaddress()

        # send node 0 taddr to zaddr to get out of coinbase
        mytaddr = self.nodes[0].getnewaddress()
        recipients = []
        recipients.append({
            "address": myzaddr0,
            "amount": Decimal('10.0') - Decimal('0.0001')
        })  # utxo amount less fee
        myopid = self.nodes[0].z_sendmany(mytaddr, recipients)

        opids = []
        opids.append(myopid)

        timeout = 120
        status = None
        for x in xrange(1, timeout):
            results = self.nodes[0].z_getoperationresult(opids)
            if len(results) == 0:
                time.sleep(1)
            else:
                status = results[0]["status"]
                assert_equal("success", status)
                mytxid = results[0]["result"]["txid"]
                break

        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        # add zaddr to node 2
        myzaddr = self.nodes[2].z_getnewaddress()

        # import node 2 zaddr into node 1
        myzkey = self.nodes[2].z_exportkey(myzaddr)
        self.nodes[1].z_importkey(myzkey)

        # encrypt node 1 wallet and wait to terminate
        self.nodes[1].encryptwallet("test")
        litecoinzd_processes[1].wait()

        # restart node 1
        self.nodes[1] = start_node(1, self.options.tmpdir)
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        self.sync_all()

        # send node 0 zaddr to note 2 zaddr
        recipients = []
        recipients.append({"address": myzaddr, "amount": 7.0})
        myopid = self.nodes[0].z_sendmany(myzaddr0, recipients)

        opids = []
        opids.append(myopid)

        timeout = 120
        status = None
        for x in xrange(1, timeout):
            results = self.nodes[0].z_getoperationresult(opids)
            if len(results) == 0:
                time.sleep(1)
            else:
                status = results[0]["status"]
                assert_equal("success", status)
                mytxid = results[0]["result"]["txid"]
                break

        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        # check zaddr balance
        zsendmanynotevalue = Decimal('7.0')
        assert_equal(self.nodes[2].z_getbalance(myzaddr), zsendmanynotevalue)
        assert_equal(self.nodes[1].z_getbalance(myzaddr), zsendmanynotevalue)

        # add zaddr to node 3
        myzaddr3 = self.nodes[3].z_getnewaddress()

        # send node 2 zaddr to note 3 zaddr
        recipients = []
        recipients.append({"address": myzaddr3, "amount": 2.0})
        myopid = self.nodes[2].z_sendmany(myzaddr, recipients)

        opids = []
        opids.append(myopid)

        timeout = 120
        status = None
        for x in xrange(1, timeout):
            results = self.nodes[2].z_getoperationresult(opids)
            if len(results) == 0:
                time.sleep(1)
            else:
                status = results[0]["status"]
                assert_equal("success", status)
                mytxid = results[0]["result"]["txid"]
                break

        self.sync_all()
        self.nodes[2].generate(1)
        self.sync_all()

        # check zaddr balance
        zsendmany2notevalue = Decimal('2.0')
        zsendmanyfee = Decimal('0.0001')
        zaddrremaining = zsendmanynotevalue - zsendmany2notevalue - zsendmanyfee
        assert_equal(self.nodes[3].z_getbalance(myzaddr3), zsendmany2notevalue)
        assert_equal(self.nodes[2].z_getbalance(myzaddr), zaddrremaining)

        # Parallel encrypted wallet can't cache nullifiers for received notes,
        # and therefore can't detect spends. So it sees a balance corresponding
        # to the sum of both notes it received (one as change).
        # TODO: Devise a way to avoid this issue (#1528)
        assert_equal(self.nodes[1].z_getbalance(myzaddr),
                     zsendmanynotevalue + zaddrremaining)

        # send node 2 zaddr on node 1 to taddr
        # This requires that node 1 be unlocked, which triggers caching of
        # uncached nullifiers.
        self.nodes[1].walletpassphrase("test", 600)
        mytaddr1 = self.nodes[1].getnewaddress()
        recipients = []
        recipients.append({"address": mytaddr1, "amount": 1.0})
        myopid = self.nodes[1].z_sendmany(myzaddr, recipients)

        opids = []
        opids.append(myopid)

        timeout = 120
        status = None
        for x in xrange(1, timeout):
            results = self.nodes[1].z_getoperationresult(opids)
            if len(results) == 0:
                time.sleep(1)
            else:
                status = results[0]["status"]
                assert_equal("success", status)
                mytxid = results[0]["result"]["txid"]
                [mytxid]  # hush pyflakes
                break

        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()

        # check zaddr balance
        # Now that the encrypted wallet has been unlocked, the note nullifiers
        # have been cached and spent notes can be detected. Thus the two wallets
        # are in agreement once more.
        zsendmany3notevalue = Decimal('1.0')
        zaddrremaining2 = zaddrremaining - zsendmany3notevalue - zsendmanyfee
        assert_equal(self.nodes[1].z_getbalance(myzaddr), zaddrremaining2)
        assert_equal(self.nodes[2].z_getbalance(myzaddr), zaddrremaining2)

        # Test viewing keys

        node3mined = Decimal('250.0')
        assert_equal(
            {
                k: Decimal(v)
                for k, v in self.nodes[3].z_gettotalbalance().items()
            }, {
                'transparent': node3mined,
                'private': zsendmany2notevalue,
                'total': node3mined + zsendmany2notevalue,
            })

        # add node 1 address and node 2 viewing key to node 3
        myzvkey = self.nodes[2].z_exportviewingkey(myzaddr)
        self.nodes[3].importaddress(mytaddr1)
        self.nodes[3].z_importviewingkey(myzvkey)

        # Check the address has been imported
        assert_equal(myzaddr in self.nodes[3].z_listaddresses(), False)
        assert_equal(myzaddr in self.nodes[3].z_listaddresses(True), True)

        # Node 3 should see the same received notes as node 2
        assert_equal(self.nodes[2].z_listreceivedbyaddress(myzaddr),
                     self.nodes[3].z_listreceivedbyaddress(myzaddr))

        # Node 3's balances should be unchanged without explicitly requesting
        # to include watch-only balances
        assert_equal(
            {
                k: Decimal(v)
                for k, v in self.nodes[3].z_gettotalbalance().items()
            }, {
                'transparent': node3mined,
                'private': zsendmany2notevalue,
                'total': node3mined + zsendmany2notevalue,
            })

        # Wallet can't cache nullifiers for notes received by addresses it only has a
        # viewing key for, and therefore can't detect spends. So it sees a balance
        # corresponding to the sum of all notes the address received.
        # TODO: Fix this during the Sapling upgrade (via #2277)
        assert_equal(
            {
                k: Decimal(v)
                for k, v in self.nodes[3].z_gettotalbalance(1, True).items()
            }, {
                'transparent':
                node3mined + Decimal('1.0'),
                'private':
                zsendmany2notevalue + zsendmanynotevalue + zaddrremaining +
                zaddrremaining2,
                'total':
                node3mined + Decimal('1.0') + zsendmany2notevalue +
                zsendmanynotevalue + zaddrremaining + zaddrremaining2,
            })

        # Check individual balances reflect the above
        assert_equal(self.nodes[3].z_getbalance(mytaddr1), Decimal('1.0'))
        assert_equal(self.nodes[3].z_getbalance(myzaddr),
                     zsendmanynotevalue + zaddrremaining + zaddrremaining2)
示例#57
0
    def run_test(self):
        testnode0 = TestNode()
        connections = []
        connections.append(
            NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], testnode0,
                     "regtest", OVERWINTER_PROTO_VERSION))
        testnode0.add_connection(connections[0])

        # Start up network handling in another thread
        NetworkThread().start()
        testnode0.wait_for_verack()

        # Verify mininodes are connected to zprimed nodes
        peerinfo = self.nodes[0].getpeerinfo()
        versions = [x["version"] for x in peerinfo]
        assert_equal(1, versions.count(OVERWINTER_PROTO_VERSION))
        assert_equal(0, peerinfo[0]["banscore"])

        # Mine some blocks so we can spend
        coinbase_blocks = self.nodes[0].generate(200)
        node_address = self.nodes[0].getnewaddress()

        # Sync nodes 0 and 1
        sync_blocks(self.nodes[:2])
        sync_mempools(self.nodes[:2])

        # Verify block count
        assert_equal(self.nodes[0].getblockcount(), 200)
        assert_equal(self.nodes[1].getblockcount(), 200)
        assert_equal(self.nodes[2].getblockcount(), 0)

        # Mininodes send expiring soon transaction in "tx" message to zprimed node
        self.send_transaction(testnode0, coinbase_blocks[0], node_address, 203)

        # Assert that the tx is not in the mempool (expiring soon)
        assert_equal([], self.nodes[0].getrawmempool())
        assert_equal([], self.nodes[1].getrawmempool())
        assert_equal([], self.nodes[2].getrawmempool())

        # Mininodes send transaction in "tx" message to zprimed node
        tx2 = self.send_transaction(testnode0, coinbase_blocks[1],
                                    node_address, 204)

        # tx2 is not expiring soon
        assert_equal([tx2.hash], self.nodes[0].getrawmempool())
        assert_equal([tx2.hash], self.nodes[1].getrawmempool())
        # node 2 is isolated
        assert_equal([], self.nodes[2].getrawmempool())

        # Verify txid for tx2
        self.verify_inv(testnode0, tx2)
        self.send_data_message(testnode0, tx2)
        self.verify_last_tx(testnode0, tx2)

        # Sync and mine an empty block with node 2, leaving tx in the mempool of node0 and node1
        for blkhash in coinbase_blocks:
            blk = self.nodes[0].getblock(blkhash, 0)
            self.nodes[2].submitblock(blk)
        self.nodes[2].generate(1)

        # Verify block count
        assert_equal(self.nodes[0].getblockcount(), 200)
        assert_equal(self.nodes[1].getblockcount(), 200)
        assert_equal(self.nodes[2].getblockcount(), 201)

        # Reconnect node 2 to the network
        connect_nodes_bi(self.nodes, 0, 2)

        # Set up test node for node 2
        testnode2 = TestNode()
        connections.append(
            NodeConn('127.0.0.1', p2p_port(2), self.nodes[2], testnode2,
                     "regtest", OVERWINTER_PROTO_VERSION))
        testnode2.add_connection(connections[-1])

        # Verify block count
        sync_blocks(self.nodes[:3])
        assert_equal(self.nodes[0].getblockcount(), 201)
        assert_equal(self.nodes[1].getblockcount(), 201)
        assert_equal(self.nodes[2].getblockcount(), 201)

        # Verify contents of mempool
        assert_equal([tx2.hash], self.nodes[0].getrawmempool())
        assert_equal([tx2.hash], self.nodes[1].getrawmempool())
        assert_equal([], self.nodes[2].getrawmempool())

        # Confirm tx2 cannot be submitted to a mempool because it is expiring soon.
        try:
            rawtx2 = hexlify(tx2.serialize())
            self.nodes[2].sendrawtransaction(rawtx2)
            fail("Sending transaction should have failed")
        except JSONRPCException as e:
            assert_equal(
                "tx-expiring-soon: expiryheight is 204 but should be at least 205 to avoid transaction expiring soon",
                e.error['message'])

        self.send_data_message(testnode0, tx2)

        # Sync up with node after p2p messages delivered
        testnode0.sync_with_ping()

        # Verify node 0 does not reply to "getdata" by sending "tx" message, as tx2 is expiring soon
        with mininode_lock:
            assert_equal(testnode0.last_tx, None)

        # Verify mininode received a "notfound" message containing the txid of tx2
        with mininode_lock:
            msg = testnode0.last_notfound
            assert_equal(len(msg.inv), 1)
            assert_equal(tx2.sha256, msg.inv[0].hash)

        # Create a transaction to verify that processing of "getdata" messages is functioning
        tx3 = self.send_transaction(testnode0, coinbase_blocks[2],
                                    node_address, 999)

        self.send_data_message(testnode0, tx3)
        self.verify_last_tx(testnode0, tx3)
        # Verify txid for tx3 is returned in "inv", but tx2 which is expiring soon is not returned
        self.verify_inv(testnode0, tx3)
        self.verify_inv(testnode2, tx3)

        # Verify contents of mempool
        assert_equal({tx2.hash, tx3.hash}, set(self.nodes[0].getrawmempool()))
        assert_equal({tx2.hash, tx3.hash}, set(self.nodes[1].getrawmempool()))
        assert_equal({tx3.hash}, set(self.nodes[2].getrawmempool()))

        # Verify banscore for nodes are still zero
        assert_equal(
            0, sum(peer["banscore"] for peer in self.nodes[0].getpeerinfo()))
        assert_equal(
            0, sum(peer["banscore"] for peer in self.nodes[2].getpeerinfo()))

        [c.disconnect_node() for c in connections]
示例#58
0
    def run_test(self):
        # Make sure can't switch off usehd after wallet creation
        self.stop_node(1)
        self.nodes[1].assert_start_raises_init_error([
            '-usehd=0'
        ], "Error: Error loading : You can't disable HD on an already existing HD wallet"
                                                     )
        self.start_node(1)
        connect_nodes_bi(self.nodes, 0, 1)

        # Make sure we use hd, keep masterkeyid
        masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
        assert_equal(masterkeyid,
                     self.nodes[1].getwalletinfo()['hdmasterkeyid'])
        assert_equal(len(masterkeyid), 40)

        # create an internal key
        change_addr = self.nodes[1].getrawchangeaddress()
        change_addrV = self.nodes[1].getaddressinfo(change_addr)
        assert_equal(change_addrV["hdkeypath"],
                     "m/88'/1'/0'")  #first internal child key

        # Import a non-HD private key in the HD wallet
        non_hd_add = self.nodes[0].getnewaddress()
        self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add))

        # This should be enough to keep the master key and the non-HD key
        self.nodes[1].backupwallet(
            os.path.join(self.nodes[1].datadir, "hd.bak"))
        #self.nodes[1].dumpwallet(os.path.join(self.nodes[1].datadir, "hd.dump"))

        # Derive some HD addresses and remember the last
        # Also send funds to each add
        self.nodes[0].generate(COINBASE_MATURITY + 1)
        hd_add = None
        NUM_HD_ADDS = 10
        for i in range(NUM_HD_ADDS):
            hd_add = self.nodes[1].getnewaddress()
            hd_info = self.nodes[1].getaddressinfo(hd_add)
            assert_equal(hd_info["hdkeypath"], "m/88'/0'/" + str(i) + "'")
            assert_equal(hd_info["hdseedid"], masterkeyid)
            assert_equal(hd_info["hdmasterkeyid"], masterkeyid)
            self.nodes[0].sendtoaddress(hd_add, 1)
            self.nodes[0].generate(1)
        self.nodes[0].sendtoaddress(non_hd_add, 1)
        self.nodes[0].generate(1)

        # create an internal key (again)
        change_addr = self.nodes[1].getrawchangeaddress()
        change_addrV = self.nodes[1].getaddressinfo(change_addr)
        assert_equal(change_addrV["hdkeypath"],
                     "m/88'/1'/1'")  #second internal child key

        self.sync_all()
        assert_equal(self.nodes[1].getbalance(), NUM_HD_ADDS + 1)

        self.log.info("Restore backup ...")
        self.stop_node(1)
        # we need to delete the complete regtest directory
        # otherwise node1 would auto-recover all funds in flag the keypool keys as used
        shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "blocks"))
        shutil.rmtree(
            os.path.join(self.nodes[1].datadir, "regtest", "chainstate"))
        shutil.copyfile(
            os.path.join(self.nodes[1].datadir, "hd.bak"),
            os.path.join(self.nodes[1].datadir, "regtest", "wallets",
                         "wallet.dat"))
        self.start_node(1)

        # Assert that derivation is deterministic
        hd_add_2 = None
        for i in range(NUM_HD_ADDS):
            hd_add_2 = self.nodes[1].getnewaddress()
            hd_info_2 = self.nodes[1].getaddressinfo(hd_add_2)
            assert_equal(hd_info_2["hdkeypath"], "m/88'/0'/" + str(i) + "'")
            assert_equal(hd_info_2["hdseedid"], masterkeyid)
            assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid)
        assert_equal(hd_add, hd_add_2)
        connect_nodes_bi(self.nodes, 0, 1)
        self.sync_all()

        # Needs rescan
        self.stop_node(1)
        self.start_node(1, extra_args=self.extra_args[1] + ['-rescan'])
        assert_equal(self.nodes[1].getbalance(), NUM_HD_ADDS + 1)

        # Try a RPC based rescan
        self.stop_node(1)
        shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "blocks"))
        shutil.rmtree(
            os.path.join(self.nodes[1].datadir, "regtest", "chainstate"))
        shutil.copyfile(
            os.path.join(self.nodes[1].datadir, "hd.bak"),
            os.path.join(self.nodes[1].datadir, "regtest", "wallets",
                         "wallet.dat"))
        self.start_node(1, extra_args=self.extra_args[1])
        connect_nodes_bi(self.nodes, 0, 1)
        self.sync_all()
        # Wallet automatically scans blocks older than key on startup
        assert_equal(self.nodes[1].getbalance(), NUM_HD_ADDS + 1)
        out = self.nodes[1].rescanblockchain(0, 1)
        assert_equal(out['start_height'], 0)
        assert_equal(out['stop_height'], 1)
        out = self.nodes[1].rescanblockchain()
        assert_equal(out['start_height'], 0)
        assert_equal(out['stop_height'], self.nodes[1].getblockcount())
        assert_equal(self.nodes[1].getbalance(), NUM_HD_ADDS + 1)

        # send a tx and make sure its using the internal chain for the changeoutput
        txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
        outs = self.nodes[1].decoderawtransaction(
            self.nodes[1].gettransaction(txid)['hex'])['vout']
        keypath = ""
        for out in outs:
            if out['value'] != 1:
                keypath = self.nodes[1].getaddressinfo(
                    out['scriptPubKey']['addresses'][0])['hdkeypath']

        assert_equal(keypath[0:8], "m/88'/1'")

        # Generate a new HD seed on node 1 and make sure it is set
        orig_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
        self.nodes[1].sethdseed()
        new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
        assert orig_masterkeyid != new_masterkeyid
        addr = self.nodes[1].getnewaddress()
        assert_equal(
            self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/88\'/0\'/0\''
        )  # Make sure the new address is the first from the keypool
        self.nodes[1].keypoolrefill(1)  # Fill keypool with 1 key

        # Set a new HD seed on node 1 without flushing the keypool
        new_seed = self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())
        orig_masterkeyid = new_masterkeyid
        self.nodes[1].sethdseed(False, new_seed)
        new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
        assert orig_masterkeyid != new_masterkeyid
        addr = self.nodes[1].getnewaddress()
        assert_equal(orig_masterkeyid,
                     self.nodes[1].getaddressinfo(addr)['hdseedid'])
        assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'],
                     'm/88\'/0\'/1\''
                     )  # Make sure the new address continues previous keypool

        # Check that the next address is from the new seed
        self.nodes[1].keypoolrefill(1)
        next_addr = self.nodes[1].getnewaddress()
        assert_equal(new_masterkeyid,
                     self.nodes[1].getaddressinfo(next_addr)['hdseedid'])
        assert_equal(
            self.nodes[1].getaddressinfo(next_addr)['hdkeypath'],
            'm/88\'/0\'/0\''
        )  # Make sure the new address is not from previous keypool
        assert next_addr != addr

        # Sethdseed parameter validity
        assert_raises_rpc_error(-1, 'sethdseed', self.nodes[0].sethdseed,
                                False, new_seed, 0)
        assert_raises_rpc_error(-5, "Invalid private key",
                                self.nodes[1].sethdseed, False, "not_wif")
        assert_raises_rpc_error(-1, "JSON value is not a boolean as expected",
                                self.nodes[1].sethdseed, "Not_bool")
        assert_raises_rpc_error(-1, "JSON value is not a string as expected",
                                self.nodes[1].sethdseed, False, True)
        assert_raises_rpc_error(-5, "Already have this key",
                                self.nodes[1].sethdseed, False, new_seed)
        assert_raises_rpc_error(
            -5, "Already have this key", self.nodes[1].sethdseed, False,
            self.nodes[1].dumpprivkey(self.nodes[1].getnewaddress()))
示例#59
0
    def run_test(self):
        print("Mining blocks...")
        feeTolerance = Decimal(
            "0.00000002"
        )  #if the fee's positive delta is higher than this value tests will fail, neg. delta always fail the tests

        self.nodes[2].generate(1)
        self.sync_all()
        self.nodes[0].generate(201)
        self.sync_all()

        watchonly_address = self.nodes[0].getnewaddress()
        watchonly_pubkey = self.nodes[0].validateaddress(
            watchonly_address)["pubkey"]
        watchonly_amount = 200
        self.nodes[3].importpubkey(watchonly_pubkey, "", True)
        watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address,
                                                     watchonly_amount)
        self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(),
                                    watchonly_amount / 10)

        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0)

        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        ###############
        # simple test #
        ###############
        inputs = []
        outputs = {self.nodes[0].getnewaddress(): 1.0}
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)
        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        assert_equal(len(dec_tx['vin']) > 0,
                     True)  #test if we have enought inputs

        ##############################
        # simple test with two coins #
        ##############################
        inputs = []
        outputs = {self.nodes[0].getnewaddress(): 2.2}
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        assert_equal(len(dec_tx['vin']) > 0,
                     True)  #test if we have enough inputs

        ##############################
        # simple test with two coins #
        ##############################
        inputs = []
        outputs = {self.nodes[0].getnewaddress(): 2.6}
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        assert_equal(len(dec_tx['vin']) > 0, True)
        assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')

        ################################
        # simple test with two outputs #
        ################################
        inputs = []
        outputs = {
            self.nodes[0].getnewaddress(): 2.6,
            self.nodes[1].getnewaddress(): 2.5
        }
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        for out in dec_tx['vout']:
            totalOut += out['value']

        assert_equal(len(dec_tx['vin']) > 0, True)
        assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')

        #########################################################################
        # test a fundrawtransaction with a VIN greater than the required amount #
        #########################################################################
        utx = False
        listunspent = self.nodes[2].listunspent()
        for aUtx in listunspent:
            if aUtx['amount'] == 5.0:
                utx = aUtx
                break

        assert_equal(utx != False, True)

        inputs = [{'txid': utx['txid'], 'vout': utx['vout']}]
        outputs = {self.nodes[0].getnewaddress(): Decimal('1.0')}
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        for out in dec_tx['vout']:
            totalOut += out['value']

        assert_equal(fee + totalOut,
                     utx['amount'])  #compare vin total and totalout+fee

        #####################################################################
        # test a fundrawtransaction with which will not get a change output #
        #####################################################################
        utx = False
        listunspent = self.nodes[2].listunspent()
        for aUtx in listunspent:
            if aUtx['amount'] == 5.0:
                utx = aUtx
                break

        assert_equal(utx != False, True)

        inputs = [{'txid': utx['txid'], 'vout': utx['vout']}]
        outputs = {
            self.nodes[0].getnewaddress(): Decimal('5.0') - fee - feeTolerance
        }
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        for out in dec_tx['vout']:
            totalOut += out['value']

        assert_equal(rawtxfund['changepos'], -1)
        assert_equal(fee + totalOut,
                     utx['amount'])  #compare vin total and totalout+fee

        #########################################################################
        # test a fundrawtransaction with a VIN smaller than the required amount #
        #########################################################################
        utx = False
        listunspent = self.nodes[2].listunspent()
        for aUtx in listunspent:
            if aUtx['amount'] == 1.0:
                utx = aUtx
                break

        assert_equal(utx != False, True)

        inputs = [{'txid': utx['txid'], 'vout': utx['vout']}]
        outputs = {self.nodes[0].getnewaddress(): Decimal('1.0')}
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)

        # 4-byte version + 4-byte versionGroupId + 1-byte vin count + 36-byte prevout then script_len
        rawtx = rawtx[:90] + "0100" + rawtx[92:]

        dec_tx = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
        assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        matchingOuts = 0
        for i, out in enumerate(dec_tx['vout']):
            totalOut += out['value']
            if out['scriptPubKey']['addresses'][0] in outputs:
                matchingOuts += 1
            else:
                assert_equal(i, rawtxfund['changepos'])

        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
        assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex'])

        assert_equal(matchingOuts, 1)
        assert_equal(len(dec_tx['vout']), 2)

        ###########################################
        # test a fundrawtransaction with two VINs #
        ###########################################
        utx = False
        utx2 = False
        listunspent = self.nodes[2].listunspent()
        for aUtx in listunspent:
            if aUtx['amount'] == 1.0:
                utx = aUtx
            if aUtx['amount'] == 5.0:
                utx2 = aUtx

        assert_equal(utx != False, True)

        inputs = [{
            'txid': utx['txid'],
            'vout': utx['vout']
        }, {
            'txid': utx2['txid'],
            'vout': utx2['vout']
        }]
        outputs = {self.nodes[0].getnewaddress(): 6.0}
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        matchingOuts = 0
        for out in dec_tx['vout']:
            totalOut += out['value']
            if out['scriptPubKey']['addresses'][0] in outputs:
                matchingOuts += 1

        assert_equal(matchingOuts, 1)
        assert_equal(len(dec_tx['vout']), 2)

        matchingIns = 0
        for vinOut in dec_tx['vin']:
            for vinIn in inputs:
                if vinIn['txid'] == vinOut['txid']:
                    matchingIns += 1

        assert_equal(
            matchingIns,
            2)  #we now must see two vins identical to vins given as params

        #########################################################
        # test a fundrawtransaction with two VINs and two vOUTs #
        #########################################################
        utx = False
        utx2 = False
        listunspent = self.nodes[2].listunspent()
        for aUtx in listunspent:
            if aUtx['amount'] == 1.0:
                utx = aUtx
            if aUtx['amount'] == 5.0:
                utx2 = aUtx

        assert_equal(utx != False, True)

        inputs = [{
            'txid': utx['txid'],
            'vout': utx['vout']
        }, {
            'txid': utx2['txid'],
            'vout': utx2['vout']
        }]
        outputs = {
            self.nodes[0].getnewaddress(): 6.0,
            self.nodes[0].getnewaddress(): 1.0
        }
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)
        assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        fee = rawtxfund['fee']
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
        totalOut = 0
        matchingOuts = 0
        for out in dec_tx['vout']:
            totalOut += out['value']
            if out['scriptPubKey']['addresses'][0] in outputs:
                matchingOuts += 1

        assert_equal(matchingOuts, 2)
        assert_equal(len(dec_tx['vout']), 3)

        ##############################################
        # test a fundrawtransaction with invalid vin #
        ##############################################
        listunspent = self.nodes[2].listunspent()
        inputs = [{
            'txid':
            "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1",
            'vout': 0
        }]  #invalid vin!
        outputs = {self.nodes[0].getnewaddress(): 1.0}
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)

        errorString = ""
        try:
            rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        except JSONRPCException as e:
            errorString = e.error['message']

        assert_equal("Insufficient" in errorString, True)

        ############################################################
        #compare fee of a standard pubkeyhash transaction
        inputs = []
        outputs = {self.nodes[1].getnewaddress(): 1.1}
        rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[0].fundrawtransaction(rawTx)

        #create same transaction over sendtoaddress
        txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1)
        signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert (feeDelta >= 0 and feeDelta <= feeTolerance)
        ############################################################

        ############################################################
        #compare fee of a standard pubkeyhash transaction with multiple outputs
        inputs = []
        outputs = {
            self.nodes[1].getnewaddress(): 1.1,
            self.nodes[1].getnewaddress(): 1.2,
            self.nodes[1].getnewaddress(): 0.1,
            self.nodes[1].getnewaddress(): 1.3,
            self.nodes[1].getnewaddress(): 0.2,
            self.nodes[1].getnewaddress(): 0.3
        }
        rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[0].fundrawtransaction(rawTx)
        #create same transaction over sendtoaddress
        txId = self.nodes[0].sendmany("", outputs)
        signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert (feeDelta >= 0 and feeDelta <= feeTolerance)
        ############################################################

        ############################################################
        #compare fee of a 2of2 multisig p2sh transaction

        # create 2of2 addr
        addr1 = self.nodes[1].getnewaddress()
        addr2 = self.nodes[1].getnewaddress()

        addr1Obj = self.nodes[1].validateaddress(addr1)
        addr2Obj = self.nodes[1].validateaddress(addr2)

        mSigObj = self.nodes[1].addmultisigaddress(
            2, [addr1Obj['pubkey'], addr2Obj['pubkey']])

        inputs = []
        outputs = {mSigObj: 1.1}
        rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[0].fundrawtransaction(rawTx)

        #create same transaction over sendtoaddress
        txId = self.nodes[0].sendtoaddress(mSigObj, 1.1)
        signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert (feeDelta >= 0 and feeDelta <= feeTolerance)
        ############################################################

        ############################################################
        #compare fee of a standard pubkeyhash transaction

        # create 4of5 addr
        addr1 = self.nodes[1].getnewaddress()
        addr2 = self.nodes[1].getnewaddress()
        addr3 = self.nodes[1].getnewaddress()
        addr4 = self.nodes[1].getnewaddress()
        addr5 = self.nodes[1].getnewaddress()

        addr1Obj = self.nodes[1].validateaddress(addr1)
        addr2Obj = self.nodes[1].validateaddress(addr2)
        addr3Obj = self.nodes[1].validateaddress(addr3)
        addr4Obj = self.nodes[1].validateaddress(addr4)
        addr5Obj = self.nodes[1].validateaddress(addr5)

        mSigObj = self.nodes[1].addmultisigaddress(4, [
            addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'],
            addr4Obj['pubkey'], addr5Obj['pubkey']
        ])

        inputs = []
        outputs = {mSigObj: 1.1}
        rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[0].fundrawtransaction(rawTx)

        #create same transaction over sendtoaddress
        txId = self.nodes[0].sendtoaddress(mSigObj, 1.1)
        signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert (feeDelta >= 0 and feeDelta <= feeTolerance)
        ############################################################

        ############################################################
        # spend a 2of2 multisig transaction over fundraw

        # create 2of2 addr
        addr1 = self.nodes[2].getnewaddress()
        addr2 = self.nodes[2].getnewaddress()

        addr1Obj = self.nodes[2].validateaddress(addr1)
        addr2Obj = self.nodes[2].validateaddress(addr2)

        mSigObj = self.nodes[2].addmultisigaddress(
            2, [addr1Obj['pubkey'], addr2Obj['pubkey']])

        # send 1.2 BTC to msig addr
        txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()

        oldBalance = self.nodes[1].getbalance()
        inputs = []
        outputs = {self.nodes[1].getnewaddress(): 1.1}
        rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[2].fundrawtransaction(rawTx)

        signedTx = self.nodes[2].signrawtransaction(fundedTx['hex'])
        txId = self.nodes[2].sendrawtransaction(signedTx['hex'])
        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()

        # make sure funds are received at node1
        assert_equal(oldBalance + Decimal('1.10000000'),
                     self.nodes[1].getbalance())

        ############################################################
        # locked wallet test
        self.nodes[1].encryptwallet("test")
        self.nodes.pop(1)
        stop_nodes(self.nodes)
        wait_bitcoinds()

        self.nodes = start_nodes(4, self.options.tmpdir)

        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 0, 2)
        connect_nodes_bi(self.nodes, 0, 3)
        self.is_network_split = False
        self.sync_all()

        error = False
        try:
            self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2)
        except:
            error = True
        assert (error)

        oldBalance = self.nodes[0].getbalance()

        inputs = []
        outputs = {self.nodes[0].getnewaddress(): 1.1}
        rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[1].fundrawtransaction(rawTx)

        #now we need to unlock
        self.nodes[1].walletpassphrase("test", 100)
        signedTx = self.nodes[1].signrawtransaction(fundedTx['hex'])
        txId = self.nodes[1].sendrawtransaction(signedTx['hex'])
        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()

        # make sure funds are received at node1
        assert_equal(oldBalance + Decimal('98.10000000'),
                     self.nodes[0].getbalance())

        ###############################################
        # multiple (~19) inputs tx test | Compare fee #
        ###############################################

        #empty node1, send some small coins from node0 to node1
        self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(),
                                    self.nodes[1].getbalance(), "", "", True)
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        for i in range(0, 20):
            self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        #fund a tx with ~20 small inputs
        inputs = []
        outputs = {
            self.nodes[0].getnewaddress(): 0.15,
            self.nodes[0].getnewaddress(): 0.04
        }
        rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[1].fundrawtransaction(rawTx)

        #create same transaction over sendtoaddress
        txId = self.nodes[1].sendmany("", outputs)
        signedFee = self.nodes[1].getrawmempool(True)[txId]['fee']

        #compare fee
        feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
        assert (feeDelta >= 0 and feeDelta <= feeTolerance * 19)  #~19 inputs

        #############################################
        # multiple (~19) inputs tx test | sign/send #
        #############################################

        #again, empty node1, send some small coins from node0 to node1
        self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(),
                                    self.nodes[1].getbalance(), "", "", True)
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        for i in range(0, 20):
            self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        #fund a tx with ~20 small inputs
        oldBalance = self.nodes[0].getbalance()

        inputs = []
        outputs = {
            self.nodes[0].getnewaddress(): 0.15,
            self.nodes[0].getnewaddress(): 0.04
        }
        rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
        fundedTx = self.nodes[1].fundrawtransaction(rawTx)
        fundedAndSignedTx = self.nodes[1].signrawtransaction(fundedTx['hex'])
        txId = self.nodes[1].sendrawtransaction(fundedAndSignedTx['hex'])
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()
        assert_equal(oldBalance + Decimal('97.19000000'),
                     self.nodes[0].getbalance())  #0.19+block reward

        #####################################################
        # test fundrawtransaction with OP_RETURN and no vin #
        #####################################################

        rawtx = "0100000000010000000000000000066a047465737400000000"
        dec_tx = self.nodes[2].decoderawtransaction(rawtx)

        assert_equal(len(dec_tx['vin']), 0)
        assert_equal(len(dec_tx['vout']), 1)

        rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
        dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])

        assert_greater_than(len(dec_tx['vin']), 0)  # at least one vin
        assert_equal(len(dec_tx['vout']), 2)  # one change output added

        ##################################################
        # test a fundrawtransaction using only watchonly #
        ##################################################

        inputs = []
        outputs = {self.nodes[2].getnewaddress(): watchonly_amount / 2}
        rawtx = self.nodes[3].createrawtransaction(inputs, outputs)

        result = self.nodes[3].fundrawtransaction(rawtx, True)
        res_dec = self.nodes[0].decoderawtransaction(result["hex"])
        assert_equal(len(res_dec["vin"]), 1)
        assert_equal(res_dec["vin"][0]["txid"], watchonly_txid)

        assert_equal("fee" in result.keys(), True)
        assert_greater_than(result["changepos"], -1)

        ###############################################################
        # test fundrawtransaction using the entirety of watched funds #
        ###############################################################

        inputs = []
        outputs = {self.nodes[2].getnewaddress(): watchonly_amount}
        rawtx = self.nodes[3].createrawtransaction(inputs, outputs)

        result = self.nodes[3].fundrawtransaction(rawtx, True)
        res_dec = self.nodes[0].decoderawtransaction(result["hex"])
        assert_equal(len(res_dec["vin"]), 2)
        assert (res_dec["vin"][0]["txid"] == watchonly_txid
                or res_dec["vin"][1]["txid"] == watchonly_txid)

        assert_greater_than(result["fee"], 0)
        assert_greater_than(result["changepos"], -1)
        assert_equal(
            result["fee"] + res_dec["vout"][result["changepos"]]["value"],
            watchonly_amount / 10)

        signedtx = self.nodes[3].signrawtransaction(result["hex"])
        assert (not signedtx["complete"])
        signedtx = self.nodes[0].signrawtransaction(signedtx["hex"])
        assert (signedtx["complete"])
        self.nodes[0].sendrawtransaction(signedtx["hex"])
示例#60
0
    def run_test(self):
        mc_node1 = self.nodes[0]
        mc_node2 = self.nodes[1]
        sc_node1 = self.sc_nodes[0]

        # Synchronize mc_node1 and mc_node2
        self.sync_all()

        # Generate 1 SC block without any MC block info
        scblock_id0 = generate_next_blocks(sc_node1, "first node", 1)[0]
        # Verify that SC block has no MC headers, ref data, ommers
        check_mcheaders_amount(0, scblock_id0, sc_node1)
        check_mcreferencedata_amount(0, scblock_id0, sc_node1)
        check_ommers_amount(0, scblock_id0, sc_node1)

        # Generate 1 MC block on the first MC node
        mcblock_hash1 = mc_node1.generate(1)[0]
        # Synchronize mc_node1 and mc_node2, then disconnect them.
        self.sync_all()
        disconnect_nodes_bi(self.nodes, 0, 1)

        # Generate 1 more MC block on the first MC node
        mcblock_hash2 = mc_node1.generate(1)[0]

        # Generate 1 SC block, that should put 2 MC blocks inside
        # SC block contains MC `mcblock_hash1` that is common for MC Nodes 1,2 and `mcblock_hash2` that is known only by MC Node 1.
        scblock_id1 = generate_next_blocks(sc_node1, "first node", 1)[0]
        check_scparent(scblock_id0, scblock_id1, sc_node1)
        # Verify that SC block contains MC block as a MainchainReference
        check_mcheaders_amount(2, scblock_id1, sc_node1)
        check_mcreferencedata_amount(2, scblock_id1, sc_node1)
        check_mcreference_presence(mcblock_hash1, scblock_id1, sc_node1)
        check_mcreference_presence(mcblock_hash2, scblock_id1, sc_node1)
        check_ommers_amount(0, scblock_id1, sc_node1)

        # Generate another 2 MC blocks on the second MC node
        fork_mcblock_hash1 = mc_node2.generate(1)[0]
        fork_mcblock_hash2 = mc_node2.generate(1)[0]

        # Connect and synchronize MC node 1 to MC node 2
        connect_nodes_bi(self.nodes, 0, 1)
        self.sync_all()
        # MC Node 1 should replace mcblock_hash2 Tip with [fork_mcblock_hash1, fork_mcblock_hash2]
        assert_equal(fork_mcblock_hash2, mc_node1.getbestblockhash())

        # Generate 1 SC block
        # SC block must contains `mcblock_hash1` again and add fork_mcblock_hash1,2
        # Ommered block also contains common `mcblock_hash1`, but moreover an orphaned `mcblock_hash2`
        scblock_id2 = generate_next_blocks(sc_node1, "first node", 1)[0]
        check_scparent(scblock_id0, scblock_id2, sc_node1)
        # Verify that SC block contains newly created MC blocks as a MainchainHeaders and no MainchainRefData
        check_mcheaders_amount(3, scblock_id2, sc_node1)
        check_mcreferencedata_amount(0, scblock_id2, sc_node1)
        check_mcheader_presence(mcblock_hash1, scblock_id2, sc_node1)
        check_mcheader_presence(fork_mcblock_hash1, scblock_id2, sc_node1)
        check_mcheader_presence(fork_mcblock_hash2, scblock_id2, sc_node1)
        # Verify that SC block contains 1 Ommer with 1 MainchainHeader
        check_ommers_amount(1, scblock_id2, sc_node1)
        check_ommers_cumulative_score(1, scblock_id2, sc_node1)
        check_ommer(scblock_id1, [mcblock_hash1, mcblock_hash2], scblock_id2,
                    sc_node1)