Ejemplo n.º 1
0
 def test_double_spend(self,mineblock = True):
     self.log.info("test double spend")
     node = self.nodes[0]
     ct = Contract(node)
     [ct.call_payable(amount = 100) for i in range(10)]
     node.generate(2)
     self.sync_all()
     addr = self.nodes[1].getnewaddress()
     addr2 = self.nodes[1].getnewaddress()
     contract_balance = ct.get_balance()
     for i in range(10):
         ct.call_reorgTest(addr,addr2,amount = 0,debug = False)
         # print("before:",ct.get_balance(), node.getbalanceof(addr), node.getbalanceof(addr2))
         # self.sync_all()
         if mineblock:
             self.nodes[1].generate(random.randint(1,4))
             self.sync_all()
         # print("after:",ct.get_balance(), node.getbalanceof(addr), node.getbalanceof(addr2))
     self.sync_all()
     node.generate(2)
     self.sync_all()
     print(ct.get_balance(),node.getbalanceof(addr),node.getbalanceof(addr2))
     addr_balance = node.getbalanceof(addr)
     addr2_balance = node.getbalanceof(addr2)
     if not mineblock:
         if addr_balance == 0:
             assert_equal(addr2_balance, 10)
         else:
             assert_equal(addr_balance, 10)
         assert_equal(ct.get_balance(),contract_balance - 10)
     else:
         assert_equal(ct.get_balance(), contract_balance - addr_balance - addr2_balance)
Ejemplo n.º 2
0
    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)
            # why after this call ,ct balance at node1 is 1980,it should 1990
            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.txid)
        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 at node3:",
                      ct.get_balance(exec_node=self.node3))

            else:
                # 这里也在node1中的内存池?
                tx_b12 = ct.call_callOtherContractTest(ct2.contract_id,
                                                       'callOtherContractTest',
                                                       ct.contract_id,
                                                       "contractDataTest",
                                                       amount=0)
                tx_b13 = ct.call_reentrancyTest(amount=0).txid
                print("tx_b13:", tx_b13)
                print("ct balance:", ct.get_balance(exec_node=self.node1))
            print("ct balance at node3:", ct.get_balance(exec_node=self.node3))
            print("ct balance at node1:", ct.get_balance(exec_node=self.node1))
            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:
            assert_equal(sorted(self.node1.getrawmempool()),
                         sorted([tx_b12.txid, tx_b13]))
        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 at node3:", ct.get_balance(exec_node=self.node3))
        print("ct balance at node1:", ct.get_balance(exec_node=self.node1))
        print("join network")
        connect_nodes_bi(self.nodes, 1, 2)
        sync_blocks(self.nodes)

        print("ct balance at node1:", ct.get_balance(exec_node=self.node1))
        print("ct balance at node3:", 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())))
            with_send_crash_point2 = len(self.node1.getrawmempool())
            for tx in self.node1.getrawmempool():
                # tx_ai,tx_a11,tx_a12
                if tx == tx_a1:
                    self.log.info("tx_a1 in mempool")
                elif tx == tx_a11:
                    self.log.info("tx_a11 in mempool")
                elif tx == tx_a12:
                    self.log.info("tx_a12 in mempool")
                elif tx == tmp_ct.publish_txid:
                    self.log.info("node1 tmp_ct in mempool")
                elif tx == tx_a13.txid:
                    self.log.info("tx_a13 in mempool")
                if crash_point == 2:
                    if tx == tx_b12.txid:
                        self.log.info("tx_b12 in mempool")
                    elif tx == tx_b13:
                        self.log.info("tx_b13 in mempool")
            # 短链的块内交易必须是打回内存池的,否则可能有bug了
            # 这里不能确定具体数量,不好判断
            assert len(self.node1.getrawmempool()) >= 5 and len(
                self.node1.getrawmempool()) < 8
        else:
            print(
                " assert_equal(len(self.node1.getrawmempool()), 3),should {} == 3"
                .format(len(self.node1.getrawmempool())))
            for tx in self.node1.getrawmempool():
                # tx_ai,tx_a11,tx_a12
                if tx == tx_a1:
                    self.log.info("tx_a1 in mempool")
                elif tx == tx_a11:
                    self.log.info("tx_a11 in mempool")
                elif tx == tx_a12:
                    self.log.info("tx_a12 in mempool")
            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 - 10  #这里20是因为send都从第一个合约里边去扣了
        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])))
        if with_send:
            assert_equal(self.node0.getbalanceof(ct2.contract_id), 1000 -
                         10 if crash_point == 1 else 1000)  # 减去合约的send调用
            assert_equal(self.node1.getbalanceof(ct2.contract_id), 1000 -
                         10 if crash_point == 1 else 1000)  # 减去合约的send调用
            assert_equal(self.node2.getbalanceof(ct2.contract_id), 1000 -
                         10 if crash_point == 1 else 1000)  # 减去合约的send调用
            assert_equal(self.node3.getbalanceof(ct2.contract_id), 1000 -
                         10 if crash_point == 1 else 1000)  # 减去合约的send调用
        else:
            assert_equal(self.node0.getbalanceof(ct2.contract_id),
                         1000)  # 减去合约的send调用
            assert_equal(self.node1.getbalanceof(ct2.contract_id),
                         1000)  # 减去合约的send调用
            assert_equal(self.node2.getbalanceof(ct2.contract_id),
                         1000)  # 减去合约的send调用
            assert_equal(self.node3.getbalanceof(ct2.contract_id),
                         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(), [])
        if with_send and crash_point == 1:
            assert_equal(self.node1.getbalanceof(ct.contract_id), 4000 - 20)
        elif with_send and crash_point == 2:
            # what the he?
            assert_equal(
                self.node1.getbalanceof(ct.contract_id),
                4000 - 20 if with_send_crash_point2 == 7 else 4000 - 10)
        else:
            assert_equal(self.node1.getbalanceof(ct.contract_id), 4000)
        bal = 4000
        if with_send and crash_point == 1:
            bal = 4000 - 20  #应该是4000- 20 的,但是现在的send都是从第一个合约里扣
        elif with_send and crash_point == 2:
            bal = 4000 - 10
        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 test_double_sendcoins(self):
        '''
        测试同一个合约,分别在主链与分叉链上转走全部金额到不同的地址
        理论短链的交易不应该打回到内存池,因为合约没钱
        ab0[contract_ab]
          /         \
        aa1 [cca1]   bb1 [ccb1]
         |           |
        aa2         bb2
         |           |
        aa3         bb3
                     |
                    bb4
                     |
                    ...
        :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)
        ct.call_payable(amount=100)
        print(ct.publish_txid)
        self.sync_all()
        self.node0.generate(2)
        self.sync_all()
        blocks_num = self.node1.getblockcount()
        contract_balance = 100

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

        # in group 1
        addr_N1 = self.node1.getnewaddress()
        txid1 = ct.call_sendCoinTest(addr_N1, contract_balance, amount=0).txid
        self.node1.generate(2)
        self.sync_all([self.nodes[:2], self.nodes[2:]])
        assert_equal(self.node1.getbalanceof(addr_N1), 100)
        assert_equal(ct.get_balance(), 0)

        # in group 2
        addr_N3 = self.node3.getnewaddress()
        txid2 = ct.call_sendCoinTest(addr_N3,
                                     contract_balance,
                                     amount=0,
                                     exec_node=self.node3).txid
        self.node3.generate(3)
        self.sync_all([self.nodes[:2], self.nodes[2:]])
        assert_equal(self.node3.getbalanceof(addr_N3), 100)
        assert_equal(ct.get_balance(exec_node=self.node3), 0)

        # join network
        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
        assert_equal(self.node1.getbalanceof(addr_N1), 0)
        assert_equal(self.node3.getbalanceof(addr_N3), contract_balance)
        assert_equal(ct.get_balance(), 0)
        assert_equal(ct.get_balance(exec_node=self.node3), 0)
        assert txid1 not in self.node1.getrawmempool()