def generate_transactions(self, _): self.call_contract_function( self.contract, "transfer", [Web3.toChecksumAddress(priv_to_addr(self.accounts[0])), 1000], self.default_account_key, self.contract_address, True, True, storage_limit=512) self.call_contract_function( self.contract, "approve", [Web3.toChecksumAddress(priv_to_addr(self.accounts[1])), 500], self.accounts[0], self.contract_address, True, True, storage_limit=512) self.call_contract_function( self.contract, "transferFrom", [ Web3.toChecksumAddress(priv_to_addr(self.accounts[0])), Web3.toChecksumAddress(priv_to_addr(self.default_account_key)), 300 ], self.accounts[1], self.contract_address, True, True, storage_limit=512)
def __init__(self): super().__init__() self.nonce_map = {} self.genesis_priv_key = default_config['GENESIS_PRI_KEY'] self.genesis_addr = priv_to_addr(self.genesis_priv_key) self.eth_priv_key = EthTransactionTest.ETH_KEY self.eth_addr = priv_to_addr(self.eth_priv_key) self.eth_hex_addr = encode_hex_0x(self.eth_addr)
def run_test(self): block_number = 10 for i in range(1, block_number): chosen_peer = random.randint(0, self.num_nodes - 1) block_hash = self.nodes[chosen_peer].generate_empty_blocks(1) self.log.info("generate block %s", block_hash) wait_for_block_count(self.nodes[0], block_number, timeout=30) sync_blocks(self.nodes, timeout=30) self.log.info("generated blocks received by all") self.stop_node(0, kill=True) self.log.info("node 0 stopped") block_hash = self.nodes[-1].generate_empty_blocks(1) self.log.info("generate block %s", block_hash) wait_for_block_count(self.nodes[1], block_number + 1) sync_blocks(self.nodes[1:], timeout=30) self.log.info("blocks sync success among running nodes") self.start_node(0) sync_blocks(self.nodes, timeout=30) self.log.info("Pass 1") for i in range(1, self.num_nodes): self.stop_node(i) self.nodes[0].add_p2p_connection(P2PInterface()) network_thread_start() self.nodes[0].p2p.wait_for_status() client = RpcClient(self.nodes[0]) gas_price = 1 value = 1 receiver_sk, _ = ec_random_keys() sender_key = default_config["GENESIS_PRI_KEY"] tx = create_transaction(pri_key=sender_key, receiver=priv_to_addr(receiver_sk), value=value, nonce=0, gas_price=gas_price) self.nodes[0].p2p.send_protocol_msg(Transactions(transactions=[tx])) self.log.debug("New tx %s: %s send value %d to %s", 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:]) def check_packed(): client.generate_block(1) return checktx(self.nodes[0], tx.hash_hex()) wait_until(lambda: check_packed()) sender_addr = eth_utils.encode_hex(priv_to_addr(sender_key)) receiver_addr = eth_utils.encode_hex(priv_to_addr(receiver_sk)) sender_balance = default_config["TOTAL_COIN"] - value - gas_price * 21000 # Generate 2 * CACHE_INDEX_STRIDE to start evicting anticone cache self.nodes[0].generate_empty_blocks(2000) assert_equal(client.get_balance(sender_addr), sender_balance) assert_equal(client.get_balance(receiver_addr), value) time.sleep(1) self.stop_node(0) self.start_node(0) self.log.info("Wait for node 0 to recover from crash") wait_until(lambda: client.get_balance(sender_addr) == sender_balance) wait_until(lambda: client.get_balance(receiver_addr) == value) self.log.info("Pass 2")
def run_test(self): file_path = os.path.dirname(os.path.realpath(__file__)).split("/") file_path.pop(-1) file_path.extend(["internal_contract", "metadata", "Staking.json"]) file_path = "/".join(file_path) staking_contract_dict = json.loads(open(os.path.join(file_path), "r").read()) staking_contract = get_contract_instance(contract_dict=staking_contract_dict) staking_contract_addr = Web3.toChecksumAddress("843c409373ffd5c0bec1dddb7bec830856757b65") self.problem = "0x2bc79b7514884ab00da924607d71542cc4fed3beb8518e747726ae30ab6c7944" self.solution = "0xc4d2751c52311d0d7efe44e5c4195e058ad5ef4bb89b3e1761b24dc277b132c2" self.priv_key = default_config["GENESIS_PRI_KEY"] self.sender = encode_hex_0x(priv_to_addr(self.priv_key)) self.sender_checksum = Web3.toChecksumAddress(self.sender) self.pub = [] self.pri = [] self.rpc = RpcClient(self.nodes[0]) gas = CONTRACT_DEFAULT_GAS gas_price = 10 # lock token for genesis account self.tx_conf = {"from":self.sender, "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0} self.tx_conf['to'] = staking_contract_addr tx_data = decode_hex(staking_contract.functions.deposit(1000000 * 10 ** 18).buildTransaction(self.tx_conf)["data"]) tx = self.rpc.new_tx(value=0, receiver=staking_contract_addr, data=tx_data, gas=gas, gas_price=gas_price) self.rpc.send_tx(tx, True) for i in range(10): priv_key = random.randint(0, 2 ** 256).to_bytes(32, "big") pub_key = encode_hex_0x(priv_to_addr(priv_key)) self.pub.append(pub_key) self.pri.append(priv_key) transaction = self.rpc.new_tx(sender=self.sender, receiver=pub_key, value=1000000 * 10 ** 18, priv_key=self.priv_key) self.rpc.send_tx(transaction, True) # deposit 10000 tokens tx_data = decode_hex(staking_contract.functions.deposit(10000 * 10 ** 18).buildTransaction(self.tx_conf)["data"]) tx = self.rpc.new_tx(value=0, sender=pub_key, receiver=self.tx_conf["to"], gas=gas, data=tx_data, priv_key=priv_key) self.rpc.send_tx(tx) self.tx_conf = {"from":self.sender, "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0} self.filter = Filter(from_epoch="earliest", to_epoch="latest_state") self.testEventContract() self.tx_conf = {"from":self.sender, "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0} self.testBallotContract() self.tx_conf = {"from":self.sender, "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0} self.testPayContract() self.tx_conf = {"from":self.sender, "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0} self.testHTLCContract() self.tx_conf = {"from":self.sender, "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0} self.testDaiContract() self.tx_conf = {"from":self.sender, "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0} self.testMappingContract() self.tx_conf = {"from":self.sender, "gas":int_to_hex(gas), "gasPrice":int_to_hex(gas_price), "chainId":0} self.testDaiJoinContract() self.log.info("Pass")
def __init__(self): super().__init__() self.nonce_map = {} self.genesis_priv_key = default_config['GENESIS_PRI_KEY'] self.genesis_addr = priv_to_addr(self.genesis_priv_key) self.balance_map = {self.genesis_priv_key: default_config['TOTAL_COIN']}
def generate_transactions(self, i): self.call_contract_function( self.vote_contract, "createIssue", [ i, Web3.toChecksumAddress(self.token_address), [j for j in range(self.num_of_options)], [ Web3.toChecksumAddress(priv_to_addr(acc)) for acc in self.accounts ], "v" ], self.default_account_key, self.vote_address, True, True, storage_limit=64) for i in range(self.num_of_options): self.call_contract_function( self.vote_contract, "vote", [i, random.randint(0, self.num_of_options - 1)], self.default_account_key, self.vote_address, True, True, storage_limit=64)
def call_contract_function(self, contract, name, args, sender_key, contract_addr=None, wait=False, check_status=False, storage_limit=0): # If contract address is empty, call the constructor. if contract_addr: func = getattr(contract.functions, name) else: func = getattr(contract, name) attributes = { 'nonce': self.get_nonce(priv_to_addr(sender_key)), ** SmartContractBenchBase.REQUEST_BASE } if contract_addr: attributes['receiver'] = decode_hex(contract_addr) attributes['to'] = contract_addr else: attributes['receiver'] = b'' tx_data = func(*args).buildTransaction(attributes) tx_data['data'] = decode_hex(tx_data['data']) tx_data['pri_key'] = sender_key tx_data['gas_price'] = tx_data['gasPrice'] tx_data['storage_limit'] = storage_limit tx_data.pop('gasPrice', None) tx_data.pop('chainId', None) tx_data.pop('to', None) transaction = create_transaction(**tx_data) self._send_transaction(transaction, wait, check_status) return transaction
def new_address_and_transfer(self, count=1, amount=100000000000000, wait=False, check_status=False): results = [] for _ in range(count): pri_key, pub_key = ec_random_keys() transaction = self.transfer(self.default_account_key, priv_to_addr(pri_key), amount, wait, check_status) results.append([pri_key, transaction]) return results
def call_contract_function(self, contract, name, args, sender_key, value=None, contract_addr=None, wait=False, check_status=False): if contract_addr: func = getattr(contract.functions, name) else: func = getattr(contract, name) attrs = { 'nonce': self.get_nonce(priv_to_addr(sender_key)), **Issue988Test.REQUEST_BASE } if contract_addr: attrs['receiver'] = decode_hex(contract_addr) attrs['to'] = contract_addr else: attrs['receiver'] = b'' tx_data = func(*args).buildTransaction(attrs) tx_data['data'] = decode_hex(tx_data['data']) tx_data['pri_key'] = sender_key tx_data['gas_price'] = tx_data['gasPrice'] if value: tx_data['value'] = value tx_data.pop('gasPrice', None) tx_data.pop('chainId', None) tx_data.pop('to', None) transaction = create_transaction(**tx_data) self.send_transaction(transaction, wait, check_status) return transaction
def run_test(self): client = RpcClient(self.nodes[0]) genesis_address = "0x" + encode_hex( priv_to_addr(default_config['GENESIS_PRI_KEY'])) genesis_balance = default_config["TOTAL_COIN"] client.generate_empty_blocks(ERA_EPOCH_COUNT * 10) print(client.epoch_number("latest_checkpoint")) assert client.epoch_number("latest_checkpoint") > 0 # Just assert we can still get the balance assert_equal(client.get_balance(genesis_address, client.EPOCH_NUM(1)), genesis_balance)
def run_test(self): priv_key = default_config["GENESIS_PRI_KEY"] sender = eth_utils.encode_hex(priv_to_addr(priv_key)) # deploy contract bytecode_file = os.path.join( os.path.dirname(os.path.realpath(__file__)), CONTRACT_PATH) assert (os.path.isfile(bytecode_file)) bytecode = open(bytecode_file).read() _, contractAddr = self.deploy_contract(sender, priv_key, bytecode) self.log.info(f"contract deployed at address {contractAddr}") # emit events throughout a few eras num_events = 0 while self.rpc[ARCHIVE_NODE].epoch_number( ) < NUM_ERAS * ERA_EPOCH_COUNT: self.call_contract(sender, priv_key, contractAddr, encode_hex_0x(keccak(b"foo()"))) num_events += 1 self.log.info(f"num_events = {num_events}") self.log.info( f"epoch_number = {self.rpc[ARCHIVE_NODE].epoch_number()}") # sync blocks and wait for gc sync_blocks(self.nodes) time.sleep(1) latest_checkpoint = self.rpc[FULL_NODE].epoch_number( "latest_checkpoint") assert_greater_than(latest_checkpoint, 0) # filtering the whole epoch range should fail on full nodes filter = Filter(from_epoch="earliest", to_epoch="latest_state", topics=[CALLED_TOPIC]) logs_archive = self.rpc[ARCHIVE_NODE].get_logs(filter) assert_equal(len(logs_archive), num_events) assert_raises_rpc_error(None, None, self.rpc[FULL_NODE].get_logs, filter) # filtering since the latest checkpoint should yield the same result filter = Filter(from_epoch="latest_checkpoint", to_epoch="latest_state", topics=[CALLED_TOPIC]) logs_archive = self.rpc[ARCHIVE_NODE].get_logs(filter) assert_greater_than(len(logs_archive), 0) logs_full = self.rpc[FULL_NODE].get_logs(filter) assert_equal(logs_archive, logs_full) self.log.info("Pass")
def check_account(self, k, balance_map): addr = eth_utils.encode_hex(priv_to_addr(k)) try: balance = self.rpc_client.get_balance(addr) except Exception as e: self.log.info("Fail to get balance, error=%s", str(e)) return False if balance == balance_map[k]: return True else: self.log.info("Remote balance:%d, local balance:%d", balance, balance_map[k]) time.sleep(1) return False
def check_account(self, k, balance_map, node): addr = eth_utils.encode_hex(priv_to_addr(k)) try: balance = parse_as_int(node.cfx_getBalance(addr)) except Exception as e: self.log.debug("Fail to get balance, error=%s", str(e)) return False if balance == balance_map[k]: return True else: self.log.info("Remote balance:%d, local balance:%d", balance, balance_map[k]) time.sleep(1) return False
def run_test(self): priv_key = default_config["GENESIS_PRI_KEY"] sender = eth_utils.encode_hex(priv_to_addr(priv_key)) # deploy storage test contract bytecode_file = os.path.join( os.path.dirname(os.path.realpath(__file__)), CONTRACT_PATH) assert (os.path.isfile(bytecode_file)) bytecode = open(bytecode_file).read() _, contractAddr = self.deploy_contract(sender, priv_key, bytecode) # call contract throughout a few eras self.call_contract(sender, priv_key, contractAddr, encode_hex_0x(keccak(b"increment()"))) self.rpc[FULLNODE0].generate_blocks(SNAPSHOT_EPOCH_COUNT) self.call_contract(sender, priv_key, contractAddr, encode_hex_0x(keccak(b"increment()"))) self.rpc[FULLNODE0].generate_blocks(SNAPSHOT_EPOCH_COUNT) self.call_contract(sender, priv_key, contractAddr, encode_hex_0x(keccak(b"destroy()"))) self.rpc[FULLNODE0].generate_blocks(SNAPSHOT_EPOCH_COUNT) # check storage root of non-existent contract root_full = self.rpc[FULLNODE0].get_storage_root( "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", epoch=hex(1)) root_light = self.rpc[LIGHTNODE].get_storage_root( "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", epoch=hex(1)) assert_equal(root_full, root_light) # make sure the storage roots are verifiable on the light node latest_epoch = self.rpc[FULLNODE0].epoch_number() self.rpc[FULLNODE0].generate_blocks(SNAPSHOT_EPOCH_COUNT) sync_blocks(self.nodes) # check storage roots first_available_epoch = (latest_epoch - 1) // SNAPSHOT_EPOCH_COUNT \ * SNAPSHOT_EPOCH_COUNT - SNAPSHOT_EPOCH_COUNT * 2 + 1 # After latest_epoch is obtained the test generated SNAPSHOT_EPOCH_COUNT more blocks. first_available_epoch += SNAPSHOT_EPOCH_COUNT # The proof is only available since the second available snapshot. first_available_epoch += SNAPSHOT_EPOCH_COUNT for epoch in range(first_available_epoch, latest_epoch): root_full = self.rpc[FULLNODE0].get_storage_root(contractAddr, epoch=hex(epoch)) root_light = self.rpc[LIGHTNODE].get_storage_root(contractAddr, epoch=hex(epoch)) assert_equal(root_full, root_light) self.log.info(f"Pass (epoch {epoch})") self.log.info("Pass")
def check_account(self, k, balance_map): addr = eth_utils.encode_hex(priv_to_addr(k)) try: balance = parse_as_int(self.nodes[0].cfx_getBalance(addr)) staking_balance = parse_as_int(self.nodes[0].cfx_getStakingBalance(addr)) collateral_for_storage = parse_as_int(self.nodes[0].cfx_getCollateralForStorage(addr)) except Exception as e: self.log.info("Fail to get balance, error=%s", str(e)) return False if balance + staking_balance + collateral_for_storage == balance_map[k]: return True else: self.log.info("Remote balance:%d, local balance:%d", balance + staking_balance + collateral_for_storage, balance_map[k]) time.sleep(1) return False
def check_account(self, k, balance_map): addr = eth_utils.encode_hex(priv_to_addr(k)) client = RpcClient(self.nodes[0]) try: balance = client.get_balance(addr) staking_balance = client.get_staking_balance(addr) collateral_for_storage = client.get_collateral_for_storage(addr) except Exception as e: self.log.info("Fail to get balance, error=%s", str(e)) return False if balance + staking_balance + collateral_for_storage == balance_map[ k]: return True else: self.log.info("Remote balance:%d, local balance:%d", balance + staking_balance + collateral_for_storage, balance_map[k]) time.sleep(1) return False
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 __init__(self): super().__init__() self.nonce_map = {} self.default_account_key = default_config["GENESIS_PRI_KEY"] self.default_account_address = priv_to_addr(self.default_account_key)
def transfer(self, sender_key, receiver, amount, wait=False, check_status=False): nonce = self.get_nonce(priv_to_addr(sender_key)) transaction = create_transaction(nonce, 1, 21000, amount, receiver, pri_key=sender_key) self._send_transaction(transaction, wait, check_status) return transaction
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} block_gen_thread = BlockGenThread(self.nodes, self.log, interval_base=0.2) block_gen_thread.start() '''Check if transaction from uncommitted new address can be accepted''' tx_n = 5 new_keys = set() gas_price = 1 for i in range(tx_n): sender_key = genesis_key receiver_sk, _ = ec_random_keys() new_keys.add(receiver_sk) value = int((balance_map[sender_key] - ((tx_n - i) * 21000 * gas_price)) * random.random()) balance_map[receiver_sk] = value nonce = nonce_map[sender_key] receiver_addr = priv_to_addr(receiver_sk) tx = create_transaction(pri_key=sender_key, receiver=receiver_addr, value=value, nonce=nonce, gas_price=gas_price) r = random.randint(0, self.num_nodes - 1) r = 0 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(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) 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)) self.log.info("Pass 1") '''Test Random Transactions''' wait_for_account_stable() for key in new_keys: nonce_map[key] = wait_for_initial_nonce_for_privkey(self.nodes[0], key) 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 storage_limit = 0 if 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 = CONTRACT_DEFAULT_GAS is_payment = False storage_limit = 200000 else: value = 1 receiver_sk = random.choice(list(balance_map)) receiver = priv_to_addr(receiver_sk) balance_map[receiver_sk] += value is_payment = True # 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, storage_limit=storage_limit) r = random.randint(0, self.num_nodes - 1) r = 0 self.nodes[r].p2p.send_protocol_msg(Transactions(transactions=[tx])) all_txs.append(tx) nonce_map[sender_key] = nonce + 1 if is_payment: balance_map[sender_key] -= value + gas_price * gas else: balance_map[sender_key] -= value + gas_price * charged_of_huge_gas(gas) 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(priv_to_addr(k))) wait_until(lambda: self.check_account(k, balance_map)) block_gen_thread.stop() block_gen_thread.join() sync_blocks(self.nodes) self.log.info("Pass")
def run_test(self): start_p2p_connection(self.nodes) block_gen_thread = BlockGenThread(self.nodes, self.log, interval_base=0.2) block_gen_thread.start() genesis_key = default_config["GENESIS_PRI_KEY"] tx_n = 100 gas_price = 1 shard_balance = [] for s in range(self.n_shard): ''' Send random transactions to this shard s ''' shard_nodes = self.nodes[s * self.shard_size:(s + 1) * self.shard_size] # We can not use genesis accounts in two shards, because they may generate transactions # that are valid in another shard and breaks our assertion about the final shard state. start_sk, _ = ec_random_keys() value = default_config["TOTAL_COIN"] - 21000 tx = create_transaction(pri_key=genesis_key, receiver=priv_to_addr(start_sk), value=value, nonce=0, gas_price=gas_price) shard_nodes[0].p2p.send_protocol_msg( Transactions(transactions=[tx])) balance_map = {start_sk: value} nonce_map = { start_sk: wait_for_initial_nonce_for_privkey(shard_nodes[0], start_sk) } account_n = 10 # Initialize new accounts new_keys = set() for _ in range(account_n): value = max(int(balance_map[start_sk] * random.random()), 21000 * tx_n) receiver_sk, _ = ec_random_keys() new_keys.add(receiver_sk) tx = create_transaction(pri_key=start_sk, receiver=priv_to_addr(receiver_sk), value=value, nonce=nonce_map[start_sk], gas_price=gas_price) shard_nodes[0].p2p.send_protocol_msg( Transactions(transactions=[tx])) balance_map[receiver_sk] = value nonce_map[start_sk] += 1 balance_map[start_sk] -= value + gas_price * 21000 wait_for_account_stable() for key in new_keys: nonce_map[key] = wait_for_initial_nonce_for_privkey( shard_nodes[0], key) for i in range(tx_n): sender_key = random.choice(list(balance_map)) nonce = nonce_map[sender_key] value = 0 receiver_sk = random.choice(list(balance_map)) balance_map[receiver_sk] += value tx = create_transaction(pri_key=sender_key, receiver=priv_to_addr(receiver_sk), value=value, nonce=nonce, gas_price=gas_price) r = random.randint(0, self.shard_size - 1) shard_nodes[r].p2p.send_protocol_msg( Transactions(transactions=[tx])) nonce_map[sender_key] = nonce + 1 balance_map[sender_key] -= value + gas_price * 21000 self.log.info( "New tx %s: %s send value %d to %s, sender balance:%d, receiver balance:%d", encode_hex(tx.hash), eth_utils.encode_hex(priv_to_addr(sender_key))[-4:], value, eth_utils.encode_hex(priv_to_addr(receiver_sk))[-4:], balance_map[sender_key], balance_map[receiver_sk]) self.log.debug("Send Transaction %s to node %d", encode_hex(tx.hash), r) time.sleep(random.random() / 10) for k in balance_map: self.log.info("Check account sk:%s addr:%s", bytes_to_int(k), eth_utils.encode_hex(priv_to_addr(k))) wait_until( lambda: self.check_account(k, balance_map, shard_nodes[0])) shard_balance.append(balance_map) def epochCheck(node): r = node.cfx_epochNumber() return int(r, 0) > 110 wait_until(lambda: epochCheck(self.nodes[0])) wait_until( lambda: epochCheck(self.nodes[int(self.num_nodes / self.n_shard)])) for s in range(self.n_shard): for idx in range(self.shard_size): connect_nodes(self.nodes, s * self.shard_size - 1 + idx, s * self.shard_size + idx) block_gen_thread.stop() block_gen_thread.join() sync_blocks(self.nodes) ''' Check if the balance state of every node matches ''' success_shard = -1 # use the state of node 0 to find the winning shard for s in range(self.n_shard): balance_map = shard_balance[s] unmatch = False for k in balance_map: if not self.check_account(k, balance_map, self.nodes[0]): unmatch = True self.log.info( "Final balance does not match shard %s, check next", s) break if unmatch: continue success_shard = s break assert success_shard != -1, "The final state of node 0 matches no shard state" self.log.info("Shard %s succeeds", success_shard) for i in range(1, self.num_nodes): balance_map = shard_balance[success_shard] for k in balance_map: if not self.check_account(k, balance_map, self.nodes[i]): raise AssertionError( "Final balance of node {} does not match node 0, sender={}" .format(i, k)) self.log.info("Pass")
def run_test(self): 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")
def run_test(self): priv_key = default_config["GENESIS_PRI_KEY"] sender = eth_utils.encode_hex(priv_to_addr(priv_key)) self.rpc = RpcClient(self.nodes[0]) # apply filter, we expect no logs filter = Filter() result = self.rpc.get_logs(filter) assert_equal(result, []) # deploy contract bytecode_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), CONTRACT_PATH) assert(os.path.isfile(bytecode_file)) bytecode = open(bytecode_file).read() _, contractAddr = self.deploy_contract(sender, priv_key, bytecode) # apply filter, we expect a single log with 2 topics filter = Filter(from_epoch="earliest", to_epoch="latest_state") logs0 = self.rpc.get_logs(filter) self.assert_response_format_correct(logs0) assert_equal(len(logs0), 1) assert_equal(len(logs0[0]["topics"]), 2) assert_equal(logs0[0]["topics"][0], CONSTRUCTED_TOPIC) assert_equal(logs0[0]["topics"][1], self.address_to_topic(sender)) assert_equal(logs0[0]["data"], self.address_to_topic(sender)) # call method receipt = self.call_contract(sender, priv_key, contractAddr, encode_hex_0x(keccak(b"foo()")), storage_limit=64) # apply filter, we expect two logs with 2 and 3 topics respectively filter = Filter(from_epoch="earliest", to_epoch="latest_state") logs1 = self.rpc.get_logs(filter) self.assert_response_format_correct(logs1) assert_equal(len(logs1), 2) assert_equal(logs1[0], logs0[0]) assert_equal(len(logs1[1]["topics"]), 3) assert_equal(logs1[1]["topics"][0], FOO_TOPIC) assert_equal(logs1[1]["topics"][1], self.address_to_topic(sender)) assert_equal(logs1[1]["topics"][2], self.number_to_topic(1)) # apply filter for specific block, we expect a single log with 3 topics filter = Filter(block_hashes=[receipt["blockHash"]]) logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), 1) assert_equal(logs[0], logs1[1]) # call many times for ii in range(2, NUM_CALLS): self.call_contract(sender, priv_key, contractAddr, encode_hex_0x(keccak(b"foo()")), storage_limit=0) # apply filter, we expect NUM_CALLS log entries with increasing uint32 fields filter = Filter(from_epoch="earliest", to_epoch="latest_state") logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), NUM_CALLS) for ii in range(2, NUM_CALLS): assert_equal(len(logs[ii]["topics"]), 3) assert_equal(logs[ii]["topics"][0], FOO_TOPIC) assert(logs[ii]["topics"][1] == self.address_to_topic(sender)) assert_equal(logs[ii]["topics"][2], self.number_to_topic(ii)) # apply filter for specific topics filter = Filter(topics=[CONSTRUCTED_TOPIC]) logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), 1) filter = Filter(topics=[FOO_TOPIC]) logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), NUM_CALLS - 1) filter = Filter(topics=[None, self.address_to_topic(sender)]) logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), NUM_CALLS) # find logs with `FOO_TOPIC` as 1st topic and `3` or `4` as 3rd topic filter = Filter(topics=[FOO_TOPIC, None, [self.number_to_topic(3), self.number_to_topic(4)]]) logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), 2) # apply filter with limit filter = Filter(limit=hex(NUM_CALLS // 2)) logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), NUM_CALLS // 2) # apply filter with offset filter = Filter(offset=hex(NUM_CALLS // 4)) logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), 3 * NUM_CALLS // 4) # apply filter for specific contract address _, contractAddr2 = self.deploy_contract(sender, priv_key, bytecode) filter = Filter(address=[contractAddr]) logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), NUM_CALLS) filter = Filter(address=[contractAddr2]) logs = self.rpc.get_logs(filter) self.assert_response_format_correct(logs) assert_equal(len(logs), 1) # apply filter to very first epoch, we expect no logs filter = Filter(from_epoch="earliest", to_epoch="earliest") result = self.rpc.get_logs(filter) assert_equal(result, []) # generate two blocks with `NUM_CALLS` transactions in each; # transactions will generate 2 logs each parent_hash = self.rpc.block_by_epoch("latest_mined")['hash'] start_nonce = self.rpc.get_nonce(sender) txs1 = [self.rpc.new_contract_tx(receiver=contractAddr, data_hex=encode_hex_0x(keccak(b"bar()")), sender=sender, priv_key=priv_key, storage_limit=64, nonce = start_nonce + ii) for ii in range(0, NUM_CALLS)] block_hash_1 = self.rpc.generate_custom_block(parent_hash = parent_hash, referee = [], txs = txs1) epoch_1 = self.rpc.block_by_hash(block_hash_1)["epochNumber"] txs2 = [self.rpc.new_contract_tx(receiver=contractAddr, data_hex=encode_hex_0x(keccak(b"bar()")), sender=sender, priv_key=priv_key, storage_limit=64, nonce = start_nonce + NUM_CALLS + ii) for ii in range(0, NUM_CALLS)] block_hash_2 = self.rpc.generate_custom_block(parent_hash = block_hash_1, referee = [], txs = txs2) epoch_2 = self.rpc.block_by_hash(block_hash_2)["epochNumber"] txs = txs1 txs.extend(txs2) # blocks not executed yet, filtering should fail # filter = Filter(block_hashes=[block_hash_1, block_hash_2], topics=[BAR_TOPIC]) # assert_raises_rpc_error(None, None, self.rpc.get_logs, filter) # generate some more blocks to ensure our two blocks are executed self.rpc.generate_blocks(10) # filtering for these two blocks should return logs in correct order filter = Filter(block_hashes=[block_hash_1, block_hash_2], topics=[BAR_TOPIC]) logs = self.rpc.get_logs(filter) assert_equal(len(logs), 4 * NUM_CALLS) log_index = 0 transaction_index = 0 transaction_log_index = 0 for ii in range(0, 4 * NUM_CALLS): assert_equal(logs[ii]["address"], contractAddr) assert_equal(logs[ii]["blockHash"], block_hash_1 if ii < 2 * NUM_CALLS else block_hash_2) assert_equal(logs[ii]["epochNumber"], epoch_1 if ii < 2 * NUM_CALLS else epoch_2) assert_equal(logs[ii]["transactionHash"], txs[ii // 2].hash_hex()) assert_equal(len(logs[ii]["topics"]), 3) assert_equal(logs[ii]["topics"][0], BAR_TOPIC) assert_equal(logs[ii]["topics"][1], self.address_to_topic(sender)) assert_equal(logs[ii]["topics"][2], self.number_to_topic(ii)) # logIndex: # 0, 1, 2, 3, 4, 6, 7, 8, ..., 2 * NUM_CALLS, 0, 1, 2, ... assert_equal(logs[ii]["logIndex"], hex(log_index % (2 * NUM_CALLS))) log_index += 1 # transactionIndex: # 0, 0, 1, 1, 2, 2, 3, 3, ..., NUM_CALLS, 0, 0, 1, 1, ... assert_equal(logs[ii]["transactionIndex"], hex((transaction_index // 2) % NUM_CALLS)) transaction_index += 1 # transactionLogIndex: # 0, 1, 0, 1, 0, 1, 0, 1, ... assert_equal(logs[ii]["transactionLogIndex"], hex(transaction_log_index % 2)) transaction_log_index += 1 # block hash order should not affect log order filter = Filter(block_hashes=[block_hash_2, block_hash_1], topics=[BAR_TOPIC]) logs2 = self.rpc.get_logs(filter) assert_equal(logs, logs2) # given a limit, we should receive the _last_ few logs filter = Filter(block_hashes=[block_hash_1, block_hash_2], limit = hex(3 * NUM_CALLS + NUM_CALLS // 2), topics=[BAR_TOPIC]) logs = self.rpc.get_logs(filter) assert_equal(len(logs), 3 * NUM_CALLS + NUM_CALLS // 2) for ii in range(0, 3 * NUM_CALLS + NUM_CALLS // 2): assert_equal(len(logs[ii]["topics"]), 3) assert_equal(logs[ii]["topics"][0], BAR_TOPIC) assert_equal(logs[ii]["topics"][1], self.address_to_topic(sender)) assert_equal(logs[ii]["topics"][2], self.number_to_topic(NUM_CALLS // 2 + ii)) # given an offset and a limit, we should receive the corresponding logs filter = Filter(block_hashes=[block_hash_1, block_hash_2], offset = hex(NUM_CALLS // 2), limit = hex(NUM_CALLS // 2), topics=[BAR_TOPIC]) logs = self.rpc.get_logs(filter) assert_equal(len(logs), NUM_CALLS // 2) for ii in range(0, NUM_CALLS // 2): assert_equal(len(logs[ii]["topics"]), 3) assert_equal(logs[ii]["topics"][0], BAR_TOPIC) assert_equal(logs[ii]["topics"][1], self.address_to_topic(sender)) assert_equal(logs[ii]["topics"][2], self.number_to_topic(3 * NUM_CALLS + ii)) filter = Filter(from_epoch = epoch_1, to_epoch = epoch_2, offset = hex(NUM_CALLS // 2), limit = hex(NUM_CALLS // 2), topics=[BAR_TOPIC]) logs2 = self.rpc.get_logs(filter) assert_equal(logs, logs2) # test paging use case BATCH_SIZE = 7 filter = Filter(block_hashes=[block_hash_1, block_hash_2], topics=[BAR_TOPIC]) all_logs = self.rpc.get_logs(filter) collected_logs = [] offset = 0 while True: filter = Filter(block_hashes=[block_hash_1, block_hash_2], offset = hex(offset), limit = hex(BATCH_SIZE), topics=[BAR_TOPIC]) logs = self.rpc.get_logs(filter) if len(logs) == 0: break collected_logs = logs + collected_logs offset += BATCH_SIZE assert_equal(collected_logs, all_logs) # get-logs-filter-max-epoch-range should limit the number of epochs queried. self.stop_node(0) self.start_node(0, ["--get-logs-filter-max-epoch-range", "16"]) filter = Filter(from_epoch="0x0", to_epoch="0x0f", topics=[BAR_TOPIC]) # should not raise error self.rpc.get_logs(filter) filter = Filter(from_epoch="0x0", to_epoch="0x10", topics=[BAR_TOPIC]) assert_raises_rpc_error(None, None, self.rpc.get_logs, filter) self.log.info("Pass")
def run_test(self): self.rpc = RpcClient(self.nodes[0]) priv_key = default_config["GENESIS_PRI_KEY"] sender = eth_utils.encode_hex(priv_to_addr(priv_key)) block_reward = 7000000000000000000 # deploy storage test contract bytecode_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), CONTRACT_PATH) assert (os.path.isfile(bytecode_file)) bytecode = open(bytecode_file).read() # 1. Produce an empty block self.rpc.generate_block() # 2. Deploy a contract: this will create 6 blocks and the first block contains 'create contract' transaction, # the other 5 blocks are empty. receipt, _ = self.deploy_contract(sender, priv_key, bytecode) # 3. Produce 10 empty blocks, and the miner's reward for the first block will be updated to world-state for _ in range(10): self.rpc.generate_block() balance = parse_as_int(self.nodes[0].cfx_getBalance(self.mining_author)) count = self.nodes[0].getblockcount() expected = block_reward self.log.info("block count: %d, balance: %d, expected: %d", count, balance, expected) assert_equal(balance, expected) # 4. Produce 1 empty block, and the miner will receive reward for the second block. This block reward should # contains transaction fee. self.rpc.generate_blocks(1) balance = parse_as_int(self.nodes[0].cfx_getBalance(self.mining_author)) count = self.nodes[0].getblockcount() transaction_fee = parse_as_int(receipt['gasFee']) expected += block_reward + transaction_fee self.log.info("block count: %d, balance: %d, expected: %d, transaction_fee: %d", count, balance, expected, transaction_fee) assert_equal(balance, expected) # 5. Produce 1 empty block, and the miner will receive reward for the third empty block. This block reward # should contains storage maintenance fee. self.rpc.generate_blocks(1) balance = parse_as_int(self.nodes[0].cfx_getBalance(self.mining_author)) count = self.nodes[0].getblockcount() collateral_for_storage = self.rpc.get_collateral_for_storage(sender) storage_fee = collateral_for_storage * 4 // 100 // 63072000 expected += block_reward + storage_fee self.log.info("block count: %d, balance: %d, expected: %d, collateral_for_storage: %d, storage_fee: %d", count, balance, expected, collateral_for_storage, storage_fee) assert_equal(balance, expected) # 6. Produce 1 empty block, and the miner will receive reward for the forth empty block. This block reward # should contains storage maintenance fee. self.rpc.generate_blocks(1) balance = parse_as_int(self.nodes[0].cfx_getBalance(self.mining_author)) count = self.nodes[0].getblockcount() collateral_for_storage = self.rpc.get_collateral_for_storage(sender) storage_fee = collateral_for_storage * 4 // 100 // 63072000 expected += storage_fee + block_reward self.log.info("block count: %d, balance: %d, expected: %d, collateral_for_storage: %d, storage_fee: %d", count, balance, expected, collateral_for_storage, storage_fee) assert_equal(balance, expected)
def run_test(self): priv_key = default_config["GENESIS_PRI_KEY"] sender = eth_utils.encode_hex(priv_to_addr(priv_key)) # check storage root of non-existent contract root = self.rpc[FULLNODE0].get_storage_root( "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6") assert_equal(root["delta"], None) assert_equal(root["delta"], None) assert_equal(root["delta"], None) # deploy storage test contract bytecode_file = os.path.join( os.path.dirname(os.path.realpath(__file__)), CONTRACT_PATH) assert (os.path.isfile(bytecode_file)) bytecode = open(bytecode_file).read() _, contractAddr = self.deploy_contract(sender, priv_key, bytecode) # get storage root; expect: (D0, I0, S0) = (?, NULL, NULL) root0 = self.rpc[FULLNODE0].get_storage_root(contractAddr) assert_is_hash_string(root0["delta"]) assert_equal(root0["intermediate"], None) assert_equal(root0["snapshot"], None) # update storage; expect: (D1, I1, S1) == (?, I0, S0) # NOTE: call_contract will generate some blocks but it should be < SNAPSHOT_EPOCH_COUNT self.call_contract(sender, priv_key, contractAddr, encode_hex_0x(keccak(b"increment()"))) root1 = self.rpc[FULLNODE0].get_storage_root(contractAddr) assert_is_hash_string(root1["delta"]) assert_ne(root1["delta"], root0["delta"]) assert_equal(root1["intermediate"], None) assert_equal(root1["snapshot"], None) # go to next era self.rpc[FULLNODE0].generate_blocks(SNAPSHOT_EPOCH_COUNT) # get storage root; expect: (D2, I2, S2) == (NULL, D1, NULL) # (the previous delta trie became the current intermediate trie) root2 = self.rpc[FULLNODE0].get_storage_root(contractAddr) assert_equal(root2["delta"], None) assert_equal(root2["intermediate"], root1["delta"]) assert_equal(root2["snapshot"], None) # update storage; expect: (D3, I3, S3) == (?, I2, S2) # NOTE: call_contract will generate some blocks but it should be < SNAPSHOT_EPOCH_COUNT self.call_contract(sender, priv_key, contractAddr, encode_hex_0x(keccak(b"increment()"))) root3 = self.rpc[FULLNODE0].get_storage_root(contractAddr) assert_is_hash_string(root3["delta"]) assert_ne(root3["delta"], root2["delta"]) assert_equal(root3["intermediate"], root2["intermediate"]) assert_equal(root3["snapshot"], root2["snapshot"]) # go to next era self.rpc[FULLNODE0].generate_blocks(SNAPSHOT_EPOCH_COUNT) # get storage root; expect: (D4, I4, S4) == (NULL, D3, ?) # (the previous delta trie became the current intermediate trie) # (note that storage root in the snapshot will not match due to differences in padding) root4 = self.rpc[FULLNODE0].get_storage_root(contractAddr) assert_equal(root4["delta"], None) assert_equal(root4["intermediate"], root3["delta"]) assert_is_hash_string(root4["snapshot"]) # check if other node's storage root matches sync_blocks(self.nodes[:]) root = self.rpc[FULLNODE1].get_storage_root(contractAddr) assert (root == root4) # destroy account # NOTE: call_contract will generate some blocks but it should be < SNAPSHOT_EPOCH_COUNTs self.call_contract(sender, priv_key, contractAddr, encode_hex_0x(keccak(b"destroy()"))) root5 = self.rpc[FULLNODE0].get_storage_root(contractAddr) assert_equal(root5["delta"], "TOMBSTONE") assert_equal(root5["intermediate"], root4["intermediate"]) assert_equal(root5["snapshot"], root4["snapshot"]) self.log.info("Pass")
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")
for sender in all_senders: try: print("Check {} with addr {}".format(sender.client.node.url, sender.addr)) sender.wait_for_balance() senders.append(sender) except Exception as e: print(sender.client.node.url, "is not available for Exception", e) break # start threads to send txs to different nodes print("begin to send txs ...") workers = [] for s in senders: t = TpsWorker(s, num_receivers) workers.append(t) t.start() for w in workers: w.join() # main if len(sys.argv) == 1: print("faucet private key not specified.") sys.exit(1) faucet_priv_key = sys.argv[1] faucet_addr = eth_utils.encode_hex(priv_to_addr(faucet_priv_key)) bootnodes = load_boot_nodes() num_threads = 1 if len(sys.argv) < 3 else int(sys.argv[2]) num_receivers = 20 if len(sys.argv) < 4 else int(sys.argv[3]) work(faucet_addr, faucet_priv_key, bootnodes, num_threads, num_receivers)
def run_test(self): start_p2p_connection(self.nodes) block_gen_thread = BlockGenThread(self.nodes, self.log) block_gen_thread.start() file_dir = os.path.dirname(os.path.realpath(__file__)) self.log.info("Initializing contract") self.buggy_contract = get_contract_instance(source=os.path.join( file_dir, "contracts/reentrancy.sol"), contract_name="Reentrance") self.exploit_contract = get_contract_instance( source=os.path.join(file_dir, "contracts/reentrancy_exploit.sol"), contract_name="ReentranceExploit") user1, _ = ec_random_keys() user1_addr = priv_to_addr(user1) user1_addr_hex = eth_utils.encode_hex(user1_addr) user2, _ = ec_random_keys() user2_addr = priv_to_addr(user2) user2_addr_hex = eth_utils.encode_hex(user2_addr) # setup balance value = (10**15 + 2000) * 10**18 + ReentrancyTest.REQUEST_BASE['gas'] tx = create_transaction(pri_key=self.genesis_priv_key, receiver=user1_addr, value=value, nonce=self.get_nonce(self.genesis_addr), gas_price=ReentrancyTest.REQUEST_BASE['gas']) self.send_transaction(tx, True, False) tx = create_transaction(pri_key=self.genesis_priv_key, receiver=user2_addr, value=value, nonce=self.get_nonce(self.genesis_addr), gas_price=ReentrancyTest.REQUEST_BASE['gas']) self.send_transaction(tx, True, False) user1_balance = parse_as_int( self.nodes[0].cfx_getBalance(user1_addr_hex)) assert_equal(user1_balance, value) user2_balance_before_contract_construction = parse_as_int( self.nodes[0].cfx_getBalance(user2_addr_hex)) assert_equal(user2_balance_before_contract_construction, value) transaction = self.call_contract_function(self.buggy_contract, "constructor", [], self.genesis_priv_key, storage_limit=20000) contract_addr = self.wait_for_tx([transaction], True)[0]['contractCreated'] transaction = self.call_contract_function(self.exploit_contract, "constructor", [], user2, storage_limit=200000) exploit_addr = self.wait_for_tx([transaction], True)[0]['contractCreated'] user2_balance_after_contract_construction = parse_as_int( self.nodes[0].cfx_getBalance(user2_addr_hex)) self.log.debug("user2 balance contract created %s" % user2_balance_after_contract_construction) assert_greater_than_or_equal( user2_balance_before_contract_construction, user2_balance_after_contract_construction) user2_refund_upper_bound = \ user2_balance_before_contract_construction - \ user2_balance_after_contract_construction transaction = self.call_contract_function(self.buggy_contract, "addBalance", [], user1, 10**18, contract_addr, True, True, storage_limit=128) transaction = self.call_contract_function( self.exploit_contract, "deposit", [Web3.toChecksumAddress(contract_addr)], user2, 10**18, exploit_addr, True, True, storage_limit=128) user1_balance = parse_as_int( self.nodes[0].cfx_getBalance(user1_addr_hex)) assert_greater_than_or_equal(user1_balance, 899999999999999999999999950000000) user2_balance_after_deposit = parse_as_int( self.nodes[0].cfx_getBalance(user2_addr_hex)) # User2 paid storage collateral `vulnerable_contract` in deposit call. user2_refund_upper_bound += 10**18 // 16 self.log.debug("user2 balance after deposit %s" % user2_balance_after_deposit) assert_greater_than_or_equal(user2_balance_after_contract_construction, user2_balance_after_deposit + 10**18) assert_greater_than_or_equal(user2_balance_after_deposit, 899999999999999999999999900000000) contract_balance = parse_as_int( self.nodes[0].cfx_getBalance(contract_addr)) assert_equal(contract_balance, 2 * 10**18) user2_balance_in_contract = RpcClient(self.nodes[0]).call( contract_addr, self.buggy_contract.functions.balanceOf( Web3.toChecksumAddress(exploit_addr)).buildTransaction({ "from": user2_addr_hex, "to": contract_addr, "gas": int_to_hex(CONTRACT_DEFAULT_GAS), "gasPrice": int_to_hex(1), "chainId": 0 })["data"]) assert_equal(parse_as_int(user2_balance_in_contract), 10**18) transaction = self.call_contract_function(self.exploit_contract, "launch_attack", [], user2, 0, exploit_addr, True, True, storage_limit=128) transaction = self.call_contract_function(self.exploit_contract, "get_money", [], user2, 0, exploit_addr, True, True, storage_limit=128) user1_balance = parse_as_int( self.nodes[0].cfx_getBalance(user1_addr_hex)) assert_greater_than_or_equal(user1_balance, 899999999999999999999999950000000) contract_balance = parse_as_int( self.nodes[0].cfx_getBalance(contract_addr)) assert_equal(contract_balance, 1 * 10**18) user2_balance_in_contract = RpcClient(self.nodes[0]).call( contract_addr, self.buggy_contract.functions.balanceOf( Web3.toChecksumAddress(exploit_addr)).buildTransaction({ "from": user2_addr_hex, "to": contract_addr, "gas": int_to_hex(CONTRACT_DEFAULT_GAS), "gasPrice": int_to_hex(1), "chainId": 0 })["data"]) assert_equal(parse_as_int(user2_balance_in_contract), 0) self.log.debug("user2 balance in contract %s" % user2_balance_in_contract) user2_balance_after_contract_destruct = parse_as_int( self.nodes[0].cfx_getBalance(user2_addr_hex)) self.log.debug("user2 balance after contract destruct %s" % user2_balance_after_contract_destruct) assert_greater_than_or_equal( user2_balance_after_contract_destruct, user2_balance_after_deposit + user2_refund_upper_bound + 10**18) block_gen_thread.stop() block_gen_thread.join()
def run_test(self): 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")
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!")