use of org.hyperledger.besu.ethereum.core.Transaction in project besu by hyperledger.
the class TransactionSimulator method processWithWorldUpdater.
@Nonnull
public Optional<TransactionSimulatorResult> processWithWorldUpdater(final CallParameter callParams, final TransactionValidationParams transactionValidationParams, final OperationTracer operationTracer, final BlockHeader header, final WorldUpdater updater) {
final ProtocolSpec protocolSpec = protocolSchedule.getByBlockNumber(header.getNumber());
final Address senderAddress = callParams.getFrom() != null ? callParams.getFrom() : DEFAULT_FROM;
BlockHeader blockHeaderToProcess = header;
if (transactionValidationParams.isAllowExceedingBalance() && header.getBaseFee().isPresent()) {
blockHeaderToProcess = BlockHeaderBuilder.fromHeader(header).baseFee(Wei.ZERO).blockHeaderFunctions(protocolSpec.getBlockHeaderFunctions()).buildBlockHeader();
}
final Account sender = updater.get(senderAddress);
final long nonce = sender != null ? sender.getNonce() : 0L;
final long gasLimit = callParams.getGasLimit() >= 0 ? callParams.getGasLimit() : blockHeaderToProcess.getGasLimit();
final Wei value = callParams.getValue() != null ? callParams.getValue() : Wei.ZERO;
final Bytes payload = callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY;
final MainnetTransactionProcessor transactionProcessor = protocolSchedule.getByBlockNumber(blockHeaderToProcess.getNumber()).getTransactionProcessor();
final Optional<Transaction> maybeTransaction = buildTransaction(callParams, transactionValidationParams, header, senderAddress, nonce, gasLimit, value, payload);
if (maybeTransaction.isEmpty()) {
return Optional.empty();
}
final Transaction transaction = maybeTransaction.get();
final TransactionProcessingResult result = transactionProcessor.processTransaction(blockchain, updater, blockHeaderToProcess, transaction, protocolSpec.getMiningBeneficiaryCalculator().calculateBeneficiary(blockHeaderToProcess), new BlockHashLookup(blockHeaderToProcess, blockchain), false, transactionValidationParams, operationTracer);
// If GoQuorum privacy enabled, and value = zero, get max gas possible for a PMT hash.
// It is possible to have a data field that has a lower intrinsic value than the PMT hash.
// This means a potential over-estimate of gas, but the tx, if sent with this gas, will not
// fail.
final boolean goQuorumCompatibilityMode = transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode();
if (goQuorumCompatibilityMode && value.isZero()) {
final long privateGasEstimateAndState = protocolSpec.getGasCalculator().getMaximumTransactionCost(64);
if (privateGasEstimateAndState > result.getEstimateGasUsedByTransaction()) {
// modify the result to have the larger estimate
final TransactionProcessingResult resultPmt = TransactionProcessingResult.successful(result.getLogs(), privateGasEstimateAndState, result.getGasRemaining(), result.getOutput(), result.getValidationResult());
return Optional.of(new TransactionSimulatorResult(transaction, resultPmt));
}
}
return Optional.of(new TransactionSimulatorResult(transaction, result));
}
use of org.hyperledger.besu.ethereum.core.Transaction in project besu by hyperledger.
the class PrivateMigrationBlockProcessor method processBlock.
public AbstractBlockProcessor.Result processBlock(final Blockchain blockchain, final MutableWorldState worldState, final BlockHeader blockHeader, final List<Transaction> transactions, final List<BlockHeader> ommers) {
long gasUsed = 0;
final List<TransactionReceipt> receipts = new ArrayList<>();
for (final Transaction transaction : transactions) {
final long remainingGasBudget = blockHeader.getGasLimit() - gasUsed;
if (Long.compareUnsigned(transaction.getGasLimit(), remainingGasBudget) > 0) {
LOG.warn("Transaction processing error: transaction gas limit {} exceeds available block budget" + " remaining {}", transaction.getGasLimit(), remainingGasBudget);
return AbstractBlockProcessor.Result.failed();
}
final WorldUpdater worldStateUpdater = worldState.updater();
final BlockHashLookup blockHashLookup = new BlockHashLookup(blockHeader, blockchain);
final Address miningBeneficiary = miningBeneficiaryCalculator.calculateBeneficiary(blockHeader);
final TransactionProcessingResult result = transactionProcessor.processTransaction(blockchain, worldStateUpdater, blockHeader, transaction, miningBeneficiary, blockHashLookup, true, TransactionValidationParams.processingBlock());
if (result.isInvalid()) {
return AbstractBlockProcessor.Result.failed();
}
worldStateUpdater.commit();
gasUsed = transaction.getGasLimit() - result.getGasRemaining() + gasUsed;
final TransactionReceipt transactionReceipt = transactionReceiptFactory.create(transaction.getType(), result, worldState, gasUsed);
receipts.add(transactionReceipt);
}
if (!rewardCoinbase(worldState, blockHeader, ommers, skipZeroBlockRewards)) {
return AbstractBlockProcessor.Result.failed();
}
return AbstractBlockProcessor.Result.successful(receipts);
}
use of org.hyperledger.besu.ethereum.core.Transaction in project besu by hyperledger.
the class SigningPrivateMarkerTransactionFactory method signAndBuild.
protected Bytes signAndBuild(final UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction, final KeyPair signingKey) {
final Transaction transaction = Transaction.builder().type(TransactionType.FRONTIER).nonce(unsignedPrivateMarkerTransaction.getNonce()).gasPrice(unsignedPrivateMarkerTransaction.getGasPrice().map(Wei::fromQuantity).orElse(null)).gasLimit(unsignedPrivateMarkerTransaction.getGasLimit()).to(Address.fromPlugin(unsignedPrivateMarkerTransaction.getTo().get())).value(Wei.fromQuantity(unsignedPrivateMarkerTransaction.getValue())).payload(unsignedPrivateMarkerTransaction.getPayload()).signAndBuild(signingKey);
final BytesValueRLPOutput out = new BytesValueRLPOutput();
transaction.writeTo(out);
return out.encoded();
}
use of org.hyperledger.besu.ethereum.core.Transaction in project besu by hyperledger.
the class PrivateStorageMigration method migratePrivateStorage.
public void migratePrivateStorage() {
final long migrationStartTimestamp = System.currentTimeMillis();
final long chainHeadBlockNumber = blockchain.getChainHeadBlockNumber();
LOG.info("Migrating private storage database...");
for (long blockNumber = 0; blockNumber <= chainHeadBlockNumber; blockNumber++) {
final Block block = blockchain.getBlockByNumber(blockNumber).orElseThrow(PrivateStorageMigrationException::new);
final Hash blockHash = block.getHash();
final BlockHeader blockHeader = block.getHeader();
LOG.info("Processing block {} ({}/{})", blockHash, blockNumber, chainHeadBlockNumber);
createPrivacyGroupHeadBlockMap(blockHeader);
final int lastPmtIndex = findLastPMTIndexInBlock(block);
if (lastPmtIndex >= 0) {
final ProtocolSpec protocolSpec = protocolSchedule.getByBlockNumber(blockNumber);
final PrivateMigrationBlockProcessor privateMigrationBlockProcessor = privateMigrationBlockProcessorBuilder.apply(protocolSpec);
final MutableWorldState publicWorldState = blockchain.getBlockHeader(blockHeader.getParentHash()).flatMap(header -> publicWorldStateArchive.getMutable(header.getStateRoot(), header.getHash())).orElseThrow(PrivateStorageMigrationException::new);
final List<Transaction> transactionsToProcess = block.getBody().getTransactions().subList(0, lastPmtIndex + 1);
final List<BlockHeader> ommers = block.getBody().getOmmers();
privateMigrationBlockProcessor.processBlock(blockchain, publicWorldState, blockHeader, transactionsToProcess, ommers);
}
}
if (isResultingPrivateStateRootAtHeadValid()) {
privateStateStorage.updater().putDatabaseVersion(SCHEMA_VERSION_1_4_0).commit();
} else {
throw new PrivateStorageMigrationException("Inconsistent state root. Please re-sync.");
}
final long migrationDuration = System.currentTimeMillis() - migrationStartTimestamp;
LOG.info("Migration took {} seconds", migrationDuration / 1000.0);
}
use of org.hyperledger.besu.ethereum.core.Transaction in project besu by hyperledger.
the class TransactionPool method validateTransaction.
private ValidationResult<TransactionInvalidReason> validateTransaction(final Transaction transaction, final boolean isLocal) {
final BlockHeader chainHeadBlockHeader = getChainHeadBlockHeader();
final FeeMarket feeMarket = protocolSchedule.getByBlockNumber(chainHeadBlockHeader.getNumber()).getFeeMarket();
// Check whether it's a GoQuorum transaction
boolean goQuorumCompatibilityMode = getTransactionValidator().getGoQuorumCompatibilityMode();
if (transaction.isGoQuorumPrivateTransaction(goQuorumCompatibilityMode)) {
final Optional<Wei> weiValue = ofNullable(transaction.getValue());
if (weiValue.isPresent() && !weiValue.get().isZero()) {
return ValidationResult.invalid(TransactionInvalidReason.ETHER_VALUE_NOT_SUPPORTED);
}
}
// executable:
if ((!effectiveGasPriceIsAboveConfiguredMinGasPrice(transaction) && !miningParameters.isMiningEnabled()) || (!feeMarket.satisfiesFloorTxCost(transaction))) {
return ValidationResult.invalid(TransactionInvalidReason.GAS_PRICE_TOO_LOW);
}
final ValidationResult<TransactionInvalidReason> basicValidationResult = getTransactionValidator().validate(transaction, chainHeadBlockHeader.getBaseFee(), TransactionValidationParams.transactionPool());
if (!basicValidationResult.isValid()) {
return basicValidationResult;
}
if (isLocal && strictReplayProtectionShouldBeEnforceLocally(chainHeadBlockHeader) && transaction.getChainId().isEmpty()) {
// Strict replay protection is enabled but the tx is not replay-protected
return ValidationResult.invalid(TransactionInvalidReason.REPLAY_PROTECTED_SIGNATURE_REQUIRED);
}
if (transaction.getGasLimit() > chainHeadBlockHeader.getGasLimit()) {
return ValidationResult.invalid(TransactionInvalidReason.EXCEEDS_BLOCK_GAS_LIMIT, String.format("Transaction gas limit of %s exceeds block gas limit of %s", transaction.getGasLimit(), chainHeadBlockHeader.getGasLimit()));
}
if (transaction.getType().equals(TransactionType.EIP1559) && !feeMarket.implementsBaseFee()) {
return ValidationResult.invalid(TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, "EIP-1559 transaction are not allowed yet");
}
return protocolContext.getWorldStateArchive().getMutable(chainHeadBlockHeader.getStateRoot(), chainHeadBlockHeader.getHash(), false).map(worldState -> {
final Account senderAccount = worldState.get(transaction.getSender());
return getTransactionValidator().validateForSender(transaction, senderAccount, TransactionValidationParams.transactionPool());
}).orElseGet(() -> ValidationResult.invalid(CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE));
}
Aggregations