Exemple #1
0
    def build_computation(self, message, transaction):
        """Apply the message to the VM."""
        transaction_context = self.get_transaction_context(transaction)
        if message.is_create:
            is_collision = self.vm_state.account_db.account_has_code_or_nonce(
                message.storage_address)

            if is_collision:
                # The address of the newly created contract has *somehow* collided
                # with an existing contract address.
                computation = self.vm_state.get_computation(
                    message, transaction_context)
                computation._error = ContractCreationCollision(
                    "Address collision while creating contract: {0}".format(
                        encode_hex(message.storage_address), ))
                self.vm_state.logger.debug(
                    "Address collision while creating contract: %s",
                    encode_hex(message.storage_address),
                )
            else:
                computation = self.vm_state.get_computation(
                    message,
                    transaction_context,
                ).apply_create_message()
        else:
            computation = self.vm_state.get_computation(
                message, transaction_context).apply_message()

        return computation
Exemple #2
0
def _apply_frontier_create_message(vm, message):
    computation = vm.apply_message(message)

    if computation.is_error:
        return computation
    else:
        contract_code = computation.output

        if contract_code:
            contract_code_gas_fee = len(contract_code) * constants.GAS_CODEDEPOSIT
            try:
                computation.gas_meter.consume_gas(
                    contract_code_gas_fee,
                    reason="Write contract code for CREATE",
                )
            except OutOfGas:
                computation.output = b''
            else:
                vm.logger.debug(
                    "SETTING CODE: %s -> length: %s | hash: %s",
                    encode_hex(message.storage_address),
                    len(contract_code),
                    encode_hex(keccak(contract_code))
                )
                with vm.state_db() as state_db:
                    state_db.set_code(message.storage_address, contract_code)
        return computation
Exemple #3
0
    def run_computation(self, transaction, message):
        """Apply the message to the VM."""
        transaction_context = self.get_transaction_context_class()(
            gas_price=transaction.gas_price,
            origin=transaction.sender,
        )
        if message.is_create:
            is_collision = self.read_only_state_db.account_has_code_or_nonce(
                message.storage_address)

            if is_collision:
                # The address of the newly created contract has *somehow* collided
                # with an existing contract address.
                computation = self.get_computation(message,
                                                   transaction_context)
                computation._error = ContractCreationCollision(
                    "Address collision while creating contract: {0}".format(
                        encode_hex(message.storage_address), ))
                self.logger.debug(
                    "Address collision while creating contract: %s",
                    encode_hex(message.storage_address),
                )
            else:
                computation = self.get_computation(
                    message,
                    transaction_context,
                ).apply_create_message()
        else:
            computation = self.get_computation(
                message, transaction_context).apply_message()

        return computation
Exemple #4
0
    def validate_uncles(self, block):
        recent_ancestors = dict(
            (ancestor.hash, ancestor)
            for ancestor in self.get_ancestors(MAX_UNCLE_DEPTH + 1),
        )
        recent_uncles = []
        for ancestor in recent_ancestors.values():
            recent_uncles.extend([uncle.hash for uncle in ancestor.uncles])
        recent_ancestors[block.hash] = block
        recent_uncles.append(block.hash)

        for uncle in block.uncles:
            if uncle.hash in recent_ancestors:
                raise ValidationError(
                    "Duplicate uncle: {0}".format(encode_hex(uncle.hash)))
            recent_uncles.append(uncle.hash)

            if uncle.hash in recent_ancestors:
                raise ValidationError(
                    "Uncle {0} cannot be an ancestor of {1}".format(
                        encode_hex(uncle.hash), encode_hex(block.hash)))

            if uncle.parent_hash not in recent_ancestors or (
               uncle.parent_hash == block.header.parent_hash):
                raise ValidationError(
                    "Uncle's parent {0} is not an ancestor of {1}".format(
                        encode_hex(uncle.parent_hash), encode_hex(block.hash)))

            self.validate_seal(uncle)
Exemple #5
0
    def apply_create_message(self):
        computation = self.apply_message()

        if computation.is_error:
            return computation
        else:
            contract_code = computation.output

            if contract_code:
                contract_code_gas_fee = len(
                    contract_code) * constants.GAS_CODEDEPOSIT
                try:
                    computation.consume_gas(
                        contract_code_gas_fee,
                        reason="Write contract code for CREATE",
                    )
                except OutOfGas:
                    computation.output = b''
                else:
                    self.logger.debug(
                        "SETTING CODE: %s -> length: %s | hash: %s",
                        encode_hex(self.msg.storage_address),
                        len(contract_code), encode_hex(keccak(contract_code)))
                    self.state.account_db.set_code(self.msg.storage_address,
                                                   contract_code)
            return computation
Exemple #6
0
    def get_canonical_transaction(self,
                                  transaction_hash: Hash32) -> BaseTransaction:
        """
        Returns the requested transaction as specified by the transaction hash
        from the canonical chain.

        Raises TransactionNotFound if no transaction with the specified hash is
        found in the main chain.
        """
        (block_num,
         index) = self.chaindb.get_transaction_index(transaction_hash)
        VM = self.get_vm_class_for_block_number(block_num)

        transaction = self.chaindb.get_transaction_by_index(
            block_num,
            index,
            VM.get_transaction_class(),
        )

        if transaction.hash == transaction_hash:
            return transaction
        else:
            raise TransactionNotFound(
                "Found transaction {} instead of {} in block {} at {}".format(
                    encode_hex(transaction.hash),
                    encode_hex(transaction_hash),
                    block_num,
                    index,
                ))
Exemple #7
0
    def validate_uncles(self, block):
        recent_ancestors = dict(
            (ancestor.hash, ancestor)
            for ancestor in self.get_ancestors(MAX_UNCLE_DEPTH + 1),
        )
        recent_uncles = []
        for ancestor in recent_ancestors.values():
            recent_uncles.extend([uncle.hash for uncle in ancestor.uncles])
        recent_ancestors[block.hash] = block
        recent_uncles.append(block.hash)

        for uncle in block.uncles:
            if uncle.hash in recent_ancestors:
                raise ValidationError(
                    "Duplicate uncle: {0}".format(encode_hex(uncle.hash)))
            recent_uncles.append(uncle.hash)

            if uncle.hash in recent_ancestors:
                raise ValidationError(
                    "Uncle {0} cannot be an ancestor of {1}".format(
                        encode_hex(uncle.hash), encode_hex(block.hash)))

            if uncle.parent_hash not in recent_ancestors or (
               uncle.parent_hash == block.header.parent_hash):
                raise ValidationError(
                    "Uncle's parent {0} is not an ancestor of {1}".format(
                        encode_hex(uncle.parent_hash), encode_hex(block.hash)))

            self.validate_seal(uncle)
Exemple #8
0
def _apply_frontier_message(vm, message):
    snapshot = vm.snapshot()

    if message.depth > constants.STACK_DEPTH_LIMIT:
        raise StackDepthLimit("Stack depth limit reached")

    if message.should_transfer_value and message.value:
        with vm.state_db() as state_db:
            sender_balance = state_db.get_balance(message.sender)

            if sender_balance < message.value:
                raise InsufficientFunds("Insufficient funds: {0} < {1}".format(
                    sender_balance, message.value))

            state_db.delta_balance(message.sender, -1 * message.value)
            state_db.delta_balance(message.storage_address, message.value)

        vm.logger.debug(
            "TRANSFERRED: %s from %s -> %s",
            message.value,
            encode_hex(message.sender),
            encode_hex(message.storage_address),
        )

    with vm.state_db() as state_db:
        state_db.touch_account(message.storage_address)

    computation = vm.apply_computation(message)

    if computation.error:
        vm.revert(snapshot)
    else:
        vm.commit(snapshot)

    return computation
Exemple #9
0
    def persist_header(self, header):
        """
        :returns: iterable of headers newly on the canonical chain
        """
        if header.parent_hash != GENESIS_PARENT_HASH and not self.header_exists(header.parent_hash):
            raise ParentNotFound(
                "Cannot persist block header ({}) with unknown parent ({})".format(
                    encode_hex(header.hash), encode_hex(header.parent_hash)))

        self.db.set(
            header.hash,
            rlp.encode(header),
        )

        if header.parent_hash == GENESIS_PARENT_HASH:
            score = header.difficulty
        else:
            score = self.get_score(header.parent_hash) + header.difficulty
        self.db.set(
            make_block_hash_to_score_lookup_key(header.hash),
            rlp.encode(score, sedes=rlp.sedes.big_endian_int))

        try:
            head_score = self.get_score(self.get_canonical_head().hash)
        except CanonicalHeadNotFound:
            new_headers = self._set_as_canonical_chain_head(header)
        else:
            if score > head_score:
                new_headers = self._set_as_canonical_chain_head(header)
            else:
                new_headers = []

        return new_headers
Exemple #10
0
    def persist_header_to_db(self, header):
        """
        :returns: iterable of headers newly on the canonical chain
        """
        if header.parent_hash != GENESIS_PARENT_HASH and not self.header_exists(header.parent_hash):
            raise ParentNotFound(
                "Cannot persist block header ({}) with unknown parent ({})".format(
                    encode_hex(header.hash), encode_hex(header.parent_hash)))

        self.db.set(
            header.hash,
            rlp.encode(header),
        )

        if header.parent_hash == GENESIS_PARENT_HASH:
            score = header.difficulty
        else:
            score = self.get_score(header.parent_hash) + header.difficulty
        self.db.set(
            make_block_hash_to_score_lookup_key(header.hash),
            rlp.encode(score, sedes=rlp.sedes.big_endian_int))

        try:
            head_score = self.get_score(self.get_canonical_head().hash)
        except CanonicalHeadNotFound:
            new_headers = self._set_as_canonical_chain_head(header)
        else:
            if score > head_score:
                new_headers = self._set_as_canonical_chain_head(header)
            else:
                new_headers = []

        return new_headers
Exemple #11
0
    def validate_uncles(self, block: BaseBlock) -> None:
        """
        Validate the uncles for the given block.
        """
        # Check for duplicates
        uncle_groups = groupby(operator.attrgetter('hash'), block.uncles)
        duplicate_uncles = tuple(sorted(
            hash for hash, twins in uncle_groups.items() if len(twins) > 1
        ))
        if duplicate_uncles:
            raise ValidationError(
                "Block contains duplicate uncles:\n"
                " - {0}".format(' - '.join(duplicate_uncles))
            )

        recent_ancestors = tuple(
            ancestor
            for ancestor
            in self.get_ancestors(MAX_UNCLE_DEPTH + 1, header=block.header)
        )
        recent_ancestor_hashes = {ancestor.hash for ancestor in recent_ancestors}
        recent_uncle_hashes = _extract_uncle_hashes(recent_ancestors)

        for uncle in block.uncles:
            if uncle.hash == block.hash:
                raise ValidationError("Uncle has same hash as block")

            # ensure the uncle has not already been included.
            if uncle.hash in recent_uncle_hashes:
                raise ValidationError(
                    "Duplicate uncle: {0}".format(encode_hex(uncle.hash))
                )

            # ensure that the uncle is not one of the canonical chain blocks.
            if uncle.hash in recent_ancestor_hashes:
                raise ValidationError(
                    "Uncle {0} cannot be an ancestor of {1}".format(
                        encode_hex(uncle.hash), encode_hex(block.hash)))

            # ensure that the uncle was built off of one of the canonical chain
            # blocks.
            if uncle.parent_hash not in recent_ancestor_hashes or (
               uncle.parent_hash == block.header.parent_hash):
                raise ValidationError(
                    "Uncle's parent {0} is not an ancestor of {1}".format(
                        encode_hex(uncle.parent_hash), encode_hex(block.hash)))

            # Now perform VM level validation of the uncle
            self.validate_seal(uncle)

            try:
                uncle_parent = self.get_block_header_by_hash(uncle.parent_hash)
            except HeaderNotFound:
                raise ValidationError(
                    "Uncle ancestor not found: {0}".format(uncle.parent_hash)
                )

            uncle_vm_class = self.get_vm_class_for_block_number(uncle.block_number)
            uncle_vm_class.validate_uncle(block, uncle, uncle_parent)
Exemple #12
0
 def validate_gaslimit(self, header):
     parent_header = self.get_block_header_by_hash(header.parent_hash)
     low_bound, high_bound = compute_gas_limit_bounds(parent_header)
     if header.gas_limit < low_bound:
         raise ValidationError(
             "The gas limit on block {0} is too low: {1}. It must be at least {2}".format(
                 encode_hex(header.hash), header.gas_limit, low_bound))
     elif header.gas_limit > high_bound:
         raise ValidationError(
             "The gas limit on block {0} is too high: {1}. It must be at most {2}".format(
                 encode_hex(header.hash), header.gas_limit, high_bound))
Exemple #13
0
 def validate_gaslimit(self, header):
     parent_header = self.get_block_header_by_hash(header.parent_hash)
     low_bound, high_bound = compute_gas_limit_bounds(parent_header)
     if header.gas_limit < low_bound:
         raise ValidationError(
             "The gas limit on block {0} is too low: {1}. It must be at least {2}".format(
                 encode_hex(header.hash), header.gas_limit, low_bound))
     elif header.gas_limit > high_bound:
         raise ValidationError(
             "The gas limit on block {0} is too high: {1}. It must be at most {2}".format(
                 encode_hex(header.hash), header.gas_limit, high_bound))
Exemple #14
0
 def _get_new_logs(self):
     shard_id_topic_hex = encode_hex(
         self.shard_id.to_bytes(32, byteorder='big'))
     new_logs = self.log_handler.get_new_logs(
         address=self.vmc_address,
         topics=[
             encode_hex(self.COLLATION_ADDED_TOPIC),
             shard_id_topic_hex,
         ],
     )
     for log in new_logs:
         yield parse_collation_added_log(log)
Exemple #15
0
def check_pow(block_number, mining_hash, mix_hash, nonce, difficulty):
    validate_length(mix_hash, 32, title="Mix Hash")
    validate_length(mining_hash, 32, title="Mining Hash")
    validate_length(nonce, 8, title="POW Nonce")
    cache = get_cache(block_number)
    mining_output = hashimoto_light(
        block_number, cache, mining_hash, big_endian_to_int(nonce))
    if mining_output[b'mix digest'] != mix_hash:
        raise ValidationError("mix hash mismatch; {0} != {1}".format(
            encode_hex(mining_output[b'mix digest']), encode_hex(mix_hash)))
    result = big_endian_to_int(mining_output[b'result'])
    validate_lte(result, 2**256 // difficulty, title="POW Difficulty")
Exemple #16
0
def check_pow(block_number, mining_hash, mix_hash, nonce, difficulty):
    validate_length(mix_hash, 32, title="Mix Hash")
    validate_length(mining_hash, 32, title="Mining Hash")
    validate_length(nonce, 8, title="POW Nonce")
    cache = get_cache(block_number)
    mining_output = hashimoto_light(
        block_number, cache, mining_hash, big_endian_to_int(nonce))
    if mining_output[b'mix digest'] != mix_hash:
        raise ValidationError("mix hash mismatch; {0} != {1}".format(
            encode_hex(mining_output[b'mix digest']), encode_hex(mix_hash)))
    result = big_endian_to_int(mining_output[b'result'])
    validate_lte(result, 2**256 // difficulty, title="POW Difficulty")
Exemple #17
0
    def run_pre_computation(self, transaction):
        # Validate the transaction
        transaction.validate()

        self.validate_transaction(transaction)

        gas_fee = transaction.gas * transaction.gas_price
        with self.mutable_state_db() as state_db:
            # Buy Gas
            state_db.delta_balance(transaction.sender, -1 * gas_fee)

            # Increment Nonce
            state_db.increment_nonce(transaction.sender)

            # Setup VM Message
            message_gas = transaction.gas - transaction.intrinsic_gas

            if transaction.to == constants.CREATE_CONTRACT_ADDRESS:
                contract_address = generate_contract_address(
                    transaction.sender,
                    state_db.get_nonce(transaction.sender) - 1,
                )
                data = b''
                code = transaction.data
            else:
                contract_address = None
                data = transaction.data
                code = state_db.get_code(transaction.to)

        self.logger.info(
            ("TRANSACTION: sender: %s | to: %s | value: %s | gas: %s | "
             "gas-price: %s | s: %s | r: %s | v: %s | data-hash: %s"),
            encode_hex(transaction.sender),
            encode_hex(transaction.to),
            transaction.value,
            transaction.gas,
            transaction.gas_price,
            transaction.s,
            transaction.r,
            transaction.v,
            encode_hex(keccak(transaction.data)),
        )

        return Message(
            gas=message_gas,
            to=transaction.to,
            sender=transaction.sender,
            value=transaction.value,
            data=data,
            code=code,
            create_address=contract_address,
        )
Exemple #18
0
    def __enter__(self):
        self.logger.debug(
            ("COMPUTATION STARTING: gas: %s | from: %s | to: %s | value: %s "
             "| depth %s | static: %s"),
            self.msg.gas,
            encode_hex(self.msg.sender),
            encode_hex(self.msg.to),
            self.msg.value,
            self.msg.depth,
            "y" if self.msg.is_static else "n",
        )

        return self
Exemple #19
0
    def build_evm_message(self, transaction):

        transaction_context = self.get_transaction_context(transaction)
        gas_fee = transaction.gas * transaction_context.gas_price

        # Buy Gas
        self.vm_state.account_db.delta_balance(transaction.sender,
                                               -1 * gas_fee)

        # Increment Nonce
        self.vm_state.account_db.increment_nonce(transaction.sender)

        # Setup VM Message
        message_gas = transaction.gas - transaction.intrinsic_gas

        if transaction.to == constants.CREATE_CONTRACT_ADDRESS:
            contract_address = generate_contract_address(
                transaction.sender,
                self.vm_state.account_db.get_nonce(transaction.sender) - 1,
            )
            data = b''
            code = transaction.data
        else:
            contract_address = None
            data = transaction.data
            code = self.vm_state.account_db.get_code(transaction.to)

        self.vm_state.logger.debug(
            ("TRANSACTION: sender: %s | to: %s | value: %s | gas: %s | "
             "gas-price: %s | s: %s | r: %s | v: %s | data-hash: %s"),
            encode_hex(transaction.sender),
            encode_hex(transaction.to),
            transaction.value,
            transaction.gas,
            transaction.gas_price,
            transaction.s,
            transaction.r,
            transaction.v,
            encode_hex(keccak(transaction.data)),
        )

        message = Message(
            gas=message_gas,
            to=transaction.to,
            sender=transaction.sender,
            value=transaction.value,
            data=data,
            code=code,
            create_address=contract_address,
        )
        return message
Exemple #20
0
    def apply_create_message(self):
        snapshot = self.vm_state.snapshot()

        # EIP161 nonce incrementation
        with self.vm_state.state_db() as state_db:
            state_db.increment_nonce(self.msg.storage_address)

        computation = self.apply_message()

        if computation.is_error:
            self.vm_state.revert(snapshot)
            return computation
        else:
            contract_code = computation.output

            if contract_code and len(contract_code) >= EIP170_CODE_SIZE_LIMIT:
                computation._error = OutOfGas(
                    "Contract code size exceeds EIP170 limit of {0}.  Got code of "
                    "size: {1}".format(
                        EIP170_CODE_SIZE_LIMIT,
                        len(contract_code),
                    ))
                self.vm_state.revert(snapshot)
            elif contract_code:
                contract_code_gas_cost = len(
                    contract_code) * constants.GAS_CODEDEPOSIT
                try:
                    computation.gas_meter.consume_gas(
                        contract_code_gas_cost,
                        reason="Write contract code for CREATE",
                    )
                except OutOfGas as err:
                    # Different from Frontier: reverts state on gas failure while
                    # writing contract code.
                    computation._error = err
                    self.vm_state.revert(snapshot)
                else:
                    if self.logger:
                        self.logger.debug(
                            "SETTING CODE: %s -> length: %s | hash: %s",
                            encode_hex(self.msg.storage_address),
                            len(contract_code),
                            encode_hex(keccak(contract_code)))

                    with self.vm_state.state_db() as state_db:
                        state_db.set_code(self.msg.storage_address,
                                          contract_code)
                    self.vm_state.commit(snapshot)
            else:
                self.vm_state.commit(snapshot)
            return computation
Exemple #21
0
    def run_post_computation(self, transaction, computation):
        # Self Destruct Refunds
        num_deletions = len(computation.get_accounts_for_deletion())
        if num_deletions:
            computation.gas_meter.refund_gas(REFUND_SELFDESTRUCT *
                                             num_deletions)

        # Gas Refunds
        gas_remaining = computation.get_gas_remaining()
        gas_refunded = computation.get_gas_refund()
        gas_used = transaction.gas - gas_remaining
        gas_refund = min(gas_refunded, gas_used // 2)
        gas_refund_amount = (gas_refund +
                             gas_remaining) * transaction.gas_price

        if gas_refund_amount:
            self.logger.debug(
                'TRANSACTION REFUND: %s -> %s',
                gas_refund_amount,
                encode_hex(computation.msg.sender),
            )

            with self.mutable_state_db() as state_db:
                state_db.delta_balance(computation.msg.sender,
                                       gas_refund_amount)

        # Miner Fees
        transaction_fee = (transaction.gas - gas_remaining -
                           gas_refund) * transaction.gas_price
        self.logger.debug(
            'TRANSACTION FEE: %s -> %s',
            transaction_fee,
            encode_hex(self.coinbase),
        )
        with self.mutable_state_db() as state_db:
            state_db.delta_balance(self.coinbase, transaction_fee)

        # Process Self Destructs
        with self.mutable_state_db() as state_db:
            for account, beneficiary in computation.get_accounts_for_deletion(
            ):
                # TODO: need to figure out how we prevent multiple selfdestructs from
                # the same account and if this is the right place to put this.
                self.logger.debug('DELETING ACCOUNT: %s', encode_hex(account))

                # TODO: this balance setting is likely superflous and can be
                # removed since `delete_account` does this.
                state_db.set_balance(account, 0)
                state_db.delete_account(account)

        return computation
Exemple #22
0
    def apply_create_message(self):
        snapshot = self.vm_state.snapshot()

        # EIP161 nonce incrementation
        with self.vm_state.state_db() as state_db:
            state_db.increment_nonce(self.msg.storage_address)

        computation = self.apply_message()

        if computation.is_error:
            self.vm_state.revert(snapshot)
            return computation
        else:
            contract_code = computation.output

            if contract_code and len(contract_code) >= EIP170_CODE_SIZE_LIMIT:
                computation._error = OutOfGas(
                    "Contract code size exceeds EIP170 limit of {0}.  Got code of "
                    "size: {1}".format(
                        EIP170_CODE_SIZE_LIMIT,
                        len(contract_code),
                    )
                )
                self.vm_state.revert(snapshot)
            elif contract_code:
                contract_code_gas_cost = len(contract_code) * constants.GAS_CODEDEPOSIT
                try:
                    computation.gas_meter.consume_gas(
                        contract_code_gas_cost,
                        reason="Write contract code for CREATE",
                    )
                except OutOfGas as err:
                    # Different from Frontier: reverts state on gas failure while
                    # writing contract code.
                    computation._error = err
                    self.vm_state.revert(snapshot)
                else:
                    if self.logger:
                        self.logger.debug(
                            "SETTING CODE: %s -> length: %s | hash: %s",
                            encode_hex(self.msg.storage_address),
                            len(contract_code),
                            encode_hex(keccak(contract_code))
                        )

                    with self.vm_state.state_db() as state_db:
                        state_db.set_code(self.msg.storage_address, contract_code)
                    self.vm_state.commit(snapshot)
            else:
                self.vm_state.commit(snapshot)
            return computation
Exemple #23
0
    def __enter__(self):
        self.logger.debug(
            (
                "COMPUTATION STARTING: gas: %s | from: %s | to: %s | value: %s "
                "| depth %s | static: %s"
            ),
            self.msg.gas,
            encode_hex(self.msg.sender),
            encode_hex(self.msg.to),
            self.msg.value,
            self.msg.depth,
            "y" if self.msg.is_static else "n",
        )

        return self
Exemple #24
0
def format_block(block: BaseBlock) -> str:
    return (
        "\n\n"
        "------------------------Block------------------------------------\n"
        "Number #{b.number:>12} Hash {hash}\n"
        "-----------------------------------------------------------------\n"
    ).format(b=block, hash=encode_hex(block.hash))
Exemple #25
0
 def get_pending_transaction(self, transaction_hash, transaction_class):
     try:
         data = self.db.get(make_transaction_hash_to_data_lookup_key(transaction_hash))
         return rlp.decode(data, sedes=transaction_class)
     except KeyError:
         raise TransactionNotFound(
             "Transaction with hash {} not found".format(encode_hex(transaction_hash)))
Exemple #26
0
    def __call__(self, computation):
        computation.consume_gas(self.gas_cost, reason=self.mnemonic)

        value, start_position, size = computation.stack_pop(
            num_items=3,
            type_hint=constants.UINT256,
        )

        computation.extend_memory(start_position, size)

        insufficient_funds = computation.state.account_db.get_balance(
            computation.msg.storage_address
        ) < value
        stack_too_deep = computation.msg.depth + 1 > constants.STACK_DEPTH_LIMIT

        if insufficient_funds or stack_too_deep:
            computation.stack_push(0)
            return

        call_data = computation.memory_read(start_position, size)

        create_msg_gas = self.max_child_gas_modifier(
            computation.get_gas_remaining()
        )
        computation.consume_gas(create_msg_gas, reason="CREATE")

        creation_nonce = computation.state.account_db.get_nonce(computation.msg.storage_address)
        computation.state.account_db.increment_nonce(computation.msg.storage_address)

        contract_address = generate_contract_address(
            computation.msg.storage_address,
            creation_nonce,
        )

        is_collision = computation.state.account_db.account_has_code_or_nonce(contract_address)

        if is_collision:
            self.logger.debug(
                "Address collision while creating contract: %s",
                encode_hex(contract_address),
            )
            computation.stack_push(0)
            return

        child_msg = computation.prepare_child_message(
            gas=create_msg_gas,
            to=constants.CREATE_CONTRACT_ADDRESS,
            value=value,
            data=b'',
            code=call_data,
            create_address=contract_address,
        )

        child_computation = computation.apply_child_computation(child_msg)

        if child_computation.is_error:
            computation.stack_push(0)
        else:
            computation.stack_push(contract_address)
        computation.return_gas(child_computation.get_gas_remaining())
Exemple #27
0
    def import_block(self,
                     block: BaseBlock,
                     perform_validation: bool = True) -> BaseBlock:
        """
        Imports a complete block.
        """
        try:
            parent_header = self.get_block_header_by_hash(
                block.header.parent_hash)
        except HeaderNotFound:
            raise ValidationError(
                "Attempt to import block #{}.  Cannot import block {} before importing "
                "its parent block at {}".format(
                    block.number,
                    block.hash,
                    block.header.parent_hash,
                ))

        base_header_for_import = self.create_header_from_parent(parent_header)
        imported_block = self.get_vm(base_header_for_import).import_block(
            block)

        # Validate the imported block.
        if perform_validation:
            ensure_imported_block_unchanged(imported_block, block)
            self.validate_block(imported_block)

        self.chaindb.persist_block(imported_block)
        self.logger.debug(
            'IMPORTED_BLOCK: number %s | hash %s',
            imported_block.number,
            encode_hex(imported_block.hash),
        )
        return imported_block
Exemple #28
0
    def import_block(self, block, perform_validation=True):
        """
        Imports a complete block.
        """
        if block.number > self.header.block_number:
            raise ValidationError(
                "Attempt to import block #{0}.  Cannot import block with number "
                "greater than current block #{1}.".format(
                    block.number,
                    self.header.block_number,
                )
            )

        parent_chain = self.get_chain_at_block_parent(block)
        imported_block = parent_chain.get_vm().import_block(block)

        # Validate the imported block.
        if perform_validation:
            ensure_imported_block_unchanged(imported_block, block)
            self.validate_block(imported_block)

        self.chaindb.persist_block(imported_block)
        self.header = self.create_header_from_parent(self.get_canonical_head())
        self.logger.debug(
            'IMPORTED_BLOCK: number %s | hash %s',
            imported_block.number,
            encode_hex(imported_block.hash),
        )
        return imported_block
Exemple #29
0
    def _decode_header_to_dict(
            cls, encoded_header: bytes) -> Iterator[Tuple[str, Any]]:
        if len(encoded_header) != cls.smc_encoded_size:
            raise ValidationError(
                "Expected encoded header to be of size: {0}. Got size {1} instead.\n- {2}"
                .format(
                    cls.smc_encoded_size,
                    len(encoded_header),
                    encode_hex(encoded_header),
                ))

        start_indices = accumulate(lambda i, field: i + field[2],
                                   cls.fields_with_sizes, 0)
        field_bounds = sliding_window(2, start_indices)
        for byte_range, field in zip(field_bounds, cls._meta.fields):
            start_index, end_index = byte_range
            field_name, field_type = field

            field_bytes = encoded_header[start_index:end_index]
            if field_type == rlp.sedes.big_endian_int:
                # remove the leading zeros, to avoid `not minimal length` error in deserialization
                formatted_field_bytes = field_bytes.lstrip(b'\x00')
            elif field_type == address:
                formatted_field_bytes = field_bytes[-20:]
            else:
                formatted_field_bytes = field_bytes
            yield field_name, field_type.deserialize(formatted_field_bytes)
Exemple #30
0
    def import_block(self, block, perform_validation=True):
        """
        Imports a complete block.
        """
        if block.number > self.header.block_number:
            raise ValidationError(
                "Attempt to import block #{0}.  Cannot import block with number "
                "greater than current block #{1}.".format(
                    block.number,
                    self.header.block_number,
                )
            )

        parent_chain = self.get_chain_at_block_parent(block)
        imported_block = parent_chain.get_vm().import_block(block)

        # Validate the imported block.
        if perform_validation:
            ensure_imported_block_unchanged(imported_block, block)
            self.validate_block(imported_block)

        self.chaindb.persist_block_to_db(imported_block)
        self.header = self.create_header_from_parent(self.get_canonical_head())
        self.logger.debug(
            'IMPORTED_BLOCK: number %s | hash %s',
            imported_block.number,
            encode_hex(imported_block.hash),
        )
        return imported_block
Exemple #31
0
 def get_pending_transaction(self, transaction_hash, transaction_class):
     try:
         data = self.db.get(make_transaction_hash_to_data_lookup_key(transaction_hash))
         return rlp.decode(data, sedes=transaction_class)
     except KeyError:
         raise TransactionNotFound(
             "Transaction with hash {} not found".format(encode_hex(transaction_hash)))
Exemple #32
0
    def get_transaction_index(self, transaction_hash):
        try:
            encoded_key = self.db.get(make_transaction_hash_to_block_lookup_key(transaction_hash))
        except KeyError:
            raise TransactionNotFound(
                "Transaction {} not found in canonical chain".format(encode_hex(transaction_hash)))

        transaction_key = rlp.decode(encoded_key, sedes=TransactionKey)
        return (transaction_key.block_number, transaction_key.index)
Exemple #33
0
    def get_transaction_index(self, transaction_hash):
        try:
            encoded_key = self.db.get(make_transaction_hash_to_block_lookup_key(transaction_hash))
        except KeyError:
            raise TransactionNotFound(
                "Transaction {} not found in canonical chain".format(encode_hex(transaction_hash)))

        transaction_key = rlp.decode(encoded_key, sedes=TransactionKey)
        return (transaction_key.block_number, transaction_key.index)
Exemple #34
0
    def run_post_computation(self, transaction, computation):
        state_db_cm = functools.partial(self.state_db,
                                        access_list=transaction.prefix_list)

        # Self Destruct Refunds
        num_deletions = len(computation.get_accounts_for_deletion())
        if num_deletions:
            computation.refund_gas(REFUND_SELFDESTRUCT * num_deletions)

        # Gas Refunds
        transaction_fee, gas_refund_amount = computation.compute_transaction_fee_and_refund(
        )

        if gas_refund_amount:
            self.logger.debug(
                'TRANSACTION REFUND: %s -> %s',
                gas_refund_amount,
                encode_hex(computation.msg.to),
            )

            with state_db_cm() as state_db:
                state_db.delta_balance(computation.msg.to, gas_refund_amount)

        # Miner Fees
        self.logger.debug(
            'TRANSACTION FEE: %s',
            transaction_fee,
        )

        # Process Self Destructs
        with state_db_cm() as state_db:
            for account, beneficiary in computation.get_accounts_for_deletion(
            ):
                # TODO: need to figure out how we prevent multiple selfdestructs from
                # the same account and if this is the right place to put this.
                self.logger.debug('DELETING ACCOUNT: %s', encode_hex(account))

                # TODO: this balance setting is likely superflous and can be
                # removed since `delete_account` does this.
                state_db.set_balance(account, 0)
                state_db.delete_account(account)

        return computation
Exemple #35
0
    def get_canonical_transaction(self, transaction_hash):
        (block_num, index) = self.chaindb.get_transaction_index(transaction_hash)
        VM = self.get_vm_class_for_block_number(block_num)

        transaction = self.chaindb.get_transaction_by_index(
            block_num,
            index,
            VM.get_transaction_class(),
        )

        if transaction.hash == transaction_hash:
            return transaction
        else:
            raise TransactionNotFound("Found transaction {} instead of {} in block {} at {}".format(
                encode_hex(transaction.hash),
                encode_hex(transaction_hash),
                block_num,
                index,
            ))
Exemple #36
0
    def get_canonical_transaction(self, transaction_hash):
        (block_num, index) = self.chaindb.get_transaction_index(transaction_hash)
        VM = self.get_vm_class_for_block_number(block_num)

        transaction = self.chaindb.get_transaction_by_index(
            block_num,
            index,
            VM.get_transaction_class(),
        )

        if transaction.hash == transaction_hash:
            return transaction
        else:
            raise TransactionNotFound("Found transaction {} instead of {} in block {} at {}".format(
                encode_hex(transaction.hash),
                encode_hex(transaction_hash),
                block_num,
                index,
            ))
Exemple #37
0
    def run_pre_computation(self, transaction):
        state_db_cm = functools.partial(self.state_db,
                                        access_list=transaction.prefix_list)

        # Validate the transaction
        transaction.validate()

        self.validate_transaction(transaction)

        with state_db_cm() as state_db:
            # Setup VM Message
            message_gas = transaction.gas - transaction.intrinsic_gas

            if transaction.code:
                data = b''
                code = transaction.code
                is_create = True
            else:
                data = transaction.data
                code = state_db.get_code(transaction.to)
                is_create = False

        self.logger.info(
            ("TRANSACTION: to: %s | gas: %s | "
             "data-hash: %s | code-hash: %s | salt: %s"),
            encode_hex(transaction.to),
            transaction.gas,
            encode_hex(keccak(transaction.data)),
            encode_hex(keccak(transaction.code)),
            encode_hex(transaction.salt),
        )

        return ShardingMessage(
            gas=message_gas,
            to=transaction.to,
            sender=ENTRY_POINT,
            value=0,
            data=data,
            code=code,
            is_create=is_create,
            access_list=transaction.prefix_list,
        )
Exemple #38
0
    def apply_message(self):
        snapshot = self.vm_state.snapshot()

        if self.msg.depth > constants.STACK_DEPTH_LIMIT:
            raise StackDepthLimit("Stack depth limit reached")

        if self.msg.should_transfer_value and self.msg.value:
            with self.vm_state.state_db() as state_db:
                sender_balance = state_db.get_balance(self.msg.sender)

                if sender_balance < self.msg.value:
                    raise InsufficientFunds(
                        "Insufficient funds: {0} < {1}".format(
                            sender_balance, self.msg.value))

                state_db.delta_balance(self.msg.sender, -1 * self.msg.value)
                state_db.delta_balance(self.msg.storage_address,
                                       self.msg.value)

            self.logger.debug(
                "TRANSFERRED: %s from %s -> %s",
                self.msg.value,
                encode_hex(self.msg.sender),
                encode_hex(self.msg.storage_address),
            )

        with self.vm_state.state_db() as state_db:
            state_db.touch_account(self.msg.storage_address)

        computation = self.apply_computation(
            self.vm_state,
            self.msg,
            self.opcodes,
            self.precompiles,
        )

        if computation.is_error:
            self.vm_state.revert(snapshot)
        else:
            self.vm_state.commit(snapshot)

        return computation
Exemple #39
0
    def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None:
        if exc_value and isinstance(exc_value, VMError):
            self.logger.debug(
                (
                    "COMPUTATION ERROR: gas: %s | from: %s | to: %s | value: %s | "
                    "depth: %s | static: %s | error: %s"
                ),
                self.msg.gas,
                encode_hex(self.msg.sender),
                encode_hex(self.msg.to),
                self.msg.value,
                self.msg.depth,
                "y" if self.msg.is_static else "n",
                exc_value,
            )
            self._error = exc_value
            if self.should_burn_gas:
                self.consume_gas(
                    self._gas_meter.gas_remaining,
                    reason=" ".join((
                        "Zeroing gas due to VM Exception:",
                        str(exc_value),
                    )),
                )

            # suppress VM exceptions
            return True
        elif exc_type is None:
            self.logger.debug(
                (
                    "COMPUTATION SUCCESS: from: %s | to: %s | value: %s | "
                    "depth: %s | static: %s | gas-used: %s | gas-remaining: %s"
                ),
                encode_hex(self.msg.sender),
                encode_hex(self.msg.to),
                self.msg.value,
                self.msg.depth,
                "y" if self.msg.is_static else "n",
                self.msg.gas - self._gas_meter.gas_remaining,
                self._gas_meter.gas_remaining,
            )
Exemple #40
0
    def __exit__(self, exc_type, exc_value, traceback):
        if exc_value and isinstance(exc_value, VMError):
            self.logger.debug(
                (
                    "COMPUTATION ERROR: gas: %s | from: %s | to: %s | value: %s | "
                    "depth: %s | static: %s | error: %s"
                ),
                self.msg.gas,
                encode_hex(self.msg.sender),
                encode_hex(self.msg.to),
                self.msg.value,
                self.msg.depth,
                "y" if self.msg.is_static else "n",
                exc_value,
            )
            self._error = exc_value
            if self.should_burn_gas:
                self.gas_meter.consume_gas(
                    self.gas_meter.gas_remaining,
                    reason=" ".join((
                        "Zeroing gas due to VM Exception:",
                        str(exc_value),
                    )),
                )

            # suppress VM exceptions
            return True
        elif exc_type is None:
            self.logger.debug(
                (
                    "COMPUTATION SUCCESS: from: %s | to: %s | value: %s | "
                    "depth: %s | static: %s | gas-used: %s | gas-remaining: %s"
                ),
                encode_hex(self.msg.sender),
                encode_hex(self.msg.to),
                self.msg.value,
                self.msg.depth,
                "y" if self.msg.is_static else "n",
                self.msg.gas - self.gas_meter.gas_remaining,
                self.gas_meter.gas_remaining,
            )
Exemple #41
0
def _selfdestruct(computation, beneficiary):
    local_balance = computation.state.account_db.get_balance(computation.msg.storage_address)
    beneficiary_balance = computation.state.account_db.get_balance(beneficiary)

    # 1st: Transfer to beneficiary
    computation.state.account_db.set_balance(beneficiary, local_balance + beneficiary_balance)
    # 2nd: Zero the balance of the address being deleted (must come after
    # sending to beneficiary in case the contract named itself as the
    # beneficiary.
    computation.state.account_db.set_balance(computation.msg.storage_address, 0)

    computation.logger.debug(
        "SELFDESTRUCT: %s (%s) -> %s",
        encode_hex(computation.msg.storage_address),
        local_balance,
        encode_hex(beneficiary),
    )

    # 3rd: Register the account to be deleted
    computation.register_account_for_deletion(beneficiary)
    raise Halt('SELFDESTRUCT')
Exemple #42
0
    def get_block_header_by_hash(self, block_hash):
        """
        Returns the requested block header as specified by block hash.

        Raises BlockNotFound if it is not present in the db.
        """
        validate_word(block_hash, title="Block Hash")
        try:
            block = self.db.get(block_hash)
        except KeyError:
            raise BlockNotFound("No block with hash {0} found".format(
                encode_hex(block_hash)))
        return rlp.decode(block, sedes=BlockHeader)
Exemple #43
0
def _selfdestruct(computation, beneficiary):
    with computation.vm_state.state_db() as state_db:
        local_balance = state_db.get_balance(computation.msg.storage_address)
        beneficiary_balance = state_db.get_balance(beneficiary)

        # 1st: Transfer to beneficiary
        state_db.set_balance(beneficiary, local_balance + beneficiary_balance)
        # 2nd: Zero the balance of the address being deleted (must come after
        # sending to beneficiary in case the contract named itself as the
        # beneficiary.
        state_db.set_balance(computation.msg.storage_address, 0)

    computation.vm_state.logger.debug(
        "SELFDESTRUCT: %s (%s) -> %s",
        encode_hex(computation.msg.storage_address),
        local_balance,
        encode_hex(beneficiary),
    )

    # 3rd: Register the account to be deleted
    computation.register_account_for_deletion(beneficiary)
    raise Halt('SELFDESTRUCT')
Exemple #44
0
    def apply_create_message(self):
        snapshot = self.vm_state.snapshot()

        computation = self.apply_message()

        if computation.is_error:
            self.vm_state.revert(snapshot)
            return computation
        else:
            contract_code = computation.output

            if contract_code:
                contract_code_gas_cost = len(contract_code) * constants.GAS_CODEDEPOSIT
                try:
                    computation.gas_meter.consume_gas(
                        contract_code_gas_cost,
                        reason="Write contract code for CREATE",
                    )
                except OutOfGas as err:
                    # Different from Frontier: reverts state on gas failure while
                    # writing contract code.
                    computation._error = err
                    self.vm_state.revert(snapshot)
                else:
                    if self.logger:
                        self.logger.debug(
                            "SETTING CODE: %s -> length: %s | hash: %s",
                            encode_hex(self.msg.storage_address),
                            len(contract_code),
                            encode_hex(keccak(contract_code))
                        )

                    with self.vm_state.state_db() as state_db:
                        state_db.set_code(self.msg.storage_address, contract_code)
                    self.vm_state.commit(snapshot)
            else:
                self.vm_state.commit(snapshot)
            return computation
Exemple #45
0
    def execute_transaction(self, transaction):
        computation = _execute_frontier_transaction(self, transaction)

        #
        # EIP161 state clearing
        #
        touched_accounts = collect_touched_accounts(computation)

        with self.state_db() as state_db:
            for account in touched_accounts:
                if state_db.account_exists(account) and state_db.account_is_empty(account):
                    self.logger.debug(
                        "CLEARING EMPTY ACCOUNT: %s",
                        encode_hex(account),
                    )
                    state_db.delete_account(account)

        return computation
Exemple #46
0
def sstore(computation):
    slot, value = computation.stack.pop(num_items=2, type_hint=constants.UINT256)

    with computation.vm_state.state_db(read_only=True) as state_db:
        current_value = state_db.get_storage(
            address=computation.msg.storage_address,
            slot=slot,
        )

    is_currently_empty = not bool(current_value)
    is_going_to_be_empty = not bool(value)

    if is_currently_empty:
        gas_refund = 0
    elif is_going_to_be_empty:
        gas_refund = constants.REFUND_SCLEAR
    else:
        gas_refund = 0

    if is_currently_empty and is_going_to_be_empty:
        gas_cost = constants.GAS_SRESET
    elif is_currently_empty:
        gas_cost = constants.GAS_SSET
    elif is_going_to_be_empty:
        gas_cost = constants.GAS_SRESET
    else:
        gas_cost = constants.GAS_SRESET

    computation.gas_meter.consume_gas(gas_cost, reason="SSTORE: {0}[{1}] -> {2} ({3})".format(
        encode_hex(computation.msg.storage_address),
        slot,
        value,
        current_value,
    ))

    if gas_refund:
        computation.gas_meter.refund_gas(gas_refund)

    with computation.vm_state.state_db() as state_db:
        state_db.set_storage(
            address=computation.msg.storage_address,
            slot=slot,
            value=value,
        )
Exemple #47
0
def _execute_frontier_transaction(vm_state, transaction):
    # Reusable for other forks

    #
    # 1) Pre Computation
    #

    # Validate the transaction
    transaction.validate()

    vm_state.validate_transaction(transaction)

    gas_fee = transaction.gas * transaction.gas_price
    with vm_state.state_db() as state_db:
        # Buy Gas
        state_db.delta_balance(transaction.sender, -1 * gas_fee)

        # Increment Nonce
        state_db.increment_nonce(transaction.sender)

        # Setup VM Message
        message_gas = transaction.gas - transaction.intrinsic_gas

        if transaction.to == constants.CREATE_CONTRACT_ADDRESS:
            contract_address = generate_contract_address(
                transaction.sender,
                state_db.get_nonce(transaction.sender) - 1,
            )
            data = b''
            code = transaction.data
        else:
            contract_address = None
            data = transaction.data
            code = state_db.get_code(transaction.to)

    vm_state.logger.info(
        (
            "TRANSACTION: sender: %s | to: %s | value: %s | gas: %s | "
            "gas-price: %s | s: %s | r: %s | v: %s | data-hash: %s"
        ),
        encode_hex(transaction.sender),
        encode_hex(transaction.to),
        transaction.value,
        transaction.gas,
        transaction.gas_price,
        transaction.s,
        transaction.r,
        transaction.v,
        encode_hex(keccak(transaction.data)),
    )

    message = Message(
        gas=message_gas,
        to=transaction.to,
        sender=transaction.sender,
        value=transaction.value,
        data=data,
        code=code,
        create_address=contract_address,
    )
    transaction_context = vm_state.get_transaction_context_class()(
        gas_price=transaction.gas_price,
        origin=transaction.sender,
    )

    #
    # 2) Apply the message to the VM.
    #
    if message.is_create:
        with vm_state.state_db(read_only=True) as state_db:
            is_collision = state_db.account_has_code_or_nonce(contract_address)

        if is_collision:
            # The address of the newly created contract has *somehow* collided
            # with an existing contract address.
            computation = vm_state.get_computation(message, transaction_context)
            computation._error = ContractCreationCollision(
                "Address collision while creating contract: {0}".format(
                    encode_hex(contract_address),
                )
            )
            vm_state.logger.debug(
                "Address collision while creating contract: %s",
                encode_hex(contract_address),
            )
        else:
            computation = vm_state.get_computation(
                message,
                transaction_context,
            ).apply_create_message()
    else:
        computation = vm_state.get_computation(message, transaction_context).apply_message()

    #
    # 2) Post Computation
    #
    # Self Destruct Refunds
    num_deletions = len(computation.get_accounts_for_deletion())
    if num_deletions:
        computation.gas_meter.refund_gas(REFUND_SELFDESTRUCT * num_deletions)

    # Gas Refunds
    gas_remaining = computation.get_gas_remaining()
    gas_refunded = computation.get_gas_refund()
    gas_used = transaction.gas - gas_remaining
    gas_refund = min(gas_refunded, gas_used // 2)
    gas_refund_amount = (gas_refund + gas_remaining) * transaction.gas_price

    if gas_refund_amount:
        vm_state.logger.debug(
            'TRANSACTION REFUND: %s -> %s',
            gas_refund_amount,
            encode_hex(message.sender),
        )

        with vm_state.state_db() as state_db:
            state_db.delta_balance(message.sender, gas_refund_amount)

    # Miner Fees
    transaction_fee = (transaction.gas - gas_remaining - gas_refund) * transaction.gas_price
    vm_state.logger.debug(
        'TRANSACTION FEE: %s -> %s',
        transaction_fee,
        encode_hex(vm_state.coinbase),
    )
    with vm_state.state_db() as state_db:
        state_db.delta_balance(vm_state.coinbase, transaction_fee)

    # Process Self Destructs
    with vm_state.state_db() as state_db:
        for account, beneficiary in computation.get_accounts_for_deletion():
            # TODO: need to figure out how we prevent multiple selfdestructs from
            # the same account and if this is the right place to put this.
            vm_state.logger.debug('DELETING ACCOUNT: %s', encode_hex(account))

            # TODO: this balance setting is likely superflous and can be
            # removed since `delete_account` does this.
            state_db.set_balance(account, 0)
            state_db.delete_account(account)

    return computation
Exemple #48
0
    def __call__(self, computation):
        computation.gas_meter.consume_gas(self.gas_cost, reason=self.mnemonic)

        value, start_position, size = computation.stack.pop(
            num_items=3,
            type_hint=constants.UINT256,
        )

        computation.extend_memory(start_position, size)

        with computation.vm_state.state_db(read_only=True) as state_db:
            insufficient_funds = state_db.get_balance(
                computation.msg.storage_address) < value
        stack_too_deep = computation.msg.depth + 1 > constants.STACK_DEPTH_LIMIT

        if insufficient_funds or stack_too_deep:
            computation.stack.push(0)
            return

        call_data = computation.memory.read(start_position, size)

        create_msg_gas = self.max_child_gas_modifier(
            computation.gas_meter.gas_remaining
        )
        computation.gas_meter.consume_gas(create_msg_gas, reason="CREATE")

        with computation.vm_state.state_db() as state_db:
            creation_nonce = state_db.get_nonce(computation.msg.storage_address)
            state_db.increment_nonce(computation.msg.storage_address)

            contract_address = generate_contract_address(
                computation.msg.storage_address,
                creation_nonce,
            )

            is_collision = state_db.account_has_code_or_nonce(contract_address)

        if is_collision:
            computation.vm_state.logger.debug(
                "Address collision while creating contract: %s",
                encode_hex(contract_address),
            )
            computation.stack.push(0)
            return

        child_msg = computation.prepare_child_message(
            gas=create_msg_gas,
            to=constants.CREATE_CONTRACT_ADDRESS,
            value=value,
            data=b'',
            code=call_data,
            create_address=contract_address,
        )

        child_computation = computation.apply_child_computation(child_msg)

        if child_computation.is_error:
            computation.stack.push(0)
        else:
            computation.stack.push(contract_address)
        computation.gas_meter.return_gas(child_computation.gas_meter.gas_remaining)
Exemple #49
0
 def hex_hash(self):
     return encode_hex(self.hash)
def test_round_trip_with_hex_string_start(value):
    intermediate_value = decode_hex(value)
    round_trip_value = encode_hex(intermediate_value)
    assert round_trip_value == value
def test_basic_hexadecimal_encoding(value, expected):
    actual = encode_hex(value)
    assert actual == expected
Exemple #52
0
 def __repr__(self):
     return '<BlockHeader #{0} {1}>'.format(
         self.block_number,
         encode_hex(self.hash)[2:10],
     )