Пример #1
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")
    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")
Пример #4
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!")
Пример #5
0
    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()
Пример #6
0
    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")
Пример #7
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")
    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()
    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
Пример #10
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")
Пример #11
0
    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()
Пример #12
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)
Пример #13
0
    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()
Пример #14
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)
Пример #15
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")
Пример #16
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")
Пример #17
0
    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()
    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")
Пример #19
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")