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)
Exemple #2
0
    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
Exemple #3
0
    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)
Exemple #4
0
    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 []
Exemple #5
0
    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
Exemple #6
0
    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]
Exemple #7
0
    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
Exemple #8
0
    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 []
Exemple #9
0
    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
Exemple #10
0
    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]