Search in sources :

Example 1 with TransactionType

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);
    }
}
Also used : BytesValueRLPInput(org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput) RLPInput(org.hyperledger.besu.ethereum.rlp.RLPInput) TransactionType(org.hyperledger.besu.plugin.data.TransactionType) LogsBloomFilter(org.hyperledger.besu.evm.log.LogsBloomFilter) Log(org.hyperledger.besu.evm.log.Log) Hash(org.hyperledger.besu.datatypes.Hash) Bytes(org.apache.tuweni.bytes.Bytes) RLPException(org.hyperledger.besu.ethereum.rlp.RLPException) BytesValueRLPInput(org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput)

Example 2 with TransactionType

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)));
    }
}
Also used : Bytes(org.apache.tuweni.bytes.Bytes) TransactionType(org.hyperledger.besu.plugin.data.TransactionType)

Example 3 with TransactionType

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();
}
Also used : TransactionType(org.hyperledger.besu.plugin.data.TransactionType) TransactionInvalidReason(org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason) BigInteger(java.math.BigInteger) Wei(org.hyperledger.besu.datatypes.Wei)

Aggregations

TransactionType (org.hyperledger.besu.plugin.data.TransactionType)3 Bytes (org.apache.tuweni.bytes.Bytes)2 BigInteger (java.math.BigInteger)1 Hash (org.hyperledger.besu.datatypes.Hash)1 Wei (org.hyperledger.besu.datatypes.Wei)1 BytesValueRLPInput (org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput)1 RLPException (org.hyperledger.besu.ethereum.rlp.RLPException)1 RLPInput (org.hyperledger.besu.ethereum.rlp.RLPInput)1 TransactionInvalidReason (org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason)1 Log (org.hyperledger.besu.evm.log.Log)1 LogsBloomFilter (org.hyperledger.besu.evm.log.LogsBloomFilter)1