def apply_create_message( cls, state: StateAPI, message: MessageAPI, transaction_context: TransactionContextAPI) -> ComputationAPI: computation = cls.apply_message(state, message, transaction_context) if computation.is_error: return computation else: contract_code = computation.output if contract_code: contract_code_gas_fee = len(contract_code) * GAS_CODEDEPOSIT try: computation.consume_gas( contract_code_gas_fee, reason="Write contract code for CREATE", ) except OutOfGas: computation.output = b'' else: cls.logger.debug2( "SETTING CODE: %s -> length: %s | hash: %s", encode_hex(message.storage_address), len(contract_code), encode_hex(keccak(contract_code))) state.set_code(message.storage_address, contract_code) return computation
def validate_daejun_transaction(state : StateAPI, transaction: SignedTransactionAPI) -> None: ## homesated logic ## if transaction.s > SECPK1_N // 2 or transaction.s == 0: raise ValidationError("Invalid signature S value") ## frontier logic ## # gas_cost = transaction.gas * transaction.gas_price sender_balance = state.get_balance(transaction.sender) # if sender_balance < gas_cost: # raise ValidationError( # f"Sender {transaction.sender!r} cannot afford txn gas " # f"{gas_cost} with account balance {sender_balance}" # ) # total_cost = transaction.value + gas_cost total_cost = transaction.value if sender_balance < total_cost: raise ValidationError("Sender account balance cannot afford txn") sender_nonce = state.get_nonce(transaction.sender) if sender_nonce != transaction.nonce: raise ValidationError( f"Invalid transaction nonce: Expected {sender_nonce}, but got {transaction.nonce}" )
def setup_state(desired_state: AccountState, state: StateAPI) -> None: for account, account_data in desired_state.items(): for slot, value in account_data['storage'].items(): state.set_storage(account, slot, value) nonce = account_data['nonce'] code = account_data['code'] balance = account_data['balance'] state.set_nonce(account, nonce) state.set_code(account, code) state.set_balance(account, balance) state.persist()
def _get_computation_error(state: StateAPI, transaction: SignedTransactionAPI) -> Optional[VMError]: snapshot = state.snapshot() try: computation = state.apply_transaction(transaction) if computation.is_error: return computation.error else: return None finally: state.revert(snapshot)
def apply_state_dict(state: StateAPI, state_dict: AccountState) -> None: for account, account_data in state_dict.items(): state.set_balance(account, account_data["balance"]) state.set_nonce(account, account_data["nonce"]) state.set_code(account, account_data["code"]) for slot, value in account_data["storage"].items(): state.set_storage(account, slot, value)
def make_receipt(base_header: BlockHeaderAPI, transaction: SignedTransactionAPI, computation: ComputationAPI, state: StateAPI) -> ReceiptAPI: receipt_without_state_root = make_frontier_receipt( base_header, transaction, computation) return receipt_without_state_root.copy( state_root=state.make_state_root())
def validate_frontier_transaction(state: StateAPI, transaction: SignedTransactionAPI) -> None: gas_cost = transaction.gas * transaction.gas_price sender_balance = state.get_balance(transaction.sender) if sender_balance < gas_cost: raise ValidationError( f"Sender {transaction.sender!r} cannot afford txn gas " f"{gas_cost} with account balance {sender_balance}" ) total_cost = transaction.value + gas_cost if sender_balance < total_cost: raise ValidationError("Sender account balance cannot afford txn") sender_nonce = state.get_nonce(transaction.sender) if sender_nonce != transaction.nonce: raise ValidationError( f"Invalid transaction nonce: Expected {sender_nonce}, but got {transaction.nonce}" )
def validate_frontier_transaction(state: StateAPI, transaction: SignedTransactionAPI) -> None: gas_cost = transaction.gas * transaction.gas_price sender_balance = state.get_balance(transaction.sender) if sender_balance < gas_cost: raise ValidationError( "Sender {} cannot afford txn gas {} with account balance {}". format( transaction.sender, gas_cost, sender_balance, )) total_cost = transaction.value + gas_cost if sender_balance < total_cost: raise ValidationError("Sender account balance cannot afford txn") if state.get_nonce(transaction.sender) != transaction.nonce: raise ValidationError("Invalid transaction nonce")
def make_receipt(cls, base_header: BlockHeaderAPI, transaction: SignedTransactionAPI, computation: ComputationAPI, state: StateAPI) -> ReceiptAPI: gas_used = base_header.gas_used + cls.finalize_gas_used( transaction, computation) receipt_without_state_root = make_frontier_receipt( computation, gas_used) return receipt_without_state_root.copy( state_root=state.make_state_root())
def validate_frontier_transaction(state: StateAPI, transaction: SignedTransactionAPI) -> None: max_gas_cost = transaction.gas * state.get_gas_price(transaction) sender_balance = state.get_balance(transaction.sender) if sender_balance < max_gas_cost: raise ValidationError( f"Sender {transaction.sender!r} cannot afford txn gas " f"{max_gas_cost} with account balance {sender_balance}") total_cost = transaction.value + max_gas_cost if sender_balance < total_cost: raise ValidationError( f"Sender does not have enough balance to cover transaction value and gas " f" (has {sender_balance}, needs {total_cost})") sender_nonce = state.get_nonce(transaction.sender) if sender_nonce != transaction.nonce: raise ValidationError( f"Invalid transaction nonce: Expected {sender_nonce}, but got {transaction.nonce}" )
def apply_create_message( cls, state: StateAPI, message: MessageAPI, transaction_context: TransactionContextAPI) -> ComputationAPI: snapshot = state.snapshot() computation = cls.apply_message(state, message, transaction_context) if computation.is_error: 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.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 state.revert(snapshot) else: if cls.logger: cls.logger.debug2( "SETTING CODE: %s -> length: %s | hash: %s", encode_hex(message.storage_address), len(contract_code), encode_hex(keccak(contract_code))) state.set_code(message.storage_address, contract_code) state.commit(snapshot) else: state.commit(snapshot) return computation
def apply_message( cls, state: StateAPI, message: MessageAPI, transaction_context: TransactionContextAPI) -> ComputationAPI: snapshot = state.snapshot() if message.depth > STACK_DEPTH_LIMIT: raise StackDepthLimit("Stack depth limit reached") if message.should_transfer_value and message.value: sender_balance = state.get_balance(message.sender) if sender_balance < message.value: raise InsufficientFunds( f"Insufficient funds: {sender_balance} < {message.value}") state.delta_balance(message.sender, -1 * message.value) state.delta_balance(message.storage_address, message.value) cls.logger.debug2( "TRANSFERRED: %s from %s -> %s", message.value, encode_hex(message.sender), encode_hex(message.storage_address), ) state.touch_account(message.storage_address) computation = cls.apply_computation( state, message, transaction_context, ) if computation.is_error: state.revert(snapshot) else: state.commit(snapshot) return computation