Search in sources :

Example 1 with OperationTracer

use of org.hyperledger.besu.evm.tracing.OperationTracer in project besu by hyperledger.

the class MainnetTransactionProcessor method processTransaction.

public TransactionProcessingResult processTransaction(final Blockchain blockchain, final WorldUpdater worldState, final ProcessableBlockHeader blockHeader, final Transaction transaction, final Address miningBeneficiary, final OperationTracer operationTracer, final BlockHashLookup blockHashLookup, final Boolean isPersistingPrivateState, final TransactionValidationParams transactionValidationParams, final PrivateMetadataUpdater privateMetadataUpdater) {
    try {
        LOG.trace("Starting execution of {}", transaction);
        ValidationResult<TransactionInvalidReason> validationResult = transactionValidator.validate(transaction, blockHeader.getBaseFee(), transactionValidationParams);
        // be signed correctly to extract the sender).
        if (!validationResult.isValid()) {
            LOG.debug("Invalid transaction: {}", validationResult.getErrorMessage());
            return TransactionProcessingResult.invalid(validationResult);
        }
        final Address senderAddress = transaction.getSender();
        final EvmAccount sender = worldState.getOrCreateSenderAccount(senderAddress);
        validationResult = transactionValidator.validateForSender(transaction, sender, transactionValidationParams);
        if (!validationResult.isValid()) {
            LOG.debug("Invalid transaction: {}", validationResult.getErrorMessage());
            return TransactionProcessingResult.invalid(validationResult);
        }
        final MutableAccount senderMutableAccount = sender.getMutable();
        final long previousNonce = senderMutableAccount.incrementNonce();
        final Wei transactionGasPrice = feeMarket.getTransactionPriceCalculator().price(transaction, blockHeader.getBaseFee());
        LOG.trace("Incremented sender {} nonce ({} -> {})", senderAddress, previousNonce, sender.getNonce());
        final Wei upfrontGasCost = transaction.getUpfrontGasCost(transactionGasPrice);
        final Wei previousBalance = senderMutableAccount.decrementBalance(upfrontGasCost);
        LOG.trace("Deducted sender {} upfront gas cost {} ({} -> {})", senderAddress, upfrontGasCost, previousBalance, sender.getBalance());
        final List<AccessListEntry> accessListEntries = transaction.getAccessList().orElse(List.of());
        // we need to keep a separate hash set of addresses in case they specify no storage.
        // No-storage is a common pattern, especially for Externally Owned Accounts
        final Set<Address> addressList = new HashSet<>();
        final Multimap<Address, Bytes32> storageList = HashMultimap.create();
        int accessListStorageCount = 0;
        for (final var entry : accessListEntries) {
            final Address address = entry.getAddress();
            addressList.add(address);
            final List<Bytes32> storageKeys = entry.getStorageKeys();
            storageList.putAll(address, storageKeys);
            accessListStorageCount += storageKeys.size();
        }
        final long intrinsicGas = gasCalculator.transactionIntrinsicGasCost(transaction.getPayload(), transaction.isContractCreation());
        final long accessListGas = gasCalculator.accessListGasCost(accessListEntries.size(), accessListStorageCount);
        final long gasAvailable = transaction.getGasLimit() - intrinsicGas - accessListGas;
        LOG.trace("Gas available for execution {} = {} - {} (limit - intrinsic)", gasAvailable, transaction.getGasLimit(), intrinsicGas);
        final WorldUpdater worldUpdater = worldState.updater();
        final Deque<MessageFrame> messageFrameStack = new ArrayDeque<>();
        final ImmutableMap.Builder<String, Object> contextVariablesBuilder = ImmutableMap.<String, Object>builder().put(KEY_IS_PERSISTING_PRIVATE_STATE, isPersistingPrivateState).put(KEY_TRANSACTION, transaction).put(KEY_TRANSACTION_HASH, transaction.getHash());
        if (privateMetadataUpdater != null) {
            contextVariablesBuilder.put(KEY_PRIVATE_METADATA_UPDATER, privateMetadataUpdater);
        }
        final MessageFrame.Builder commonMessageFrameBuilder = MessageFrame.builder().messageFrameStack(messageFrameStack).maxStackSize(maxStackSize).worldUpdater(worldUpdater.updater()).initialGas(gasAvailable).originator(senderAddress).gasPrice(transactionGasPrice).sender(senderAddress).value(transaction.getValue()).apparentValue(transaction.getValue()).blockValues(blockHeader).depth(0).completer(__ -> {
        }).miningBeneficiary(miningBeneficiary).blockHashLookup(blockHashLookup).contextVariables(contextVariablesBuilder.build()).accessListWarmAddresses(addressList).accessListWarmStorage(storageList);
        final MessageFrame initialFrame;
        if (transaction.isContractCreation()) {
            final Address contractAddress = Address.contractAddress(senderAddress, senderMutableAccount.getNonce() - 1L);
            final Bytes initCodeBytes = transaction.getPayload();
            initialFrame = commonMessageFrameBuilder.type(MessageFrame.Type.CONTRACT_CREATION).address(contractAddress).contract(contractAddress).inputData(Bytes.EMPTY).code(contractCreationProcessor.getCodeFromEVM(Hash.hash(initCodeBytes), initCodeBytes)).build();
        } else {
            // isContractCall tests isPresent
            @SuppressWarnings("OptionalGetWithoutIsPresent") final Address to = transaction.getTo().get();
            final Optional<Account> maybeContract = Optional.ofNullable(worldState.get(to));
            initialFrame = commonMessageFrameBuilder.type(MessageFrame.Type.MESSAGE_CALL).address(to).contract(to).inputData(transaction.getPayload()).code(maybeContract.map(c -> messageCallProcessor.getCodeFromEVM(c.getCodeHash(), c.getCode())).orElse(Code.EMPTY_CODE)).build();
        }
        messageFrameStack.addFirst(initialFrame);
        while (!messageFrameStack.isEmpty()) {
            process(messageFrameStack.peekFirst(), operationTracer);
        }
        if (initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) {
            worldUpdater.commit();
        }
        if (LOG.isTraceEnabled()) {
            LOG.trace("Gas used by transaction: {}, by message call/contract creation: {}", transaction.getGasLimit() - initialFrame.getRemainingGas(), gasAvailable - initialFrame.getRemainingGas());
        }
        // Refund the sender by what we should and pay the miner fee (note that we're doing them one
        // after the other so that if it is the same account somehow, we end up with the right result)
        final long selfDestructRefund = gasCalculator.getSelfDestructRefundAmount() * initialFrame.getSelfDestructs().size();
        final long refundGas = initialFrame.getGasRefund() + selfDestructRefund;
        final long refunded = refunded(transaction, initialFrame.getRemainingGas(), refundGas);
        final Wei refundedWei = transactionGasPrice.multiply(refunded);
        senderMutableAccount.incrementBalance(refundedWei);
        final long gasUsedByTransaction = transaction.getGasLimit() - initialFrame.getRemainingGas();
        if (!worldState.getClass().equals(GoQuorumMutablePrivateWorldStateUpdater.class)) {
            // if this is not a private GoQuorum transaction we have to update the coinbase
            final var coinbase = worldState.getOrCreate(miningBeneficiary).getMutable();
            final long coinbaseFee = transaction.getGasLimit() - refunded;
            if (blockHeader.getBaseFee().isPresent()) {
                final Wei baseFee = blockHeader.getBaseFee().get();
                if (transactionGasPrice.compareTo(baseFee) < 0) {
                    return TransactionProcessingResult.failed(gasUsedByTransaction, refunded, ValidationResult.invalid(TransactionInvalidReason.TRANSACTION_PRICE_TOO_LOW, "transaction price must be greater than base fee"), Optional.empty());
                }
            }
            final CoinbaseFeePriceCalculator coinbaseCalculator = blockHeader.getBaseFee().isPresent() ? coinbaseFeePriceCalculator : CoinbaseFeePriceCalculator.frontier();
            final Wei coinbaseWeiDelta = coinbaseCalculator.price(coinbaseFee, transactionGasPrice, blockHeader.getBaseFee());
            coinbase.incrementBalance(coinbaseWeiDelta);
        }
        initialFrame.getSelfDestructs().forEach(worldState::deleteAccount);
        if (clearEmptyAccounts) {
            clearEmptyAccounts(worldState);
        }
        if (initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) {
            return TransactionProcessingResult.successful(initialFrame.getLogs(), gasUsedByTransaction, refunded, initialFrame.getOutputData(), validationResult);
        } else {
            return TransactionProcessingResult.failed(gasUsedByTransaction, refunded, validationResult, initialFrame.getRevertReason());
        }
    } catch (final RuntimeException re) {
        LOG.error("Critical Exception Processing Transaction", re);
        return TransactionProcessingResult.invalid(ValidationResult.invalid(TransactionInvalidReason.INTERNAL_ERROR, "Internal Error in Besu - " + re));
    }
}
Also used : EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) KEY_TRANSACTION_HASH(org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) Account(org.hyperledger.besu.evm.account.Account) AccessListEntry(org.hyperledger.besu.evm.AccessListEntry) LoggerFactory(org.slf4j.LoggerFactory) FeeMarket(org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket) OperationTracer(org.hyperledger.besu.evm.tracing.OperationTracer) GoQuorumMutablePrivateWorldStateUpdater(org.hyperledger.besu.ethereum.worldstate.GoQuorumMutablePrivateWorldStateUpdater) Bytes(org.apache.tuweni.bytes.Bytes) KEY_PRIVATE_METADATA_UPDATER(org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER) Deque(java.util.Deque) Multimap(com.google.common.collect.Multimap) Address(org.hyperledger.besu.datatypes.Address) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) AbstractMessageProcessor(org.hyperledger.besu.evm.processor.AbstractMessageProcessor) HashMultimap(com.google.common.collect.HashMultimap) Wei(org.hyperledger.besu.datatypes.Wei) TransactionInvalidReason(org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason) Code(org.hyperledger.besu.evm.Code) Bytes32(org.apache.tuweni.bytes.Bytes32) ProcessableBlockHeader(org.hyperledger.besu.ethereum.core.ProcessableBlockHeader) PrivateMetadataUpdater(org.hyperledger.besu.ethereum.privacy.storage.PrivateMetadataUpdater) KEY_IS_PERSISTING_PRIVATE_STATE(org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_IS_PERSISTING_PRIVATE_STATE) Logger(org.slf4j.Logger) ImmutableMap(com.google.common.collect.ImmutableMap) Blockchain(org.hyperledger.besu.ethereum.chain.Blockchain) CoinbaseFeePriceCalculator(org.hyperledger.besu.ethereum.core.feemarket.CoinbaseFeePriceCalculator) Set(java.util.Set) BlockHashLookup(org.hyperledger.besu.ethereum.vm.BlockHashLookup) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) GasCalculator(org.hyperledger.besu.evm.gascalculator.GasCalculator) List(java.util.List) KEY_TRANSACTION(org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION) MutableAccount(org.hyperledger.besu.evm.account.MutableAccount) Optional(java.util.Optional) MessageFrame(org.hyperledger.besu.evm.frame.MessageFrame) ArrayDeque(java.util.ArrayDeque) Transaction(org.hyperledger.besu.ethereum.core.Transaction) Hash(org.hyperledger.besu.datatypes.Hash) EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) Account(org.hyperledger.besu.evm.account.Account) MutableAccount(org.hyperledger.besu.evm.account.MutableAccount) Address(org.hyperledger.besu.datatypes.Address) MessageFrame(org.hyperledger.besu.evm.frame.MessageFrame) Bytes32(org.apache.tuweni.bytes.Bytes32) Bytes(org.apache.tuweni.bytes.Bytes) AccessListEntry(org.hyperledger.besu.evm.AccessListEntry) EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) TransactionInvalidReason(org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason) MutableAccount(org.hyperledger.besu.evm.account.MutableAccount) HashSet(java.util.HashSet) CoinbaseFeePriceCalculator(org.hyperledger.besu.ethereum.core.feemarket.CoinbaseFeePriceCalculator) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) GoQuorumMutablePrivateWorldStateUpdater(org.hyperledger.besu.ethereum.worldstate.GoQuorumMutablePrivateWorldStateUpdater) ArrayDeque(java.util.ArrayDeque) ImmutableMap(com.google.common.collect.ImmutableMap) Wei(org.hyperledger.besu.datatypes.Wei)

Example 2 with OperationTracer

use of org.hyperledger.besu.evm.tracing.OperationTracer in project besu by hyperledger.

the class PrivateTransactionProcessor method processTransaction.

public TransactionProcessingResult processTransaction(final WorldUpdater publicWorldState, final WorldUpdater privateWorldState, final ProcessableBlockHeader blockHeader, final Hash pmtHash, final PrivateTransaction transaction, final Address miningBeneficiary, final OperationTracer operationTracer, final Function<Long, Hash> blockHashLookup, final Bytes privacyGroupId) {
    try {
        LOG.trace("Starting private execution of {}", transaction);
        final Address senderAddress = transaction.getSender();
        final EvmAccount maybePrivateSender = privateWorldState.getAccount(senderAddress);
        final MutableAccount sender = maybePrivateSender != null ? maybePrivateSender.getMutable() : privateWorldState.createAccount(senderAddress, 0, Wei.ZERO).getMutable();
        final ValidationResult<TransactionInvalidReason> validationResult = privateTransactionValidator.validate(transaction, sender.getNonce(), false);
        if (!validationResult.isValid()) {
            return TransactionProcessingResult.invalid(validationResult);
        }
        final long previousNonce = sender.incrementNonce();
        LOG.trace("Incremented private sender {} nonce ({} -> {})", senderAddress, previousNonce, sender.getNonce());
        final WorldUpdater mutablePrivateWorldStateUpdater = new DefaultMutablePrivateWorldStateUpdater(publicWorldState, privateWorldState);
        final Deque<MessageFrame> messageFrameStack = new ArrayDeque<>();
        final MessageFrame.Builder commonMessageFrameBuilder = MessageFrame.builder().messageFrameStack(messageFrameStack).maxStackSize(maxStackSize).worldUpdater(mutablePrivateWorldStateUpdater).initialGas(Long.MAX_VALUE).originator(senderAddress).gasPrice(transaction.getGasPrice()).sender(senderAddress).value(transaction.getValue()).apparentValue(transaction.getValue()).blockValues(blockHeader).depth(0).completer(__ -> {
        }).miningBeneficiary(miningBeneficiary).blockHashLookup(blockHashLookup).contextVariables(Map.of(KEY_TRANSACTION_HASH, pmtHash));
        final MessageFrame initialFrame;
        if (transaction.isContractCreation()) {
            final Address privateContractAddress = Address.privateContractAddress(senderAddress, previousNonce, privacyGroupId);
            LOG.debug("Calculated contract address {} from sender {} with nonce {} and privacy group {}", privateContractAddress, senderAddress, previousNonce, privacyGroupId);
            final Bytes initCodeBytes = transaction.getPayload();
            initialFrame = commonMessageFrameBuilder.type(MessageFrame.Type.CONTRACT_CREATION).address(privateContractAddress).contract(privateContractAddress).inputData(Bytes.EMPTY).code(contractCreationProcessor.getCodeFromEVM(Hash.hash(initCodeBytes), initCodeBytes)).build();
        } else {
            final Address to = transaction.getTo().get();
            final Optional<Account> maybeContract = Optional.ofNullable(mutablePrivateWorldStateUpdater.get(to));
            initialFrame = commonMessageFrameBuilder.type(MessageFrame.Type.MESSAGE_CALL).address(to).contract(to).inputData(transaction.getPayload()).code(maybeContract.map(c -> messageCallProcessor.getCodeFromEVM(c.getCodeHash(), c.getCode())).orElse(Code.EMPTY_CODE)).build();
        }
        messageFrameStack.addFirst(initialFrame);
        while (!messageFrameStack.isEmpty()) {
            process(messageFrameStack.peekFirst(), operationTracer);
        }
        if (initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) {
            mutablePrivateWorldStateUpdater.commit();
        }
        if (initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) {
            return TransactionProcessingResult.successful(initialFrame.getLogs(), 0, 0, initialFrame.getOutputData(), ValidationResult.valid());
        } else {
            return TransactionProcessingResult.failed(0, 0, ValidationResult.invalid(TransactionInvalidReason.PRIVATE_TRANSACTION_FAILED), initialFrame.getRevertReason());
        }
    } catch (final RuntimeException re) {
        LOG.error("Critical Exception Processing Transaction", re);
        return TransactionProcessingResult.invalid(ValidationResult.invalid(TransactionInvalidReason.INTERNAL_ERROR, "Internal Error in Besu - " + re));
    }
}
Also used : ValidationResult(org.hyperledger.besu.ethereum.mainnet.ValidationResult) EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) KEY_TRANSACTION_HASH(org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) Account(org.hyperledger.besu.evm.account.Account) LoggerFactory(org.slf4j.LoggerFactory) OperationTracer(org.hyperledger.besu.evm.tracing.OperationTracer) Bytes(org.apache.tuweni.bytes.Bytes) Deque(java.util.Deque) Address(org.hyperledger.besu.datatypes.Address) Function(java.util.function.Function) MainnetTransactionValidator(org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator) AbstractMessageProcessor(org.hyperledger.besu.evm.processor.AbstractMessageProcessor) Map(java.util.Map) Wei(org.hyperledger.besu.datatypes.Wei) TransactionInvalidReason(org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason) Code(org.hyperledger.besu.evm.Code) ProcessableBlockHeader(org.hyperledger.besu.ethereum.core.ProcessableBlockHeader) Logger(org.slf4j.Logger) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) GasCalculator(org.hyperledger.besu.evm.gascalculator.GasCalculator) DefaultMutablePrivateWorldStateUpdater(org.hyperledger.besu.ethereum.worldstate.DefaultMutablePrivateWorldStateUpdater) MutableAccount(org.hyperledger.besu.evm.account.MutableAccount) Optional(java.util.Optional) MessageFrame(org.hyperledger.besu.evm.frame.MessageFrame) ArrayDeque(java.util.ArrayDeque) Transaction(org.hyperledger.besu.ethereum.core.Transaction) Hash(org.hyperledger.besu.datatypes.Hash) EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) Account(org.hyperledger.besu.evm.account.Account) MutableAccount(org.hyperledger.besu.evm.account.MutableAccount) Address(org.hyperledger.besu.datatypes.Address) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) MessageFrame(org.hyperledger.besu.evm.frame.MessageFrame) ArrayDeque(java.util.ArrayDeque) Bytes(org.apache.tuweni.bytes.Bytes) EvmAccount(org.hyperledger.besu.evm.account.EvmAccount) TransactionInvalidReason(org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason) MutableAccount(org.hyperledger.besu.evm.account.MutableAccount) DefaultMutablePrivateWorldStateUpdater(org.hyperledger.besu.ethereum.worldstate.DefaultMutablePrivateWorldStateUpdater)

Example 3 with OperationTracer

use of org.hyperledger.besu.evm.tracing.OperationTracer in project besu by hyperledger.

the class EvmToolCommand method run.

@Override
public void run() {
    try {
        final EvmToolComponent component = DaggerEvmToolComponent.builder().dataStoreModule(new DataStoreModule()).genesisFileModule(network == null ? genesisFile == null ? GenesisFileModule.createGenesisModule(NetworkName.DEV) : GenesisFileModule.createGenesisModule(genesisFile) : GenesisFileModule.createGenesisModule(network)).evmToolCommandOptionsModule(daggerOptions).metricsSystemModule(new MetricsSystemModule()).build();
        final BlockHeader blockHeader = BlockHeaderBuilder.create().parentHash(Hash.EMPTY).coinbase(Address.ZERO).difficulty(Difficulty.ONE).number(1).gasLimit(5000).timestamp(Instant.now().toEpochMilli()).ommersHash(Hash.EMPTY_LIST_HASH).stateRoot(Hash.EMPTY_TRIE_HASH).transactionsRoot(Hash.EMPTY).receiptsRoot(Hash.EMPTY).logsBloom(LogsBloomFilter.empty()).gasUsed(0).extraData(Bytes.EMPTY).mixHash(Hash.EMPTY).nonce(0).blockHeaderFunctions(new MainnetBlockHeaderFunctions()).buildBlockHeader();
        Log4j2ConfiguratorUtil.setAllLevels("", repeat == 0 ? Level.INFO : Level.OFF);
        int repeat = this.repeat;
        Log4j2ConfiguratorUtil.setLevel("org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", Level.OFF);
        final ProtocolSpec protocolSpec = component.getProtocolSpec().apply(0);
        Log4j2ConfiguratorUtil.setLevel("org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", null);
        final PrecompileContractRegistry precompileContractRegistry = protocolSpec.getPrecompileContractRegistry();
        final EVM evm = protocolSpec.getEvm();
        Code code = evm.getCode(Hash.hash(codeHexString), codeHexString);
        final Stopwatch stopwatch = Stopwatch.createUnstarted();
        long lastTime = 0;
        do {
            final boolean lastLoop = repeat == 0;
            final // You should have picked Mercy.
            OperationTracer tracer = lastLoop && showJsonResults ? new StandardJsonTracer(System.out, !noMemory) : OperationTracer.NO_TRACING;
            var updater = component.getWorldUpdater();
            updater.getOrCreate(sender);
            updater.getOrCreate(receiver);
            final Deque<MessageFrame> messageFrameStack = new ArrayDeque<>();
            messageFrameStack.add(MessageFrame.builder().type(MessageFrame.Type.MESSAGE_CALL).messageFrameStack(messageFrameStack).worldUpdater(updater).initialGas(gas).contract(Address.ZERO).address(receiver).originator(sender).sender(sender).gasPrice(gasPriceGWei).inputData(callData).value(ethValue).apparentValue(ethValue).code(code).blockValues(blockHeader).depth(0).completer(c -> {
            }).miningBeneficiary(blockHeader.getCoinbase()).blockHashLookup(new BlockHashLookup(blockHeader, component.getBlockchain())).build());
            final MessageCallProcessor mcp = new MessageCallProcessor(evm, precompileContractRegistry);
            stopwatch.start();
            while (!messageFrameStack.isEmpty()) {
                final MessageFrame messageFrame = messageFrameStack.peek();
                mcp.process(messageFrame, tracer);
                if (lastLoop) {
                    if (messageFrame.getExceptionalHaltReason().isPresent()) {
                        out.println(messageFrame.getExceptionalHaltReason().get());
                    }
                    if (messageFrame.getRevertReason().isPresent()) {
                        out.println(new String(messageFrame.getRevertReason().get().toArray(), StandardCharsets.UTF_8));
                    }
                }
                if (messageFrameStack.isEmpty()) {
                    stopwatch.stop();
                    if (lastTime == 0) {
                        lastTime = stopwatch.elapsed().toNanos();
                    }
                }
                if (lastLoop && messageFrameStack.isEmpty()) {
                    final Transaction tx = new Transaction(0, Wei.ZERO, Long.MAX_VALUE, Optional.ofNullable(receiver), Wei.ZERO, null, callData, sender, Optional.empty());
                    final long intrinsicGasCost = protocolSpec.getGasCalculator().transactionIntrinsicGasCost(tx.getPayload(), tx.isContractCreation());
                    final long accessListCost = tx.getAccessList().map(list -> protocolSpec.getGasCalculator().accessListGasCost(list)).orElse(0L);
                    final long evmGas = gas - messageFrame.getRemainingGas();
                    out.println();
                    out.println(new JsonObject().put("gasUser", "0x" + Long.toHexString(evmGas)).put("timens", lastTime).put("time", lastTime / 1000).put("gasTotal", "0x" + Long.toHexString(evmGas + intrinsicGasCost) + accessListCost));
                }
            }
            lastTime = stopwatch.elapsed().toNanos();
            stopwatch.reset();
        } while (repeat-- > 0);
    } catch (final IOException e) {
        LOG.error("Unable to create Genesis module", e);
    }
}
Also used : MessageCallProcessor(org.hyperledger.besu.evm.processor.MessageCallProcessor) Stopwatch(com.google.common.base.Stopwatch) LoggerFactory(org.slf4j.LoggerFactory) PrecompileContractRegistry(org.hyperledger.besu.evm.precompile.PrecompileContractRegistry) Level(org.apache.logging.log4j.Level) OperationTracer(org.hyperledger.besu.evm.tracing.OperationTracer) Bytes(org.apache.tuweni.bytes.Bytes) Deque(java.util.Deque) Address(org.hyperledger.besu.datatypes.Address) EVM(org.hyperledger.besu.evm.EVM) NetworkName(org.hyperledger.besu.cli.config.NetworkName) Wei(org.hyperledger.besu.datatypes.Wei) JsonObject(io.vertx.core.json.JsonObject) Command(picocli.CommandLine.Command) Code(org.hyperledger.besu.evm.Code) CommandLine(picocli.CommandLine) MainnetBlockHeaderFunctions(org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions) PrintStream(java.io.PrintStream) Log4j2ConfiguratorUtil(org.hyperledger.besu.util.Log4j2ConfiguratorUtil) Difficulty(org.hyperledger.besu.ethereum.core.Difficulty) Logger(org.slf4j.Logger) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) BlockHeaderBuilder(org.hyperledger.besu.ethereum.core.BlockHeaderBuilder) LogsBloomFilter(org.hyperledger.besu.evm.log.LogsBloomFilter) IOException(java.io.IOException) BlockHashLookup(org.hyperledger.besu.ethereum.vm.BlockHashLookup) Instant(java.time.Instant) File(java.io.File) StandardCharsets(java.nio.charset.StandardCharsets) List(java.util.List) Option(picocli.CommandLine.Option) INHERIT(picocli.CommandLine.ScopeType.INHERIT) Optional(java.util.Optional) MessageFrame(org.hyperledger.besu.evm.frame.MessageFrame) ProtocolSpec(org.hyperledger.besu.ethereum.mainnet.ProtocolSpec) ArrayDeque(java.util.ArrayDeque) Transaction(org.hyperledger.besu.ethereum.core.Transaction) StandardJsonTracer(org.hyperledger.besu.evm.tracing.StandardJsonTracer) Hash(org.hyperledger.besu.datatypes.Hash) MessageFrame(org.hyperledger.besu.evm.frame.MessageFrame) Stopwatch(com.google.common.base.Stopwatch) JsonObject(io.vertx.core.json.JsonObject) StandardJsonTracer(org.hyperledger.besu.evm.tracing.StandardJsonTracer) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) MainnetBlockHeaderFunctions(org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions) MessageCallProcessor(org.hyperledger.besu.evm.processor.MessageCallProcessor) IOException(java.io.IOException) PrecompileContractRegistry(org.hyperledger.besu.evm.precompile.PrecompileContractRegistry) Code(org.hyperledger.besu.evm.Code) ArrayDeque(java.util.ArrayDeque) BlockHashLookup(org.hyperledger.besu.ethereum.vm.BlockHashLookup) Transaction(org.hyperledger.besu.ethereum.core.Transaction) ProtocolSpec(org.hyperledger.besu.ethereum.mainnet.ProtocolSpec) EVM(org.hyperledger.besu.evm.EVM)

Example 4 with OperationTracer

use of org.hyperledger.besu.evm.tracing.OperationTracer in project besu by hyperledger.

the class StateTestSubCommand method traceTestSpecs.

private void traceTestSpecs(final String test, final List<GeneralStateTestCaseEipSpec> specs) {
    Log4j2ConfiguratorUtil.setLevel("org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", Level.OFF);
    final var referenceTestProtocolSchedules = ReferenceTestProtocolSchedules.create();
    Log4j2ConfiguratorUtil.setLevel("org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", null);
    final // You should have picked Mercy.
    OperationTracer tracer = parentCommand.showJsonResults ? new StandardJsonTracer(output, !parentCommand.noMemory) : OperationTracer.NO_TRACING;
    for (final GeneralStateTestCaseEipSpec spec : specs) {
        final BlockHeader blockHeader = spec.getBlockHeader();
        final WorldState initialWorldState = spec.getInitialWorldState();
        final Transaction transaction = spec.getTransaction();
        final ObjectNode summaryLine = objectMapper.createObjectNode();
        if (transaction == null) {
            // Check the world state root hash.
            summaryLine.put("test", test);
            summaryLine.put("fork", spec.getFork());
            summaryLine.put("d", spec.getDataIndex());
            summaryLine.put("g", spec.getGasIndex());
            summaryLine.put("v", spec.getValueIndex());
            summaryLine.put("pass", spec.getExpectException() != null);
            summaryLine.put("validationError", "Transaction had out-of-bounds parameters");
        } else {
            final MutableWorldState worldState = new DefaultMutableWorldState(initialWorldState);
            // `TransactionProcessor`, so these tests are skipped.
            if (transaction.getGasLimit() > blockHeader.getGasLimit() - blockHeader.getGasUsed()) {
                return;
            }
            final String forkName = fork == null ? spec.getFork() : fork;
            final ProtocolSchedule protocolSchedule = referenceTestProtocolSchedules.getByName(forkName);
            if (protocolSchedule == null) {
                throw new UnsupportedForkException(forkName);
            }
            final MainnetTransactionProcessor processor = protocolSchedule.getByBlockNumber(0).getTransactionProcessor();
            final WorldUpdater worldStateUpdater = worldState.updater();
            final ReferenceTestBlockchain blockchain = new ReferenceTestBlockchain(blockHeader.getNumber());
            final Stopwatch timer = Stopwatch.createStarted();
            final TransactionProcessingResult result = processor.processTransaction(blockchain, worldStateUpdater, blockHeader, transaction, blockHeader.getCoinbase(), new BlockHashLookup(blockHeader, blockchain), false, TransactionValidationParams.processingBlock(), tracer);
            timer.stop();
            if (shouldClearEmptyAccounts(spec.getFork())) {
                final Account coinbase = worldStateUpdater.getOrCreate(spec.getBlockHeader().getCoinbase());
                if (coinbase != null && coinbase.isEmpty()) {
                    worldStateUpdater.deleteAccount(coinbase.getAddress());
                }
                final Account sender = worldStateUpdater.getAccount(transaction.getSender());
                if (sender != null && sender.isEmpty()) {
                    worldStateUpdater.deleteAccount(sender.getAddress());
                }
            }
            worldStateUpdater.commit();
            summaryLine.put("output", result.getOutput().toUnprefixedHexString());
            final UInt256 gasUsed = UInt256.valueOf(transaction.getGasLimit() - result.getGasRemaining());
            summaryLine.put("gasUsed", StandardJsonTracer.shortNumber(gasUsed));
            summaryLine.put("time", timer.elapsed(TimeUnit.NANOSECONDS));
            // Check the world state root hash.
            summaryLine.put("test", test);
            summaryLine.put("fork", spec.getFork());
            summaryLine.put("d", spec.getDataIndex());
            summaryLine.put("g", spec.getGasIndex());
            summaryLine.put("v", spec.getValueIndex());
            summaryLine.put("postHash", worldState.rootHash().toHexString());
            final List<Log> logs = result.getLogs();
            final Hash actualLogsHash = Hash.hash(RLP.encode(out -> out.writeList(logs, Log::writeTo)));
            summaryLine.put("postLogsHash", actualLogsHash.toHexString());
            summaryLine.put("pass", spec.getExpectException() == null && worldState.rootHash().equals(spec.getExpectedRootHash()) && actualLogsHash.equals(spec.getExpectedLogsHash()));
            if (result.isInvalid()) {
                summaryLine.put("validationError", result.getValidationResult().getErrorMessage());
            } else if (spec.getExpectException() != null) {
                summaryLine.put("validationError", "Exception '" + spec.getExpectException() + "' was expected but did not occur");
            }
        }
        output.println(summaryLine);
    }
}
Also used : WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) Account(org.hyperledger.besu.evm.account.Account) Parameters(picocli.CommandLine.Parameters) LoggerFactory(org.slf4j.LoggerFactory) Level(org.apache.logging.log4j.Level) OperationTracer(org.hyperledger.besu.evm.tracing.OperationTracer) UnsupportedForkException(org.hyperledger.besu.evmtool.exception.UnsupportedForkException) ParentCommand(picocli.CommandLine.ParentCommand) Map(java.util.Map) UInt256(org.apache.tuweni.units.bigints.UInt256) ReferenceTestBlockchain(org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain) GeneralStateTestCaseSpec(org.hyperledger.besu.ethereum.referencetests.GeneralStateTestCaseSpec) TransactionValidationParams(org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams) Log(org.hyperledger.besu.evm.log.Log) StandardCharsets(java.nio.charset.StandardCharsets) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) List(java.util.List) Option(picocli.CommandLine.Option) GeneralStateTestCaseEipSpec(org.hyperledger.besu.ethereum.referencetests.GeneralStateTestCaseEipSpec) ReferenceTestProtocolSchedules(org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules) Hash(org.hyperledger.besu.datatypes.Hash) Stopwatch(com.google.common.base.Stopwatch) DefaultMutableWorldState(org.hyperledger.besu.ethereum.worldstate.DefaultMutableWorldState) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ArrayList(java.util.ArrayList) ProtocolSchedule(org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule) JavaType(com.fasterxml.jackson.databind.JavaType) Command(picocli.CommandLine.Command) PrintStream(java.io.PrintStream) WorldState(org.hyperledger.besu.evm.worldstate.WorldState) Log4j2ConfiguratorUtil(org.hyperledger.besu.util.Log4j2ConfiguratorUtil) Logger(org.slf4j.Logger) COMMAND_NAME(org.hyperledger.besu.evmtool.StateTestSubCommand.COMMAND_NAME) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) Feature(com.fasterxml.jackson.core.JsonParser.Feature) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) MutableWorldState(org.hyperledger.besu.ethereum.core.MutableWorldState) MainnetTransactionProcessor(org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor) RLP(org.hyperledger.besu.ethereum.rlp.RLP) IOException(java.io.IOException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) BlockHashLookup(org.hyperledger.besu.ethereum.vm.BlockHashLookup) InputStreamReader(java.io.InputStreamReader) File(java.io.File) TimeUnit(java.util.concurrent.TimeUnit) ReferenceTestProtocolSchedules.shouldClearEmptyAccounts(org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules.shouldClearEmptyAccounts) BufferedReader(java.io.BufferedReader) Transaction(org.hyperledger.besu.ethereum.core.Transaction) StandardJsonTracer(org.hyperledger.besu.evm.tracing.StandardJsonTracer) InputStream(java.io.InputStream) Account(org.hyperledger.besu.evm.account.Account) DefaultMutableWorldState(org.hyperledger.besu.ethereum.worldstate.DefaultMutableWorldState) MutableWorldState(org.hyperledger.besu.ethereum.core.MutableWorldState) Stopwatch(com.google.common.base.Stopwatch) DefaultMutableWorldState(org.hyperledger.besu.ethereum.worldstate.DefaultMutableWorldState) WorldState(org.hyperledger.besu.evm.worldstate.WorldState) MutableWorldState(org.hyperledger.besu.ethereum.core.MutableWorldState) StandardJsonTracer(org.hyperledger.besu.evm.tracing.StandardJsonTracer) Hash(org.hyperledger.besu.datatypes.Hash) UnsupportedForkException(org.hyperledger.besu.evmtool.exception.UnsupportedForkException) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) Log(org.hyperledger.besu.evm.log.Log) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) DefaultMutableWorldState(org.hyperledger.besu.ethereum.worldstate.DefaultMutableWorldState) ProtocolSchedule(org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) MainnetTransactionProcessor(org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor) Transaction(org.hyperledger.besu.ethereum.core.Transaction) BlockHashLookup(org.hyperledger.besu.ethereum.vm.BlockHashLookup) GeneralStateTestCaseEipSpec(org.hyperledger.besu.ethereum.referencetests.GeneralStateTestCaseEipSpec) ReferenceTestBlockchain(org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain) UInt256(org.apache.tuweni.units.bigints.UInt256)

Aggregations

Hash (org.hyperledger.besu.datatypes.Hash)4 Transaction (org.hyperledger.besu.ethereum.core.Transaction)4 OperationTracer (org.hyperledger.besu.evm.tracing.OperationTracer)4 Logger (org.slf4j.Logger)4 ArrayDeque (java.util.ArrayDeque)3 Deque (java.util.Deque)3 List (java.util.List)3 Optional (java.util.Optional)3 Bytes (org.apache.tuweni.bytes.Bytes)3 Address (org.hyperledger.besu.datatypes.Address)3 Wei (org.hyperledger.besu.datatypes.Wei)3 TransactionProcessingResult (org.hyperledger.besu.ethereum.processing.TransactionProcessingResult)3 BlockHashLookup (org.hyperledger.besu.ethereum.vm.BlockHashLookup)3 Code (org.hyperledger.besu.evm.Code)3 Account (org.hyperledger.besu.evm.account.Account)3 MessageFrame (org.hyperledger.besu.evm.frame.MessageFrame)3 WorldUpdater (org.hyperledger.besu.evm.worldstate.WorldUpdater)3 LoggerFactory (org.slf4j.LoggerFactory)3 Stopwatch (com.google.common.base.Stopwatch)2 File (java.io.File)2