use of org.hyperledger.besu.plugin.data.TransactionType in project besu by hyperledger.
the class LogsWrapper method readFrom.
/**
* Creates a transaction receipt for the given RLP
*
* @param rlpInput the RLP-encoded transaction receipt
* @param revertReasonAllowed whether the rlp input is allowed to have a revert reason
* @return the transaction receipt
*/
public static TransactionReceipt readFrom(final RLPInput rlpInput, final boolean revertReasonAllowed) {
RLPInput input = rlpInput;
TransactionType transactionType = TransactionType.FRONTIER;
if (!rlpInput.nextIsList()) {
final Bytes typedTransactionReceiptBytes = input.readBytes();
transactionType = TransactionType.of(typedTransactionReceiptBytes.get(0));
input = new BytesValueRLPInput(typedTransactionReceiptBytes.slice(1), false);
}
input.enterList();
// Get the first element to check later to determine the
// correct transaction receipt encoding to use.
final RLPInput firstElement = input.readAsRlp();
final long cumulativeGas = input.readLongScalar();
// The logs below will populate the bloom filter upon construction.
// TODO consider validating that the logs and bloom filter match.
final LogsBloomFilter bloomFilter = LogsBloomFilter.readFrom(input);
final List<Log> logs = input.readList(Log::readFrom);
final Optional<Bytes> revertReason;
if (input.isEndOfCurrentList()) {
revertReason = Optional.empty();
} else {
if (!revertReasonAllowed) {
throw new RLPException("Unexpected value at end of TransactionReceipt");
}
revertReason = Optional.of(input.readBytes());
}
// byte for success (0x01) or failure (0x80).
if (firstElement.raw().size() == 1) {
final int status = firstElement.readIntScalar();
input.leaveList();
return new TransactionReceipt(transactionType, status, cumulativeGas, logs, bloomFilter, revertReason);
} else {
final Hash stateRoot = Hash.wrap(firstElement.readBytes32());
input.leaveList();
return new TransactionReceipt(transactionType, stateRoot, cumulativeGas, logs, bloomFilter, revertReason);
}
}
use of org.hyperledger.besu.plugin.data.TransactionType in project besu by hyperledger.
the class TransactionDecoder method decodeForWire.
public static Transaction decodeForWire(final RLPInput rlpInput, final boolean goQuorumCompatibilityMode) {
if (rlpInput.nextIsList()) {
return decodeFrontier(rlpInput, goQuorumCompatibilityMode);
} else {
final Bytes typedTransactionBytes = rlpInput.readBytes();
final TransactionType transactionType = TransactionType.of(typedTransactionBytes.get(0) & 0xff);
return getDecoder(transactionType).decode(RLP.input(typedTransactionBytes.slice(1)));
}
}
use of org.hyperledger.besu.plugin.data.TransactionType in project besu by hyperledger.
the class MainnetTransactionValidator method validate.
/**
* Asserts whether a transaction is valid.
*
* @param transaction the transaction to validate
* @param baseFee optional baseFee
* @param transactionValidationParams Validation parameters that will be used
* @return An empty {@link Optional} if the transaction is considered valid; otherwise an {@code
* Optional} containing a {@link TransactionInvalidReason} that identifies why the transaction
* is invalid.
*/
public ValidationResult<TransactionInvalidReason> validate(final Transaction transaction, final Optional<Wei> baseFee, final TransactionValidationParams transactionValidationParams) {
final ValidationResult<TransactionInvalidReason> signatureResult = validateTransactionSignature(transaction);
if (!signatureResult.isValid()) {
return signatureResult;
}
if (goQuorumCompatibilityMode && transaction.hasCostParams()) {
return ValidationResult.invalid(TransactionInvalidReason.GAS_PRICE_MUST_BE_ZERO, "gasPrice must be set to zero on a GoQuorum compatible network");
}
final TransactionType transactionType = transaction.getType();
if (!acceptedTransactionTypes.contains(transactionType)) {
return ValidationResult.invalid(TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, String.format("Transaction type %s is invalid, accepted transaction types are %s", transactionType, acceptedTransactionTypes));
}
if (baseFee.isPresent()) {
final Wei price = feeMarket.getTransactionPriceCalculator().price(transaction, baseFee);
if (!transactionValidationParams.isAllowMaxFeeGasBelowBaseFee() && price.compareTo(baseFee.orElseThrow()) < 0) {
return ValidationResult.invalid(TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, "gasPrice is less than the current BaseFee");
}
// assert transaction.max_fee_per_gas >= transaction.max_priority_fee_per_gas
if (transaction.getType().supports1559FeeMarket() && transaction.getMaxPriorityFeePerGas().get().getAsBigInteger().compareTo(transaction.getMaxFeePerGas().get().getAsBigInteger()) > 0) {
return ValidationResult.invalid(TransactionInvalidReason.MAX_PRIORITY_FEE_PER_GAS_EXCEEDS_MAX_FEE_PER_GAS, "max priority fee per gas cannot be greater than max fee per gas");
}
}
if (transaction.getNonce() == MAX_NONCE) {
return ValidationResult.invalid(TransactionInvalidReason.NONCE_TOO_HIGH, "Nonces must be less than 2^64-1");
}
if (transaction.getGasPrice().or(transaction::getMaxFeePerGas).orElse(Wei.ZERO).getAsBigInteger().multiply(new BigInteger(1, Longs.toByteArray(transaction.getGasLimit()))).bitLength() > 256) {
return ValidationResult.invalid(TransactionInvalidReason.UPFRONT_FEE_TOO_HIGH, "gasLimit x price must be less than 2^256");
}
final long intrinsicGasCost = gasCalculator.transactionIntrinsicGasCost(transaction.getPayload(), transaction.isContractCreation()) + (transaction.getAccessList().map(gasCalculator::accessListGasCost).orElse(0L));
if (Long.compareUnsigned(intrinsicGasCost, transaction.getGasLimit()) > 0) {
return ValidationResult.invalid(TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT, String.format("intrinsic gas cost %s exceeds gas limit %s", intrinsicGasCost, transaction.getGasLimit()));
}
return ValidationResult.valid();
}
Aggregations