Esempio n. 1
0
    def reindex(self, justchainstate=False, with_contract=False):
        self.nodes[0].generate(3)

        if with_contract:
            # make some contract transactions
            cid = self.nodes[0].publishcontract(
                generate_contract(self.options.tmpdir))['contractaddress']
            self.nodes[0].callcontract(True, 10, cid,
                                       self.nodes[0].getnewaddress(),
                                       'payable')
            for i in range(10):
                self.nodes[0].callcontract(True, 0, cid,
                                           self.nodes[0].getnewaddress(),
                                           'dustChangeTest',
                                           self.nodes[0].getnewaddress())
        self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
        self.nodes[0].generate(2)

        # TODO 还需要测试跨链交易的情况

        blockcount = self.nodes[0].getblockcount()
        self.stop_nodes()
        extra_args = [[
            "-reindex-chainstate" if justchainstate else "-reindex",
            "-checkblockindex=1"
        ]]
        self.start_nodes(extra_args)

        while self.nodes[0].getblockcount() < blockcount:
            print(self.nodes[0].getblockcount(), blockcount)
            time.sleep(0.1)
        assert_equal(self.nodes[0].getblockcount(), blockcount)
        self.log.info("Success")
Esempio n. 2
0
    def __init__(self,
                 node,
                 contract_path=None,
                 sender=None,
                 immediate=True,
                 debug=True):
        '''

        :param node:
        :param contract_path:
        :param sender:
        :param immediate:
        '''
        self.bind_node = node
        self.debug = debug
        if contract_path is None:
            contract_path = tempfile.mkdtemp(prefix="contract_")
        self.contract_path = generate_contract(contract_path)
        if sender is not None:
            self.publisher = sender

        self.has_publish = False
        if immediate:
            # if true than publish it right now
            self.publish()
Esempio n. 3
0
    def run_test(self):
        """Main test logic"""
        # prepare
        for n in self.nodes:
            n.generate(2)  # make some coins
            self.sync_all()

        # main test
        self.contract_file = generate_contract(self.options.tmpdir)
        self.tips_num = 1
        self.log.info("start test_publish_fork_with_utxo,normal utxo")
        self.test_publish_fork_with_utxo()
        self.log.info("start test_publish_fork_with_utxo,contract utxo")
        self.test_publish_fork_with_utxo(is_contract_output=True)
        self.log.info("start double publish on both chain")
        self.test_double_publish()
        self.log.info("start test_callcontract_fork,without send")
        self.test_callcontract_fork()
        self.log.info("start test_callcontract_fork,with send, crash point 1")
        self.test_callcontract_fork(with_send=True, crash_point=1)
        self.log.info("start test_callcontract_fork,with send,crash point 2")
        self.test_callcontract_fork(with_send=True, crash_point=2)
        self.log.info("start mix transaction reorg test,no generate")
        self.test_mix_contract_transaction_fork()
        self.log.info("start mix transaction reorg test,with generate")
        self.test_mix_contract_transaction_fork(gen_blocks=True)
Esempio n. 4
0
    def run_test(self):
        """Main test logic"""
        # prepare
        node = self.nodes[0]
        node2 = self.nodes[1]
        node.generate(nblocks=2)  # make some coins
        self.sync_all()

        # publish
        contract = generate_contract(self.options.tmpdir)
        result = node.publishcontract(contract)
        contract_id = result['contractaddress']
        sender = result['senderaddress']

        call_contract = caller_factory(self, contract_id, sender)
        # call
        # no coins
        assert_contains(call_contract(PAYABLE, amount=10000000), "Insufficient funds")

        # # 非法的入参
        for amount in [10000000000, -1, 0, Decimal("0.00000009").quantize(Decimal("0.000000"))]:
            call_contract(PAYABLE, amount=amount)

        # 非法sender
        for sender_addr in [sender + "x", contract_id]:
            assert_contains(caller_factory(self, contract_id, sender_addr)(PAYABLE), "Invalid sender address")

        # # 合约不存在
        assert_contains(caller_factory(self, "2PPWpHssgXjA8yEgfd3Vo36Hhx1eimbGCcP", sender)(PAYABLE),
                        "GetContractInfo fail")

        # # 地址错误
        for addr in [contract_id + 'x', sender]:
            caller_factory(self, addr, sender)(PAYABLE)

        # 函数不存在
        if not SKIP:
            assert_contains(call_contract("payable2"), "can not find function")

        # send不能被裸调用
        # bug被修复前,暂时跳过
        if not SKIP:
            assert_contains(call_contract("send",sender,0),'can not call lua internal function directly')
            assert_contains(call_contract("rpcSendTest"), 'can not call lua internal function directly')

        # when not commit transaction, make sure contract tx is not in mempool
        if not SKIP:
            mempool = node.getrawmempool()
            node.callcontract(False, 1, contract_id, sender, PAYABLE)
            assert mempool == node.getrawmempool()

        # recharge to contract
        txid = call_contract(PAYABLE,amount = 1000)['txid']
        sync_mempools(self.nodes)
        assert txid in node.getrawmempool()
        assert txid in node2.getrawmempool()
        assert_equal(node.getbalanceof(contract_id), 0)  #合约的余额只会在一定的确认数之后才可以查看,在内存池中是不生效的
        node.generate(nblocks=1)
        self.sync_all()
        assert txid not in node.getrawmempool()
        assert txid not in node2.getrawmempool()
        assert_equal(node.getbalanceof(contract_id), 1000)  # 确认合约余额

        # doubleSpendTest
        self.test_double_spend(mineblock=False)
        self.test_double_spend()
        call_contract("doubleSpendTest", node.getnewaddress(),throw_exception = True)

        # cmsgpackTest
        if not SKIP:
            assert_contains(call_contract("cmsgpackTest", node.getnewaddress(), 0), 'cmsgpack => sc >= LUACMSGPACK_MAX_NESTING')
        self.sync_all()


        # # tailLoopTest
        call_contract("tailLoopTest", 896)  # v452,594 is the limit
        assert_contains(call_contract("tailLoopTest", 897), "run out of limit instruction")


        # # tailLoopTest2
        call_contract("tailLoopTest2", 11)
        assert_contains(call_contract("tailLoopTest2", 12), "Too many args in lua function")

        # # unpackTest
        assert_contains(call_contract("unpackTest"), "too many results to unpack")

        # localFuncTest
        if not SKIP:
            assert_contains(call_contract("localFuncTest"), "can not find function")

        # longReturnTest
        if not SKIP:
            c = generate_contract(self.options.tmpdir, err_type="long_string_return")
            addre = node.publishcontract(c)['contractaddress']
            node.callcontract(True,1,addre,sender,'longReturnTest')

        # contractDataTest
        call_contract("contractDataTest")
        assert_equal(call_contract("get", "size")['return'][0], 127)

        # make sure node1 mempool is empty
        node.generate(nblocks=2)
        assert_equal([], node.getrawmempool())
        # sendCoinTest
        # send to mgc address
        new_address = node.getnewaddress()
        txid = call_contract("sendCoinTest", new_address, 1)['txid']
        assert txid in node.getrawmempool()
        call_contract("sendCoinTest", new_address, "1e-3")
        assert_contains(call_contract("sendCoinTest", new_address, 2 ** 31 - 1), "not enough amount ")
        assert_contains(call_contract("sendCoinTest", new_address, 0.1), "JSON integer out of range")
        assert_contains(call_contract("sendCoinTest", new_address, 0), "SendCoins => amount(0) out of range")
        assert_contains(call_contract("sendCoinTest", new_address, -1), "SendCoins => amount(-100000000) out of range")
        # send all balance
        tmp_id = node.publishcontract(contract)["contractaddress"]
        tmp_caller = caller_factory(self, tmp_id, sender)
        tmp_caller(PAYABLE, amount=Decimal("1"))
        tmp_txid = tmp_caller("sendCoinTest", new_address, 1, amount=Decimal("0"),throw_exception = True)['txid']
        # 利用节点2挖矿,确保节点1的交易可以打包的块
        self.sync_all()
        node2.generate(nblocks=2)  # 这里需要挖2个,因为send的输出需要达到成熟度才可以使用
        self.sync_all()
        # make sure two transactions not in mempool
        # if assert failed it should be bug here
        assert txid not in node.getrawmempool()
        assert tmp_txid not in node.getrawmempool()
        self.sync_all()
        assert_equal(node.getbalanceof(tmp_id), 0)
        assert_equal(node.getbalanceof(new_address), 2)
        assert_equal(node2.getbalanceof(new_address), 2)
        assert_equal(node2.getbalanceof(tmp_id), 0)
        assert_contains(tmp_caller("sendCoinTest", new_address, 1), "not enough amount ")

        # send to contract
        tmp_id = node.publishcontract(contract)["contractaddress"]
        assert_contains(call_contract("sendCoinTest", tmp_id, 100), "Invalid destination address")
        node.generate(nblocks=1)

        # batchSendTest
        # 12个参数是上限,除去内部调用之后,实际能用的就只有7个参数位,并且不支持数组
        for to in range(4):
            to_list = [node.getnewaddress() for i in range(7)]
            call_contract("addWithdrawList", *to_list)
        call_contract("batchSendTest")
        node.generate(nblocks=2)
        for addr in to_list:
            assert_equal(node.getbalanceof(addr), 1)

        # updateContractTest
        call_contract("updateContract", "self", "weigun")
        assert_equal(call_contract("get", "self")['return'][0], "weigun")
        node.generate(1)

        assert_equal([],node.getrawmempool()) # make sure mempool is empty
        # cycleSelfTest
        self.log.info("begin cycleSelfTest")
        if not SKIP:
            for i in range(100):
                call_contract("cycleSelf",throw_exception = False)
                call_contract("updateContract", "this", "",throw_exception = False)
                if i % 5 == 0:
                    # print("generate block at :",i)
                    node.generate(1)
            node.generate(1)

        # assert_equal([], node.getrawmempool())  # make sure mempool is empty
        # maxContractCallTest
        call_contract("maxContractCallTest", 15)  # 15 is the limit
        assert_contains(call_contract("maxContractCallTest", 16), "run out of limit instruction")
        # callOtherContractTest
        # cycle call
        # step1 create contracts
        ca_id = contract_id
        cb_id = node.publishcontract(contract)["contractaddress"]
        cc_id = node.publishcontract(contract)["contractaddress"]
        caller_b = caller_factory(self, cb_id, sender)
        node.generate(nblocks=1)

        # step2  a->b->c->a(send will be call in last a)
        new_address = node.getnewaddress()
        if not SKIP:
            call_contract(CYCLE_CALL, cb_id, CYCLE_CALL, cc_id, CYCLE_CALL, ca_id, "sendCoinTest", new_address,throw_exception = True)
            node.generate(nblocks=1)
            assert_equal(node.getbalanceof(new_address), 1)

        # step3 a->b->c->b,modify PersistentData
        if not SKIP:
            caller_b("contractDataTest")  # after called,size should be 127
            assert_equal(caller_b("get", "size")['return'][0], 127)
            call_contract(CYCLE_CALL, cb_id, CYCLE_CALL, cc_id, CYCLE_CALL, cb_id, "reentrancyTest",
                          new_address,throw_exception = True)  # after called,size should be 127,because of replace dump
            call_contract(CYCLE_CALL, cb_id, CYCLE_CALL, cc_id, CYCLE_CALL, cb_id, "contractDataTest",
                          new_address,throw_exception = True)  # after called,size should be 127,because of replace dump
            node.generate(nblocks=1)
            assert_equal(caller_b("get", "size")['return'][0], 127)

        # lots of dust vin in contract's send transaction
        # TODO:maybe  need to set payfee param in magnachaind
        if not SKIP:
            cd_id = node.publishcontract(contract)["contractaddress"]
            caller_d = caller_factory(self, cd_id, sender)
            for i in range(2000):
                caller_d(PAYABLE, amount=Decimal("1"),throw_exception = True)
                if i % 30 == 0:
                    node.generate(nblocks=1)
            new_address = node.getnewaddress()
            caller_d("sendCoinTest", new_address, 1900, amount=Decimal("0"))
            node.generate(nblocks=2)
            assert_equal(node.getbalanceof(new_address), 1900)

        # dust change vout in send
        # node.sendtoaddress(new_sender,2)
        if not SKIP:
            tmp_id = node.publishcontract(contract)['contractaddress']
            caller_tmp = caller_factory(self, tmp_id, sender)
            senders = [node.getnewaddress() for i in range(101)]
            i = 0
            for _ in senders:
                # 充值101次,每次1个MGC
                caller_tmp(PAYABLE, amount=1,throw_exception = True)
                if i % 30 == 0:
                    node.generate(1)
                i += 1
            node.generate(2)
            assert_equal(node.getbalanceof(tmp_id), 101)
            i = 0
            for to in senders:
                # 向每个地址发送cell - 999(最小单位),cell = 100000000。这里应该有101个微交易的找零
                assert_equal(isinstance(caller_tmp("dustChangeTest", to, amount=Decimal("0"),throw_exception = True), dict), True)
                if i % 30 == 0:
                    node.generate(1)
                i += 1
            node.generate(nblocks=2)
            assert_equal(node.getbalanceof(tmp_id) * COIN, 101 * COIN - (COIN - 999 ) * 101) #因为lua没有浮点数,所以小数部分会截断掉
            bal = node.getbalanceof(tmp_id)
            print(bal)
            tmp_sender = node.getnewaddress()
            assert_equal(isinstance(caller_tmp("sendCoinTest2", tmp_sender,amount=Decimal("0"),throw_exception = True), dict),
                         True)  # 组合所有微交易的找零,应该足够0.001个MGC的
            node.generate(nblocks=2)
            assert_equal(node.getbalanceof(tmp_sender), Decimal("0.001"))
            assert_equal(node.getbalanceof(tmp_id), bal - Decimal("0.001"))

        # reentrancyTest
        last_id = node.publishcontract(contract)['contractaddress']
        caller_last = caller_factory(self, last_id, sender)
        if not SKIP:
            caller_last("reentrancyTest")
            node.generate(nblocks=1)
            assert_equal(caller_last("get", "this")['return'], [])

        # 疲劳测试
        if not SKIP:
            to_list = [node.getnewaddress() for i in range(1000)]
            for i,to in enumerate(to_list):
                caller_last(PAYABLE, amount=10)
                caller_last(CYCLE_CALL, last_id, "contractDataTest",amount=0)
                caller_last(CYCLE_CALL, last_id, "dustChangeTest",to,amount=0)
                caller_last(CYCLE_CALL, last_id, "addWithdrawList",to,amount=0)
                # caller_last(CYCLE_CALL, last_id, "batchSendTest",amount=0)
                if random.randint(1,100) > 70:
                    node.generate(nblocks=1)
                else:
                    if i % 30 == 0:
                        node.generate(nblocks=1)
Esempio n. 5
0
    def run_test(self):
        self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
        base_fee = self.relayfee * 1000

        # prepare
        node0, node1 = self.nodes[0:2]
        node0.generate(2)  # make some coins
        self.sync_all()
        contract = generate_contract(self.options.tmpdir)
        # ''''
        # 测试发布合约的交易
        self.log.info("Test contract publish transaction")
        contract = generate_contract(self.options.tmpdir)
        infos = gen_lots_of_contracts(node0, contract, MAX_CONTRACT_NUM)
        node0.prioritisetransaction(txid=infos[-1]['txid'],
                                    fee_delta=int(3 * base_fee * COIN))
        mempool_len = len(node0.getrawmempool())
        print(mempool_len)
        print(len(node0.getrawmempool()), len(node1.getrawmempool()))
        self.sync_all()
        print(len(node0.getrawmempool()), len(node1.getrawmempool()))
        node0.generate(1)
        sync_blocks(self.nodes)
        block_txnum = int(node0.getblock(node0.getbestblockhash())['tx_num'])
        mempool = node0.getrawmempool()
        print(block_txnum, len(node0.getrawmempool()),
              len(node1.getrawmempool()))
        assert infos[-1]['txid'] not in mempool  # should be mined
        assert_equal(len(node0.getrawmempool()), MAX_CONTRACT_NUM -
                     block_txnum + 1)  # can not locate the tx index in infos
        node0.generate(1)  # clear mempool
        sync_blocks(self.nodes, timeout=600)
        assert_equal(len(node0.getrawmempool()),
                     0)  # make sure mempool is clean

        # 测试调用合约的交易
        self.log.info("Test call contract transaction")
        # node0_call_contract = caller_factory(self, infos[-1]['address'], node0.getnewaddress())
        infos = infos + gen_lots_of_contracts(
            node0, contract, MAX_CONTRACT_CALL_NUM - MAX_CONTRACT_NUM)
        print(len(node0.getrawmempool()), len(node1.getrawmempool()))
        self.sync_all(timeout=6000, show_max_height=True)
        print(len(node0.getrawmempool()), len(node1.getrawmempool()))
        node0.generate(10)
        print("sync blocks....")
        sync_blocks(self.nodes, timeout=6000)
        assert_equal(len(node0.getrawmempool()),
                     0)  # make sure mempool is clean
        print("info size: %d" % (len(infos)))
        txids = [
            node0.callcontract(True, 0, infos[i]['address'],
                               node0.getnewaddress(), 'payable')['txid']
            for i in range(MAX_CONTRACT_CALL_NUM)
        ]
        node0.prioritisetransaction(txid=txids[-1],
                                    fee_delta=int(3 * base_fee * COIN))
        print("mempool size after change priority: %d" %
              (len(node0.getrawmempool())))
        node0.generate(1)
        print("mempool size after generate block: %d" %
              (len(node0.getrawmempool())))
        self.sync_all(timeout=6000, show_max_height=True)
        block_txnum = int(node0.getblock(node0.getbestblockhash())['tx_num'])
        print(block_txnum, len(node0.getrawmempool()))
        mempool = node0.getrawmempool()
        assert txids[-1] not in mempool  # should be mined
        # assert infos[-2]['txid'] in mempool
        assert len(
            node0.getrawmempool()) < 5  # can not locate the tx index in infos
        node0.generate(1)  # clear mempool
        sync_blocks(self.nodes, timeout=600)
        assert len(node0.getrawmempool()) == 0  # make sure mempool is clean

        # 测试有依赖的合约交易的优先级,依赖方式为调用同一合约
        publish_transaction = gen_lots_of_contracts(node0, contract, 1)
        print(publish_transaction)
        txid = node0.callcontract(True, 0, publish_transaction[0]['address'],
                                  node0.getnewaddress(), 'payable')['txid']
        mempool_old = node0.getrawmempool()
        node0.prioritisetransaction(txid=txid,
                                    fee_delta=int(30 * base_fee * COIN))
        mempool_new = node0.getrawmempool()
        # print(mempool_old,mempool_new)
        assert mempool_old == mempool_new  # 因为有依赖关系,所以内存池顺序应该是一致的
        node0.generate(2)
        sync_blocks(self.nodes, timeout=600)

        to = node0.getnewaddress()
        txid1 = node0.callcontract(True, 1, publish_transaction[0]['address'],
                                   node0.getnewaddress(), 'payable')['txid']
        print("txid1:", txid1)
        txid2 = node0.callcontract(True, 0, publish_transaction[0]['address'],
                                   node0.getnewaddress(), 'sendCoinTest', to,
                                   1)['txid']
        print("txid2:", txid2)
        mempool_old = node0.getrawmempool()
        node0.prioritisetransaction(txid=txid2,
                                    fee_delta=int(30 * base_fee * COIN))
        mempool_new = node0.getrawmempool()
        assert mempool_old == mempool_new  # 因为有依赖关系,所以内存池顺序应该是一致的
        self.sync_all(timeout=6000, show_max_height=True)
        assert mempool_old == node1.getrawmempool(
        )  # prioritisetransaction不会影响其他节点交易的优先级
        node0.generate(2)
        assert node0.getbalanceof(to) == 1

        # 调整有依赖的合约交易的优先级,依赖方式为输入有依赖
        node0.sendtoaddress(node1.getnewaddress(), 100)
        self.sync_all()
        node0.generate(1)
        print(node1.getbalance(), node0.getbalance())
        publish_transaction = gen_lots_of_contracts(node0, contract, 1)
        self.sync_all()
        to = node0.getnewaddress()
        txid3 = node1.callcontract(True, 1, publish_transaction[0]['address'],
                                   node1.getnewaddress(), 'payable')['txid']
        txid4 = node1.sendtoaddress(to, 1)
        mempool_old = node1.getrawmempool()
        node1.prioritisetransaction(txid=txid4,
                                    fee_delta=int(30 * base_fee * COIN))
        mempool_new = node1.getrawmempool()
        assert mempool_old == mempool_new  # 因为有依赖关系,所以内存池顺序应该是一致的
        self.sync_all(timeout=6000, show_max_height=True)
        assert mempool_old == node0.getrawmempool(
        )  # prioritisetransaction不会影响其他节点交易的优先级
        node0.generate(2)
        assert node0.getbalanceof(to) == 1
        # '''
        # 调整有依赖的合约交易的优先级,依赖方式为跨合约调用
        # 目前还不能确认顺序,所以先屏蔽这个用例
        infos = gen_lots_of_contracts(node0, contract, 2)
        print(infos)
        txid5 = node0.callcontract(True, 1, infos[0]['address'],
                                   node0.getnewaddress(), 'payable')['txid']
        txid6 = node0.callcontract(True, 1, infos[1]['address'],
                                   node0.getnewaddress(), 'payable')['txid']
        print(txid5, txid6)
        mempool_old = node0.getrawmempool(True)
        node0.prioritisetransaction(txid=txid6,
                                    fee_delta=int(30 * base_fee * COIN))
        mempool_new = node0.getrawmempool(True)
        print(mempool_old)
        print(mempool_new)
Esempio n. 6
0
    def run_test(self):
        """Main test logic"""
        # prepare
        node = self.nodes[0]
        node2 = self.nodes[1]
        node2.generate(2) # make some coins
        self.sync_all()

        # no coins
        try:
            contract = generate_contract(self.options.tmpdir)
            result = node.publishcontract(contract)
        except Exception as e:
            assert "GetSenderAddr" in repr(e)

        # make sure not in mempool when the tx failed
        assert_equal([],node.getrawmempool())

        node.generate(2) # make some coins
        self.sync_all()
        # 错误的合约
        contract = generate_contract(self.options.tmpdir,err_type = "syntax_err")
        try:
            result = node.publishcontract(contract)
        except Exception as e:
            assert 'expected near' in repr(e)

        # 超大合约
        contract = generate_contract(self.options.tmpdir,err_type = "bigfile") # should be bigfile
        try:
            result = node.publishcontract(contract)
        except Exception as e:
            assert 'code is too large' in repr(e)

        # 测试sdk发布合约的接口
        # TODO 需要单独测试prepublishcode接口
        # prepublishcodeTest
        contract = generate_contract(self.options.tmpdir)
        with open(contract) as fh:
            content = "".join(fh.readlines())
        hex_content = bytes_to_hex_str(bytes(content,encoding='utf-8'))
        coster = node.getnewaddress()
        for i in range(10):
            node.sendtoaddress(coster, 1000)
        node.generate(2)
        sender = coster
        amount = 1
        changeaddress = node.getnewaddress()
        result = node.prepublishcode(hex_content,coster,sender,amount,changeaddress)
        print(result)

        # syntax_err hex content
        contract = generate_contract(self.options.tmpdir,err_type = "syntax_err")
        with open(contract) as fh:
            content = "".join(fh.readlines())
        hex_content_tmp = bytes_to_hex_str(bytes(content,encoding='utf-8'))
        try:
            result = node.prepublishcode(hex_content_tmp, coster, sender, amount, changeaddress)
        except Exception as e:
            assert 'expected near' in repr(e)

        # empty content
        hex_content_tmp = bytes_to_hex_str(bytes("",encoding='utf-8'))
        try:
            result = node.prepublishcode(hex_content_tmp, coster, sender, amount, changeaddress)
        except Exception as e:
            assert 'code data can not empty' in repr(e)

        # not hex
        hex_content_tmp = "not hex data"
        try:
            result = node.prepublishcode(hex_content_tmp, coster, sender, amount, changeaddress)
        except Exception as e:
            assert 'code data must hex data' in repr(e)

        # coster test
        # Invalid address
        contract = generate_contract(self.options.tmpdir)
        contract_id = node.publishcontract(contract)["contractaddress"]
        node1_newaddress = self.nodes[1].getnewaddress()
        self.nodes[1].sendtoaddress(node1_newaddress, 100)
        self.nodes[1].generate(2)
        sync_blocks(self.nodes)
        for coster_tmp in ["","DFGHJK12316547645",contract_id,node1_newaddress]:
            try:
                result = node.prepublishcode(hex_content, coster_tmp, sender, amount, changeaddress)
            except Exception as e:
                assert 'Invalid MagnaChain public key address' in repr(e) or "Invalid MagnaChain fund address" in repr(e)
                continue
        node.generate(1)

        # sender test
        # Invalid address
        for sender_tmp in ["", "DFGHJK12316547645", contract_id, node1_newaddress]:
            try:
                result = node.prepublishcode(hex_content, coster, sender_tmp, amount, changeaddress)
            except Exception as e:
                assert 'Invalid MagnaChain public key address' in repr(e) or "Invalid MagnaChain sender address" in repr(e)
                continue
        node.generate(1)

        # amount test
        for amount_tmp in [10000000000, "10",-1, 0, Decimal("0.0009").quantize(Decimal("0.0000"))]:
            try:
                result = node.prepublishcode(hex_content, coster, sender, amount_tmp, changeaddress)
            except Exception as e:
                assert 'Invalid amount for send' in repr(e) or "Amount out of range" in repr(e) or "Invalid amount" in repr(e)
                continue
        node.generate(1)

        # changeaddress test
        for changeaddress_tmp in ["", "DFGHJK12316547645", contract_id, node1_newaddress]:
            try:
                result = node.prepublishcode(hex_content, coster, sender, amount_tmp, changeaddress)
            except Exception as e:
                assert 'Invalid MagnaChain public key address' in repr(e) or "Invalid MagnaChain change address" in repr(e)
                continue
        node.generate(1)

        # test fee
        # encrypt wallet test with contract
        node.node_encrypt_wallet('test')
        self.stop_node(1)
        self.start_nodes()
        connect_nodes_bi(self.nodes, 0, 1)
        node.walletpassphrase("test", 1)
        time.sleep(2) # wait for timeout
        assert_raises_rpc_error(-13,'Please enter the wallet passphrase with walletpassphrase first',node.publishcontract,contract)
        node.walletpassphrase("test", 300)
        payfee = node.getinfo()['paytxfee']
        relayfee = node.getinfo()['relayfee']
        txid = node.publishcontract(contract)['txid']
        txfee = node.gettransaction(txid)['fee']
        tx_size = count_bytes(node.getrawtransaction(txid))
        node.settxfee(20)
        txid = node.publishcontract(contract)['txid']
        print(txfee,node.gettransaction(txid)['fee'])
        assert abs(node.gettransaction(txid)['fee']) > abs(txfee) and abs(node.gettransaction(txid)['fee']) == 100
        assert_equal(node.gettransaction(txid)['confirmations'],0)
        self.sync_all()
        node2.generate(1)
        self.sync_all()
        assert_equal(node.gettransaction(txid)['confirmations'], 1)
        node.settxfee(payfee)

        # 正确的合约,并且进行重复测试
        j = 2
        contract = generate_contract(self.options.tmpdir)
        for i in range(200):
            balance = node.getbalance()
            result = node.publishcontract(contract)
            diff = balance - node.getbalance()
            assert diff > 0 and diff < 13 ,"publish fee too much:%s"%(diff)  # 该合约的费用基本是固定的,避免修改数值出现比较大的偏差
            self.log.info("publish cost:%s"%(balance - node.getbalance()))
            if i % j == 0:
                # 每个多少个交易后才打一次包
                self.sync_all()
                node.generate(1)
                j = min(64,j * 2)

        node.generate(1)