def run_test(self):
        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        self.setup_contract()
        for i in range(self.options.iter):
            self.generate_transactions(i)
Exemple #2
0
    def run_test(self):
        # Prevent easysolc from configuring the root logger to print to stderr
        self.log.propagate = False

        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        self.setup_contract()
        for i in range(self.options.iter):
            self.generate_transactions(i)
Exemple #3
0
 def run_test(self):
     n_generate_batch = 1000
     n_initial_chain = 50000
     self.log.info(
         f"Prepare the initial chain of node 0 with {n_initial_chain} blocks"
     )
     n_batches = int(n_initial_chain / n_generate_batch)
     for i in range(n_batches):
         batch_generate(self.nodes[0], n_generate_batch, self.log)
     n_fork_height = 1000
     n_star_count = 15000
     for i in range(self.num_nodes):
         self.log.info(
             f"Prepare node {i} with a chain of the length {n_fork_height} and then a star of {n_star_count} blocks."
         )
         client = RpcClient(self.nodes[i])
         fork_point = client.generate_empty_blocks(n_fork_height)[-1]
         for _ in range(n_star_count):
             client.generate_block_with_parent(fork_point)
     for i in range(self.num_nodes - 1):
         connect_nodes(self.nodes, i, i + 1)
     self.log.info(
         "Nodes connected, normal mining start at the interval of 0.5")
     block_gen_thread = BlockGenThread(self.nodes,
                                       self.log,
                                       interval_base=0.5)
     block_gen_thread.start()
     start_time = time.time()
     original_cnt = self.nodes[0].getblockcount()
     for _ in range(100):
         time.sleep(1)
         cnt = self.nodes[0].getblockcount()
         try:
             cnt1 = self.nodes[1].getblockcount()
         except Exception as e:
             self.log.info(
                 "Unable to get Node1 block count. Maybe it is busy.")
             cnt1 = -1
         try:
             cnt2 = self.nodes[2].getblockcount()
         except Exception as e:
             self.log.info(
                 "Unable to get Node2 block count. Maybe it is busy.")
             cnt2 = -1
         elapsed = time.time() - start_time
         avg_block_processing = (cnt - original_cnt) / elapsed
         self.log.info(
             f"Nodes block count {cnt};{cnt1};{cnt2}, elapsed {elapsed}, {avg_block_processing} blocks/s"
         )
     self.log.info(
         f"Merge bench average block processing speed: {avg_block_processing} blocks/s"
     )
Exemple #4
0
    def run_test(self):
        # Prevent easysolc from configuring the root logger to print to stderr
        self.log.propagate = False

        solc = Solc()
        # erc20_contract = solc.get_contract_instance(source=os.path.dirname(os.path.realpath(__file__)) + "/erc20.sol", contract_name="FixedSupplyToken")
        file_dir = os.path.dirname(os.path.realpath(__file__))
        erc20_contract = solc.get_contract_instance(
            abi_file = os.path.join(file_dir, "contracts/erc20_abi.json"),
            bytecode_file = os.path.join(file_dir, "contracts/erc20_bytecode.dat"),
        )

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = default_config["GENESIS_PRI_KEY"]
        genesis_addr = privtoaddr(genesis_key)
        nonce = 0
        gas_price = 1
        gas = 50000000
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {"from":Web3.toChecksumAddress(encode_hex_0x(genesis_addr)), "nonce":int_to_hex(nonce), "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0}
        raw_create = erc20_contract.constructor().buildTransaction(self.tx_conf)
        tx_data = decode_hex(raw_create["data"])
        tx_create = create_transaction(pri_key=genesis_key, receiver=b'', nonce=nonce, gas_price=gas_price, data=tx_data, gas=gas, value=0)
        self.nodes[0].p2p.send_protocol_msg(Transactions(transactions=[tx_create]))
        self.wait_for_tx([tx_create])
        self.log.info("Contract created, start transfering tokens")

        tx_n = 10
        self.tx_conf["to"] = Web3.toChecksumAddress(encode_hex_0x(sha3_256(rlp.encode([genesis_addr, nonce]))[-20:]))
        nonce += 1
        balance_map = {genesis_key: 1000000 * 10**18}
        sender_key = genesis_key
        all_txs = []
        for i in range(tx_n):
            value = int((balance_map[sender_key] - ((tx_n - i) * 21000 * gas_price)) * random.random())
            receiver_sk, _ = ec_random_keys()
            balance_map[receiver_sk] = value
            tx_data = decode_hex(erc20_contract.functions.transfer(Web3.toChecksumAddress(encode_hex(privtoaddr(receiver_sk))), value).buildTransaction(self.tx_conf)["data"])
            tx = create_transaction(pri_key=sender_key, receiver=decode_hex(self.tx_conf["to"]), value=0, nonce=nonce, gas=gas,
                                    gas_price=gas_price, data=tx_data)
            r = random.randint(0, self.num_nodes - 1)
            self.nodes[r].p2p.send_protocol_msg(Transactions(transactions=[tx]))
            nonce += 1
            balance_map[sender_key] -= value
            all_txs.append(tx)
        self.log.info("Wait for transactions to be executed")
        self.wait_for_tx(all_txs)
        self.log.info("Check final token balance")
        for sk in balance_map:
            addr = privtoaddr(sk)
            assert_equal(self.get_balance(erc20_contract, addr, nonce), balance_map[sk])
        block_gen_thread.stop()
        block_gen_thread.join()
        sync_blocks(self.nodes)
        self.log.info("Pass")
    def run_test(self):
        file_dir = os.path.dirname(os.path.realpath(__file__))

        storage_contract = get_contract_instance(
            abi_file=os.path.join(file_dir, "contracts/simple_storage.abi"),
            bytecode_file=os.path.join(file_dir,
                                       "contracts/simple_storage.dat"),
        )

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_addr = self.genesis_addr
        self.log.info("genesis_addr={}".format(encode_hex_0x(genesis_addr)))

        block_gen_thread = BlockGenThread(self.nodes,
                                          self.log,
                                          interval_fixed=1)
        block_gen_thread.start()

        client = RpcClient(self.nodes[0])

        tx = client.new_tx(value=int(0.625 * CFX) + GDrip,
                           receiver=self.eth_hex_addr,
                           nonce=self.get_nonce(genesis_addr))
        client.send_tx(tx, True)
        assert_equal(client.get_balance(self.eth_hex_addr),
                     int(0.625 * CFX) + GDrip)

        # deploy contract
        self.log.info("Deploying contract")
        tx = self.call_contract_function(
            contract=storage_contract,
            name="constructor",
            args=[],
            sender_key=self.eth_priv_key,
            eth_tx=True,
        )

        wait_until(lambda: self.nodes[1].tx_inspect(tx.hash_hex())['exist'],
                   timeout=10)
        block_gen_thread.stop()

        client.generate_blocks(40)
        block_hash = client.generate_custom_block(client.best_block_hash(), [],
                                                  [tx])
        wait_until(lambda: client.best_block_hash() == block_hash, timeout=10)
        client.generate_blocks(40)

        BlockGenThread(self.nodes, self.log, interval_fixed=1).start()

        receipt = self.wait_for_tx([tx])[0]

        assert_greater_than_or_equal(int(receipt['epochNumber'], 0), 80)

        self.log.info("All test done")
Exemple #6
0
    def run_test(self):
        file_dir = os.path.dirname(os.path.realpath(__file__))
        erc20_contract = get_contract_instance(
            abi_file=os.path.join(file_dir, "contracts/erc20_abi.json"),
            bytecode_file=os.path.join(file_dir,
                                       "contracts/erc20_bytecode.dat"),
        )

        gas_price = 1
        gas = CONTRACT_DEFAULT_GAS

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = default_config["GENESIS_PRI_KEY"]
        genesis_addr = encode_hex_0x(priv_to_addr(genesis_key))
        nonce = 0
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {
            "from": Web3.toChecksumAddress(genesis_addr),
            "nonce": int_to_hex(nonce),
            "gas": int_to_hex(gas),
            "gasPrice": int_to_hex(gas_price),
            "chainId": 0
        }
        raw_create = erc20_contract.constructor().buildTransaction(
            self.tx_conf)
        tx_data = decode_hex(raw_create["data"])
        tx_create = create_transaction(pri_key=genesis_key,
                                       receiver=b'',
                                       nonce=nonce,
                                       gas_price=gas_price,
                                       data=tx_data,
                                       gas=gas,
                                       value=0,
                                       storage_limit=1920)
        client = RpcClient(self.nodes[0])
        c0 = client.get_collateral_for_storage(genesis_addr)
        client.send_tx(tx_create, True)
        receipt = client.get_transaction_receipt(tx_create.hash_hex())
        c1 = client.get_collateral_for_storage(genesis_addr)
        assert_equal(c1 - c0, 1920 * 10**18 / 1024)
        contract_addr = receipt['contractCreated']
        self.log.info("Contract " + str(contract_addr) +
                      " created, start transferring tokens")

        tx_n = 10
        self.tx_conf["to"] = contract_addr
        nonce += 1
        balance_map = {genesis_key: 1000000 * 10**18}
        sender_key = genesis_key
        all_txs = []
        for i in range(tx_n):
            value = int((balance_map[sender_key] -
                         ((tx_n - i) * 21000 * gas_price)) * random.random())
            receiver_sk, _ = ec_random_keys()
            balance_map[receiver_sk] = value
            tx_data = decode_hex(
                erc20_contract.functions.transfer(
                    Web3.toChecksumAddress(
                        encode_hex(priv_to_addr(receiver_sk))),
                    value).buildTransaction(self.tx_conf)["data"])
            tx = create_transaction(pri_key=sender_key,
                                    receiver=decode_hex(self.tx_conf["to"]),
                                    value=0,
                                    nonce=nonce,
                                    gas=gas,
                                    gas_price=gas_price,
                                    data=tx_data,
                                    storage_limit=64)
            r = random.randint(0, self.num_nodes - 1)
            self.nodes[r].p2p.send_protocol_msg(
                Transactions(transactions=[tx]))
            nonce += 1
            balance_map[sender_key] -= value
            all_txs.append(tx)
        self.log.info("Wait for transactions to be executed")
        self.wait_for_tx(all_txs)
        self.log.info("Check final token balance")
        for sk in balance_map:
            addr = priv_to_addr(sk)
            assert_equal(self.get_balance(erc20_contract, addr, nonce),
                         balance_map[sk])
        c2 = client.get_collateral_for_storage(genesis_addr)
        assert_equal(c2 - c1, 64 * tx_n * 10**18 / 1024)
        block_gen_thread.stop()
        block_gen_thread.join()
        sync_blocks(self.nodes)
        self.log.info("Pass")
Exemple #7
0
    def run_test(self):
        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes, self.log, interval_base=0.2)
        block_gen_thread.start()
        genesis_key = default_config["GENESIS_PRI_KEY"]
        tx_n = 100
        gas_price = 1
        shard_size = int(self.num_nodes / self.n_shard)
        shard_balance = []

        for s in range(self.n_shard):
            ''' Send random transactions to this shard s '''
            shard_nodes = self.nodes[s * shard_size: (s + 1) * shard_size]
            receiver_sk, _ = ec_random_keys()
            value = default_config["TOTAL_COIN"] - 21000
            balance_map = {receiver_sk: value}
            nonce_map = {receiver_sk: 0}
            tx = create_transaction(pri_key=genesis_key, receiver=privtoaddr(receiver_sk), value=value, nonce=0,
                                    gas_price=gas_price)
            shard_nodes[0].p2p.send_protocol_msg(Transactions(transactions=[tx]))
            for i in range(tx_n):
                sender_key = random.choice(list(balance_map))
                nonce = nonce_map[sender_key]
                if random.random() < 0.2 and balance_map[sender_key] > 21000 * 4 * tx_n:
                    value = int(balance_map[sender_key] * 0.5)
                    receiver_sk, _ = ec_random_keys()
                    nonce_map[receiver_sk] = 0
                    balance_map[receiver_sk] = value
                else:
                    value = 1
                    receiver_sk = random.choice(list(balance_map))
                    balance_map[receiver_sk] += value
                tx = create_transaction(pri_key=sender_key, receiver=privtoaddr(receiver_sk), value=value, nonce=nonce,
                                        gas_price=gas_price)
                r = random.randint(0, shard_size - 1)
                shard_nodes[r].p2p.send_protocol_msg(Transactions(transactions=[tx]))
                nonce_map[sender_key] = nonce + 1
                balance_map[sender_key] -= value + gas_price * 21000
                self.log.info("New tx %s: %s send value %d to %s, sender balance:%d, receiver balance:%d", encode_hex(tx.hash), eth_utils.encode_hex(privtoaddr(sender_key))[-4:],
                               value, eth_utils.encode_hex(privtoaddr(receiver_sk))[-4:], balance_map[sender_key], balance_map[receiver_sk])
                self.log.debug("Send Transaction %s to node %d", encode_hex(tx.hash), r)
                time.sleep(random.random() / 10)
            for k in balance_map:
                self.log.info("Check account sk:%s addr:%s", bytes_to_int(k), eth_utils.encode_hex(privtoaddr(k)))
                wait_until(lambda: self.check_account(k, balance_map, shard_nodes[0]))
            shard_balance.append(balance_map)

        def epochCheck(node):
            r = node.cfx_epochNumber()
            return int(r, 0) > 110

        wait_until(lambda: epochCheck(self.nodes[0]))
        wait_until(lambda: epochCheck(self.nodes[int(self.num_nodes / self.n_shard)]))
        for s in range(self.n_shard):
            connect_nodes(self.nodes, s * shard_size - 1, s * shard_size)
        block_gen_thread.stop()
        block_gen_thread.join()
        sync_blocks(self.nodes)

        ''' Check if the balance state of every node matches '''
        success_shard = -1
        # use the state of node 0 to find the winning shard
        for s in range(self.n_shard):
            balance_map = shard_balance[s]
            unmatch = False
            for k in balance_map:
                if not self.check_account(k, balance_map, self.nodes[0]):
                    unmatch = True
                    self.log.info("Final balance does not match shard %s, check next", s)
                    break
            if unmatch:
                continue
            success_shard = s
            break
        assert success_shard != -1, "The final state of node 0 matches no shard state"
        self.log.info("Shard %s succeeds", success_shard)
        for i in range(1, self.num_nodes):
            balance_map = shard_balance[success_shard]
            for k in balance_map:
                if not self.check_account(k, balance_map, self.nodes[i]):
                    raise AssertionError("Final balance of node {} does not match node 0, sender={}".format(i, k))
        self.log.info("Pass")
Exemple #8
0
    def run_test(self):
        file_dir = os.path.dirname(os.path.realpath(__file__))

        storage_contract = get_contract_instance(
            abi_file=os.path.join(file_dir, "contracts/simple_storage.abi"),
            bytecode_file=os.path.join(file_dir,
                                       "contracts/simple_storage.dat"),
        )

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_addr = self.genesis_addr
        self.log.info("genesis_addr={}".format(encode_hex_0x(genesis_addr)))

        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        client = RpcClient(self.nodes[0])
        client1 = RpcClient(self.nodes[1])

        tx = client.new_tx(value=int(0.625 * CFX) + GDrip,
                           receiver=self.eth_hex_addr,
                           nonce=self.get_nonce(genesis_addr))
        client.send_tx(tx, True)
        assert_equal(client.get_balance(self.eth_hex_addr),
                     int(0.625 * CFX) + GDrip)

        # deploy pay contract
        block_gen_thread.stop(
        )  # stop the block generation to test transaction relay.
        time.sleep(3)
        self.log.info("Deploying contract")
        tx = self.call_contract_function(
            contract=storage_contract,
            name="constructor",
            args=[],
            sender_key=self.eth_priv_key,
            eth_tx=True,
        )
        assert_equal(tx["epoch_height"], 0xffff_ffff_ffff_ffff)
        wait_until(lambda: self.nodes[1].txpool_txWithPoolInfo(tx.hash_hex())[
            'exist'],
                   timeout=5)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        receipt = self.wait_for_tx([tx], True)[0]
        assert_equal(int(receipt["storageCollateralized"], 0), 640)

        contract_addr = receipt['contractCreated']
        self.log.info("contract_addr={}".format(contract_addr))
        assert_equal(client.get_collateral_for_storage(self.eth_hex_addr),
                     int(0.625 * CFX))
        assert_greater_than(GDrip, client.get_balance(self.eth_hex_addr))

        storage_contract = get_contract_instance(
            abi_file=os.path.join(file_dir, "contracts/simple_storage.abi"),
            bytecode_file=os.path.join(file_dir,
                                       "contracts/simple_storage.dat"),
        )

        # Should fail because of not enough balance for storage.
        self.log.info("Sending transaction without enough collateral")
        tx = self.call_contract_function(
            contract=storage_contract,
            contract_addr=contract_addr,
            name="setFresh",
            args=[],
            sender_key=self.eth_priv_key,
            eth_tx=True,
        )
        receipt = self.wait_for_tx([tx])[0]
        assert_equal(int(receipt["outcomeStatus"], 0), 1)

        sponsor_whitelist_contract_addr = Web3.toChecksumAddress(
            "0888000000000000000000000000000000000001")
        file_dir = os.path.dirname(os.path.realpath(__file__))
        control_contract_file_path = os.path.join(
            file_dir, "..", "internal_contract", "metadata",
            "SponsorWhitelistControl.json")
        control_contract_dict = json.loads(
            open(control_contract_file_path, "r").read())
        control_contract = get_contract_instance(
            contract_dict=control_contract_dict)
        self.log.info("Setting sponsor for collateral")
        self.call_contract_function(
            contract=control_contract,
            name="setSponsorForCollateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=1 * CFX,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True,
            check_status=True)
        self.log.info("Sending balance to eth_like tx")
        tx = client.new_tx(value=int(0.0625 * CFX),
                           receiver=self.eth_hex_addr,
                           nonce=self.get_nonce(genesis_addr))
        client.send_tx(tx, True)
        self.log.info("Setting whitelist for all")
        self.call_contract_function(
            contract=control_contract,
            name="addPrivilegeByAdmin",
            args=[
                Web3.toChecksumAddress(contract_addr),
                [Web3.toChecksumAddress("0x" + "0" * 40)]
            ],
            sender_key=self.eth_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            eth_tx=True,
            wait=True,
            check_status=True)

        # Should not fail because of sponsored
        self.log.info("Sending transaction when sponsored")
        time.sleep(3)
        block_gen_thread.stop(
        )  # stop the block generation to test transaction relay in sponsorship

        tx = self.call_contract_function(
            contract=storage_contract,
            contract_addr=contract_addr,
            name="setFresh",
            args=[],
            sender_key=self.eth_priv_key,
            eth_tx=True,
        )

        wait_until(lambda: self.nodes[1].txpool_txWithPoolInfo(tx.hash_hex())[
            'exist'],
                   timeout=5)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        receipt = self.wait_for_tx([tx])[0]
        assert_equal(receipt["storageCoveredBySponsor"], True)
        assert_equal(int(receipt["storageCollateralized"], 0), 64)

        wait_until(lambda: checktx(self.nodes[1], tx.hash_hex()), timeout=20)

        self.log.info("Pass")
    def run_test(self):
        genesis_key = default_config["GENESIS_PRI_KEY"]
        balance_map = {genesis_key: default_config["TOTAL_COIN"]}
        self.log.info("Initial State: (sk:%d, addr:%s, balance:%d)",
                      bytes_to_int(genesis_key),
                      eth_utils.encode_hex(priv_to_addr(genesis_key)),
                      balance_map[genesis_key])
        nonce_map = {genesis_key: 0}

        # '''Check if transaction from uncommitted new address can be accepted'''
        # tx_n = 5
        # receiver_sk = genesis_key
        gas_price = 1
        # for i in range(tx_n):
        #     sender_key = receiver_sk
        #     value = int((balance_map[sender_key] - ((tx_n - i) * 21000 * gas_price)) * random.random())
        #     nonce = nonce_map[sender_key]
        #     receiver_sk, _ = ec_random_keys()
        #     nonce_map[receiver_sk] = 0
        #     balance_map[receiver_sk] = value
        #     tx = create_transaction(pri_key=sender_key, receiver=privtoaddr(receiver_sk), value=value, nonce=nonce,
        #                             gas_price=gas_price)
        #     r = random.randint(0, self.num_nodes - 1)
        #     self.nodes[r].p2p.send_protocol_msg(Transactions(transactions=[tx]))
        #     nonce_map[sender_key] = nonce + 1
        #     balance_map[sender_key] -= value + gas_price * 21000
        #     self.log.debug("New tx %s: %s send value %d to %s, sender balance:%d, receiver balance:%d", encode_hex(tx.hash), eth_utils.encode_hex(privtoaddr(sender_key))[-4:],
        #                    value, eth_utils.encode_hex(privtoaddr(receiver_sk))[-4:], balance_map[sender_key], balance_map[receiver_sk])
        #     self.log.debug("Send Transaction %s to node %d", encode_hex(tx.hash), r)
        #     time.sleep(random.random() / 10 * self.delay_factor)
        block_gen_thread = BlockGenThread(self.nodes,
                                          self.log,
                                          interval_base=self.delay_factor)
        block_gen_thread.start()
        # for k in balance_map:
        #     self.log.info("Check account sk:%s addr:%s", bytes_to_int(k), eth_utils.encode_hex(privtoaddr(k)))
        #     wait_until(lambda: self.check_account(k, balance_map), timeout=60*self.delay_factor)
        # self.log.info("Pass 1")
        # self.register_test("general_1.json")
        '''Test Random Transactions'''
        all_txs = []
        tx_n = 1000
        account_n = 10

        # Initialize new accounts
        new_keys = set()
        for _ in range(account_n):
            value = int(balance_map[genesis_key] * 0.5)
            receiver_sk, _ = ec_random_keys()
            new_keys.add(receiver_sk)
            tx = create_transaction(pri_key=genesis_key,
                                    receiver=priv_to_addr(receiver_sk),
                                    value=value,
                                    nonce=nonce_map[genesis_key],
                                    gas_price=gas_price)
            self.nodes[0].p2p.send_protocol_msg(
                Transactions(transactions=[tx]))
            balance_map[receiver_sk] = value
            nonce_map[genesis_key] += 1
            balance_map[genesis_key] -= value + gas_price * 21000
        wait_for_account_stable()
        for key in new_keys:
            nonce_map[key] = wait_for_initial_nonce_for_privkey(
                self.nodes[0], key)

        self.log.info(
            "start to generate %d transactions with about %d seconds", tx_n,
            tx_n / 10 / 2 * self.delay_factor)
        for i in range(tx_n):
            sender_key = random.choice(list(balance_map))
            nonce = nonce_map[sender_key]
            value = 1
            receiver_sk = random.choice(list(balance_map))
            balance_map[receiver_sk] += value
            # not enough transaction fee (gas_price * gas_limit) should not happen for now
            assert balance_map[sender_key] >= value + gas_price * 21000
            tx = create_transaction(pri_key=sender_key,
                                    receiver=priv_to_addr(receiver_sk),
                                    value=value,
                                    nonce=nonce,
                                    gas_price=gas_price)
            r = random.randint(0, self.num_nodes - 1)
            self.nodes[r].p2p.send_protocol_msg(
                Transactions(transactions=[tx]))
            all_txs.append(tx)
            nonce_map[sender_key] = nonce + 1
            balance_map[sender_key] -= value + gas_price * 21000
            self.log.debug(
                "New tx %s: %s send value %d to %s, sender balance:%d, receiver balance:%d nonce:%d",
                encode_hex(tx.hash),
                eth_utils.encode_hex(priv_to_addr(sender_key))[-4:], value,
                eth_utils.encode_hex(priv_to_addr(receiver_sk))[-4:],
                balance_map[sender_key], balance_map[receiver_sk], nonce)
            self.log.debug("Send Transaction %s to node %d",
                           encode_hex(tx.hash), r)
            time.sleep(random.random() / 10 * self.delay_factor)
        for k in balance_map:
            self.log.info("Account %s with balance:%s", bytes_to_int(k),
                          balance_map[k])
        for tx in all_txs:
            self.log.debug("Wait for tx to confirm %s", tx.hash_hex())
            for i in range(3):
                try:
                    retry = True
                    while retry:
                        try:
                            wait_until(
                                lambda: checktx(self.nodes[0], tx.hash_hex()),
                                timeout=60 * self.delay_factor)
                            retry = False
                        except CannotSendRequest:
                            time.sleep(0.01)
                    break
                except AssertionError as _:
                    self.nodes[0].p2p.send_protocol_msg(
                        Transactions(transactions=[tx]))
                if i == 2:
                    raise AssertionError(
                        "Tx {} not confirmed after 30 seconds".format(
                            tx.hash_hex()))

        for k in balance_map:
            self.log.info("Check account sk:%s addr:%s", bytes_to_int(k),
                          eth_utils.encode_hex(priv_to_addr(k)))
            wait_until(lambda: self.check_account(k, balance_map),
                       timeout=60 * self.delay_factor)
        block_gen_thread.stop()
        block_gen_thread.join()
        sync_blocks(self.nodes, timeout=60 * self.delay_factor)
        self.log.info("Pass")
        self.register_test("general_2.json")
Exemple #10
0
    def run_test(self):
        sponsor_whitelist_contract_addr = Web3.toChecksumAddress(
            "0888000000000000000000000000000000000001")
        collateral_per_storage_key = COLLATERAL_UNIT_IN_DRIP * 64
        upper_bound = 5 * 10**7

        file_dir = os.path.dirname(os.path.realpath(__file__))

        control_contract_file_path = os.path.join(
            file_dir, "..", "internal_contract", "metadata",
            "SponsorWhitelistControl.json")
        control_contract_dict = json.loads(
            open(control_contract_file_path, "r").read())

        control_contract = get_contract_instance(
            contract_dict=control_contract_dict)

        test_contract = get_contract_instance(
            abi_file=os.path.join(
                file_dir, "contracts/commission_privilege_test_abi.json"),
            bytecode_file=os.path.join(
                file_dir, "contracts/commission_privilege_test_bytecode.dat"),
        )

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = self.genesis_priv_key
        genesis_addr = encode_hex_0x(self.genesis_addr)
        self.log.info("genesis_addr={}".format(genesis_addr))
        nonce = 0
        gas_price = 1
        gas = CONTRACT_DEFAULT_GAS
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {
            "from": Web3.toChecksumAddress(genesis_addr),
            "nonce": int_to_hex(nonce),
            "gas": int_to_hex(gas),
            "gasPrice": int_to_hex(gas_price),
            "chainId": 0
        }

        # Setup balance for node 0
        node = self.nodes[0]
        client = RpcClient(node)
        (addr1, priv_key1) = client.rand_account()
        self.log.info("addr1={}".format(addr1))
        tx = client.new_tx(sender=genesis_addr,
                           priv_key=genesis_key,
                           value=10**6,
                           nonce=self.get_nonce(self.genesis_addr),
                           receiver=addr1)
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr1), 10**6)

        # setup contract
        transaction = self.call_contract_function(
            contract=test_contract,
            name="constructor",
            args=[],
            sender_key=self.genesis_priv_key,
            storage_limit=20000)
        contract_addr = self.wait_for_tx([transaction],
                                         True)[0]['contractCreated']
        self.log.info("contract_addr={}".format(contract_addr))
        assert_equal(client.get_balance(contract_addr), 0)

        # sponsor the contract succeed
        b0 = client.get_balance(genesis_addr)
        self.call_contract_function(
            contract=control_contract,
            name="setSponsorForGas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound],
            value=10**18,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 10**18)
        assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr)
        assert_equal(client.get_sponsor_gas_bound(contract_addr), upper_bound)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - 10**18 - charged_of_huge_gas(gas))

        # set privilege for addr1
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        transaction = self.call_contract_function(
            contract=test_contract,
            name="add",
            args=[Web3.toChecksumAddress(addr1)],
            sender_key=genesis_key,
            contract_addr=contract_addr,
            wait=True,
            check_status=True,
            storage_limit=64)
        assert_equal(
            client.get_balance(genesis_addr),
            b0 - charged_of_huge_gas(gas) - collateral_per_storage_key)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + collateral_per_storage_key)
        assert_equal(
            self.wait_for_tx([transaction], True)[0]['gasCoveredBySponsor'],
            False)

        # addr1 call contract with privilege without enough cfx for gas fee
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        b1 = client.get_balance(addr1)
        transaction = self.call_contract_function(contract=test_contract,
                                                  name="foo",
                                                  args=[],
                                                  sender_key=priv_key1,
                                                  contract_addr=contract_addr,
                                                  wait=True,
                                                  check_status=True)
        assert_equal(client.get_balance(addr1), b1)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sb - charged_of_huge_gas(gas))
        assert_equal(
            self.wait_for_tx([transaction], True)[0]['gasCoveredBySponsor'],
            True)

        # sponsor collateral for the contract succeed
        b0 = client.get_balance(genesis_addr)
        self.call_contract_function(
            contract=control_contract,
            name="setSponsorForCollateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=10**18,  # 1 CFX = 1KB
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     10**18)
        assert_equal(client.get_sponsor_for_collateral(contract_addr),
                     genesis_addr)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - 10**18 - charged_of_huge_gas(gas))

        # addr1 call contract with privilege without enough cfx for storage
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        b1 = client.get_balance(addr1)
        transaction = self.call_contract_function(contract=test_contract,
                                                  name="foo",
                                                  args=[],
                                                  sender_key=priv_key1,
                                                  contract_addr=contract_addr,
                                                  wait=True,
                                                  check_status=True,
                                                  storage_limit=1024)
        assert_equal(client.get_balance(addr1), b1)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sb - charged_of_huge_gas(gas))
        assert_equal(
            self.wait_for_tx([transaction],
                             True)[0]['storageCoveredBySponsor'], True)

        # addr1 call with larger storage limit, should not packed
        transaction = self.call_contract_function(contract=test_contract,
                                                  name="foo",
                                                  args=[],
                                                  sender_key=priv_key1,
                                                  contract_addr=contract_addr,
                                                  storage_limit=1025)
        for _ in range(10):
            client.generate_block()

        tx_info = self.nodes[0].txpool_txWithPoolInfo(transaction.hash_hex())
        assert_equal(int(tx_info['local_nonce'], 16), 2)
        assert_equal(tx_info['local_balance_enough'], False)
        assert_equal(tx_info['packed'], False)

        # send 1025 * 10 ** 18 // 1024 CFX to addr1
        tx = client.new_tx(sender=genesis_addr,
                           priv_key=genesis_key,
                           value=1025 * 10**18 // 1024,
                           nonce=self.get_nonce(self.genesis_addr),
                           receiver=addr1)
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr1), 10**6 + 1025 * 10**18 // 1024)
        for _ in range(10):
            client.generate_block()
        tx_info = self.nodes[0].txpool_txWithPoolInfo(transaction.hash_hex())
        # Now addr1 pays for storage collateral by itself.
        assert_equal(
            self.wait_for_tx([transaction],
                             True)[0]['storageCoveredBySponsor'], False)
        assert_equal(int(tx_info['local_nonce'], 16), 3)
        assert_equal(tx_info['packed'], True)

        self.log.info("Pass")
    def run_test(self):
        self.log.propagate = False

        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        solc = Solc()
        file_dir = os.path.dirname(os.path.realpath(__file__))

        self.log.info("Initializing contract")

        self.buggy_contract = solc.get_contract_instance(
            source=os.path.join(file_dir, "contracts/reentrancy.sol"),
            contract_name="Reentrance")
        self.exploit_contract = solc.get_contract_instance(
            source=os.path.join(file_dir, "contracts/reentrancy_exploit.sol"),
            contract_name="ReentranceExploit")

        user1, _ = ec_random_keys()
        user1_addr = privtoaddr(user1)
        user2, _ = ec_random_keys()
        user2_addr = privtoaddr(user2)
        # tx = create_transaction(
        #     pri_key=self.default_account_key,
        #     receiver=privtoaddr(buggy_contract_owner),
        #     value=1000000000000000000000000000000000,
        #     nonce=self.get_nonce(privtoaddr(self.default_account_key)),
        #     gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        # self.send_transaction(tx, True, False)

        tx = create_transaction(pri_key=self.default_account_key,
                                receiver=user1_addr,
                                value=1000000000000000000000000000000000,
                                nonce=self.get_nonce(
                                    privtoaddr(self.default_account_key)),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        tx = create_transaction(pri_key=self.default_account_key,
                                receiver=user2_addr,
                                value=1000000000000000000000000000000000,
                                nonce=self.get_nonce(
                                    privtoaddr(self.default_account_key)),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        addr = eth_utils.encode_hex(user1_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_equal(balance, 1000000000000000000000000000000000)
        addr = eth_utils.encode_hex(user2_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_equal(balance, 1000000000000000000000000000000000)

        transaction = self.call_contract_function(self.buggy_contract,
                                                  "constructor", [],
                                                  self.default_account_key)
        contract_addr = self.wait_for_tx([transaction],
                                         True)[0]['contractCreated']

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "constructor", [], user2)
        exploit_addr = self.wait_for_tx([transaction],
                                        True)[0]['contractCreated']

        transaction = self.call_contract_function(
            self.buggy_contract, "addBalance", [], user1,
            100000000000000000000000000000000, contract_addr, True, True)
        transaction = self.call_contract_function(
            self.exploit_contract, "deposit",
            [Web3.toChecksumAddress(contract_addr)], user2,
            100000000000000000000000000000000, exploit_addr, True, True)

        addr = eth_utils.encode_hex(user1_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_equal(balance, 899999999999999999999999950000000)
        addr = eth_utils.encode_hex(user2_addr)
        assert_equal(balance, 899999999999999999999999950000000)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(contract_addr))
        assert_equal(balance, 200000000000000000000000000000000)

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "launch_attack", [], user2,
                                                  0, exploit_addr, True, True)
        transaction = self.call_contract_function(self.exploit_contract,
                                                  "get_money", [], user2, 0,
                                                  exploit_addr, True, True)

        addr = eth_utils.encode_hex(user1_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_equal(balance, 899999999999999999999999950000000)
        addr = eth_utils.encode_hex(user2_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_equal(balance, 1099999999999999999999999800000000)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(contract_addr))
        assert_equal(balance, 0)

        block_gen_thread.stop()
        block_gen_thread.join()
Exemple #12
0
    def run_test(self):
        sponsor_whitelist_contract_addr = Web3.toChecksumAddress(
            "0888000000000000000000000000000000000001")
        bytes_per_key = 64
        collateral_per_byte = 10**18 // 1024
        collateral_per_storage_key = 10**18 // 16
        # block gas limit (GENESIS_GAS_LIMIT); -1 because below gas is set to upper_bound + 1
        upper_bound = default_config["GENESIS_GAS_LIMIT"] - 1

        file_dir = os.path.dirname(os.path.realpath(__file__))

        control_contract_file_path = os.path.dirname(
            os.path.realpath(__file__)).split("/")
        control_contract_file_path.pop(-1)
        control_contract_file_path.extend(
            ["internal_contract", "metadata", "SponsorWhitelistControl.json"])
        control_contract_file_path = "/".join(control_contract_file_path)
        control_contract_dict = json.loads(
            open(os.path.join(control_contract_file_path), "r").read())

        control_contract = get_contract_instance(
            contract_dict=control_contract_dict)

        test_contract = get_contract_instance(
            abi_file=os.path.join(
                file_dir, "contracts/commission_privilege_test_abi.json"),
            bytecode_file=os.path.join(
                file_dir, "contracts/commission_privilege_test_bytecode.dat"),
        )

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = self.genesis_priv_key
        genesis_addr = encode_hex(self.genesis_addr)
        self.log.info("genesis_addr={}".format(genesis_addr))
        nonce = 0
        gas_price = 1
        gas = CONTRACT_DEFAULT_GAS
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {
            "from": Web3.toChecksumAddress(genesis_addr),
            "nonce": int_to_hex(nonce),
            "gas": int_to_hex(gas),
            "gasPrice": int_to_hex(gas_price),
            "chainId": 0
        }

        # Setup balance for node 0
        node = self.nodes[0]
        client = RpcClient(node)
        (addr1, priv_key1) = client.rand_account()
        (addr2, priv_key2) = client.rand_account()
        (addr3, priv_key3) = client.rand_account()
        (addr4, priv_key4) = client.rand_account()
        tx = client.new_tx(sender=genesis_addr,
                           priv_key=genesis_key,
                           value=10**18,
                           nonce=self.get_nonce(self.genesis_addr),
                           receiver=addr1)
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr1), 10**18)
        tx = client.new_tx(sender=genesis_addr,
                           priv_key=genesis_key,
                           value=10**18,
                           nonce=self.get_nonce(self.genesis_addr),
                           receiver=addr2)
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr2), 10**18)
        tx = client.new_tx(sender=genesis_addr,
                           priv_key=genesis_key,
                           value=3 * 10**18,
                           nonce=self.get_nonce(self.genesis_addr),
                           receiver=addr3)
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr3), 3 * 10**18)

        # setup contract
        transaction = self.call_contract_function(
            contract=test_contract,
            name="constructor",
            args=[],
            sender_key=self.genesis_priv_key,
            storage_limit=2723)
        contract_addr = self.wait_for_tx([transaction],
                                         True)[0]['contractCreated']
        self.log.info("contract_addr={}".format(contract_addr))
        assert_equal(client.get_balance(contract_addr), 0)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     2723 * collateral_per_byte)

        # sponsor the contract failed due to sponsor_balance < 1000 * upper_bound
        b0 = client.get_balance(genesis_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound],
            value=upper_bound * 1000 - 1,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 0)
        assert_equal(client.get_sponsor_for_gas(contract_addr),
                     "0x0000000000000000000000000000000000000000")
        assert_equal(client.get_sponsor_gas_bound(contract_addr), 0)
        assert_equal(client.get_balance(genesis_addr), b0 - gas)

        # sponsor the contract succeed
        b0 = client.get_balance(genesis_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound],
            value=10**18,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 10**18)
        assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr)
        assert_equal(client.get_sponsor_gas_bound(contract_addr), upper_bound)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - 10**18 - charged_of_huge_gas(gas))

        check_info = client.check_balance_against_transaction(addr1,
                                                              contract_addr,
                                                              gas,
                                                              gas_price,
                                                              storage_limit=0)
        assert_equal(check_info['willPayTxFee'], True)
        assert_equal(check_info['willPayCollateral'], True)
        assert_equal(check_info['isBalanceEnough'], True)

        check_info = client.check_balance_against_transaction(addr4,
                                                              contract_addr,
                                                              gas,
                                                              gas_price,
                                                              storage_limit=0)
        assert_equal(check_info['willPayTxFee'], True)
        assert_equal(check_info['willPayCollateral'], True)
        assert_equal(check_info['isBalanceEnough'], False)

        # set privilege for addr4
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="add",
                                    args=[Web3.toChecksumAddress(addr4)],
                                    sender_key=genesis_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True,
                                    storage_limit=64)
        assert_equal(
            client.get_balance(genesis_addr),
            b0 - charged_of_huge_gas(gas) - collateral_per_storage_key)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + collateral_per_storage_key)

        check_info = client.check_balance_against_transaction(addr4,
                                                              contract_addr,
                                                              gas,
                                                              gas_price,
                                                              storage_limit=0)
        assert_equal(check_info['willPayTxFee'], False)
        assert_equal(check_info['willPayCollateral'], True)
        assert_equal(check_info['isBalanceEnough'], True)

        # remove privilege for addr4
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="remove",
                                    args=[Web3.toChecksumAddress(addr4)],
                                    sender_key=genesis_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 - collateral_per_storage_key)
        assert_equal(
            client.get_balance(genesis_addr),
            b0 - charged_of_huge_gas(gas) + collateral_per_storage_key)

        # set privilege for addr1
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="add",
                                    args=[Web3.toChecksumAddress(addr1)],
                                    sender_key=genesis_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True,
                                    storage_limit=64)
        assert_equal(
            client.get_balance(genesis_addr),
            b0 - charged_of_huge_gas(gas) - collateral_per_storage_key)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + collateral_per_storage_key)

        # addr1 call contract with privilege
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        b1 = client.get_balance(addr1)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_balance(addr1), b1)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sb - charged_of_huge_gas(gas))

        # addr1 call contract with privilege and large tx fee
        b1 = client.get_balance(addr1)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True,
                                    gas=upper_bound + 1)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_balance(addr1),
                     b1 - charged_of_huge_gas(upper_bound + 1))

        # addr2 call contract without privilege
        b2 = client.get_balance(addr2)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_balance(addr2), b2 - charged_of_huge_gas(gas))

        # set privilege for addr2
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="add",
                                    args=[Web3.toChecksumAddress(addr2)],
                                    sender_key=genesis_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True,
                                    storage_limit=64)
        assert_equal(
            client.get_balance(genesis_addr),
            b0 - charged_of_huge_gas(gas) - collateral_per_storage_key)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + collateral_per_storage_key)

        # now, addr2 call contract with privilege
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sb - charged_of_huge_gas(gas))
        assert_equal(client.get_balance(addr2), b2)

        # remove privilege for addr1
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="remove",
                                    args=[Web3.toChecksumAddress(addr1)],
                                    sender_key=genesis_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 - collateral_per_storage_key)
        assert_equal(
            client.get_balance(genesis_addr),
            b0 - charged_of_huge_gas(gas) + collateral_per_storage_key)

        # addr1 call contract without privilege
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        b1 = client.get_balance(addr1)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_balance(addr1), b1 - charged_of_huge_gas(gas))

        # new sponsor failed due to small sponsor_balance
        b3 = client.get_balance(addr3)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound + 1],
            value=5 * 10**17,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr)
        assert_equal(client.get_balance(addr3), b3 - gas)

        # new sponsor failed due to small upper bound
        b3 = client.get_balance(addr3)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound],
            value=10**18,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr)
        assert_equal(client.get_balance(addr3), b3 - gas)

        # new sponsor succeed
        b0 = client.get_balance(genesis_addr)
        b3 = client.get_balance(addr3)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound + 1],
            value=10**18,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 10**18)
        assert_equal(client.get_sponsor_gas_bound(contract_addr),
                     upper_bound + 1)
        assert_equal(client.get_sponsor_for_gas(contract_addr), addr3)
        assert_equal(client.get_balance(addr3),
                     b3 - 10**18 - charged_of_huge_gas(gas))
        assert_equal(client.get_balance(genesis_addr), b0 + sb)

        # sponsor the contract for collateral failed due to zero sponsor balance
        b3 = client.get_balance(addr3)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=0,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     0)
        assert_equal(client.get_sponsor_for_collateral(contract_addr),
                     "0x0000000000000000000000000000000000000000")
        assert_equal(client.get_balance(addr3), b3 - gas)

        # sponsor the contract for collateral succeed
        b3 = client.get_balance(addr3)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=10**18 - 1,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     10**18 - 1)
        assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3)
        assert_equal(client.get_balance(addr3),
                     b3 - charged_of_huge_gas(gas) - 10**18 + 1)

        check_info = client.check_balance_against_transaction(addr1,
                                                              contract_addr,
                                                              gas,
                                                              gas_price,
                                                              storage_limit=0)
        assert_equal(check_info['willPayTxFee'], True)
        assert_equal(check_info['willPayCollateral'], True)
        assert_equal(check_info['isBalanceEnough'], True)

        # addr1 create 2 keys without privilege, and storage limit is 1, should failed
        b1 = client.get_balance(addr1)
        assert_equal(client.get_collateral_for_storage(contract_addr), 0)
        assert_equal(client.get_collateral_for_storage(addr1), 0)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[0, 2],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key)
        assert_equal(client.get_collateral_for_storage(contract_addr), 0)
        assert_equal(client.get_collateral_for_storage(addr1), 0)
        assert_equal(client.get_balance(addr1), b1 - gas)

        # addr1 create 2 keys without privilege, and storage limit is 2, should succeed
        b1 = client.get_balance(addr1)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[0, 2],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 2)
        assert_equal(client.get_collateral_for_storage(contract_addr), 0)
        assert_equal(client.get_collateral_for_storage(addr1),
                     collateral_per_storage_key * 2)
        assert_equal(
            client.get_balance(addr1),
            b1 - charged_of_huge_gas(gas) - collateral_per_storage_key * 2)

        # remove 1 key create by addr1
        b1 = client.get_balance(addr1)
        self.call_contract_function(contract=test_contract,
                                    name="par_del",
                                    args=[0, 1],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 2)
        assert_equal(client.get_collateral_for_storage(contract_addr), 0)
        assert_equal(client.get_collateral_for_storage(addr1),
                     collateral_per_storage_key)
        assert_equal(
            client.get_balance(addr1),
            b1 - charged_of_huge_gas(gas) + collateral_per_storage_key)

        check_info = client.check_balance_against_transaction(
            addr2, contract_addr, gas, gas_price, storage_limit=bytes_per_key)
        assert_equal(check_info['willPayTxFee'], False)
        assert_equal(check_info['willPayCollateral'], False)
        assert_equal(check_info['isBalanceEnough'], True)

        check_info = client.check_balance_against_transaction(
            addr2, contract_addr, gas, gas_price, storage_limit=10**18)
        assert_equal(check_info['willPayTxFee'], False)
        assert_equal(check_info['willPayCollateral'], True)
        assert_equal(check_info['isBalanceEnough'], True)

        # addr2 create 2 keys with privilege, and storage limit is 1, should succeed
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[2, 4],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 2)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc - collateral_per_storage_key * 2)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - charged_of_huge_gas(gas))
        assert_equal(client.get_collateral_for_storage(addr2), 0)
        assert_equal(client.get_balance(addr2), b2)

        # addr2 create 13 keys with privilege, and storage limit is 0, should succeed
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[4, 17],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=0)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 15)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc - collateral_per_storage_key * 13)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - charged_of_huge_gas(gas))
        assert_equal(client.get_collateral_for_storage(addr2), 0)
        assert_equal(client.get_balance(addr2), b2)

        # now sponsor_balance is unable to pay collateral for storage
        # the balance of addr2 is able to pay 15 collateral for storage, but not 16
        assert_greater_than(
            collateral_per_storage_key,
            client.get_sponsor_balance_for_collateral(contract_addr))
        assert_greater_than(collateral_per_storage_key * 16,
                            client.get_balance(addr2))
        assert_greater_than(client.get_balance(addr2),
                            collateral_per_storage_key * 15)

        # addr2 create 1 keys with privilege, and storage limit is 0, should failed
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[17, 18],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=0)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 15)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - gas)
        assert_equal(client.get_collateral_for_storage(addr2), 0)
        assert_equal(client.get_balance(addr2), b2)

        # addr2 create 1 keys with privilege, and storage limit is 2, should succeed
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[17, 18],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 2)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 15)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - charged_of_huge_gas(gas))
        assert_equal(client.get_collateral_for_storage(addr2),
                     collateral_per_storage_key)
        assert_equal(client.get_balance(addr2),
                     b2 - collateral_per_storage_key)

        # addr2 del 10 keys with privilege
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_del",
                                    args=[2, 12],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 5)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc + collateral_per_storage_key * 10)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - charged_of_huge_gas(gas))
        assert_equal(client.get_collateral_for_storage(addr2),
                     collateral_per_storage_key)
        assert_equal(client.get_balance(addr2), b2)

        # addr3 sponsor more, treat as transfer
        b3 = client.get_balance(addr3)
        sb = client.get_sponsor_balance_for_collateral(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=sb,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sb * 2)
        assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3)
        assert_equal(client.get_balance(addr3),
                     b3 - charged_of_huge_gas(gas) - sb)

        # genesis sponsor with sponsor balance, should failed
        b0 = client.get_balance(genesis_addr)
        sb = client.get_sponsor_balance_for_collateral(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=sb + 1,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sb)
        assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3)
        assert_equal(client.get_balance(genesis_addr), b0 - gas)

        # genesis sponsor with sponsor balance and collateral_for_storage, should succeed
        b0 = client.get_balance(genesis_addr)
        b3 = client.get_balance(addr3)
        cfs = client.get_collateral_for_storage(contract_addr)
        sb = client.get_sponsor_balance_for_collateral(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=sb + cfs + 1,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_collateral_for_storage(contract_addr), cfs)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sb + 1)
        assert_equal(client.get_sponsor_for_collateral(contract_addr),
                     genesis_addr)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - charged_of_huge_gas(gas) - sb - cfs - 1)
        assert_equal(client.get_balance(addr3), b3 + sb + cfs)

        # storage change test
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="par",
                                    args=[10, 20, 30, 41],
                                    sender_key=self.genesis_priv_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 30)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + 11 * collateral_per_storage_key)

        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="par_add_del",
                                    args=[110, 120, 110, 120],
                                    sender_key=self.genesis_priv_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 30)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + 10 * collateral_per_storage_key)

        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="par_add_del",
                                    args=[210, 220, 215, 220],
                                    sender_key=self.genesis_priv_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 30)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + 5 * collateral_per_storage_key)

        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="par_add_del",
                                    args=[310, 320, 320, 330],
                                    sender_key=self.genesis_priv_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 30)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + 10 * collateral_per_storage_key)

        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="par_add_del",
                                    args=[410, 420, 409, 430],
                                    sender_key=self.genesis_priv_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 300)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + 21 * collateral_per_storage_key)

        # test recurrence
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="rec",
                                    args=[510, 520, 3],
                                    sender_key=self.genesis_priv_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 30)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + 4 * collateral_per_storage_key)

        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="par_del",
                                    args=[510, 520],
                                    sender_key=self.genesis_priv_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 30)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 - 4 * collateral_per_storage_key)

        self.log.info("Pass")
Exemple #13
0
    def run_test(self):
        # Start mininode connection
        self.node = self.nodes[0]
        start_p2p_connection([self.node])

        block_gen_thread = BlockGenThread([self.node],
                                          self.log,
                                          num_txs=10000,
                                          interval_fixed=0.2)
        block_gen_thread.start()
        tx_n = 100000

        generate = False
        if generate:
            f = open("encoded_tx", "wb")
            '''Test Random Transactions'''
            genesis_key = default_config["GENESIS_PRI_KEY"]
            balance_map = {genesis_key: default_config["TOTAL_COIN"]}
            nonce_map = {genesis_key: 0}
            all_txs = []
            gas_price = 1
            account_n = 10

            # Initialize new accounts
            new_keys = set()
            for _ in range(account_n):
                value = int(balance_map[genesis_key] * 0.5)
                receiver_sk, _ = ec_random_keys()
                new_keys.add(receiver_sk)
                tx = create_transaction(pri_key=genesis_key,
                                        receiver=priv_to_addr(receiver_sk),
                                        value=value,
                                        nonce=nonce_map[genesis_key],
                                        gas_price=gas_price)
                all_txs.append(tx)
                balance_map[receiver_sk] = value
                nonce_map[genesis_key] += 1
                balance_map[genesis_key] -= value + gas_price * 21000
            wait_for_account_stable()
            for key in new_keys:
                nonce_map[key] = wait_for_initial_nonce_for_privkey(
                    self.nodes[0], key)

            self.log.info("start to generate %d transactions", tx_n)
            for i in range(tx_n):
                if i % 1000 == 0:
                    self.log.debug("generated %d tx", i)
                sender_key = random.choice(list(balance_map))
                if sender_key not in nonce_map:
                    nonce_map[sender_key] = wait_for_initial_nonce_for_privkey(
                        self.nodes[0], sender_key)
                nonce = nonce_map[sender_key]
                value = 1
                receiver_sk = random.choice(list(balance_map))
                balance_map[receiver_sk] += value
                # not enough transaction fee (gas_price * gas_limit) should not happen for now
                assert balance_map[sender_key] >= value + gas_price * 21000
                tx = create_transaction(pri_key=sender_key,
                                        receiver=priv_to_addr(receiver_sk),
                                        value=value,
                                        nonce=nonce,
                                        gas_price=gas_price)
                self.log.debug(
                    "%s send %d to %s nonce=%d balance: sender=%s, receiver=%s",
                    encode_hex(priv_to_addr(sender_key)), value,
                    encode_hex(priv_to_addr(receiver_sk)), nonce,
                    balance_map[sender_key], balance_map[receiver_sk])
                all_txs.append(tx)
                nonce_map[sender_key] = nonce + 1
                balance_map[sender_key] -= value + gas_price * 21000
            encoded_txs = []
            batch_tx = []
            i = 0
            for tx in all_txs:
                batch_tx.append(tx)
                i += 1
                if i % 1000 == 0:
                    encoded = rlp.encode(Transactions(transactions=batch_tx))
                    encoded_txs.append(encoded)
                    batch_tx = []
            pickle.dump(encoded_txs, f)
            pickle.dump(balance_map, f)
        else:
            f = open("encoded_tx", "rb")
            encoded_txs = pickle.load(f)
            balance_map = pickle.load(f)

        f.close()
        start_time = datetime.datetime.now()
        for encoded in encoded_txs:
            self.node.p2p.send_protocol_packet(
                int_to_bytes(TRANSACTIONS) + encoded)
        for k in balance_map:
            wait_until(lambda: self.check_account(k, balance_map))
        end_time = datetime.datetime.now()
        time_used = (end_time - start_time).total_seconds()
        block_gen_thread.stop()
        block_gen_thread.join()
        self.log.info("Time used: %f seconds", time_used)
        self.log.info("Tx per second: %f", tx_n / time_used)
    def run_test(self):
        self.log.propagate = False

        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        solc = Solc()
        file_dir = os.path.dirname(os.path.realpath(__file__))

        self.log.info("Initializing contract")

        self.buggy_contract = solc.get_contract_instance(
            source=os.path.join(file_dir, "contracts/reentrancy.sol"),
            contract_name="Reentrance")
        self.exploit_contract = solc.get_contract_instance(
            source=os.path.join(file_dir, "contracts/reentrancy_exploit.sol"),
            contract_name="ReentranceExploit")

        user1, _ = ec_random_keys()
        user1_addr = privtoaddr(user1)
        user2, _ = ec_random_keys()
        user2_addr = privtoaddr(user2)

        # setup balance
        value = (10**15 + 2000) * 10**18 + ReentrancyTest.REQUEST_BASE['gas']
        tx = create_transaction(pri_key=self.genesis_priv_key,
                                receiver=user1_addr,
                                value=value,
                                nonce=self.get_nonce(self.genesis_addr),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        tx = create_transaction(pri_key=self.genesis_priv_key,
                                receiver=user2_addr,
                                value=value,
                                nonce=self.get_nonce(self.genesis_addr),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        addr = eth_utils.encode_hex(user1_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_equal(balance, value)
        addr = eth_utils.encode_hex(user2_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_equal(balance, value)

        # lock balance in bank
        node = self.nodes[0]
        client = RpcClient(node)
        staking_contract = solc.get_contract_instance(
            abi_file=os.path.join(
                file_dir, "contracts/storage_interest_staking_abi.json"),
            bytecode_file=os.path.join(
                file_dir, "contracts/storage_interest_staking_bytecode.dat"),
        )
        staking_contract_addr = Web3.toChecksumAddress(
            "443c409373ffd5c0bec1dddb7bec830856757b65")
        tx_conf = copy.deepcopy(ReentrancyTest.REQUEST_BASE)
        tx_conf['to'] = staking_contract_addr
        tx_data = decode_hex(
            staking_contract.functions.deposit(
                2000 * 10**18).buildTransaction(tx_conf)["data"])
        tx1 = client.new_tx(value=0,
                            sender=eth_utils.encode_hex(user1_addr),
                            receiver=staking_contract_addr,
                            nonce=self.get_nonce(user1_addr),
                            data=tx_data,
                            gas=ReentrancyTest.REQUEST_BASE['gas'],
                            gas_price=ReentrancyTest.REQUEST_BASE['gasPrice'],
                            priv_key=eth_utils.encode_hex(user1))
        tx2 = client.new_tx(value=0,
                            sender=eth_utils.encode_hex(user2_addr),
                            receiver=staking_contract_addr,
                            nonce=self.get_nonce(user2_addr),
                            data=tx_data,
                            gas=ReentrancyTest.REQUEST_BASE['gas'],
                            gas_price=ReentrancyTest.REQUEST_BASE['gasPrice'],
                            priv_key=eth_utils.encode_hex(user2))
        client.send_tx(tx1)
        client.send_tx(tx2)
        self.wait_for_tx([tx1, tx2], False)

        transaction = self.call_contract_function(self.buggy_contract,
                                                  "constructor", [],
                                                  self.genesis_priv_key)
        contract_addr = self.wait_for_tx([transaction],
                                         True)[0]['contractCreated']

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "constructor", [], user2)
        exploit_addr = self.wait_for_tx([transaction],
                                        True)[0]['contractCreated']

        transaction = self.call_contract_function(
            self.buggy_contract, "addBalance", [], user1,
            100000000000000000000000000000000, contract_addr, True, True)
        transaction = self.call_contract_function(
            self.exploit_contract, "deposit",
            [Web3.toChecksumAddress(contract_addr)], user2,
            100000000000000000000000000000000, exploit_addr, True, True)

        addr = eth_utils.encode_hex(user1_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_greater_than_or_equal(balance,
                                     899999999999999999999999950000000)
        addr = eth_utils.encode_hex(user2_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_greater_than_or_equal(balance,
                                     899999999999999999999999900000000)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(contract_addr))
        assert_equal(balance, 200000000000000000000000000000000)

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "launch_attack", [], user2,
                                                  0, exploit_addr, True, True)
        transaction = self.call_contract_function(self.exploit_contract,
                                                  "get_money", [], user2, 0,
                                                  exploit_addr, True, True)

        addr = eth_utils.encode_hex(user1_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_greater_than_or_equal(balance,
                                     899999999999999999999999950000000)
        addr = eth_utils.encode_hex(user2_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_greater_than_or_equal(balance,
                                     1099999999999999999999999800000000)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(contract_addr))
        assert_equal(balance, 0)

        block_gen_thread.stop()
        block_gen_thread.join()
Exemple #15
0
    def run_test(self):
        # Start mininode connection
        self.node = self.nodes[0]
        start_p2p_connection([self.node])

        block_gen_thread = BlockGenThread([self.node],
                                          self.log,
                                          num_txs=10000,
                                          interval_fixed=0.02)
        block_gen_thread.start()
        tx_n = 500000
        batch_size = 10
        send_tps = 20000
        all_txs = []
        gas_price = 1
        account_n = 1000

        generate = False
        if generate:
            f = open("encoded_tx", "wb")
            '''Test Random Transactions'''

            self.log.info("Setting up genesis secrets")
            balance_map = {}
            nonce_map = {}
            account_i = 0
            for prikey_str in open(
                    self.conf_parameters["genesis_secrets"][1:-1],
                    "r").readlines():
                prikey = decode_hex(prikey_str[:-1])
                balance_map[prikey] = 10000000000000000000000
                nonce_map[prikey] = 0
                account_i += 1
                if account_i == account_n:
                    break

            # genesis_key = default_config["GENESIS_PRI_KEY"]
            # balance_map = {genesis_key: default_config["TOTAL_COIN"]}
            # nonce_map = {genesis_key: 0}
            # # Initialize new accounts
            # new_keys = set()
            # for _ in range(account_n):
            #     value = int(balance_map[genesis_key] / (account_n * 2))
            #     receiver_sk, _ = ec_random_keys()
            #     new_keys.add(receiver_sk)
            #     tx = create_transaction(pri_key=genesis_key, receiver=priv_to_addr(receiver_sk), value=value,
            #                             nonce=nonce_map[genesis_key], gas_price=gas_price)
            #     all_txs.append(tx)
            #     balance_map[receiver_sk] = value
            #     nonce_map[genesis_key] += 1
            #     balance_map[genesis_key] -= value + gas_price * 21000
            # wait_for_account_stable()
            # for key in new_keys:
            #     nonce_map[key] = wait_for_initial_nonce_for_privkey(self.nodes[0], key)

            self.log.info("start to generate %d transactions", tx_n)
            account_list = list(balance_map)
            for i in range(tx_n):
                if i % 1000 == 0:
                    self.log.info("generated %d tx", i)
                sender_key = random.choice(account_list)
                if sender_key not in nonce_map:
                    nonce_map[sender_key] = wait_for_initial_nonce_for_privkey(
                        self.nodes[0], sender_key)
                nonce = nonce_map[sender_key]
                value = 1
                receiver_sk = random.choice(account_list)
                balance_map[receiver_sk] += value
                # not enough transaction fee (gas_price * gas_limit) should not happen for now
                assert balance_map[sender_key] >= value + gas_price * 21000
                tx = create_transaction(pri_key=sender_key,
                                        receiver=priv_to_addr(receiver_sk),
                                        value=value,
                                        nonce=nonce,
                                        gas_price=gas_price)
                # self.log.debug("%s send %d to %s nonce=%d balance: sender=%s, receiver=%s", encode_hex(priv_to_addr(sender_key)), value, encode_hex(priv_to_addr(receiver_sk)), nonce, balance_map[sender_key], balance_map[receiver_sk])
                all_txs.append(tx)
                nonce_map[sender_key] = nonce + 1
                balance_map[sender_key] -= value + gas_price * 21000
            encoded_txs = []
            batch_tx = []
            i = 0
            for tx in all_txs:
                batch_tx.append(tx)
                i += 1
                if i % batch_size == 0:
                    encoded = rlp.encode(Transactions(transactions=batch_tx))
                    encoded_txs.append(encoded)
                    batch_tx = []
            pickle.dump(encoded_txs, f)
            pickle.dump(balance_map, f)
        else:
            f = open("encoded_tx", "rb")
            encoded_txs = pickle.load(f)
            balance_map = pickle.load(f)

        f.close()
        start_time = time.time()
        i = 0
        for encoded in encoded_txs:
            i += 1
            if i * batch_size % send_tps == 0:
                time_used = time.time() - start_time
                time.sleep(i * batch_size / send_tps - time_used)
            self.node.p2p.send_protocol_packet(encoded +
                                               int_to_bytes(TRANSACTIONS))
        self.log.info(
            f"Time used to send {tx_n} transactions in {i} iterations: {time_used}"
        )

        for k in balance_map:
            wait_until(lambda: self.check_account(k, balance_map), timeout=600)
        time_used = time.time() - start_time
        block_gen_thread.stop()
        block_gen_thread.join()
        self.log.info("Time used: %f seconds", time_used)
        self.log.info("Tx per second: %f", tx_n / time_used)
Exemple #16
0
    def run_test(self):
        file_dir = os.path.dirname(os.path.realpath(__file__))

        pay_contract = get_contract_instance(
            abi_file=os.path.join(file_dir, "contracts/pay_abi.json"),
            bytecode_file=os.path.join(file_dir, "contracts/pay_bytecode.dat"),
        )

        admin_control_contract = get_contract_instance(
            abi_file=os.path.join(file_dir, "contracts/admin_control_abi.json"),
            bytecode_file=os.path.join(file_dir, "contracts/admin_control_bytecode.dat"),
        )

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = self.genesis_priv_key
        genesis_addr = self.genesis_addr
        self.log.info("genesis_addr={}".format(encode_hex_0x(genesis_addr)))
        nonce = 0
        gas_price = 1
        gas = 50000000
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {"from":Web3.toChecksumAddress(encode_hex_0x(genesis_addr)), "nonce":int_to_hex(nonce), "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0}

        # Setup balance for node 0
        node = self.nodes[0]
        client = RpcClient(node)
        (addr, priv_key) = client.rand_account()
        self.log.info("addr=%s priv_key=%s", addr, priv_key)
        tx = client.new_tx(value=5 * 10 ** 18, receiver=addr, nonce=self.get_nonce(genesis_addr))
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr), 5000000000000000000)

        (addr2, priv_key2) = client.rand_account()
        self.log.info("addr2=%s priv_key2=%s", addr2, priv_key2)
        tx = client.new_tx(value=5 * 10 ** 18, receiver=addr2, nonce=self.get_nonce(genesis_addr))
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr2), 5000000000000000000)

        # deploy pay contract
        tx = self.call_contract_function(
            contract=pay_contract,
            name="constructor",
            args=[],
            sender_key=priv_key)
        contract_addr = self.wait_for_tx([tx], True)[0]['contractCreated']
        self.log.info("contract_addr={}".format(contract_addr))
        assert_equal(client.get_balance(contract_addr), 0)

        # deposit 10**18
        b0 = int(node.cfx_getBalance(addr), 16)
        tx = self.call_contract_function(
            contract=pay_contract,
            name="recharge",
            args=[],
            sender_key=priv_key,
            contract_addr=contract_addr,
            value=10 ** 18,
            wait=True,
            check_status=True)
        assert_equal(client.get_balance(contract_addr), 10 ** 18)
        assert_equal(client.get_balance(addr), b0 - 10 ** 18 - gas + gas // 4)
        assert_equal(client.get_admin(contract_addr), addr)

        # transfer admin (fail)
        tx = self.call_contract_function(
            contract=admin_control_contract,
            name="set_admin",
            args=[Web3.toChecksumAddress(contract_addr), Web3.toChecksumAddress(addr2)],
            sender_key=priv_key2,
            contract_addr=Web3.toChecksumAddress("0x6060de9e1568e69811c4a398f92c3d10949dc891"),
            wait=True,
            check_status=True)
        assert_equal(client.get_admin(contract_addr), addr)

        # transfer admin (success)
        tx = self.call_contract_function(
            contract=admin_control_contract,
            name="set_admin",
            args=[Web3.toChecksumAddress(contract_addr), Web3.toChecksumAddress(addr2)],
            sender_key=priv_key,
            contract_addr=Web3.toChecksumAddress("0x6060de9e1568e69811c4a398f92c3d10949dc891"),
            wait=True,
            check_status=True)
        assert_equal(client.get_admin(contract_addr), addr2)

        # destroy
        tx = self.call_contract_function(
            contract=admin_control_contract,
            name="destroy",
            args=[Web3.toChecksumAddress(contract_addr)],
            sender_key=priv_key2,
            contract_addr=Web3.toChecksumAddress("0x6060de9e1568e69811c4a398f92c3d10949dc891"),
            wait=True,
            check_status=True)
        assert_equal(client.get_balance(contract_addr), 0)
        assert_equal(client.get_balance(addr2), 5999999999912500000 + gas // 4)

        self.log.info("Pass")
    def run_test(self):
        sponsor_whitelist_contract_addr = Web3.toChecksumAddress(
            "8ad036480160591706c831f0da19d1a424e39469")
        bytes_per_key = 64
        collateral_per_storage_key = 10**18 // 16
        upper_bound = 5 * 10**7

        file_dir = os.path.dirname(os.path.realpath(__file__))

        control_contract_file_path = os.path.dirname(
            os.path.realpath(__file__)).split("/")
        control_contract_file_path.pop(-1)
        control_contract_file_path.extend(
            ["internal_contract", "metadata", "SponsorWhitelistControl.json"])
        control_contract_file_path = "/".join(control_contract_file_path)
        control_contract_dict = json.loads(
            open(os.path.join(control_contract_file_path), "r").read())

        control_contract = get_contract_instance(
            contract_dict=control_contract_dict)

        test_contract = get_contract_instance(
            abi_file=os.path.join(
                file_dir, "contracts/commission_privilege_test_abi.json"),
            bytecode_file=os.path.join(
                file_dir, "contracts/commission_privilege_test_bytecode.dat"),
        )

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = self.genesis_priv_key
        genesis_addr = encode_hex(self.genesis_addr)
        self.log.info("genesis_addr={}".format(genesis_addr))
        nonce = 0
        gas_price = 1
        gas = 50000000
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {
            "from": Web3.toChecksumAddress(genesis_addr),
            "nonce": int_to_hex(nonce),
            "gas": int_to_hex(gas),
            "gasPrice": int_to_hex(gas_price),
            "chainId": 0
        }

        # Setup balance for node 0
        node = self.nodes[0]
        client = RpcClient(node)
        (addr1, priv_key1) = client.rand_account()
        (addr2, priv_key2) = client.rand_account()
        (addr3, priv_key3) = client.rand_account()
        tx = client.new_tx(sender=genesis_addr,
                           priv_key=genesis_key,
                           value=10**18,
                           nonce=self.get_nonce(self.genesis_addr),
                           receiver=addr1)
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr1), 10**18)
        tx = client.new_tx(sender=genesis_addr,
                           priv_key=genesis_key,
                           value=10**18,
                           nonce=self.get_nonce(self.genesis_addr),
                           receiver=addr2)
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr2), 10**18)
        tx = client.new_tx(sender=genesis_addr,
                           priv_key=genesis_key,
                           value=3 * 10**18,
                           nonce=self.get_nonce(self.genesis_addr),
                           receiver=addr3)
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr3), 3 * 10**18)

        # setup contract
        transaction = self.call_contract_function(
            contract=test_contract,
            name="constructor",
            args=[],
            sender_key=self.genesis_priv_key)
        contract_addr = self.wait_for_tx([transaction],
                                         True)[0]['contractCreated']
        self.log.info("contract_addr={}".format(contract_addr))
        assert_equal(client.get_balance(contract_addr), 0)

        # sponsor the contract failed due to sponsor_balance < 1000 * upper_bound
        b0 = client.get_balance(genesis_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound],
            value=upper_bound * 1000 - 1,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 0)
        assert_equal(client.get_sponsor_for_gas(contract_addr),
                     "0x0000000000000000000000000000000000000000")
        assert_equal(client.get_sponsor_gas_bound(contract_addr), 0)
        assert_equal(client.get_balance(genesis_addr), b0 - gas)

        # sponsor the contract succeed
        b0 = client.get_balance(genesis_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound],
            value=10**18,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 10**18)
        assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr)
        assert_equal(client.get_sponsor_gas_bound(contract_addr), upper_bound)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - 10**18 - gas + 12500000)

        # set privilege for addr1
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="add",
                                    args=[Web3.toChecksumAddress(addr1)],
                                    sender_key=genesis_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - gas + 12500000 - collateral_per_storage_key)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + collateral_per_storage_key)

        # addr1 call contract with privilege
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        b1 = client.get_balance(addr1)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_balance(addr1), b1)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sb - gas + 12500000)

        # addr1 call contract with privilege and large tx fee
        b1 = client.get_balance(addr1)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True,
                                    gas=upper_bound + 1)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_balance(addr1),
                     b1 - upper_bound + upper_bound // 4 - 1)

        # addr2 call contract without privilege
        b2 = client.get_balance(addr2)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_balance(addr2), b2 - gas + 12500000)

        # set privilege for addr2
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="add",
                                    args=[Web3.toChecksumAddress(addr2)],
                                    sender_key=genesis_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - gas + 12500000 - collateral_per_storage_key)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + collateral_per_storage_key)

        # now, addr2 call contract with privilege
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sb - gas + 12500000)
        assert_equal(client.get_balance(addr2), b2)

        # remove privilege for addr1
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="remove",
                                    args=[Web3.toChecksumAddress(addr1)],
                                    sender_key=genesis_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 - collateral_per_storage_key)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - gas + 12500000 + collateral_per_storage_key)

        # addr1 call contract without privilege
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        b1 = client.get_balance(addr1)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_balance(addr1), b1 - gas + 12500000)

        # new sponsor failed due to small sponsor_balance
        b3 = client.get_balance(addr3)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound + 1],
            value=5 * 10**17,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr)
        assert_equal(client.get_balance(addr3), b3 - gas)

        # new sponsor failed due to small upper bound
        b3 = client.get_balance(addr3)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound],
            value=10**18,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), sb)
        assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr)
        assert_equal(client.get_balance(addr3), b3 - gas)

        # new sponsor succeed
        b0 = client.get_balance(genesis_addr)
        b3 = client.get_balance(addr3)
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound + 1],
            value=10**18,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 10**18)
        assert_equal(client.get_sponsor_gas_bound(contract_addr),
                     upper_bound + 1)
        assert_equal(client.get_sponsor_for_gas(contract_addr), addr3)
        assert_equal(client.get_balance(addr3), b3 - 10**18 - gas + 12500000)
        assert_equal(client.get_balance(genesis_addr), b0 + sb)

        # sponsor the contract for collateral failed due to zero sponsor balance
        b3 = client.get_balance(addr3)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=0,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     0)
        assert_equal(client.get_sponsor_for_collateral(contract_addr),
                     "0x0000000000000000000000000000000000000000")
        assert_equal(client.get_balance(addr3), b3 - gas)

        # sponsor the contract for collateral succeed
        b3 = client.get_balance(addr3)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=10**18 - 1,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     10**18 - 1)
        assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3)
        assert_equal(client.get_balance(addr3),
                     b3 - gas + 12500000 - 10**18 + 1)

        # addr1 create 2 keys without privilege, and storage limit is 1, should failed
        b1 = client.get_balance(addr1)
        assert_equal(client.get_collateral_for_storage(contract_addr), 0)
        assert_equal(client.get_collateral_for_storage(addr1), 0)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[0, 2],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key)
        assert_equal(client.get_collateral_for_storage(contract_addr), 0)
        assert_equal(client.get_collateral_for_storage(addr1), 0)
        assert_equal(client.get_balance(addr1), b1 - gas)

        # addr1 create 2 keys without privilege, and storage limit is 2, should succeed
        b1 = client.get_balance(addr1)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[0, 2],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 2)
        assert_equal(client.get_collateral_for_storage(contract_addr), 0)
        assert_equal(client.get_collateral_for_storage(addr1),
                     collateral_per_storage_key * 2)
        assert_equal(client.get_balance(addr1),
                     b1 - gas + 12500000 - collateral_per_storage_key * 2)

        # remove 1 key create by addr1
        b1 = client.get_balance(addr1)
        self.call_contract_function(contract=test_contract,
                                    name="par_del",
                                    args=[0, 1],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 2)
        assert_equal(client.get_collateral_for_storage(contract_addr), 0)
        assert_equal(client.get_collateral_for_storage(addr1),
                     collateral_per_storage_key)
        assert_equal(client.get_balance(addr1),
                     b1 - gas + 12500000 + collateral_per_storage_key)

        # addr2 create 2 keys with privilege, and storage limit is 1, should succeed
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[2, 4],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 2)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc - collateral_per_storage_key * 2)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - gas + 12500000)
        assert_equal(client.get_collateral_for_storage(addr2), 0)
        assert_equal(client.get_balance(addr2), b2)

        # addr2 create 13 keys with privilege, and storage limit is 0, should succeed
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[4, 17],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=0)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 15)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc - collateral_per_storage_key * 13)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - gas + 12500000)
        assert_equal(client.get_collateral_for_storage(addr2), 0)
        assert_equal(client.get_balance(addr2), b2)

        # now sponsor_balance is unable to pay collateral for storage
        # the balance of addr2 is able to pay 15 collateral for storage, but not 16
        assert_greater_than(
            collateral_per_storage_key,
            client.get_sponsor_balance_for_collateral(contract_addr))
        assert_greater_than(collateral_per_storage_key * 16,
                            client.get_balance(addr2))
        assert_greater_than(client.get_balance(addr2),
                            collateral_per_storage_key * 15)

        # addr2 create 1 keys with privilege, and storage limit is 0, should failed
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[17, 18],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=0)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 15)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - gas)
        assert_equal(client.get_collateral_for_storage(addr2), 0)
        assert_equal(client.get_balance(addr2), b2)

        # addr2 create 1 keys with privilege, and storage limit is 2, should succeed
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_add",
                                    args=[17, 18],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key * 2)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 15)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - gas + 12500000)
        assert_equal(client.get_collateral_for_storage(addr2),
                     collateral_per_storage_key)
        assert_equal(client.get_balance(addr2),
                     b2 - collateral_per_storage_key)

        # addr2 del 10 keys with privilege
        sbc = client.get_sponsor_balance_for_collateral(contract_addr)
        sbg = client.get_sponsor_balance_for_gas(contract_addr)
        b2 = client.get_balance(addr2)
        self.call_contract_function(contract=test_contract,
                                    name="par_del",
                                    args=[2, 12],
                                    sender_key=priv_key2,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    storage_limit=bytes_per_key)
        assert_equal(client.get_collateral_for_storage(contract_addr),
                     collateral_per_storage_key * 5)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sbc + collateral_per_storage_key * 10)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sbg - gas + 12500000)
        assert_equal(client.get_collateral_for_storage(addr2),
                     collateral_per_storage_key)
        assert_equal(client.get_balance(addr2), b2)

        # addr3 sponsor more, treat as transfer
        b3 = client.get_balance(addr3)
        sb = client.get_sponsor_balance_for_collateral(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=sb,
            sender_key=priv_key3,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sb * 2)
        assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3)
        assert_equal(client.get_balance(addr3), b3 - gas + 12500000 - sb)

        # genesis sponsor with sponsor balance, should failed
        b0 = client.get_balance(genesis_addr)
        sb = client.get_sponsor_balance_for_collateral(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=sb + 1,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sb)
        assert_equal(client.get_sponsor_for_collateral(contract_addr), addr3)
        assert_equal(client.get_balance(genesis_addr), b0 - gas)

        # genesis sponsor with sponsor balance and collateral_for_storage, should succeed
        b0 = client.get_balance(genesis_addr)
        b3 = client.get_balance(addr3)
        cfs = client.get_collateral_for_storage(contract_addr)
        sb = client.get_sponsor_balance_for_collateral(contract_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_collateral",
            args=[Web3.toChecksumAddress(contract_addr)],
            value=sb + cfs + 1,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_collateral_for_storage(contract_addr), cfs)
        assert_equal(client.get_sponsor_balance_for_collateral(contract_addr),
                     sb + cfs + 1)
        assert_equal(client.get_sponsor_for_collateral(contract_addr),
                     genesis_addr)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - gas + 12500000 - sb - cfs - 1)
        assert_equal(client.get_balance(addr3), b3 + sb + cfs)

        self.log.info("Pass")
    def run_test(self):
        genesis_key = default_config["GENESIS_PRI_KEY"]
        balance_map = {genesis_key: default_config["TOTAL_COIN"]}
        self.log.info("Initial State: (sk:%d, addr:%s, balance:%d)",
                      bytes_to_int(genesis_key),
                      eth_utils.encode_hex(privtoaddr(genesis_key)),
                      balance_map[genesis_key])
        nonce_map = {genesis_key: 0}
        '''Check if transaction from uncommitted new address can be accepted'''
        tx_n = 5
        receiver_sk = genesis_key
        gas_price = 1
        for i in range(tx_n):
            sender_key = receiver_sk
            value = int((balance_map[sender_key] -
                         ((tx_n - i) * 21000 * gas_price)) * random.random())
            nonce = nonce_map[sender_key]
            receiver_sk, _ = ec_random_keys()
            nonce_map[receiver_sk] = 0
            balance_map[receiver_sk] = value
            tx = create_transaction(pri_key=sender_key,
                                    receiver=privtoaddr(receiver_sk),
                                    value=value,
                                    nonce=nonce,
                                    gas_price=gas_price)
            r = random.randint(0, self.num_nodes - 1)
            self.nodes[r].p2p.send_protocol_msg(
                Transactions(transactions=[tx]))
            nonce_map[sender_key] = nonce + 1
            balance_map[sender_key] -= value + gas_price * 21000
            self.log.debug(
                "New tx %s: %s send value %d to %s, sender balance:%d, receiver balance:%d",
                encode_hex(tx.hash),
                eth_utils.encode_hex(privtoaddr(sender_key))[-4:], value,
                eth_utils.encode_hex(privtoaddr(receiver_sk))[-4:],
                balance_map[sender_key], balance_map[receiver_sk])
            self.log.debug("Send Transaction %s to node %d",
                           encode_hex(tx.hash), r)
            time.sleep(random.random() / 100)
        block_gen_thread = BlockGenThread(self.nodes,
                                          self.log,
                                          interval_base=0.2)
        block_gen_thread.start()
        for k in balance_map:
            self.log.info("Check account sk:%s addr:%s", bytes_to_int(k),
                          eth_utils.encode_hex(privtoaddr(k)))
            wait_until(lambda: self.check_account(k, balance_map))
        self.log.info("Pass 1")
        '''Test Random Transactions'''
        all_txs = []
        tx_n = 1000
        self.log.info(
            "start to generate %d transactions with about %d seconds", tx_n,
            tx_n / 100 / 2)
        for i in range(tx_n):
            sender_key = random.choice(list(balance_map))
            nonce = nonce_map[sender_key]
            data = b''
            rand_n = random.random()
            gas = 21000
            if rand_n < 0.1 and balance_map[sender_key] > 21000 * 4 * tx_n:
                value = int(balance_map[sender_key] * 0.5)
                receiver_sk, _ = ec_random_keys()
                receiver = privtoaddr(receiver_sk)
                nonce_map[receiver_sk] = 0
                balance_map[receiver_sk] = value
            elif rand_n > 0.9 and balance_map[sender_key] > 21000 * 4 * tx_n:
                value = 0
                receiver = b''
                data = bytes([
                    96, 128, 96, 64, 82, 52, 128, 21, 97, 0, 16, 87, 96, 0,
                    128, 253, 91, 80, 96, 5, 96, 0, 129, 144, 85, 80, 96, 230,
                    128, 97, 0, 39, 96, 0, 57, 96, 0, 243, 254, 96, 128, 96,
                    64, 82, 96, 4, 54, 16, 96, 67, 87, 96, 0, 53, 124, 1, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 144, 4, 128, 99, 96, 254, 71, 177, 20,
                    96, 72, 87, 128, 99, 109, 76, 230, 60, 20, 96, 127, 87, 91,
                    96, 0, 128, 253, 91, 52, 128, 21, 96, 83, 87, 96, 0, 128,
                    253, 91, 80, 96, 125, 96, 4, 128, 54, 3, 96, 32, 129, 16,
                    21, 96, 104, 87, 96, 0, 128, 253, 91, 129, 1, 144, 128,
                    128, 53, 144, 96, 32, 1, 144, 146, 145, 144, 80, 80, 80,
                    96, 167, 86, 91, 0, 91, 52, 128, 21, 96, 138, 87, 96, 0,
                    128, 253, 91, 80, 96, 145, 96, 177, 86, 91, 96, 64, 81,
                    128, 130, 129, 82, 96, 32, 1, 145, 80, 80, 96, 64, 81, 128,
                    145, 3, 144, 243, 91, 128, 96, 0, 129, 144, 85, 80, 80, 86,
                    91, 96, 0, 128, 84, 144, 80, 144, 86, 254, 161, 101, 98,
                    122, 122, 114, 48, 88, 32, 181, 24, 13, 149, 253, 195, 129,
                    48, 40, 237, 71, 246, 44, 124, 223, 112, 139, 118, 192,
                    219, 9, 64, 67, 245, 51, 180, 42, 67, 13, 49, 62, 21, 0, 41
                ])
                gas = 10000000
            else:
                value = 1
                receiver_sk = random.choice(list(balance_map))
                receiver = privtoaddr(receiver_sk)
                balance_map[receiver_sk] += value
            # not enough transaction fee (gas_price * gas_limit) should not happen for now
            assert balance_map[sender_key] >= value + gas_price * 21000
            tx = create_transaction(pri_key=sender_key,
                                    receiver=receiver,
                                    value=value,
                                    nonce=nonce,
                                    gas_price=gas_price,
                                    data=data,
                                    gas=gas)
            r = random.randint(0, self.num_nodes - 1)
            self.nodes[r].p2p.send_protocol_msg(
                Transactions(transactions=[tx]))
            all_txs.append(tx)
            nonce_map[sender_key] = nonce + 1
            balance_map[sender_key] -= value + gas_price * gas
            self.log.debug(
                "New tx %s: %s send value %d to %s, sender balance:%d, receiver balance:%d nonce:%d",
                encode_hex(tx.hash),
                eth_utils.encode_hex(privtoaddr(sender_key))[-4:], value,
                eth_utils.encode_hex(privtoaddr(receiver_sk))[-4:],
                balance_map[sender_key], balance_map[receiver_sk], nonce)
            self.log.debug("Send Transaction %s to node %d",
                           encode_hex(tx.hash), r)
            time.sleep(random.random() / 100)
        for k in balance_map:
            self.log.info("Account %s with balance:%s", bytes_to_int(k),
                          balance_map[k])
        for tx in all_txs:
            self.log.debug("Wait for tx to confirm %s", tx.hash_hex())
            for i in range(3):
                try:
                    retry = True
                    while retry:
                        try:
                            wait_until(
                                lambda: checktx(self.nodes[0], tx.hash_hex()),
                                timeout=120)
                            retry = False
                        except CannotSendRequest:
                            time.sleep(0.01)
                    break
                except AssertionError as _:
                    self.nodes[0].p2p.send_protocol_msg(
                        Transactions(transactions=[tx]))
                if i == 2:
                    raise AssertionError(
                        "Tx {} not confirmed after 30 seconds".format(
                            tx.hash_hex()))

        for k in balance_map:
            self.log.info("Check account sk:%s addr:%s", bytes_to_int(k),
                          eth_utils.encode_hex(privtoaddr(k)))
            wait_until(lambda: self.check_account(k, balance_map))
        block_gen_thread.stop()
        block_gen_thread.join()
        sync_blocks(self.nodes)
        self.log.info("Pass")
    def run_test(self):
        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        file_dir = os.path.dirname(os.path.realpath(__file__))

        self.log.info("Initializing contract")

        self.buggy_contract = get_contract_instance(source=os.path.join(
            file_dir, "contracts/reentrancy.sol"),
                                                    contract_name="Reentrance")
        self.exploit_contract = get_contract_instance(
            source=os.path.join(file_dir, "contracts/reentrancy_exploit.sol"),
            contract_name="ReentranceExploit")

        user1, _ = ec_random_keys()
        user1_addr = priv_to_addr(user1)
        user1_addr_hex = eth_utils.encode_hex(user1_addr)
        user2, _ = ec_random_keys()
        user2_addr = priv_to_addr(user2)
        user2_addr_hex = eth_utils.encode_hex(user2_addr)

        # setup balance
        value = (10**15 + 2000) * 10**18 + ReentrancyTest.REQUEST_BASE['gas']
        tx = create_transaction(pri_key=self.genesis_priv_key,
                                receiver=user1_addr,
                                value=value,
                                nonce=self.get_nonce(self.genesis_addr),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        tx = create_transaction(pri_key=self.genesis_priv_key,
                                receiver=user2_addr,
                                value=value,
                                nonce=self.get_nonce(self.genesis_addr),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        user1_balance = parse_as_int(
            self.nodes[0].cfx_getBalance(user1_addr_hex))
        assert_equal(user1_balance, value)
        user2_balance_before_contract_construction = parse_as_int(
            self.nodes[0].cfx_getBalance(user2_addr_hex))
        assert_equal(user2_balance_before_contract_construction, value)

        transaction = self.call_contract_function(self.buggy_contract,
                                                  "constructor", [],
                                                  self.genesis_priv_key,
                                                  storage_limit=20000)
        contract_addr = self.wait_for_tx([transaction],
                                         True)[0]['contractCreated']

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "constructor", [],
                                                  user2,
                                                  storage_limit=200000)
        exploit_addr = self.wait_for_tx([transaction],
                                        True)[0]['contractCreated']
        user2_balance_after_contract_construction = parse_as_int(
            self.nodes[0].cfx_getBalance(user2_addr_hex))
        self.log.debug("user2 balance contract created %s" %
                       user2_balance_after_contract_construction)
        assert_greater_than_or_equal(
            user2_balance_before_contract_construction,
            user2_balance_after_contract_construction)
        user2_refund_upper_bound = \
            user2_balance_before_contract_construction - \
            user2_balance_after_contract_construction

        transaction = self.call_contract_function(self.buggy_contract,
                                                  "addBalance", [],
                                                  user1,
                                                  10**18,
                                                  contract_addr,
                                                  True,
                                                  True,
                                                  storage_limit=128)
        transaction = self.call_contract_function(
            self.exploit_contract,
            "deposit", [Web3.toChecksumAddress(contract_addr)],
            user2,
            10**18,
            exploit_addr,
            True,
            True,
            storage_limit=128)

        user1_balance = parse_as_int(
            self.nodes[0].cfx_getBalance(user1_addr_hex))
        assert_greater_than_or_equal(user1_balance,
                                     899999999999999999999999950000000)
        user2_balance_after_deposit = parse_as_int(
            self.nodes[0].cfx_getBalance(user2_addr_hex))
        # User2 paid storage collateral `vulnerable_contract` in deposit call.
        user2_refund_upper_bound += 10**18 // 16
        self.log.debug("user2 balance after deposit %s" %
                       user2_balance_after_deposit)
        assert_greater_than_or_equal(user2_balance_after_contract_construction,
                                     user2_balance_after_deposit + 10**18)
        assert_greater_than_or_equal(user2_balance_after_deposit,
                                     899999999999999999999999900000000)
        contract_balance = parse_as_int(
            self.nodes[0].cfx_getBalance(contract_addr))
        assert_equal(contract_balance, 2 * 10**18)
        user2_balance_in_contract = RpcClient(self.nodes[0]).call(
            contract_addr,
            self.buggy_contract.functions.balanceOf(
                Web3.toChecksumAddress(exploit_addr)).buildTransaction({
                    "from":
                    user2_addr_hex,
                    "to":
                    contract_addr,
                    "gas":
                    int_to_hex(CONTRACT_DEFAULT_GAS),
                    "gasPrice":
                    int_to_hex(1),
                    "chainId":
                    0
                })["data"])
        assert_equal(parse_as_int(user2_balance_in_contract), 10**18)

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "launch_attack", [],
                                                  user2,
                                                  0,
                                                  exploit_addr,
                                                  True,
                                                  True,
                                                  storage_limit=128)
        transaction = self.call_contract_function(self.exploit_contract,
                                                  "get_money", [],
                                                  user2,
                                                  0,
                                                  exploit_addr,
                                                  True,
                                                  True,
                                                  storage_limit=128)

        user1_balance = parse_as_int(
            self.nodes[0].cfx_getBalance(user1_addr_hex))
        assert_greater_than_or_equal(user1_balance,
                                     899999999999999999999999950000000)
        contract_balance = parse_as_int(
            self.nodes[0].cfx_getBalance(contract_addr))
        assert_equal(contract_balance, 1 * 10**18)

        user2_balance_in_contract = RpcClient(self.nodes[0]).call(
            contract_addr,
            self.buggy_contract.functions.balanceOf(
                Web3.toChecksumAddress(exploit_addr)).buildTransaction({
                    "from":
                    user2_addr_hex,
                    "to":
                    contract_addr,
                    "gas":
                    int_to_hex(CONTRACT_DEFAULT_GAS),
                    "gasPrice":
                    int_to_hex(1),
                    "chainId":
                    0
                })["data"])

        assert_equal(parse_as_int(user2_balance_in_contract), 0)
        self.log.debug("user2 balance in contract %s" %
                       user2_balance_in_contract)
        user2_balance_after_contract_destruct = parse_as_int(
            self.nodes[0].cfx_getBalance(user2_addr_hex))
        self.log.debug("user2 balance after contract destruct %s" %
                       user2_balance_after_contract_destruct)
        assert_greater_than_or_equal(
            user2_balance_after_contract_destruct,
            user2_balance_after_deposit + user2_refund_upper_bound + 10**18)

        block_gen_thread.stop()
        block_gen_thread.join()
    def run_test(self):
        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        gas_price = 1
        gas = CONTRACT_DEFAULT_GAS
        genesis_key = default_config["GENESIS_PRI_KEY"]
        genesis_addr = encode_hex_0x(priv_to_addr(genesis_key))
        nonce = 0
        test_account_key = default_config["GENESIS_PRI_KEY_2"]
        test_account_addr = encode_hex_0x(priv_to_addr(test_account_key))
        null_addr = "0x0000000000000000000000000000000000000000"

        file_dir = os.path.dirname(os.path.realpath(__file__))
        control_contract_file_path = os.path.join(file_dir, "..",
                                                  "internal_contract",
                                                  "metadata",
                                                  "AdminControl.json")
        control_contract_dict = json.loads(
            open(control_contract_file_path, "r").read())
        admin_control_contract = get_contract_instance(
            contract_dict=control_contract_dict)
        admin_control_contract_addr = "0x0888000000000000000000000000000000000000"

        # Deploy a new instance of the create2factory other than the genesis block,
        # so that the admin is the genesis_addr, in order to test hijackAdmin function
        # in clear_admin_test_contract_addr.sol.
        self.tx_conf = {
            "from": Web3.toChecksumAddress(genesis_addr),
            "nonce": int_to_hex(nonce),
            "gas": int_to_hex(gas),
            "gasPrice": int_to_hex(gas_price),
            "chainId": 0
        }
        create2factory = get_contract_instance(
            abi_file=os.path.join(file_dir,
                                  "contracts/create2factory_abi.json"),
            bytecode_file=os.path.join(
                file_dir, "contracts/create2factory_bytecode.dat"),
        )
        raw_create = create2factory.constructor().buildTransaction(
            self.tx_conf)
        tx_data = decode_hex(raw_create["data"])
        tx_create = create_transaction(pri_key=genesis_key,
                                       receiver=b'',
                                       nonce=nonce,
                                       gas_price=gas_price,
                                       data=tx_data,
                                       gas=gas,
                                       value=0,
                                       storage_limit=1920)
        nonce += 1
        self.rpc.send_tx(tx_create, True)
        receipt = self.rpc.get_transaction_receipt(tx_create.hash_hex())
        create2factory_addr = receipt['contractCreated']

        # Clear admin by non-admin (fail)
        self.log.info("Test unable to clear admin by non-admin.")
        set_admin = admin_control_contract.functions \
            .setAdmin(Web3.toChecksumAddress(create2factory_addr), null_addr) \
            .buildTransaction({"to":admin_control_contract_addr, **self.tx_conf})
        tx_data = set_admin["data"]
        self.call_contract(test_account_addr, test_account_key,
                           admin_control_contract_addr, tx_data)
        assert_equal(self.rpc.get_admin(create2factory_addr), genesis_addr)

        clear_admin_test_contract = get_contract_instance(
            abi_file=os.path.join(file_dir,
                                  "contracts/clear_admin_at_creation.json"),
            bytecode_file=os.path.join(
                file_dir, "contracts/clear_admin_at_creation.bytecode"),
        )

        self.log.info("Test contract creation by itself")
        raw_create = clear_admin_test_contract.constructor().buildTransaction(
            self.tx_conf)
        tx_data = decode_hex(raw_create["data"])
        tx_create = create_transaction(pri_key=genesis_key,
                                       receiver=b'',
                                       nonce=nonce,
                                       gas_price=gas_price,
                                       data=tx_data,
                                       gas=gas,
                                       value=0,
                                       storage_limit=1920)
        nonce += 1
        self.rpc.send_tx(tx_create, True)
        receipt = self.rpc.get_transaction_receipt(tx_create.hash_hex())
        address = receipt["contractCreated"]
        self.log.info("  contract created at %s" % address)
        assert (address is not None)

        self.log.info(
            "Test clear admin at contract creation through create2factory")
        create_data = raw_create["data"]
        salt = 0
        data = create2factory.functions.deploy(create_data,
                                               salt).buildTransaction({
                                                   "to":
                                                   create2factory_addr,
                                                   **self.tx_conf
                                               })["data"]
        # Compute the contract address.
        clear_admin_test_contract_addr = Web3.toChecksumAddress(
            "0x" + self.rpc.call(create2factory_addr, data)[-40:])
        # Deploy the contract.
        self.call_contract(genesis_addr,
                           genesis_key,
                           create2factory_addr,
                           data,
                           value=0)
        assert_equal(self.rpc.get_admin(clear_admin_test_contract_addr),
                     null_addr)
        # The owner of create2factory_addr isn't hijacked.
        self.log.info("Test unable to hijack set admin.")
        assert_equal(self.rpc.get_admin(create2factory_addr), genesis_addr)

        self.log.info(
            "Test unable to hijack owner through deployAndHijackAdmin")
        # Create a new contract through deployAndHijackAdmin.
        new_contract_to_deploy = get_contract_instance(
            abi_file=os.path.join(file_dir, "contracts/blackhole.json"),
            bytecode_file=os.path.join(file_dir,
                                       "contracts/blackhole.bytecode"),
        )
        self.tx_conf["nonce"] = 1
        self.tx_conf["from"] = Web3.toChecksumAddress(test_account_addr)
        new_raw_create = new_contract_to_deploy.constructor().buildTransaction(
            self.tx_conf)
        create_data = new_raw_create["data"]
        data = clear_admin_test_contract.functions.deployAndHijackAdmin(
            create_data).buildTransaction({
                "to": clear_admin_test_contract_addr,
                **self.tx_conf
            })["data"]
        new_contract_addr = "0x" + self.rpc.call(
            clear_admin_test_contract_addr, data)[-40:]
        self.call_contract(test_account_addr,
                           test_account_key,
                           clear_admin_test_contract_addr,
                           data,
                           value=123)
        # Check owner of the new contract isn't the "evil address" or null address.
        assert_equal(self.rpc.get_admin(new_contract_addr), test_account_addr)

        self.log.info("Pass")
Exemple #21
0
    def run_test(self):
        genesis_key = default_config["GENESIS_PRI_KEY"]
        receiver_sk, _ = ec_random_keys()
        receiver_addr = priv_to_addr(receiver_sk)
        client = RpcClient(self.nodes[0])

        value = 100000000
        tx = create_transaction(pri_key=genesis_key,
                                receiver=receiver_addr,
                                value=value,
                                nonce=0,
                                gas_price=1,
                                epoch_height=0)
        client.send_tx(tx)
        block_gen_thread = BlockGenThread(self.nodes,
                                          self.log,
                                          interval_base=0.1)
        block_gen_thread.start()
        self.log.info(
            "Wait for the first transaction to go through with epoch_height = 0..."
        )
        wait_until(lambda: parse_as_int(self.nodes[0].cfx_getBalance(
            eth_utils.encode_hex(receiver_addr))) == value)
        self.log.info("Wait for generating more than 50 epochs")
        wait_until(lambda: parse_as_int(
            client.block_by_hash(client.best_block_hash())['height']) > 50)
        block_gen_thread.stop()
        self.log.info("Now block count:%d", self.nodes[0].getblockcount())

        tx = create_transaction(pri_key=genesis_key,
                                receiver=receiver_addr,
                                value=value,
                                nonce=1,
                                gas_price=1,
                                epoch_height=0)
        try:
            client.send_tx(tx)
            self.log.info("Bad transaction not rejected!")
            assert (False)
        except ReceivedErrorResponseError:
            self.log.info("Bad transaction rejected.")
        except:
            self.log.info("Unexpected error!")
            assert (False)
        assert (parse_as_int(self.nodes[0].cfx_getBalance(
            eth_utils.encode_hex(receiver_addr))) == value)

        epoch_height = parse_as_int(
            client.block_by_hash(client.best_block_hash())['height'])
        tx = create_transaction(pri_key=genesis_key,
                                receiver=receiver_addr,
                                value=value,
                                nonce=1,
                                gas_price=1,
                                epoch_height=epoch_height)
        client.send_tx(tx)
        block_gen_thread = BlockGenThread(self.nodes,
                                          self.log,
                                          interval_base=0.1)
        block_gen_thread.start()
        self.log.info(
            "Wait for the first transaction to go through with epoch_height = "
            + str(epoch_height) + "...")
        wait_until(lambda: parse_as_int(self.nodes[0].cfx_getBalance(
            eth_utils.encode_hex(receiver_addr))) == 2 * value)
        block_gen_thread.stop()
        self.log.info("Now block count:%d", self.nodes[0].getblockcount())
        self.log.info("Pass!")
    def run_test(self):
        file_dir = os.path.dirname(os.path.realpath(__file__))

        pay_contract = get_contract_instance(
            abi_file=os.path.join(file_dir, "contracts/pay_abi.json"),
            bytecode_file=os.path.join(file_dir, "contracts/pay_bytecode.dat"),
        )

        control_contract_file_path =os.path.join(file_dir, "../internal_contract/metadata/AdminControl.json")
        control_contract_dict = json.loads(open(control_contract_file_path, "r").read())

        admin_control_contract = get_contract_instance(contract_dict=control_contract_dict)

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = self.genesis_priv_key
        genesis_addr = self.genesis_addr
        self.log.info("genesis_addr={}".format(encode_hex_0x(genesis_addr)))
        nonce = 0
        gas_price = 1
        gas = CONTRACT_DEFAULT_GAS
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {"from":Web3.toChecksumAddress(encode_hex_0x(genesis_addr)), "nonce":int_to_hex(nonce), "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0}

        # Setup balance for node 0
        node = self.nodes[0]
        client = RpcClient(node)
        (addr, priv_key) = client.rand_account()
        self.log.info("addr=%s priv_key=%s", addr, priv_key)
        tx = client.new_tx(value=5 * 10 ** 18, receiver=addr, nonce=self.get_nonce(genesis_addr))
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr), 5000000000000000000)

        (addr2, priv_key2) = client.rand_account()
        self.log.info("addr2=%s priv_key2=%s", addr2, priv_key2)
        tx = client.new_tx(value=5 * 10 ** 18, receiver=addr2, nonce=self.get_nonce(genesis_addr))
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr2), 5000000000000000000)

        # deploy pay contract
        tx = self.call_contract_function(
            contract=pay_contract,
            name="constructor",
            args=[],
            sender_key=priv_key,
            storage_limit=512)
        contract_addr = self.wait_for_tx([tx], True)[0]['contractCreated']
        self.log.info("contract_addr={}".format(contract_addr))
        assert_equal(client.get_collateral_for_storage(addr), 512 * 976562500000000)
        assert_equal(client.get_balance(contract_addr), 0)

        # deposit 10**18
        b0 = int(node.cfx_getBalance(addr), 16)
        tx = self.call_contract_function(
            contract=pay_contract,
            name="recharge",
            args=[],
            sender_key=priv_key,
            contract_addr=contract_addr,
            value=10 ** 18,
            wait=True,
            check_status=True)
        assert_equal(client.get_balance(contract_addr), 10 ** 18)
        assert_equal(client.get_balance(addr), b0 - 10 ** 18 - charged_of_huge_gas(gas))
        assert_equal(client.get_admin(contract_addr), addr)

        # transfer admin (fail)
        tx = self.call_contract_function(
            contract=admin_control_contract,
            name="setAdmin",
            args=[Web3.toChecksumAddress(contract_addr), Web3.toChecksumAddress(addr2)],
            sender_key=priv_key2,
            contract_addr=Web3.toChecksumAddress("0x0888000000000000000000000000000000000000"),
            wait=True,
            check_status=True)
        assert_equal(client.get_admin(contract_addr), addr)
        assert_equal(client.get_balance(addr2), 5 * 10 ** 18 - charged_of_huge_gas(gas))

        # transfer admin (success)
        tx = self.call_contract_function(
            contract=admin_control_contract,
            name="setAdmin",
            args=[Web3.toChecksumAddress(contract_addr), Web3.toChecksumAddress(addr2)],
            sender_key=priv_key,
            contract_addr=Web3.toChecksumAddress("0x0888000000000000000000000000000000000000"),
            wait=True,
            check_status=True)
        assert_equal(client.get_admin(contract_addr), addr2)

        # destroy
        b0 = client.get_balance(addr)
        tx = self.call_contract_function(
            contract=admin_control_contract,
            name="destroy",
            args=[Web3.toChecksumAddress(contract_addr)],
            sender_key=priv_key2,
            contract_addr=Web3.toChecksumAddress("0x0888000000000000000000000000000000000000"),
            wait=True,
            check_status=True)
        assert_equal(client.get_balance(contract_addr), 0)
        assert_equal(client.get_balance(addr2), 6 * 10 ** 18 - charged_of_huge_gas(gas) * 2)
        assert_equal(client.get_collateral_for_storage(addr), 0)
        assert_equal(client.get_balance(addr), b0 + 512 * 976562500000000)

        self.log.info("Pass")
Exemple #23
0
    def run_test(self):
        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes,
                                          self.log,
                                          interval_base=0.2)
        block_gen_thread.start()
        genesis_key = default_config["GENESIS_PRI_KEY"]
        tx_n = 100
        gas_price = 1
        shard_balance = []

        for s in range(self.n_shard):
            ''' Send random transactions to this shard s '''
            shard_nodes = self.nodes[s * self.shard_size:(s + 1) *
                                     self.shard_size]
            # We can not use genesis accounts in two shards, because they may generate transactions
            # that are valid in another shard and breaks our assertion about the final shard state.
            start_sk, _ = ec_random_keys()
            value = default_config["TOTAL_COIN"] - 21000
            tx = create_transaction(pri_key=genesis_key,
                                    receiver=priv_to_addr(start_sk),
                                    value=value,
                                    nonce=0,
                                    gas_price=gas_price)
            shard_nodes[0].p2p.send_protocol_msg(
                Transactions(transactions=[tx]))

            balance_map = {start_sk: value}
            nonce_map = {
                start_sk:
                wait_for_initial_nonce_for_privkey(shard_nodes[0], start_sk)
            }
            account_n = 10

            # Initialize new accounts
            new_keys = set()
            for _ in range(account_n):
                value = max(int(balance_map[start_sk] * random.random()),
                            21000 * tx_n)
                receiver_sk, _ = ec_random_keys()
                new_keys.add(receiver_sk)
                tx = create_transaction(pri_key=start_sk,
                                        receiver=priv_to_addr(receiver_sk),
                                        value=value,
                                        nonce=nonce_map[start_sk],
                                        gas_price=gas_price)
                shard_nodes[0].p2p.send_protocol_msg(
                    Transactions(transactions=[tx]))
                balance_map[receiver_sk] = value
                nonce_map[start_sk] += 1
                balance_map[start_sk] -= value + gas_price * 21000
            wait_for_account_stable()
            for key in new_keys:
                nonce_map[key] = wait_for_initial_nonce_for_privkey(
                    shard_nodes[0], key)

            for i in range(tx_n):
                sender_key = random.choice(list(balance_map))
                nonce = nonce_map[sender_key]
                value = 0
                receiver_sk = random.choice(list(balance_map))
                balance_map[receiver_sk] += value
                tx = create_transaction(pri_key=sender_key,
                                        receiver=priv_to_addr(receiver_sk),
                                        value=value,
                                        nonce=nonce,
                                        gas_price=gas_price)
                r = random.randint(0, self.shard_size - 1)
                shard_nodes[r].p2p.send_protocol_msg(
                    Transactions(transactions=[tx]))
                nonce_map[sender_key] = nonce + 1
                balance_map[sender_key] -= value + gas_price * 21000
                self.log.info(
                    "New tx %s: %s send value %d to %s, sender balance:%d, receiver balance:%d",
                    encode_hex(tx.hash),
                    eth_utils.encode_hex(priv_to_addr(sender_key))[-4:], value,
                    eth_utils.encode_hex(priv_to_addr(receiver_sk))[-4:],
                    balance_map[sender_key], balance_map[receiver_sk])
                self.log.debug("Send Transaction %s to node %d",
                               encode_hex(tx.hash), r)
                time.sleep(random.random() / 10)
            for k in balance_map:
                self.log.info("Check account sk:%s addr:%s", bytes_to_int(k),
                              eth_utils.encode_hex(priv_to_addr(k)))
                wait_until(
                    lambda: self.check_account(k, balance_map, shard_nodes[0]))
            shard_balance.append(balance_map)

        def epochCheck(node):
            r = node.cfx_epochNumber()
            return int(r, 0) > 110

        wait_until(lambda: epochCheck(self.nodes[0]))
        wait_until(
            lambda: epochCheck(self.nodes[int(self.num_nodes / self.n_shard)]))
        for s in range(self.n_shard):
            for idx in range(self.shard_size):
                connect_nodes(self.nodes, s * self.shard_size - 1 + idx,
                              s * self.shard_size + idx)
        block_gen_thread.stop()
        block_gen_thread.join()
        sync_blocks(self.nodes)
        ''' Check if the balance state of every node matches '''
        success_shard = -1
        # use the state of node 0 to find the winning shard
        for s in range(self.n_shard):
            balance_map = shard_balance[s]
            unmatch = False
            for k in balance_map:
                if not self.check_account(k, balance_map, self.nodes[0]):
                    unmatch = True
                    self.log.info(
                        "Final balance does not match shard %s, check next", s)
                    break
            if unmatch:
                continue
            success_shard = s
            break
        assert success_shard != -1, "The final state of node 0 matches no shard state"
        self.log.info("Shard %s succeeds", success_shard)
        for i in range(1, self.num_nodes):
            balance_map = shard_balance[success_shard]
            for k in balance_map:
                if not self.check_account(k, balance_map, self.nodes[i]):
                    raise AssertionError(
                        "Final balance of node {} does not match node 0, sender={}"
                        .format(i, k))
        self.log.info("Pass")
    def run_test(self):
        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        client = RpcClient(self.nodes[0])

        file_dir = os.path.dirname(os.path.realpath(__file__))

        self.log.info("Initializing contract")

        self.buggy_contract = get_contract_instance(source=os.path.join(
            file_dir, "contracts/reentrancy.sol"),
                                                    contract_name="Reentrance")
        self.exploit_contract = get_contract_instance(
            source=os.path.join(file_dir, "contracts/reentrancy_exploit.sol"),
            contract_name="ReentranceExploit")

        reentrancy_config_addr = Web3.toChecksumAddress(
            "0888000000000000000000000000000000000003")
        file_dir = os.path.dirname(os.path.realpath(__file__))
        control_contract_file_path = os.path.join(file_dir, "..",
                                                  "internal_contract",
                                                  "metadata",
                                                  "ReentrancyConfig.json")
        control_contract_dict = json.loads(
            open(control_contract_file_path, "r").read())
        control_contract = get_contract_instance(
            contract_dict=control_contract_dict)

        user1, _ = ec_random_keys()
        user1_addr = priv_to_addr(user1)
        user1_addr_hex = eth_utils.encode_hex(user1_addr)
        user2, _ = ec_random_keys()
        user2_addr = priv_to_addr(user2)
        user2_addr_hex = eth_utils.encode_hex(user2_addr)

        # setup balance
        value = (10**15 + 2000) * 10**18 + ReentrancyTest.REQUEST_BASE['gas']
        tx = create_transaction(pri_key=self.genesis_priv_key,
                                receiver=user1_addr,
                                value=value,
                                nonce=self.get_nonce(self.genesis_addr),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        tx = create_transaction(pri_key=self.genesis_priv_key,
                                receiver=user2_addr,
                                value=value,
                                nonce=self.get_nonce(self.genesis_addr),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        user1_balance = client.get_balance(user1_addr_hex)
        assert_equal(user1_balance, value)
        user2_balance_before_contract_construction = client.get_balance(
            user2_addr_hex)
        assert_equal(user2_balance_before_contract_construction, value)

        transaction = self.call_contract_function(self.buggy_contract,
                                                  "constructor", [],
                                                  self.genesis_priv_key,
                                                  storage_limit=20000)
        buggy_addr = self.wait_for_tx([transaction],
                                      True)[0]['contractCreated']

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "constructor", [],
                                                  user2,
                                                  storage_limit=200000)
        exploit_addr = self.wait_for_tx([transaction],
                                        True)[0]['contractCreated']

        if self.mode == NO_PROTECTION:
            self.log.info("Disabling anti-reentrancy")
            self.call_contract_function(
                contract=control_contract,
                name="allowReentrancyByAdmin",
                args=[Web3.toChecksumAddress(buggy_addr), True],
                sender_key=self.genesis_priv_key,
                contract_addr=reentrancy_config_addr,
                storage_limit=64,
                wait=True,
                check_status=True)
            self.call_contract_function(
                contract=control_contract,
                name="allowReentrancyByAdmin",
                args=[Web3.toChecksumAddress(exploit_addr), True],
                sender_key=user2,
                contract_addr=reentrancy_config_addr,
                storage_limit=64,
                wait=True,
                check_status=True)

        user2_balance_after_contract_construction = client.get_balance(
            user2_addr_hex)
        self.log.debug("user2 balance contract created %s" %
                       user2_balance_after_contract_construction)
        assert_greater_than_or_equal(
            user2_balance_before_contract_construction,
            user2_balance_after_contract_construction)
        user2_refund_upper_bound = \
            user2_balance_before_contract_construction - \
            user2_balance_after_contract_construction

        transaction = self.call_contract_function(self.buggy_contract,
                                                  "addBalance", [],
                                                  user1,
                                                  10**18,
                                                  buggy_addr,
                                                  True,
                                                  True,
                                                  storage_limit=128)
        transaction = self.call_contract_function(
            self.exploit_contract,
            "deposit", [Web3.toChecksumAddress(buggy_addr)],
            user2,
            10**18,
            exploit_addr,
            True,
            True,
            storage_limit=128)

        user1_balance = client.get_balance(user1_addr_hex)
        assert_greater_than_or_equal(user1_balance,
                                     899999999999999999999999950000000)
        user2_balance_after_deposit = client.get_balance(user2_addr_hex)
        # User2 paid storage collateral `vulnerable_contract` in deposit call.
        user2_refund_upper_bound += 3 * 10**18 // 16
        self.log.debug("user2 balance after deposit %s" %
                       user2_balance_after_deposit)
        assert_greater_than_or_equal(user2_balance_after_contract_construction,
                                     user2_balance_after_deposit + 10**18)
        assert_greater_than_or_equal(user2_balance_after_deposit,
                                     899999999999999999999999900000000)
        contract_balance = client.get_balance(buggy_addr)
        assert_equal(contract_balance, 2 * 10**18)
        user2_balance_in_contract = RpcClient(self.nodes[0]).call(
            buggy_addr,
            self.buggy_contract.functions.balanceOf(
                Web3.toChecksumAddress(exploit_addr)).buildTransaction({
                    "from":
                    user2_addr_hex,
                    "to":
                    buggy_addr,
                    "gas":
                    int_to_hex(CONTRACT_DEFAULT_GAS),
                    "gasPrice":
                    int_to_hex(1),
                    "chainId":
                    0
                })["data"])
        assert_equal(parse_as_int(user2_balance_in_contract), 10**18)

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "launch_attack", [],
                                                  user2,
                                                  0,
                                                  exploit_addr,
                                                  True,
                                                  True,
                                                  storage_limit=128)
        transaction = self.call_contract_function(self.exploit_contract,
                                                  "get_money", [],
                                                  user2,
                                                  0,
                                                  exploit_addr,
                                                  True,
                                                  True,
                                                  storage_limit=128)

        user1_balance = client.get_balance(user1_addr_hex)
        assert_greater_than_or_equal(user1_balance,
                                     899999999999999999999999950000000)
        contract_balance = client.get_balance(buggy_addr)
        attack_benefit = 0
        if self.mode == OLD_MODE:
            # In the old mode, the second withdraw_balance will fail.
            rest_balance, attacker_rest = 1 * CFX, 0
        elif self.mode == NEW_MODE:
            # In the new mode, the protection is closed.
            rest_balance, attacker_rest = 0, 0
            attack_benefit = 1 * CFX
        else:
            raise Exception("Unrecognized reentrancy test mode")
        assert_equal(contract_balance, rest_balance)

        user2_balance_in_contract = RpcClient(self.nodes[0]).call(
            buggy_addr,
            self.buggy_contract.functions.balanceOf(
                Web3.toChecksumAddress(exploit_addr)).buildTransaction({
                    "from":
                    user2_addr_hex,
                    "to":
                    buggy_addr,
                    "gas":
                    int_to_hex(CONTRACT_DEFAULT_GAS),
                    "gasPrice":
                    int_to_hex(1),
                    "chainId":
                    0
                })["data"])

        assert_equal(parse_as_int(user2_balance_in_contract), attacker_rest)
        self.log.debug("user2 balance in contract %s" %
                       user2_balance_in_contract)
        user2_balance_after_contract_destruct = client.get_balance(
            user2_addr_hex)
        self.log.debug("user2 balance after contract destruct %s" %
                       user2_balance_after_contract_destruct)
        assert_greater_than_or_equal(
            user2_balance_after_deposit + user2_refund_upper_bound + 10**18 -
            attacker_rest + attack_benefit,
            user2_balance_after_contract_destruct,
        )

        block_gen_thread.stop()
        block_gen_thread.join()
Exemple #25
0
    def run_test(self):
        # Prevent easysolc from configuring the root logger to print to stderr
        self.log.propagate = False

        solc = Solc()
        file_dir = os.path.dirname(os.path.realpath(__file__))
        staking_contract = solc.get_contract_instance(
            abi_file=os.path.join(
                file_dir, "contracts/storage_interest_staking_abi.json"),
            bytecode_file=os.path.join(
                file_dir, "contracts/storage_interest_staking_bytecode.dat"),
        )

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = default_config["GENESIS_PRI_KEY"]
        genesis_addr = privtoaddr(genesis_key)
        nonce = 0
        gas_price = 1
        gas = 50000000
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {
            "from": Web3.toChecksumAddress(encode_hex_0x(genesis_addr)),
            "nonce": int_to_hex(nonce),
            "gas": int_to_hex(gas),
            "gasPrice": int_to_hex(gas_price),
            "chainId": 0
        }

        # Setup balance for node 0
        node = self.nodes[0]
        client = RpcClient(node)
        (addr, priv_key) = client.rand_account()
        self.log.info("addr=%s priv_key=%s", addr, priv_key)
        tx = client.new_tx(value=5 * 10**18, receiver=addr, nonce=0)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        assert_equal(node.cfx_getBalance(addr), hex(5000000000000000000))
        assert_equal(node.cfx_getBankBalance(addr), hex(0))

        self.tx_conf["to"] = Web3.toChecksumAddress(
            "443c409373ffd5c0bec1dddb7bec830856757b65")
        # deposit 10**18
        tx_data = decode_hex(
            staking_contract.functions.deposit(10**18).buildTransaction(
                self.tx_conf)["data"])
        tx = client.new_tx(value=0,
                           sender=addr,
                           receiver=self.tx_conf["to"],
                           nonce=0,
                           gas=gas,
                           data=tx_data,
                           priv_key=priv_key)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        assert_equal(node.cfx_getBankBalance(addr), hex(10**18))

        # withdraw 5 * 10**17
        tx_data = decode_hex(
            staking_contract.functions.withdraw(5 * 10**17).buildTransaction(
                self.tx_conf)["data"])
        tx = client.new_tx(value=0,
                           sender=addr,
                           receiver=self.tx_conf["to"],
                           nonce=1,
                           gas=gas,
                           data=tx_data,
                           priv_key=priv_key)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        assert_equal(node.cfx_getBankBalance(addr), hex(5 * 10**17))

        block_gen_thread.stop()
        block_gen_thread.join()
        sync_blocks(self.nodes)
        self.log.info("Pass")
    def run_test(self):
        file_dir = os.path.dirname(os.path.realpath(__file__))
        file_path = os.path.join(file_dir, "..", "internal_contract", "metadata", "Staking.json")
        staking_contract_dict = json.loads(open(os.path.join(file_path), "r").read())
        staking_contract = get_contract_instance(contract_dict=staking_contract_dict)

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = default_config["GENESIS_PRI_KEY"]
        genesis_addr = priv_to_addr(genesis_key)
        nonce = 0
        gas_price = 1
        gas = CONTRACT_DEFAULT_GAS
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {"from":Web3.toChecksumAddress(encode_hex_0x(genesis_addr)), "nonce":int_to_hex(nonce), "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0}

        total_num_blocks = 2 * 60 * 60 * 24 * 365
        accumulate_interest_rate = [2 ** 80 * total_num_blocks]
        for _ in range(1000):
            accumulate_interest_rate.append(accumulate_interest_rate[-1] * (
                40000 + 1000000 * total_num_blocks) // (total_num_blocks * 1000000))

        # Setup balance for node 0
        node = self.nodes[0]
        client = RpcClient(node)
        (addr, priv_key) = client.rand_account()
        self.log.info("addr=%s priv_key=%s", addr, priv_key)
        tx = client.new_tx(value=5 * 10 ** 18, receiver=addr)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        assert_equal(client.get_balance(addr), 5 * 10 ** 18)
        assert_equal(client.get_staking_balance(addr), 0)

        self.tx_conf["to"] = Web3.toChecksumAddress("0888000000000000000000000000000000000002")
        # deposit 10**18
        tx_data = decode_hex(staking_contract.functions.deposit(10 ** 18).buildTransaction(self.tx_conf)["data"])
        tx = client.new_tx(value=0, sender=addr, receiver=self.tx_conf["to"], gas=gas, data=tx_data, priv_key=priv_key)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        deposit_time = self.get_block_number(client, tx.hash_hex())
        assert_equal(client.get_staking_balance(addr), 10 ** 18)
        assert_equal(client.get_balance(addr), 4 * 10 ** 18 - charged_of_huge_gas(gas))

        # withdraw 5 * 10**17
        balance = client.get_balance(addr)
        capital = 5 * 10 ** 17
        tx_data = decode_hex(staking_contract.functions.withdraw(capital).buildTransaction(self.tx_conf)["data"])
        tx = client.new_tx(value=0, sender=addr, receiver=self.tx_conf["to"], gas=gas, data=tx_data, priv_key=priv_key)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        withdraw_time = self.get_block_number(client, tx.hash_hex())
        interest = capital * accumulate_interest_rate[withdraw_time] // accumulate_interest_rate[deposit_time] - capital
        assert_equal(client.get_staking_balance(addr), 10 ** 18 - capital)
        assert_equal(client.get_balance(addr), balance + capital + interest - charged_of_huge_gas(gas))

        # lock 4 * 10 ** 17 until block number 100000
        balance = client.get_balance(addr)
        tx_data = decode_hex(staking_contract.functions.vote_lock(4 * 10 ** 17, 100000).buildTransaction(self.tx_conf)["data"])
        tx = client.new_tx(value=0, sender=addr, receiver=self.tx_conf["to"], gas=gas, data=tx_data, priv_key=priv_key)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        assert_equal(client.get_balance(addr), balance - charged_of_huge_gas(gas))
        assert_equal(client.get_staking_balance(addr), 5 * 10 ** 17)

        # withdraw 5 * 10**17 and it should fail
        balance = client.get_balance(addr)
        capital = 5 * 10 ** 17
        tx_data = decode_hex(staking_contract.functions.withdraw(capital).buildTransaction(self.tx_conf)["data"])
        tx = client.new_tx(value=0, sender=addr, receiver=self.tx_conf["to"], gas=gas, data=tx_data, priv_key=priv_key)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        assert_equal(client.get_balance(addr), balance - gas)
        assert_equal(client.get_staking_balance(addr), 5 * 10 ** 17)

        # withdraw 10**17 + 1 and it should fail
        balance = client.get_balance(addr)
        tx_data = decode_hex(staking_contract.functions.withdraw(10 ** 17 + 1).buildTransaction(self.tx_conf)["data"])
        tx = client.new_tx(value=0, sender=addr, receiver=self.tx_conf["to"], gas=gas, data=tx_data, priv_key=priv_key)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        assert_equal(client.get_balance(addr), balance - gas)
        assert_equal(client.get_staking_balance(addr), 5 * 10 ** 17)

        # withdraw 10**17 and it should succeed
        balance = client.get_balance(addr)
        capital = 10 ** 17
        tx_data = decode_hex(staking_contract.functions.withdraw(capital).buildTransaction(self.tx_conf)["data"])
        tx = client.new_tx(value=0, sender=addr, receiver=self.tx_conf["to"], gas=gas, data=tx_data, priv_key=priv_key)
        client.send_tx(tx)
        self.wait_for_tx([tx])
        withdraw_time = self.get_block_number(client, tx.hash_hex())
        interest = capital * accumulate_interest_rate[withdraw_time] // accumulate_interest_rate[deposit_time] - capital
        assert_equal(client.get_balance(addr), balance + capital + interest - charged_of_huge_gas(gas))
        assert_equal(client.get_staking_balance(addr), 5 * 10 ** 17 - capital)

        block_gen_thread.stop()
        block_gen_thread.join()
        sync_blocks(self.nodes)
        self.log.info("Pass")
Exemple #27
0
    def run_test(self):
        file_dir = os.path.dirname(os.path.realpath(__file__))

        test_contract = get_contract_instance(
            abi_file=os.path.join(file_dir, "contracts/issue988_abi.json"),
            bytecode_file=os.path.join(file_dir,
                                       "contracts/issue988_bytecode.dat"),
        )

        start_p2p_connection(self.nodes)

        genesis_key = self.genesis_priv_key
        genesis_addr = self.genesis_addr
        self.log.info("genesis_addr={}".format(encode_hex_0x(genesis_addr)))
        nonce = 0
        gas_price = 1
        gas = 50000000
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {
            "from": Web3.toChecksumAddress(encode_hex_0x(genesis_addr)),
            "nonce": int_to_hex(nonce),
            "gas": int_to_hex(gas),
            "gasPrice": int_to_hex(gas_price),
            "chainId": 0
        }

        # setup balance for node 0
        node = self.nodes[0]
        client = RpcClient(node)
        (addr, priv_key) = client.rand_account()
        self.log.info("addr=%s priv_key=%s", addr, priv_key)
        tx = client.new_tx(value=20 * 10**18,
                           receiver=addr,
                           nonce=self.get_nonce(genesis_addr))
        client.send_tx(tx, True)
        assert_equal(node.cfx_getBalance(addr), hex(20000000000000000000))

        # deploy test contract
        tx = self.call_contract_function(contract=test_contract,
                                         name="constructor",
                                         args=[],
                                         sender_key=priv_key)
        contract_addr = self.wait_for_tx([tx], True)[0]['contractCreated']
        self.log.info("contract_addr={}".format(contract_addr))
        assert_equal(node.cfx_getBalance(contract_addr), hex(0))

        raw_result = self.call_contract_function_rpc(
            contract=test_contract,
            name="ktrriiwhlx",
            args=[],
            contract_addr=contract_addr)
        result = signed_bytes_to_int256(decode_hex(raw_result))
        assert_equal(result, -12076)

        raw_result = self.call_contract_function_rpc(
            contract=test_contract,
            name="qiwmzrxuhd",
            args=[],
            contract_addr=contract_addr)
        result = signed_bytes_to_int256(decode_hex(raw_result))
        assert_equal(result, -2)

        raw_result = self.call_contract_function_rpc(
            contract=test_contract,
            name="wxqpwecckl",
            args=[],
            contract_addr=contract_addr)
        result = signed_bytes_to_int256(decode_hex(raw_result))
        assert_equal(result, -1)

        self.log.info("Pass")
    def run_test(self):

        # Start mininode connection
        default_node = DefaultNode()
        self.node = default_node
        kwargs = {}
        args = {}
        kwargs['dstport'] = 32323
        kwargs['dstaddr'] = '127.0.0.1'
        default_node.peer_connect(*args, **kwargs)
        network_thread_start()
        default_node.wait_for_status()

        # Start rpc connection
        self.rpc_client = RpcClient(get_simple_rpc_proxy(
            "http://127.0.0.1:12537"))
        node_id = self.rpc_client.get_node_id()
        self.log.info("get nodeid %s", eth_utils.encode_hex(node_id))

        block_gen_thread = BlockGenThread([self.rpc_client.node], self.log, num_txs = 100, interval_fixed=0.2)
        block_gen_thread.start()
        genesis_key = default_config["GENESIS_PRI_KEY"]
        balance_map = {genesis_key: default_config["TOTAL_COIN"]}
        self.log.info("Initial State: (sk:%d, addr:%s, balance:%d)", bytes_to_int(genesis_key),
                      eth_utils.encode_hex(priv_to_addr(genesis_key)), balance_map[genesis_key])
        nonce_map = {genesis_key: 0}
        '''Test Random Transactions'''
        all_txs = []
        tx_n = 10000
        gas_price = 1
        self.log.info("start to generate %d transactions with about %d seconds", tx_n, tx_n/10/2)
        for i in range(tx_n):
            if i % 1000 == 0:
                self.log.info("generated %d tx", i)
            sender_key = random.choice(list(balance_map))
            nonce = nonce_map[sender_key]
            if random.random() < 0.1 and balance_map[sender_key] > 21000 * 4 * tx_n:
                value = int(balance_map[sender_key] * 0.5)
                receiver_sk, _ = ec_random_keys()
                nonce_map[receiver_sk] = 0
                balance_map[receiver_sk] = value
            else:
                value = 1
                receiver_sk = random.choice(list(balance_map))
                balance_map[receiver_sk] += value
            # not enough transaction fee (gas_price * gas_limit) should not happen for now
            assert balance_map[sender_key] >= value + gas_price * 21000
            tx = create_transaction(pri_key=sender_key, receiver=priv_to_addr(receiver_sk), value=value, nonce=nonce,
                                    gas_price=gas_price)
            all_txs.append(tx)
            nonce_map[sender_key] = nonce + 1
            balance_map[sender_key] -= value + gas_price * 21000
        i = 0
        for tx in all_txs:
            i += 1
            if i % 1000 == 0:
                self.log.info("Sent %d tx", i)
            self.node.send_protocol_msg(Transactions(transactions=[tx]))
        for k in balance_map:
            wait_until(lambda: self.check_account(k, balance_map))
        block_gen_thread.stop()
        block_gen_thread.join()
        self.log.info("Pass")
        while True:
            pass
    def run_test(self):
        sponsor_whitelist_contract_addr = Web3.toChecksumAddress(
            "0888000000000000000000000000000000000001")
        collateral_per_storage_key = 10**18 // 16
        upper_bound = 5 * 10**7

        file_dir = os.path.dirname(os.path.realpath(__file__))

        control_contract_file_path = os.path.dirname(
            os.path.realpath(__file__)).split("/")
        control_contract_file_path.pop(-1)
        control_contract_file_path.extend(
            ["internal_contract", "metadata", "SponsorWhitelistControl.json"])
        control_contract_file_path = "/".join(control_contract_file_path)
        control_contract_dict = json.loads(
            open(os.path.join(control_contract_file_path), "r").read())

        control_contract = get_contract_instance(
            contract_dict=control_contract_dict)

        test_contract = get_contract_instance(
            abi_file=os.path.join(
                file_dir, "contracts/commission_privilege_test_abi.json"),
            bytecode_file=os.path.join(
                file_dir, "contracts/commission_privilege_test_bytecode.dat"),
        )

        start_p2p_connection(self.nodes)

        self.log.info("Initializing contract")
        genesis_key = self.genesis_priv_key
        genesis_addr = encode_hex(self.genesis_addr)
        self.log.info("genesis_addr={}".format(genesis_addr))
        nonce = 0
        gas_price = 1
        gas = CONTRACT_DEFAULT_GAS
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()
        self.tx_conf = {
            "from": Web3.toChecksumAddress(genesis_addr),
            "nonce": int_to_hex(nonce),
            "gas": int_to_hex(gas),
            "gasPrice": int_to_hex(gas_price),
            "chainId": 0
        }

        # Setup balance for node 0
        node = self.nodes[0]
        client = RpcClient(node)
        (addr1, priv_key1) = client.rand_account()
        self.log.info("addr1={}".format(addr1))
        tx = client.new_tx(sender=genesis_addr,
                           priv_key=genesis_key,
                           value=10**6,
                           nonce=self.get_nonce(self.genesis_addr),
                           receiver=addr1)
        client.send_tx(tx, True)
        assert_equal(client.get_balance(addr1), 10**6)

        # setup contract
        transaction = self.call_contract_function(
            contract=test_contract,
            name="constructor",
            args=[],
            sender_key=self.genesis_priv_key,
            storage_limit=20000)
        contract_addr = self.wait_for_tx([transaction],
                                         True)[0]['contractCreated']
        self.log.info("contract_addr={}".format(contract_addr))
        assert_equal(client.get_balance(contract_addr), 0)

        # sponsor the contract succeed
        b0 = client.get_balance(genesis_addr)
        self.call_contract_function(
            contract=control_contract,
            name="set_sponsor_for_gas",
            args=[Web3.toChecksumAddress(contract_addr), upper_bound],
            value=10**18,
            sender_key=self.genesis_priv_key,
            contract_addr=sponsor_whitelist_contract_addr,
            wait=True)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr), 10**18)
        assert_equal(client.get_sponsor_for_gas(contract_addr), genesis_addr)
        assert_equal(client.get_sponsor_gas_bound(contract_addr), upper_bound)
        assert_equal(client.get_balance(genesis_addr),
                     b0 - 10**18 - charged_of_huge_gas(gas))

        # set privilege for addr1
        b0 = client.get_balance(genesis_addr)
        c0 = client.get_collateral_for_storage(genesis_addr)
        self.call_contract_function(contract=test_contract,
                                    name="add",
                                    args=[Web3.toChecksumAddress(addr1)],
                                    sender_key=genesis_key,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True,
                                    storage_limit=64)
        assert_equal(
            client.get_balance(genesis_addr),
            b0 - charged_of_huge_gas(gas) - collateral_per_storage_key)
        assert_equal(client.get_collateral_for_storage(genesis_addr),
                     c0 + collateral_per_storage_key)

        # addr1 call contract with privilege without enough cfx for gas fee
        sb = client.get_sponsor_balance_for_gas(contract_addr)
        b1 = client.get_balance(addr1)
        self.call_contract_function(contract=test_contract,
                                    name="foo",
                                    args=[],
                                    sender_key=priv_key1,
                                    contract_addr=contract_addr,
                                    wait=True,
                                    check_status=True)
        assert_equal(client.get_balance(addr1), 10**6)
        assert_equal(client.get_sponsor_balance_for_gas(contract_addr),
                     sb - charged_of_huge_gas(gas))

        self.log.info("Pass")
    def run_test(self):
        start_p2p_connection(self.nodes)
        block_gen_thread = BlockGenThread(self.nodes, self.log)
        block_gen_thread.start()

        file_dir = os.path.dirname(os.path.realpath(__file__))

        self.log.info("Initializing contract")

        self.buggy_contract = get_contract_instance(source=os.path.join(
            file_dir, "contracts/reentrancy.sol"),
                                                    contract_name="Reentrance")
        self.exploit_contract = get_contract_instance(
            source=os.path.join(file_dir, "contracts/reentrancy_exploit.sol"),
            contract_name="ReentranceExploit")

        user1, _ = ec_random_keys()
        user1_addr = priv_to_addr(user1)
        user2, _ = ec_random_keys()
        user2_addr = priv_to_addr(user2)

        # setup balance
        value = (10**15 + 2000) * 10**18 + ReentrancyTest.REQUEST_BASE['gas']
        tx = create_transaction(pri_key=self.genesis_priv_key,
                                receiver=user1_addr,
                                value=value,
                                nonce=self.get_nonce(self.genesis_addr),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        tx = create_transaction(pri_key=self.genesis_priv_key,
                                receiver=user2_addr,
                                value=value,
                                nonce=self.get_nonce(self.genesis_addr),
                                gas_price=ReentrancyTest.REQUEST_BASE['gas'])
        self.send_transaction(tx, True, False)

        addr = eth_utils.encode_hex(user1_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_equal(balance, value)
        addr = eth_utils.encode_hex(user2_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_equal(balance, value)

        transaction = self.call_contract_function(self.buggy_contract,
                                                  "constructor", [],
                                                  self.genesis_priv_key,
                                                  storage_limit=20000)
        contract_addr = self.wait_for_tx([transaction],
                                         True)[0]['contractCreated']

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "constructor", [],
                                                  user2,
                                                  storage_limit=200000)
        exploit_addr = self.wait_for_tx([transaction],
                                        True)[0]['contractCreated']

        transaction = self.call_contract_function(
            self.buggy_contract,
            "addBalance", [],
            user1,
            100000000000000000000000000000000,
            contract_addr,
            True,
            True,
            storage_limit=128)
        transaction = self.call_contract_function(
            self.exploit_contract,
            "deposit", [Web3.toChecksumAddress(contract_addr)],
            user2,
            100000000000000000000000000000000,
            exploit_addr,
            True,
            True,
            storage_limit=128)

        addr = eth_utils.encode_hex(user1_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_greater_than_or_equal(balance,
                                     899999999999999999999999950000000)
        addr = eth_utils.encode_hex(user2_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_greater_than_or_equal(balance,
                                     899999999999999999999999900000000)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(contract_addr))
        assert_equal(balance, 200000000000000000000000000000000)

        transaction = self.call_contract_function(self.exploit_contract,
                                                  "launch_attack", [],
                                                  user2,
                                                  0,
                                                  exploit_addr,
                                                  True,
                                                  True,
                                                  storage_limit=128)
        transaction = self.call_contract_function(self.exploit_contract,
                                                  "get_money", [],
                                                  user2,
                                                  0,
                                                  exploit_addr,
                                                  True,
                                                  True,
                                                  storage_limit=128)

        addr = eth_utils.encode_hex(user1_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_greater_than_or_equal(balance,
                                     899999999999999999999999950000000)
        addr = eth_utils.encode_hex(user2_addr)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(addr))
        assert_greater_than_or_equal(balance,
                                     1099999999999999999999999800000000)
        balance = parse_as_int(self.nodes[0].cfx_getBalance(contract_addr))
        assert_equal(balance, 0)

        block_gen_thread.stop()
        block_gen_thread.join()