Search in sources :

Example 1 with DefaultMutablePrivateWorldStateUpdater

use of org.hyperledger.besu.ethereum.worldstate.DefaultMutablePrivateWorldStateUpdater in project besu by hyperledger.

the class PrivateTransactionProcessor method processTransaction.

public TransactionProcessingResult processTransaction(final WorldUpdater publicWorldState, final WorldUpdater privateWorldState, final ProcessableBlockHeader blockHeader, final Hash pmtHash, final PrivateTransaction transaction, final Address miningBeneficiary, final OperationTracer operationTracer, final Function<Long, Hash> blockHashLookup, final Bytes privacyGroupId) {
    try {
        LOG.trace("Starting private execution of {}", transaction);
        final Address senderAddress = transaction.getSender();
        final EvmAccount maybePrivateSender = privateWorldState.getAccount(senderAddress);
        final MutableAccount sender = maybePrivateSender != null ? maybePrivateSender.getMutable() : privateWorldState.createAccount(senderAddress, 0, Wei.ZERO).getMutable();
        final ValidationResult<TransactionInvalidReason> validationResult = privateTransactionValidator.validate(transaction, sender.getNonce(), false);
        if (!validationResult.isValid()) {
            return TransactionProcessingResult.invalid(validationResult);
        }
        final long previousNonce = sender.incrementNonce();
        LOG.trace("Incremented private sender {} nonce ({} -> {})", senderAddress, previousNonce, sender.getNonce());
        final WorldUpdater mutablePrivateWorldStateUpdater = new DefaultMutablePrivateWorldStateUpdater(publicWorldState, privateWorldState);
        final Deque<MessageFrame> messageFrameStack = new ArrayDeque<>();
        final MessageFrame.Builder commonMessageFrameBuilder = MessageFrame.builder().messageFrameStack(messageFrameStack).maxStackSize(maxStackSize).worldUpdater(mutablePrivateWorldStateUpdater).initialGas(Long.MAX_VALUE).originator(senderAddress).gasPrice(transaction.getGasPrice()).sender(senderAddress).value(transaction.getValue()).apparentValue(transaction.getValue()).blockValues(blockHeader).depth(0).completer(__ -> {
        }).miningBeneficiary(miningBeneficiary).blockHashLookup(blockHashLookup).contextVariables(Map.of(KEY_TRANSACTION_HASH, pmtHash));
        final MessageFrame initialFrame;
        if (transaction.isContractCreation()) {
            final Address privateContractAddress = Address.privateContractAddress(senderAddress, previousNonce, privacyGroupId);
            LOG.debug("Calculated contract address {} from sender {} with nonce {} and privacy group {}", privateContractAddress, senderAddress, previousNonce, privacyGroupId);
            final Bytes initCodeBytes = transaction.getPayload();
            initialFrame = commonMessageFrameBuilder.type(MessageFrame.Type.CONTRACT_CREATION).address(privateContractAddress).contract(privateContractAddress).inputData(Bytes.EMPTY).code(contractCreationProcessor.getCodeFromEVM(Hash.hash(initCodeBytes), initCodeBytes)).build();
        } else {
            final Address to = transaction.getTo().get();
            final Optional<Account> maybeContract = Optional.ofNullable(mutablePrivateWorldStateUpdater.get(to));
            initialFrame = commonMessageFrameBuilder.type(MessageFrame.Type.MESSAGE_CALL).address(to).contract(to).inputData(transaction.getPayload()).code(maybeContract.map(c -> messageCallProcessor.getCodeFromEVM(c.getCodeHash(), c.getCode())).orElse(Code.EMPTY_CODE)).build();
        }
        messageFrameStack.addFirst(initialFrame);
        while (!messageFrameStack.isEmpty()) {
            process(messageFrameStack.peekFirst(), operationTracer);
        }
        if (initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) {
            mutablePrivateWorldStateUpdater.commit();
        }
        if (initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) {
            return TransactionProcessingResult.successful(initialFrame.getLogs(), 0, 0, initialFrame.getOutputData(), ValidationResult.valid());
        } else {
            return TransactionProcessingResult.failed(0, 0, ValidationResult.invalid(TransactionInvalidReason.PRIVATE_TRANSACTION_FAILED), initialFrame.getRevertReason());
        }
    } catch (final RuntimeException re) {
        LOG.error("Critical Exception Processing Transaction", re);
        return TransactionProcessingResult.invalid(ValidationResult.invalid(TransactionInvalidReason.INTERNAL_ERROR, "Internal Error in Besu - " + re));
    }
}
Also used : ValidationResult(org.hyperledger.besu.ethereum.mainnet.ValidationResult) EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) KEY_TRANSACTION_HASH(org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) Account(org.hyperledger.besu.evm.account.Account) LoggerFactory(org.slf4j.LoggerFactory) OperationTracer(org.hyperledger.besu.evm.tracing.OperationTracer) Bytes(org.apache.tuweni.bytes.Bytes) Deque(java.util.Deque) Address(org.hyperledger.besu.datatypes.Address) Function(java.util.function.Function) MainnetTransactionValidator(org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator) AbstractMessageProcessor(org.hyperledger.besu.evm.processor.AbstractMessageProcessor) Map(java.util.Map) Wei(org.hyperledger.besu.datatypes.Wei) TransactionInvalidReason(org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason) Code(org.hyperledger.besu.evm.Code) ProcessableBlockHeader(org.hyperledger.besu.ethereum.core.ProcessableBlockHeader) Logger(org.slf4j.Logger) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) GasCalculator(org.hyperledger.besu.evm.gascalculator.GasCalculator) DefaultMutablePrivateWorldStateUpdater(org.hyperledger.besu.ethereum.worldstate.DefaultMutablePrivateWorldStateUpdater) MutableAccount(org.hyperledger.besu.evm.account.MutableAccount) Optional(java.util.Optional) MessageFrame(org.hyperledger.besu.evm.frame.MessageFrame) ArrayDeque(java.util.ArrayDeque) Transaction(org.hyperledger.besu.ethereum.core.Transaction) Hash(org.hyperledger.besu.datatypes.Hash) EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) Account(org.hyperledger.besu.evm.account.Account) MutableAccount(org.hyperledger.besu.evm.account.MutableAccount) Address(org.hyperledger.besu.datatypes.Address) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) MessageFrame(org.hyperledger.besu.evm.frame.MessageFrame) ArrayDeque(java.util.ArrayDeque) Bytes(org.apache.tuweni.bytes.Bytes) EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) TransactionInvalidReason(org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason) MutableAccount(org.hyperledger.besu.evm.account.MutableAccount) DefaultMutablePrivateWorldStateUpdater(org.hyperledger.besu.ethereum.worldstate.DefaultMutablePrivateWorldStateUpdater)

Aggregations

ArrayDeque (java.util.ArrayDeque)1 Deque (java.util.Deque)1 Map (java.util.Map)1 Optional (java.util.Optional)1 Function (java.util.function.Function)1 Bytes (org.apache.tuweni.bytes.Bytes)1 Address (org.hyperledger.besu.datatypes.Address)1 Hash (org.hyperledger.besu.datatypes.Hash)1 Wei (org.hyperledger.besu.datatypes.Wei)1 ProcessableBlockHeader (org.hyperledger.besu.ethereum.core.ProcessableBlockHeader)1 Transaction (org.hyperledger.besu.ethereum.core.Transaction)1 MainnetTransactionValidator (org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator)1 KEY_TRANSACTION_HASH (org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH)1 ValidationResult (org.hyperledger.besu.ethereum.mainnet.ValidationResult)1 TransactionProcessingResult (org.hyperledger.besu.ethereum.processing.TransactionProcessingResult)1 TransactionInvalidReason (org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason)1 DefaultMutablePrivateWorldStateUpdater (org.hyperledger.besu.ethereum.worldstate.DefaultMutablePrivateWorldStateUpdater)1 Code (org.hyperledger.besu.evm.Code)1 Account (org.hyperledger.besu.evm.account.Account)1 EvmAccount (org.hyperledger.besu.evm.account.EvmAccount)1