def add_transactions_to_blockchain_db(base_db, tx_list: List): # sort by time tx_list.sort(key=lambda x: x[3]) for tx_key in tx_list: sender_priv_key = tx_key[0] receive_priv_key = tx_key[1] amount = tx_key[2] tx_timestamp = int(tx_key[3]) if len(tx_key) > 4: gas_price = to_wei(tx_key[4], 'gwei') else: gas_price = to_wei(1, 'gwei') total_gas = gas_price sender_chain = MainnetChain(base_db, sender_priv_key.public_key.to_canonical_address(), sender_priv_key) dummy_sender_chain = MainnetChain(JournalDB(base_db), sender_priv_key.public_key.to_canonical_address(), sender_priv_key) dummy_sender_chain.create_and_sign_transaction_for_queue_block( gas_price=gas_price, gas=GAS_TX, to=receive_priv_key.public_key.to_canonical_address(), value=amount, data=b"", v=0, r=0, s=0 ) # import the block into the dummy chain to complete it and make sure it is valid imported_block = dummy_sender_chain.import_current_queue_block() # altering block timestamp and importing again timestamp_modified_imported_block = imported_block.copy( header=imported_block.header.copy(timestamp=tx_timestamp).get_signed(sender_priv_key, dummy_sender_chain.network_id)) sender_chain.import_block(timestamp_modified_imported_block, allow_unprocessed=False) # then receive the transactions dummy_receiver_chain = MainnetChain(JournalDB(base_db), receive_priv_key.public_key.to_canonical_address(), receive_priv_key) dummy_receiver_chain.populate_queue_block_with_receive_tx() imported_block = dummy_receiver_chain.import_current_queue_block() # altering block timestamp and importing again timestamp_modified_imported_block = imported_block.copy( header=imported_block.header.copy(timestamp=tx_timestamp).get_signed(receive_priv_key, dummy_receiver_chain.network_id)) # print('XXXXXXXXXX') # print(tx_timestamp) receiver_chain = MainnetChain(base_db, receive_priv_key.public_key.to_canonical_address(), receive_priv_key) receiver_chain.import_block(timestamp_modified_imported_block, allow_unprocessed=False)
def create_dev_fixed_blockchain_database(base_db, key_balance_dict, use_real_genesis = False): logger.debug("generating test fixed blockchain db") earliest_timestamp = int(time.time()) required_total_supply = 0 for balance_timestamp in key_balance_dict.values(): required_total_supply += balance_timestamp[0] if balance_timestamp[1] < earliest_timestamp: earliest_timestamp = balance_timestamp[1] required_total_supply = required_total_supply*2 #initialize db if use_real_genesis: sender_chain = import_genesis_block(base_db) else: genesis_params, genesis_state = create_new_genesis_params_and_state(GENESIS_PRIVATE_KEY, required_total_supply, earliest_timestamp - 100000) sender_chain = MainnetChain.from_genesis(base_db, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), genesis_params, genesis_state) sender_chain.chaindb.initialize_historical_minimum_gas_price_at_genesis(min_gas_price=1, net_tpc_cap=5) prev_timestamp = 0 for priv_key, balance_timestamp in key_balance_dict.items(): sender_chain = MainnetChain(base_db, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) dummy_sender_chain = MainnetChain(JournalDB(base_db), GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) balance = balance_timestamp[0] timestamp = balance_timestamp[1] if timestamp < prev_timestamp: raise ValueError("timestamps must be in ascending order") receiver_privkey = priv_key dummy_sender_chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=0x0c3500, to=receiver_privkey.public_key.to_canonical_address(), value=balance, data=b"", v=0, r=0, s=0 ) # import the block into the dummy chain to complete it and make sure it is valid imported_block = dummy_sender_chain.import_current_queue_block() # altering block timestamp and importing again timestamp_modified_imported_block = imported_block.copy(header = imported_block.header.copy(timestamp = timestamp).get_signed(GENESIS_PRIVATE_KEY,dummy_sender_chain.network_id)) sender_chain.import_block(timestamp_modified_imported_block, allow_unprocessed = False) #logger.debug("Receiving ") #then receive the transactions receiver_chain = MainnetChain(base_db, receiver_privkey.public_key.to_canonical_address(), receiver_privkey) dummy_receiver_chain = MainnetChain(JournalDB(base_db), receiver_privkey.public_key.to_canonical_address(), receiver_privkey) dummy_receiver_chain.populate_queue_block_with_receive_tx() imported_block = dummy_receiver_chain.import_current_queue_block() # altering block timestamp and importing again timestamp_modified_imported_block = imported_block.copy(header=imported_block.header.copy(timestamp=timestamp).get_signed(receiver_privkey, dummy_receiver_chain.network_id)) receiver_chain.import_block(timestamp_modified_imported_block, allow_unprocessed=False) logger.debug("finished creating fixed blockchain")
def _test_airdrop_calling_erc_20(): # testdb = LevelDB('/home/tommy/.local/share/helios/instance_test/mainnet/chain/full/') # testdb = JournalDB(testdb) testdb = MemoryDB() chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) coin_mature_time = chain.get_vm(timestamp=Timestamp(int( time.time()))).consensus_db.coin_mature_time_for_staking genesis_params, genesis_state = create_new_genesis_params_and_state( GENESIS_PRIVATE_KEY, 1000000 * 10**18, int(time.time()) - coin_mature_time * 10000) # import genesis block chain = MainnetChain.from_genesis( testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), genesis_params, genesis_state, GENESIS_PRIVATE_KEY) # # erc20 contract deploy # compiled_erc20_sol = load_compiled_sol_dict( 'contract_data/erc20_compiled.pkl') EXPECTED_TOTAL_SUPPLY = 10000000000000000000000 erc20_contract_interface = compiled_erc20_sol[ 'contract_data/erc20.sol:SimpleToken'] w3 = Web3() SimpleToken = w3.eth.contract(abi=erc20_contract_interface['abi'], bytecode=erc20_contract_interface['bin']) # Build transaction to deploy the contract w3_erc20_tx = SimpleToken.constructor().buildTransaction(W3_TX_DEFAULTS) max_gas = 20000000 chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=max_gas, to=CREATE_CONTRACT_ADDRESS, value=0, data=decode_hex(w3_erc20_tx['data']), v=0, r=0, s=0) #time.sleep(1) print("deploying erc20 smart contract") imported_block = chain.import_current_queue_block() #now we need to add the block to the smart contract list_of_smart_contracts = chain.get_vm( ).state.account_db.get_smart_contracts_with_pending_transactions() erc20_contract_address = list_of_smart_contracts[0] chain = MainnetChain(testdb, erc20_contract_address, private_keys[0]) chain.populate_queue_block_with_receive_tx() imported_block = chain.import_current_queue_block() # # airdrop contract deploy # compiled_airdrop_sol = load_compiled_sol_dict( 'contract_data/airdrop_compiled.pkl') EXPECTED_TOTAL_SUPPLY = 10000000000000000000000 airdrop_contract_interface = compiled_airdrop_sol[ 'contract_data/airdrop.sol:Airdrop'] Airdrop = w3.eth.contract(abi=airdrop_contract_interface['abi'], bytecode=airdrop_contract_interface['bin']) # Build transaction to deploy the contract w3_airdrop_tx = Airdrop.constructor().buildTransaction(W3_TX_DEFAULTS) chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=max_gas, to=CREATE_CONTRACT_ADDRESS, value=0, data=decode_hex(w3_airdrop_tx['data']), v=0, r=0, s=0) print("deploying airdrop smart contract") imported_block = chain.import_current_queue_block() # now we need to add the block to the smart contract list_of_smart_contracts = chain.get_vm( ).state.account_db.get_smart_contracts_with_pending_transactions() airdrop_contract_address = list_of_smart_contracts[0] chain = MainnetChain(testdb, airdrop_contract_address, private_keys[0]) chain.populate_queue_block_with_receive_tx() imported_block = chain.import_current_queue_block() # # Interacting with deployed smart contract step 1) add send transaction # chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) print(erc20_contract_interface['abi']) simple_token = w3.eth.contract( address=Web3.toChecksumAddress(erc20_contract_address), abi=erc20_contract_interface['abi'], ) airdrop_token_balance = 1000 w3_erc20_send = simple_token.functions.transfer( Web3.toChecksumAddress(airdrop_contract_address), airdrop_token_balance).buildTransaction(W3_TX_DEFAULTS) chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=max_gas, to=erc20_contract_address, value=0, data=decode_hex(w3_erc20_send['data']), v=0, r=0, s=0) imported_block = chain.import_current_queue_block() chain = MainnetChain(testdb, erc20_contract_address, private_keys[0]) chain.populate_queue_block_with_receive_tx() imported_block = chain.import_current_queue_block() from pprint import pprint receipt = chain.chaindb.get_receipts(imported_block.header, Receipt)[0] receipt_dict = format_receipt_for_web3_to_extract_events( receipt, imported_block.receive_transactions[0].hash, chain) rich_logs = simple_token.events.Transfer().processReceipt(receipt_dict) print(rich_logs) print(rich_logs[0]['args']) print('a') assert (to_int( chain.chaindb.get_receipts( imported_block.header, Receipt)[0].logs[0].data) == airdrop_token_balance) chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) w3_erc20_balance = simple_token.functions.balanceOf( Web3.toChecksumAddress(airdrop_contract_address)).buildTransaction( W3_TX_DEFAULTS) chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=max_gas, to=erc20_contract_address, value=0, data=decode_hex(w3_erc20_balance['data']), v=0, r=0, s=0) imported_block = chain.import_current_queue_block() chain = MainnetChain(testdb, erc20_contract_address, private_keys[0]) chain.populate_queue_block_with_receive_tx() imported_block = chain.import_current_queue_block() print(chain.chaindb.get_receipts(imported_block.header, Receipt)[0].logs) exit() #now lets look at the reciept to see the result assert (to_int( chain.chaindb.get_receipts( imported_block.header, Receipt)[0].logs[0].data) == EXPECTED_TOTAL_SUPPLY) print("Total supply call gave expected result!") gas_used = to_int( chain.chaindb.get_receipts(imported_block.header, Receipt)[0].gas_used) # # Interacting with deployed smart contract step 3) Receiving refund of extra gas that wasn't used in the computation # initial_balance = chain.get_vm().state.account_db.get_balance( GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) chain.populate_queue_block_with_receive_tx() imported_block = chain.import_current_queue_block() final_balance = chain.get_vm().state.account_db.get_balance( GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) assert ((final_balance - initial_balance) == (max_gas - gas_used)) print("Refunded gas is the expected amount.")
def test_get_receipts(): testdb2 = MemoryDB() MainnetChain.from_genesis( testdb2, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), MAINNET_GENESIS_PARAMS, MAINNET_GENESIS_STATE) """ Create some receive transactions for RECEIVER """ sender_chain = MainnetChain(testdb2, SENDER.public_key.to_canonical_address(), SENDER) min_time_between_blocks = sender_chain.get_vm( timestamp=Timestamp(int(time.time()))).min_time_between_blocks for i in range(6): sender_chain.create_and_sign_transaction_for_queue_block( gas_price=i + 1, gas=0x0c3500, to=RECEIVER.public_key.to_canonical_address(), value=i + 100000000000, data=b"", v=0, r=0, s=0) sender_chain.import_current_queue_block() receiver_chain = MainnetChain(testdb2, RECEIVER.public_key.to_canonical_address(), RECEIVER) receiver_chain.populate_queue_block_with_receive_tx() imported_block_1 = receiver_chain.import_current_queue_block() """ Create some send transactions for RECEIVER """ receiver_chain = MainnetChain(testdb2, RECEIVER.public_key.to_canonical_address(), RECEIVER) for i in range(6): receiver_chain.create_and_sign_transaction_for_queue_block( gas_price=i + 1, gas=0x0c3500, to=SENDER.public_key.to_canonical_address(), value=i, data=b"", v=0, r=0, s=0) """ Create a transaction with data in it. """ compiled_sol = load_compiled_sol_dict('contract_data/erc20_compiled.pkl') contract_interface = compiled_sol['contract_data/erc20.sol:SimpleToken'] w3 = Web3() SimpleToken = w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin']) # Build transaction to deploy the contract w3_tx1 = SimpleToken.constructor().buildTransaction(W3_TX_DEFAULTS) from hvm.constants import CREATE_CONTRACT_ADDRESS receiver_chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=1375666, to=CREATE_CONTRACT_ADDRESS, value=0, data=decode_hex(w3_tx1['data']), v=0, r=0, s=0) receiver_chain.populate_queue_block_with_receive_tx() print("waiting {} seconds before importing next block".format( min_time_between_blocks)) time.sleep(min_time_between_blocks) imported_block = receiver_chain.import_current_queue_block() for i in range(7): if i < 6: receipt = sender_chain.chaindb.get_transaction_receipt( imported_block.transactions[i].hash) assert (receipt.status_code == b'\x01') assert (receipt.gas_used == GAS_TX) assert (receipt.bloom == 0) assert (receipt.logs == ()) if i == 6: receipt = sender_chain.chaindb.get_transaction_receipt( imported_block.transactions[i].hash) assert (receipt.status_code == b'\x01') assert (receipt.gas_used == 1375666) assert ( receipt.bloom == 243379359099696592952569079439667912256345493617967967903663341910531480774353059570732838085077727505416158987674861080353852392619637689071728561054211502067278701792094127192831079015338935810676425927305370163403783027301927515372719270157454901551766020292792184739669125690737609931485501648741152187826071626833444578979111366057983284511641401113379885201162016756050289195516614302086913696386892161910800529278878068496138240 ) assert (len(receipt.logs) == 1) for i in range(6): receipt = sender_chain.chaindb.get_transaction_receipt( imported_block_1.receive_transactions[i].hash) assert (receipt.status_code == b'\x01') assert (receipt.gas_used == 0) assert (receipt.bloom == 0) assert (receipt.logs == ()) # test_get_receipts()
def test_erc_20_smart_contract_deploy_system(): # testdb = LevelDB('/home/tommy/.local/share/helios/instance_test/mainnet/chain/full/') # testdb = JournalDB(testdb) testdb = MemoryDB() chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) coin_mature_time = chain.get_vm(timestamp=Timestamp(int( time.time()))).consensus_db.coin_mature_time_for_staking now = int(time.time()) key_balance_dict = { private_keys[0]: (1000000000000, now - coin_mature_time * 10 - 100) } create_dev_fixed_blockchain_database(testdb, key_balance_dict) chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) min_time_between_blocks = chain.get_vm( timestamp=Timestamp(int(time.time()))).min_time_between_blocks for private_key, balance_time in key_balance_dict.items(): assert (chain.get_vm().state.account_db.get_balance( private_key.public_key.to_canonical_address()) == balance_time[0]) SOLIDITY_SRC_FILE = 'contract_data/erc20.sol' EXPECTED_TOTAL_SUPPLY = 10000000000000000000000 #compiled_sol = compile_files([SOLIDITY_SRC_FILE]) compiled_sol = load_compiled_sol_dict('contract_data/erc20_compiled.pkl') contract_interface = compiled_sol['{}:SimpleToken'.format( SOLIDITY_SRC_FILE)] w3 = Web3() SimpleToken = w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin']) # Build transaction to deploy the contract w3_tx1 = SimpleToken.constructor().buildTransaction(W3_TX_DEFAULTS) max_gas = 20000000 chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=max_gas, to=CREATE_CONTRACT_ADDRESS, value=0, data=decode_hex(w3_tx1['data']), v=0, r=0, s=0) #time.sleep(1) print("deploying smart contract") initial_balance = chain.get_vm().state.account_db.get_balance( GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) imported_block = chain.import_current_queue_block() final_balance = chain.get_vm().state.account_db.get_balance( GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) gas_used = to_int( chain.chaindb.get_receipts(imported_block.header, Receipt)[0].gas_used) assert ((initial_balance - final_balance) == gas_used) print(GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) print( generate_contract_address( GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), imported_block.transactions[0].nonce)) print( chain.chaindb.get_receipts(imported_block.header, Receipt)[0].logs[0].address) #contractAddress print("Used the correct amount of gas.") #now we need to add the block to the smart contract list_of_smart_contracts = chain.get_vm( ).state.account_db.get_smart_contracts_with_pending_transactions() deployed_contract_address = list_of_smart_contracts[0] print(list_of_smart_contracts) chain = MainnetChain(testdb, deployed_contract_address, private_keys[0]) chain.populate_queue_block_with_receive_tx() imported_block = chain.import_current_queue_block() list_of_smart_contracts = chain.get_vm( ).state.account_db.get_smart_contracts_with_pending_transactions() print(list_of_smart_contracts) #lets make sure it didn't create a refund transaction for the initial sender. print(chain.get_vm().state.account_db.has_receivable_transactions( GENESIS_PRIVATE_KEY.public_key.to_canonical_address())) # print('ASDASD') # print(chain.chaindb.get_receipts(imported_block.header, Receipt)[0].logs[0].data) # # Interacting with deployed smart contract step 1) add send transaction # chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) simple_token = w3.eth.contract( address=Web3.toChecksumAddress(deployed_contract_address), abi=contract_interface['abi'], ) w3_tx2 = simple_token.functions.totalSupply().buildTransaction( W3_TX_DEFAULTS) chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=max_gas, to=deployed_contract_address, value=0, data=decode_hex(w3_tx2['data']), v=0, r=0, s=0) #lets make sure it subtracts the entire max gas initial_balance = chain.get_vm().state.account_db.get_balance( GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) print("waiting {} seconds before importing next block".format( min_time_between_blocks)) time.sleep(min_time_between_blocks) chain.import_current_queue_block() final_balance = chain.get_vm().state.account_db.get_balance( GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) assert ((initial_balance - final_balance) == max_gas) # # Interacting with deployed smart contract step 2) add receive transaction to smart contract chain # chain = MainnetChain(testdb, deployed_contract_address, private_keys[0]) chain.populate_queue_block_with_receive_tx() print("waiting {} seconds before importing next block".format( min_time_between_blocks)) time.sleep(min_time_between_blocks) imported_block = chain.import_current_queue_block() receipt = chain.chaindb.get_receipts(imported_block.header, Receipt)[0] receipt_dict = format_receipt_for_web3_to_extract_events( receipt, imported_block.receive_transactions[0].hash, chain) rich_logs = simple_token.events.Print().processReceipt(receipt_dict) print(rich_logs[0]['args']) print('a') #now lets look at the reciept to see the result assert (to_int( chain.chaindb.get_receipts( imported_block.header, Receipt)[0].logs[0].data) == EXPECTED_TOTAL_SUPPLY) print("Total supply call gave expected result!") gas_used = to_int( chain.chaindb.get_receipts(imported_block.header, Receipt)[0].gas_used) # # Interacting with deployed smart contract step 3) Receiving refund of extra gas that wasn't used in the computation # initial_balance = chain.get_vm().state.account_db.get_balance( GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) chain = MainnetChain(testdb, GENESIS_PRIVATE_KEY.public_key.to_canonical_address(), GENESIS_PRIVATE_KEY) chain.populate_queue_block_with_receive_tx() print("waiting {} seconds before importing next block".format( min_time_between_blocks)) time.sleep(min_time_between_blocks) imported_block = chain.import_current_queue_block() final_balance = chain.get_vm().state.account_db.get_balance( GENESIS_PRIVATE_KEY.public_key.to_canonical_address()) assert ((final_balance - initial_balance) == (max_gas - gas_used)) print("Refunded gas is the expected amount.")