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);
}
Aggregations