async def block_creation_loop(self): while self.is_operational: self.logger.debug("Start of block creation loop") if await self.consensus.current_sync_stage >= 4: chain_addresses = self.chain.get_vm( ).state.account_db.get_smart_contracts_with_pending_transactions( ) for chain_address in chain_addresses: # 1) Add the new block, 2) Propogate it to the network # need to create a new chain to avoid conflicts with multiple processes chain = self.node.get_new_private_chain(chain_address) chain.populate_queue_block_with_receive_tx() self.logger.debug( "Importing new block on smart contract chain {}". format(encode_hex(chain_address))) new_block = await chain.coro_import_current_queue_block() self.logger.debug( "Sending new smart contract block to network") self.event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, new_block), only_propogate_to_network=True)) self.logger.debug( "Successfully updated smart contract chain") await asyncio.sleep(1)
async def sendRawBlock(self, encoded_micro_block): chain = self.get_new_chain() encoded_micro_block = decode_hex(encoded_micro_block) micro_block = rlp.decode(encoded_micro_block, sedes=chain.get_vm().micro_block_class) block_class = self._chain_class.get_vm_class_for_block_timestamp(timestamp = micro_block.header.timestamp).get_block_class() full_block = block_class.from_micro_block(micro_block) min_time_between_blocks = chain.get_vm(header=full_block.header).min_time_between_blocks # Validate the block here if(full_block.header.timestamp < (int(time.time()) - MAX_ALLOWED_AGE_OF_NEW_RPC_BLOCK)): raise BaseRPCError("The block timestamp is to old. We can only import new blocks over RPC.") if(full_block.header.timestamp > int(time.time() + BLOCK_TIMESTAMP_FUTURE_ALLOWANCE)): raise BaseRPCError("The block timestamp is in the future and cannot be accepted. You should check your computer clock.") try: canonical_head = chain.chaindb.get_canonical_head(full_block.header.chain_address) if canonical_head.block_number >= full_block.header.block_number: raise BaseRPCError("You are attempting to replace an existing block. This is not allowed.") if full_block.header.timestamp < (canonical_head.timestamp + min_time_between_blocks): raise BaseRPCError("Not enough time has passed for you to add a new block yet. New blocks can only be added to your chain every {} seconds".format(min_time_between_blocks)) except CanonicalHeadNotFound: pass if((full_block.header.block_number != 0) and (not chain.chaindb.is_in_canonical_chain(full_block.header.parent_hash))): raise BaseRPCError("Parent block not found on canonical chain.") #Check our current syncing stage. Must be sync stage 4. current_sync_stage_response = await self._event_bus.request( CurrentSyncStageRequest() ) if current_sync_stage_response.sync_stage < FULLY_SYNCED_STAGE_ID: raise BaseRPCError("This node is still syncing with the network. Please wait until this node has synced.") if not does_block_meet_min_gas_price(full_block, chain): required_min_gas_price = self._chain.chaindb.get_required_block_min_gas_price() raise Exception("Block transactions don't meet the minimum gas price requirement of {}".format(required_min_gas_price)) self._event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, full_block), from_rpc=True) ) return True
async def block_creation_loop(self): while self.is_operational: self.logger.debug("Start of block creation loop") if await self.consensus.current_sync_stage >= 4: chain_addresses = self.chain.get_vm( ).state.account_db.get_smart_contracts_with_pending_transactions( ) for chain_address in chain_addresses: # 1) Add the new block, 2) Propogate it to the network # need to create a new chain to avoid conflicts with multiple processes chain = self.node.get_new_private_chain(chain_address) # make the chain read only for creating the block. We don't want to actually import it here. chain.enable_read_only_db() allowed_time_of_next_block = chain.get_allowed_time_of_next_block( chain_address) now = int(time.time()) if now < allowed_time_of_next_block: continue chain.populate_queue_block_with_receive_tx() self.logger.debug( "Importing new block on smart contract chain {}". format(encode_hex(chain_address))) new_block = await chain.coro_import_current_queue_block() self.logger.debug( "Sending new smart contract block to network") self.event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, new_block))) self.logger.debug( "Successfully created new block for smart contract chain, sent to event bus" ) await asyncio.sleep(1)
async def devDeploySmartContract(self): from hvm.constants import CREATE_CONTRACT_ADDRESS from hvm.chains.mainnet import ( GENESIS_PRIVATE_KEY, GENESIS_WALLET_ADDRESS, ) self._chain.set_new_wallet_address( wallet_address=GENESIS_WALLET_ADDRESS, private_key=GENESIS_PRIVATE_KEY) self._chain.reinitialize() self._chain.enable_journal_db() journal_record = self._chain.record_journal() smart_contract_data = '0x608060405234801561001057600080fd5b50601260ff16600a0a61271002600181905550601260ff16600a0a612710026000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff1660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef601260ff16600a0a612710026040518082815260200191505060405180910390a361129e806100db6000396000f3006080604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014f57806318160ddd146101b457806323b872dd146101df5780632ff2e9dc14610264578063313ce5671461028f57806366188463146102c057806370a082311461032557806395d89b411461037c578063a9059cbb1461040c578063d73dd62314610471578063dd62ed3e146104d6575b600080fd5b3480156100cb57600080fd5b506100d461054d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101145780820151818401526020810190506100f9565b50505050905090810190601f1680156101415780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015b57600080fd5b5061019a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b3480156101c057600080fd5b506101c9610678565b6040518082815260200191505060405180910390f35b3480156101eb57600080fd5b5061024a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106bb565b604051808215151515815260200191505060405180910390f35b34801561027057600080fd5b50610279610a75565b6040518082815260200191505060405180910390f35b34801561029b57600080fd5b506102a4610a84565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102cc57600080fd5b5061030b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610a89565b604051808215151515815260200191505060405180910390f35b34801561033157600080fd5b50610366600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d1a565b6040518082815260200191505060405180910390f35b34801561038857600080fd5b50610391610d62565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103d15780820151818401526020810190506103b6565b50505050905090810190601f1680156103fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561041857600080fd5b50610457600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610d9b565b604051808215151515815260200191505060405180910390f35b34801561047d57600080fd5b506104bc600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610fba565b604051808215151515815260200191505060405180910390f35b3480156104e257600080fd5b50610537600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506111b6565b6040518082815260200191505060405180910390f35b6040805190810160405280600b81526020017f53696d706c65546f6b656e00000000000000000000000000000000000000000081525081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60007f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da6001546040518082815260200191505060405180910390a1600154905090565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515156106f857600080fd5b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561074557600080fd5b600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482111515156107d057600080fd5b610821826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461123d90919063ffffffff16565b6000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108b4826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461125690919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061098582600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461123d90919063ffffffff16565b600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b601260ff16600a0a6127100281565b601281565b600080600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905080831115610b9a576000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610c2e565b610bad838261123d90919063ffffffff16565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a3600191505092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6040805190810160405280600381526020017f53494d000000000000000000000000000000000000000000000000000000000081525081565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610dd857600080fd5b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610e2557600080fd5b610e76826000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461123d90919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f09826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461125690919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b600061104b82600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461125690919063ffffffff16565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600082821115151561124b57fe5b818303905092915050565b6000818301905082811015151561126957fe5b809050929150505600a165627a7a723058203065ebd182d2e9529433f647283c9d4f1f9e7d600744ec301b2a0aae6a250a530029' max_gas = 20000000 self._chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=max_gas, to=CREATE_CONTRACT_ADDRESS, value=0, data=decode_hex(smart_contract_data), v=0, r=0, s=0) block_to_import = self._chain.import_current_queue_block() self._chain.discard_journal(journal_record) self._chain.disable_journal_db() self._event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, block_to_import), only_propogate_to_network=False)) return []
async def sendRawBlock(self, encoded_micro_block): chain = self.get_new_chain() encoded_micro_block = decode_hex(encoded_micro_block) micro_block = rlp.decode(encoded_micro_block, sedes=chain.get_vm().micro_block_class) block_class = self._chain_class.get_vm_class_for_block_timestamp( timestamp=micro_block.header.timestamp).get_block_class() full_block = block_class.from_micro_block(micro_block) min_time_between_blocks = chain.get_vm( header=full_block.header).min_time_between_blocks # Validate the block here if (full_block.header.timestamp < (int(time.time()) - MAX_ALLOWED_AGE_OF_NEW_RPC_BLOCK)): raise BaseRPCError( "The block timestamp is to old. We can only import new blocks over RPC." ) if (full_block.header.timestamp > int(time.time() + BLOCK_TIMESTAMP_FUTURE_ALLOWANCE)): raise BaseRPCError( "The block timestamp is in the future and cannot be accepted. You should check your computer clock." ) try: canonical_head = chain.chaindb.get_canonical_head( full_block.header.chain_address) if canonical_head.block_number >= full_block.header.block_number: raise BaseRPCError( "You are attempting to replace an existing block. This is not allowed." ) if full_block.header.timestamp < (canonical_head.timestamp + min_time_between_blocks): raise BaseRPCError( "Not enough time has passed for you to add a new block yet. New blocks can only be added to your chain every {} seconds" .format(min_time_between_blocks)) except CanonicalHeadNotFound: pass if ((full_block.header.block_number != 0) and (not chain.chaindb.is_in_canonical_chain( full_block.header.parent_hash))): raise BaseRPCError("Parent block not found on canonical chain.") # Check our current syncing stage. Must be sync stage 4. current_sync_stage_response = await self._event_bus.request( CurrentSyncStageRequest()) if current_sync_stage_response.sync_stage < FULLY_SYNCED_STAGE_ID: raise BaseRPCError( "This node is still syncing with the network. Please wait until this node has synced and try again." ) # Check that our block import queue is not deep. It could cause min gas to increase before this block makes it there. current_block_import_queue_length = await self._event_bus.request( BlockImportQueueLengthRequest()) if current_block_import_queue_length.queue_length > MAX_ALLOWED_LENGTH_BLOCK_IMPORT_QUEUE: raise BaseRPCError( "This node's block import queue is saturated. Please wait a moment and try again." ) # Make sure it meets the local min gas price if not does_block_meet_min_gas_price(full_block, chain): required_min_gas_price = self._chain.min_gas_db.get_required_block_min_gas_price( ) raise Exception( "Block transactions don't meet the minimum gas price requirement of {}" .format(required_min_gas_price)) # Make sure it meets the average min gas price of the network. If it doesnt, then it won't reach consensus. current_network_min_gas_price_response = await self._event_bus.request( AverageNetworkMinGasPriceRequest()) network_min_gas_price_wei = to_wei( current_network_min_gas_price_response.min_gas_price, 'gwei') if network_min_gas_price_wei > get_block_average_transaction_gas_price( full_block): raise BaseRPCError( "This block doesn't meet the minimum gas requirements to reach consensus on the network. It must have at least {} average gas price on all transactions." .format(current_network_min_gas_price_response.min_gas_price)) self._event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, full_block), from_rpc=True)) return True
async def _send_transactions(self, transactions, account): async with self._importing_block_lock: print("Importing block") normalized_wallet_address = to_normalized_address(account.address) wallet_address_hex = account.address wallet_address = decode_hex(wallet_address_hex) chain = self.get_new_chain(Address(wallet_address), account._key_obj) # make the chain read only for creating the block. We don't want to actually import it here. chain.enable_read_only_db() signed_transactions = [] for i in range(len(transactions)): tx = transactions[i] if to_normalized_address(tx['from']) != normalized_wallet_address: raise BaseRPCError("When sending multiple transactions at once, they must all be from the same address") if 'gasPrice' in tx: gas_price = tx['gasPrice'] else: gas_price = to_wei(chain.chaindb.get_required_block_min_gas_price()+1, 'gwei') if 'gas' in tx: gas = tx['gas'] else: gas = GAS_TX if 'data' in tx: data = tx['data'] else: data = b'' if 'nonce' in tx: nonce = tx['nonce'] else: if normalized_wallet_address in self._current_tx_nonce: nonce_from_state = chain.get_vm().state.account_db.get_nonce(wallet_address) nonce = chain.get_vm().state.account_db.get_nonce(wallet_address) transactions[i]['nonce'] = nonce signed_tx = chain.create_and_sign_transaction_for_queue_block( gas_price=gas_price, gas=GAS_TX, to=decode_hex(tx['to']), value=to_int_if_hex(tx['value']), data=data, v=0, r=0, s=0 ) signed_transactions.append(signed_tx) # We put this part down here because we have to return the hashes of all the transactions. # Check when the next block can be. If we are early, queue up the tx. allowed_time_of_next_block = chain.get_allowed_time_of_next_block() min_time_between_blocks = chain.min_time_between_blocks now = int(time.time()) # Or, we may have just sent a block and it hasn't been imported yet. Lets check. Then send to queue if that is the case. if normalized_wallet_address in self._newest_block_times_sent_to_event_bus: if self._newest_block_times_sent_to_event_bus[normalized_wallet_address] >= allowed_time_of_next_block: allowed_time_of_next_block = self._newest_block_times_sent_to_event_bus[normalized_wallet_address] + min_time_between_blocks if now < allowed_time_of_next_block: for tx in transactions: await self._add_transaction_to_queue(tx) asyncio.ensure_future(self._import_delayed_block_with_queue(account, allowed_time_of_next_block-now, min_time_between_blocks)) else: block = chain.import_current_queue_block() self._event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, block), from_rpc=True) ) self._newest_block_times_sent_to_event_bus[normalized_wallet_address] = block.header.timestamp if len(signed_transactions) == 1: return encode_hex(signed_transactions[0].hash) else: return [encode_hex(tx.hash) for tx in signed_transactions]
async def _send_transactions(self, transactions, account, include_receive: bool = True): async with self._importing_block_lock: print("Importing block") normalized_wallet_address = to_normalized_address(account.address) wallet_address_hex = account.address wallet_address = decode_hex(wallet_address_hex) chain = self.get_new_chain(Address(wallet_address), account._key_obj) allowed_time_of_next_block = chain.get_allowed_time_of_next_block() now = int(time.time()) if now < allowed_time_of_next_block: raise BaseRPCError("The minimum time between blocks has not passed. You must wait until {} to send the next block. " "Use personal_sendTrasactions to send multiple transactions at once.".format(allowed_time_of_next_block)) # make the chain read only for creating the block. We don't want to actually import it here. chain.enable_read_only_db() if include_receive: chain.populate_queue_block_with_receive_tx() signed_transactions = [] min_gas_price = to_wei(chain.chaindb.get_required_block_min_gas_price(), 'gwei') safe_min_gas_price = to_wei(chain.chaindb.get_required_block_min_gas_price()+5, 'gwei') for i in range(len(transactions)): tx = transactions[i] if to_normalized_address(tx['from']) != normalized_wallet_address: raise BaseRPCError("When sending multiple transactions at once, they must all be from the same address") if 'gasPrice' in tx: gas_price = to_int_if_hex(tx['gasPrice']) else: gas_price = safe_min_gas_price if 'gas' in tx: gas = to_int_if_hex(tx['gas']) else: gas = GAS_TX if 'data' in tx: data = tx['data'] else: data = b'' if 'nonce' in tx: nonce = to_int_if_hex(tx['nonce']) else: nonce = None transactions[i]['nonce'] = nonce signed_tx = chain.create_and_sign_transaction_for_queue_block( gas_price=gas_price, gas=gas, to=decode_hex(tx['to']), value=to_int_if_hex(tx['value']), data=data, nonce=nonce, v=0, r=0, s=0 ) signed_transactions.append(signed_tx) block = chain.import_current_queue_block() if not does_block_meet_min_gas_price(block, chain): raise Exception("The average gas price of all transactions in your block does not meet the required minimum gas price. Your average block gas price: {}. Min gas price: {}".format( get_block_average_transaction_gas_price(block), min_gas_price)) if len(signed_transactions) == 0 and len(block.receive_transactions) == 0: raise BaseRPCError("Cannot send block if it has no send or receive transactions.") self._event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, block), from_rpc=True) ) send_transaction_hashes = [encode_hex(tx.hash) for tx in signed_transactions] receive_transaction_hashes = [encode_hex(tx.hash) for tx in block.receive_transactions] all_transaction_hashes = send_transaction_hashes all_transaction_hashes.extend(receive_transaction_hashes) if not include_receive: return all_transaction_hashes[0] else: return all_transaction_hashes
async def devAddValidNewBlock(self, version): if version == 1: ''' import a valid block ''' from eth_keys import keys from hvm.constants import random_private_keys #primary_private_keys = [b'p.Oids\xedb\xa3\x93\xc5\xad\xb9\x8d\x92\x94\x00\x06\xb9\x82\xde\xb9\xbdBg\\\x82\xd4\x90W\xd0\xd5', b'\xa41\x95@\xbb\xa5\xde\xbbc\xffR\x8a\x18\x06\x95\xa3\xd7\xd2\x95]5{\x12\xe4n\xb6R\xd7S\x96\xf0+', b'\xd8>Fh\xefT\x04jf\x13\xca|E\xc4\x91\xed\x07\xcd\x02fW\xd8s;\xd8\xe4\xde\xb9\xbc\xe4\xf0I', b'\x83\x1d\xf6\xaf-\x00\xbfS4\x0f\xcds\x18"\xdd\x906]e\xfc\xe6\x0c?\xb1v20\xced7y\xf4', b")M\xf4\x1c\xb7\xe0Z\xf4\x17F\x9b\x089'\x004\xd3\x89\xd8\x80\xf5`\xa2\x11\x00\x90\xbd\x0f&KjZ", b'RI\xda\xbc7\xc4\xe8\tz\xfaI\x1f\xa1\x02{v\x0e\xac\x87W\xa2s\x81L4M\xad\xbd\xb3\x84\xaae', b'>kG\xd5\xb3qG\x84\xa6"\x1c~\xb6\xbf\x96\xac\n\x88\xfb\x05\x8aG\r\xe9Z\x16\x15\xb1P\xe0\xb7[', b'\x87\xf6\xb1\xa7v\x8bv<\xa3\xe5\xb18\xa7u\x99\xbaBa\xe9\xd5\x0e\xcb\x0f?\x84nZ\xba\xdf\xa3\x8a~', b'`$g\xe9\xa5r\xd2\xacG&\xf81^\x98\xf7\xda\xa5\xf4\x93)\xf3\x0c\x18\x84\xe4)!\x9dR\xa0\xac\xd3', b'\xcfd\xd5|\xe2\xf1\xda\xb9\x1f|\xb9\xdc\xeb \xd7\xb0\x81g\xdc\x03\xd6dQ\xf14\x19`\x94o\xf7\xc7\x1b', b'}LO\x14($d\n!\x1a\x91\xa8S\xb3\x05\xaa\x89\xf2\x0b\x97\xd3\x1c#\xe7\x86g`\xf1\x1a\xedXW'] def get_primary_node_private_helios_key(instance_number=0): return keys.PrivateKey(random_private_keys[instance_number]) from hvm.chains.mainnet import ( GENESIS_PRIVATE_KEY, GENESIS_WALLET_ADDRESS, ) SENDER = GENESIS_PRIVATE_KEY RECEIVER = get_primary_node_private_helios_key(1) RECEIVER2 = get_primary_node_private_helios_key(2) RECEIVER3 = get_primary_node_private_helios_key(3) RECEIVER4 = get_primary_node_private_helios_key(4) #create tx and blocks from the genesis block. self._chain.set_new_wallet_address( wallet_address=RECEIVER4.public_key.to_canonical_address(), private_key=RECEIVER4) self._chain.reinitialize() self._chain.enable_journal_db() journal_record = self._chain.record_journal() self._chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=0x0c3500, to=RECEIVER.public_key.to_canonical_address(), value=1, data=b"", v=0, r=0, s=0) block_to_import = self._chain.import_current_queue_block() self._chain.discard_journal(journal_record) self._chain.disable_journal_db() self._event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, block_to_import), only_propogate_to_network=False)) return [] elif version == 2: ''' import a valid block ''' from eth_keys import keys # primary_private_keys = [ # b'p.Oids\xedb\xa3\x93\xc5\xad\xb9\x8d\x92\x94\x00\x06\xb9\x82\xde\xb9\xbdBg\\\x82\xd4\x90W\xd0\xd5', # b'\xa41\x95@\xbb\xa5\xde\xbbc\xffR\x8a\x18\x06\x95\xa3\xd7\xd2\x95]5{\x12\xe4n\xb6R\xd7S\x96\xf0+', # b'\xd8>Fh\xefT\x04jf\x13\xca|E\xc4\x91\xed\x07\xcd\x02fW\xd8s;\xd8\xe4\xde\xb9\xbc\xe4\xf0I', # b'\x83\x1d\xf6\xaf-\x00\xbfS4\x0f\xcds\x18"\xdd\x906]e\xfc\xe6\x0c?\xb1v20\xced7y\xf4', # b")M\xf4\x1c\xb7\xe0Z\xf4\x17F\x9b\x089'\x004\xd3\x89\xd8\x80\xf5`\xa2\x11\x00\x90\xbd\x0f&KjZ", # b'RI\xda\xbc7\xc4\xe8\tz\xfaI\x1f\xa1\x02{v\x0e\xac\x87W\xa2s\x81L4M\xad\xbd\xb3\x84\xaae', # b'>kG\xd5\xb3qG\x84\xa6"\x1c~\xb6\xbf\x96\xac\n\x88\xfb\x05\x8aG\r\xe9Z\x16\x15\xb1P\xe0\xb7[', # b'\x87\xf6\xb1\xa7v\x8bv<\xa3\xe5\xb18\xa7u\x99\xbaBa\xe9\xd5\x0e\xcb\x0f?\x84nZ\xba\xdf\xa3\x8a~', # b'`$g\xe9\xa5r\xd2\xacG&\xf81^\x98\xf7\xda\xa5\xf4\x93)\xf3\x0c\x18\x84\xe4)!\x9dR\xa0\xac\xd3', # b'\xcfd\xd5|\xe2\xf1\xda\xb9\x1f|\xb9\xdc\xeb \xd7\xb0\x81g\xdc\x03\xd6dQ\xf14\x19`\x94o\xf7\xc7\x1b', # b'}LO\x14($d\n!\x1a\x91\xa8S\xb3\x05\xaa\x89\xf2\x0b\x97\xd3\x1c#\xe7\x86g`\xf1\x1a\xedXW'] def get_primary_node_private_helios_key(instance_number=0): return keys.PrivateKey(random_private_keys[instance_number]) from hvm.chains.mainnet import ( GENESIS_PRIVATE_KEY, GENESIS_WALLET_ADDRESS, ) SENDER = GENESIS_PRIVATE_KEY RECEIVER = get_primary_node_private_helios_key(1) RECEIVER2 = get_primary_node_private_helios_key(2) RECEIVER3 = get_primary_node_private_helios_key(3) RECEIVER4 = get_primary_node_private_helios_key(4) # create tx and blocks from the genesis block. self._chain.set_new_wallet_address( wallet_address=GENESIS_WALLET_ADDRESS, private_key=GENESIS_PRIVATE_KEY) self._chain.reinitialize() self._chain.enable_journal_db() journal_record = self._chain.record_journal() blocks_to_import = [] for i in range(10): self._chain.create_and_sign_transaction_for_queue_block( gas_price=0x01, gas=0x0c3500, to=RECEIVER.public_key.to_canonical_address(), value=1, data=b"", v=0, r=0, s=0) block_to_import = self._chain.import_current_queue_block() blocks_to_import.append(block_to_import) self._chain.discard_journal(journal_record) self._chain.disable_journal_db() for block_to_import in blocks_to_import: self._event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, block_to_import))) return []
async def _send_transactions(self, transactions, account, include_receive: bool = True): async with self._importing_block_lock: print("Importing block") # Check our current syncing stage. Must be sync stage 4. current_sync_stage_response = await self._event_bus.request( CurrentSyncStageRequest()) if current_sync_stage_response.sync_stage < FULLY_SYNCED_STAGE_ID: raise BaseRPCError( "This node is still syncing with the network. Please wait until this node has synced." ) # Check that our block import queue is not deep. It could cause min gas to increase before this block makes it there. current_block_import_queue_length = await self._event_bus.request( BlockImportQueueLengthRequest()) if current_block_import_queue_length.queue_length > MAX_ALLOWED_LENGTH_BLOCK_IMPORT_QUEUE: raise BaseRPCError( "This node is currently at it's maximum capacity of new blocks. Please wait a moment while we process them, and try again." ) normalized_wallet_address = to_normalized_address(account.address) wallet_address_hex = account.address wallet_address = decode_hex(wallet_address_hex) chain = self.get_new_chain(Address(wallet_address), account._key_obj) allowed_time_of_next_block = chain.get_allowed_time_of_next_block() now = int(time.time()) if now < allowed_time_of_next_block: raise BaseRPCError( "The minimum time between blocks has not passed. You must wait until {} to send the next block. " "Use personal_sendTrasactions to send multiple transactions at once." .format(allowed_time_of_next_block)) # make the chain read only for creating the block. We don't want to actually import it here. chain.enable_read_only_db() if include_receive: chain.populate_queue_block_with_receive_tx() signed_transactions = [] # Make sure it meets the average min gas price of the network. If it doesnt, then it won't reach consensus. current_network_min_gas_price_response = await self._event_bus.request( AverageNetworkMinGasPriceRequest()) network_min_gas_price = current_network_min_gas_price_response.min_gas_price local_min_gas_price = chain.min_gas_db.get_required_block_min_gas_price( ) actual_min_gas_price = max( [network_min_gas_price, local_min_gas_price]) min_gas_price = to_wei(actual_min_gas_price, 'gwei') safe_min_gas_price = to_wei(actual_min_gas_price + 5, 'gwei') for i in range(len(transactions)): tx = transactions[i] if to_normalized_address( tx['from']) != normalized_wallet_address: raise BaseRPCError( "When sending multiple transactions at once, they must all be from the same address" ) if 'gasPrice' in tx: gas_price = to_int_if_hex(tx['gasPrice']) else: gas_price = safe_min_gas_price if 'gas' in tx: gas = to_int_if_hex(tx['gas']) else: gas = GAS_TX if 'data' in tx: data = tx['data'] else: data = b'' if 'nonce' in tx: nonce = to_int_if_hex(tx['nonce']) else: nonce = None transactions[i]['nonce'] = nonce signed_tx = chain.create_and_sign_transaction_for_queue_block( gas_price=gas_price, gas=gas, to=decode_hex(tx['to']), value=to_int_if_hex(tx['value']), data=data, nonce=nonce, v=0, r=0, s=0) signed_transactions.append(signed_tx) block = chain.import_current_queue_block() average_block_gas_price = get_block_average_transaction_gas_price( block) if average_block_gas_price < min_gas_price: raise Exception( "The average gas price of all transactions in your block does not meet the required minimum gas price. Your average block gas price: {}. Min gas price: {}" .format(average_block_gas_price, min_gas_price)) if len(signed_transactions) == 0 and len( block.receive_transactions) == 0: raise BaseRPCError( "Cannot send block if it has no send or receive transactions." ) self._event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, block), from_rpc=True)) send_transaction_hashes = [ encode_hex(tx.hash) for tx in signed_transactions ] receive_transaction_hashes = [ encode_hex(tx.hash) for tx in block.receive_transactions ] all_transaction_hashes = send_transaction_hashes all_transaction_hashes.extend(receive_transaction_hashes) if not include_receive: return all_transaction_hashes[0] else: return all_transaction_hashes
async def _send_transactions(self, transactions, account): async with self._importing_block_lock: print("Importing block") normalized_wallet_address = to_normalized_address(account.address) wallet_address_hex = account.address wallet_address = decode_hex(wallet_address_hex) chain = self.get_new_chain(Address(wallet_address), account._key_obj) allowed_time_of_next_block = chain.get_allowed_time_of_next_block() now = int(time.time()) if now < allowed_time_of_next_block: raise BaseRPCError( "The minimum time between blocks has not passed. You must wait until {} to send the next block. " "Use personal_sendTrasactions to send multiple transactions at once." .format(allowed_time_of_next_block)) # make the chain read only for creating the block. We don't want to actually import it here. chain.enable_read_only_db() signed_transactions = [] for i in range(len(transactions)): tx = transactions[i] if to_normalized_address( tx['from']) != normalized_wallet_address: raise BaseRPCError( "When sending multiple transactions at once, they must all be from the same address" ) if 'gasPrice' in tx: gas_price = tx['gasPrice'] else: gas_price = to_wei( chain.chaindb.get_required_block_min_gas_price() + 1, 'gwei') if 'gas' in tx: gas = tx['gas'] else: gas = GAS_TX if 'data' in tx: data = tx['data'] else: data = b'' if 'nonce' in tx: nonce = tx['nonce'] else: nonce = None transactions[i]['nonce'] = nonce signed_tx = chain.create_and_sign_transaction_for_queue_block( gas_price=gas_price, gas=GAS_TX, to=decode_hex(tx['to']), value=to_int_if_hex(tx['value']), data=data, nonce=nonce, v=0, r=0, s=0) signed_transactions.append(signed_tx) block = chain.import_current_queue_block() self._event_bus.broadcast( NewBlockEvent(block=cast(P2PBlock, block), from_rpc=True)) if len(signed_transactions) == 1: return encode_hex(signed_transactions[0].hash) else: return [encode_hex(tx.hash) for tx in signed_transactions]