Search in sources :

Example 1 with GoQuorumMutablePrivateWorldStateUpdater

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

the class GoQuorumBlockProcessor method processBlock.

@Override
public Result processBlock(final Blockchain blockchain, final MutableWorldState publicWorldState, final MutableWorldState privateWorldState, final Block block) {
    final BlockHeader blockHeader = block.getHeader();
    final List<Transaction> transactions = block.getBody().getTransactions();
    final List<BlockHeader> ommers = block.getBody().getOmmers();
    final List<TransactionReceipt> publicTxReceipts = new ArrayList<>();
    final List<TransactionReceipt> privateTxReceipts = new ArrayList<>();
    long currentGasUsed = 0;
    final GoQuorumPrivateStorage.Updater privateStorageUpdater = goQuorumPrivateStorage.updater();
    for (final Transaction transaction : transactions) {
        if (!hasAvailableBlockBudget(blockHeader, transaction, currentGasUsed)) {
            return AbstractBlockProcessor.Result.failed();
        }
        final WorldUpdater publicWorldStateUpdater = publicWorldState.updater();
        final BlockHashLookup blockHashLookup = new BlockHashLookup(blockHeader, blockchain);
        final Address miningBeneficiary = miningBeneficiaryCalculator.calculateBeneficiary(blockHeader);
        WorldUpdater effectiveWorldUpdater = null;
        Transaction effectiveTransaction;
        final boolean isGoQuorumPrivateTransaction = transaction.isGoQuorumPrivateTransaction(transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode());
        if (isGoQuorumPrivateTransaction) {
            // private transaction
            try {
                effectiveTransaction = retrievePrivateTransactionFromEnclave(transaction);
                effectiveWorldUpdater = new GoQuorumMutablePrivateWorldStateUpdater(publicWorldStateUpdater, privateWorldState.updater());
            } catch (final EnclaveClientException e) {
                // private transaction but not party to it
                // We do not have to execute anything, but we still need to validate the transaction
                effectiveTransaction = null;
                final ValidationResult<TransactionInvalidReason> validationResult = validateTransaction(blockHeader, transaction, publicWorldStateUpdater);
                if (!validationResult.isValid()) {
                    return AbstractBlockProcessor.Result.failed();
                }
            }
        } else {
            // public Transaction
            effectiveWorldUpdater = publicWorldState.updater();
            effectiveTransaction = transaction;
        }
        if (effectiveTransaction != null) {
            // public tx, or private tx that we are party to
            final TransactionProcessingResult result = transactionProcessor.processTransaction(blockchain, effectiveWorldUpdater, blockHeader, effectiveTransaction, miningBeneficiary, OperationTracer.NO_TRACING, blockHashLookup, true, TransactionValidationParams.processingBlock(), null);
            if (result.isInvalid()) {
                LOG.info("Block processing error: transaction invalid '{}'. Block {} Transaction {}", result.getValidationResult().getInvalidReason(), blockHeader.getHash().toHexString(), transaction.getHash().toHexString());
                return AbstractBlockProcessor.Result.failed();
            }
            if (isGoQuorumPrivateTransaction) {
                // private transaction we are party to
                publicTxReceipts.add(transactionReceiptFactory.create(transaction.getType(), publicResultForWhenWeHaveAPrivateTransaction(transaction), publicWorldState, currentGasUsed));
                privateTxReceipts.add(transactionReceiptFactory.create(transaction.getType(), result, privateWorldState, currentGasUsed));
                publicWorldStateUpdater.getOrCreate(effectiveTransaction.getSender()).getMutable().incrementNonce();
                effectiveWorldUpdater.commit();
            } else {
                // public transaction
                final long gasUsed = transaction.getGasLimit() - result.getGasRemaining();
                currentGasUsed += gasUsed;
                publicTxReceipts.add(transactionReceiptFactory.create(transaction.getType(), result, publicWorldState, currentGasUsed));
                privateTxReceipts.add(null);
                effectiveWorldUpdater.commit();
            }
        } else {
            // private transaction we are not party to
            publicTxReceipts.add(transactionReceiptFactory.create(transaction.getType(), publicResultForWhenWeHaveAPrivateTransaction(transaction), publicWorldState, currentGasUsed));
            privateTxReceipts.add(null);
            publicWorldStateUpdater.getOrCreate(transaction.getSender()).getMutable().incrementNonce();
        }
        publicWorldStateUpdater.commit();
    }
    if (!rewardCoinbase(publicWorldState, blockHeader, ommers, skipZeroBlockRewards)) {
        // no need to log, rewardCoinbase logs the error.
        return AbstractBlockProcessor.Result.failed();
    }
    // create the bloom for the private transactions in the block and store it
    final LogsBloomFilter.Builder privateBloomBuilder = LogsBloomFilter.builder();
    privateTxReceipts.stream().filter(pr -> pr != null).forEach(pr -> privateBloomBuilder.insertFilter(pr.getBloomFilter()));
    blockHeader.setPrivateLogsBloom(privateBloomBuilder.build());
    publicWorldState.persist(blockHeader);
    privateWorldState.persist(null);
    privateStorageUpdater.putPrivateStateRootHashMapping(publicWorldState.rootHash(), privateWorldState.rootHash());
    privateStorageUpdater.commit();
    return Result.successful(publicTxReceipts, privateTxReceipts);
}
Also used : MainnetBlockProcessor(org.hyperledger.besu.ethereum.mainnet.MainnetBlockProcessor) ValidationResult(org.hyperledger.besu.ethereum.mainnet.ValidationResult) EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) LoggerFactory(org.slf4j.LoggerFactory) OperationTracer(org.hyperledger.besu.evm.tracing.OperationTracer) GoQuorumMutablePrivateWorldStateUpdater(org.hyperledger.besu.ethereum.worldstate.GoQuorumMutablePrivateWorldStateUpdater) Bytes(org.apache.tuweni.bytes.Bytes) Address(org.hyperledger.besu.datatypes.Address) GoQuorumReceiveResponse(org.hyperledger.besu.enclave.types.GoQuorumReceiveResponse) MainnetTransactionValidator(org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator) ArrayList(java.util.ArrayList) GoQuorumPrivacyParameters(org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters) GoQuorumEnclave(org.hyperledger.besu.enclave.GoQuorumEnclave) TransactionReceipt(org.hyperledger.besu.ethereum.core.TransactionReceipt) Wei(org.hyperledger.besu.datatypes.Wei) TransactionInvalidReason(org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason) Block(org.hyperledger.besu.ethereum.core.Block) AbstractBlockProcessor(org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor) Logger(org.slf4j.Logger) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) Blockchain(org.hyperledger.besu.ethereum.chain.Blockchain) LogsBloomFilter(org.hyperledger.besu.evm.log.LogsBloomFilter) MutableWorldState(org.hyperledger.besu.ethereum.core.MutableWorldState) MainnetTransactionProcessor(org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor) BlockHashLookup(org.hyperledger.besu.ethereum.vm.BlockHashLookup) TransactionValidationParams(org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams) EnclaveClientException(org.hyperledger.besu.enclave.EnclaveClientException) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) List(java.util.List) Optional(java.util.Optional) MiningBeneficiaryCalculator(org.hyperledger.besu.ethereum.mainnet.MiningBeneficiaryCalculator) Transaction(org.hyperledger.besu.ethereum.core.Transaction) Collections(java.util.Collections) Address(org.hyperledger.besu.datatypes.Address) LogsBloomFilter(org.hyperledger.besu.evm.log.LogsBloomFilter) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) TransactionReceipt(org.hyperledger.besu.ethereum.core.TransactionReceipt) ArrayList(java.util.ArrayList) GoQuorumMutablePrivateWorldStateUpdater(org.hyperledger.besu.ethereum.worldstate.GoQuorumMutablePrivateWorldStateUpdater) ValidationResult(org.hyperledger.besu.ethereum.mainnet.ValidationResult) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) Transaction(org.hyperledger.besu.ethereum.core.Transaction) BlockHashLookup(org.hyperledger.besu.ethereum.vm.BlockHashLookup) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) EnclaveClientException(org.hyperledger.besu.enclave.EnclaveClientException)

Aggregations

ArrayList (java.util.ArrayList)1 Collections (java.util.Collections)1 List (java.util.List)1 Optional (java.util.Optional)1 Bytes (org.apache.tuweni.bytes.Bytes)1 Address (org.hyperledger.besu.datatypes.Address)1 Wei (org.hyperledger.besu.datatypes.Wei)1 EnclaveClientException (org.hyperledger.besu.enclave.EnclaveClientException)1 GoQuorumEnclave (org.hyperledger.besu.enclave.GoQuorumEnclave)1 GoQuorumReceiveResponse (org.hyperledger.besu.enclave.types.GoQuorumReceiveResponse)1 Blockchain (org.hyperledger.besu.ethereum.chain.Blockchain)1 Block (org.hyperledger.besu.ethereum.core.Block)1 BlockHeader (org.hyperledger.besu.ethereum.core.BlockHeader)1 GoQuorumPrivacyParameters (org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters)1 MutableWorldState (org.hyperledger.besu.ethereum.core.MutableWorldState)1 Transaction (org.hyperledger.besu.ethereum.core.Transaction)1 TransactionReceipt (org.hyperledger.besu.ethereum.core.TransactionReceipt)1 AbstractBlockProcessor (org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor)1 MainnetBlockProcessor (org.hyperledger.besu.ethereum.mainnet.MainnetBlockProcessor)1 MainnetTransactionProcessor (org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor)1