Search in sources :

Example 16 with Program

use of org.ethereum.vm.program.Program in project rskj by rsksmart.

the class TransactionExecutor method create.

private void create() {
    RskAddress newContractAddress = tx.getContractAddress();
    if (isEmpty(tx.getData())) {
        mEndGas = toBI(tx.getGasLimit()).subtract(BigInteger.valueOf(basicTxCost));
        cacheTrack.createAccount(newContractAddress);
    } else {
        ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(tx, txindex, executionBlock, cacheTrack, blockStore);
        this.vm = new VM(vmConfig, precompiledContracts);
        BlockchainConfig configForBlock = config.getBlockchainConfig().getConfigForBlock(executionBlock.getNumber());
        this.program = new Program(vmConfig, precompiledContracts, configForBlock, tx.getData(), programInvoke, tx);
        // reset storage if the contract with the same address already exists
        // TCK test case only - normally this is near-impossible situation in the real network
        ContractDetails contractDetails = program.getStorage().getContractDetails(newContractAddress);
        for (DataWord key : contractDetails.getStorageKeys()) {
            program.storageSave(key, DataWord.ZERO);
        }
    }
    Coin endowment = tx.getValue();
    cacheTrack.transfer(tx.getSender(), newContractAddress, endowment);
}
Also used : ProgramInvoke(org.ethereum.vm.program.invoke.ProgramInvoke) Coin(co.rsk.core.Coin) BlockchainConfig(org.ethereum.config.BlockchainConfig) Program(org.ethereum.vm.program.Program) RskAddress(co.rsk.core.RskAddress) ContractDetails(org.ethereum.db.ContractDetails)

Example 17 with Program

use of org.ethereum.vm.program.Program in project rskj by rsksmart.

the class TransactionExecutor method call.

private void call() {
    if (!readyToExecute) {
        return;
    }
    logger.trace("Call transaction {} {}", toBI(tx.getNonce()), tx.getHash());
    RskAddress targetAddress = tx.getReceiveAddress();
    // DataWord(targetAddress)) can fail with exception:
    // java.lang.RuntimeException: Data word can't exceed 32 bytes:
    // if targetAddress size is greater than 32 bytes.
    // But init() will detect this earlier
    precompiledContract = precompiledContracts.getContractForAddress(new DataWord(targetAddress.getBytes()));
    if (precompiledContract != null) {
        precompiledContract.init(tx, executionBlock, track, blockStore, receiptStore, result.getLogInfoList());
        long requiredGas = precompiledContract.getGasForData(tx.getData());
        BigInteger txGasLimit = toBI(tx.getGasLimit());
        if (!localCall && txGasLimit.compareTo(BigInteger.valueOf(requiredGas)) < 0) {
            // no refund
            // no endowment
            execError(String.format("Out of Gas calling precompiled contract 0x%s, required: %d, left: %s ", targetAddress.toString(), (requiredGas + basicTxCost), mEndGas));
            mEndGas = BigInteger.ZERO;
            return;
        } else {
            long gasUsed = requiredGas + basicTxCost;
            mEndGas = txGasLimit.subtract(BigInteger.valueOf(requiredGas + basicTxCost));
            // FIXME: save return for vm trace
            try {
                byte[] out = precompiledContract.execute(tx.getData());
                result.setHReturn(out);
            } catch (RuntimeException e) {
                result.setException(e);
            }
            result.spendGas(gasUsed);
        }
    } else {
        byte[] code = track.getCode(targetAddress);
        if (isEmpty(code)) {
            mEndGas = toBI(tx.getGasLimit()).subtract(BigInteger.valueOf(basicTxCost));
            result.spendGas(basicTxCost);
        } else {
            ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(tx, txindex, executionBlock, cacheTrack, blockStore);
            this.vm = new VM(vmConfig, precompiledContracts);
            BlockchainConfig configForBlock = config.getBlockchainConfig().getConfigForBlock(executionBlock.getNumber());
            this.program = new Program(vmConfig, precompiledContracts, configForBlock, code, programInvoke, tx);
        }
    }
    if (result.getException() == null) {
        Coin endowment = tx.getValue();
        cacheTrack.transfer(tx.getSender(), targetAddress, endowment);
    }
}
Also used : ProgramInvoke(org.ethereum.vm.program.invoke.ProgramInvoke) Coin(co.rsk.core.Coin) BlockchainConfig(org.ethereum.config.BlockchainConfig) Program(org.ethereum.vm.program.Program) RskAddress(co.rsk.core.RskAddress) BigInteger(java.math.BigInteger)

Example 18 with Program

use of org.ethereum.vm.program.Program in project rskj by rsksmart.

the class VM method dumpLine.

/*
     * Dumping the VM state at the current operation in various styles
     *  - standard  Not Yet Implemented
     *  - standard+ (owner address, program counter, operation, gas left)
     *  - pretty (stack, memory, storage, level, contract,
     *              vmCounter, internalSteps, operation
                    gasBefore, gasCost, memWords)
     */
private void dumpLine(OpCode op, long gasBefore, long gasCost, long memWords, Program program) {
    if ("standard+".equals(vmConfig.dumpStyle())) {
        switch(op) {
            case STOP:
            case RETURN:
            case SUICIDE:
                ContractDetails details = program.getStorage().getContractDetails(new RskAddress(program.getOwnerAddress()));
                List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
                Collections.sort(storageKeys);
                storageKeys.forEach(key -> dumpLogger.trace("{} {}", Hex.toHexString(key.getNoLeadZeroesData()), Hex.toHexString(details.getStorage().get(key).getNoLeadZeroesData())));
                break;
            default:
                break;
        }
        String addressString = Hex.toHexString(program.getOwnerAddress().getLast20Bytes());
        String pcString = Hex.toHexString(new DataWord(program.getPC()).getNoLeadZeroesData());
        String opString = Hex.toHexString(new byte[] { op.val() });
        String gasString = Long.toHexString(program.getRemainingGas());
        dumpLogger.trace("{} {} {} {}", addressString, pcString, opString, gasString);
    } else if ("pretty".equals(vmConfig.dumpStyle())) {
        dumpLogger.trace("-------------------------------------------------------------------------");
        dumpLogger.trace("    STACK");
        program.getStack().forEach(item -> dumpLogger.trace("{}", item));
        dumpLogger.trace("    MEMORY");
        String memoryString = program.memoryToString();
        if (!"".equals(memoryString)) {
            dumpLogger.trace("{}", memoryString);
        }
        dumpLogger.trace("    STORAGE");
        ContractDetails details = program.getStorage().getContractDetails(new RskAddress(program.getOwnerAddress()));
        List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
        Collections.sort(storageKeys);
        storageKeys.forEach(key -> dumpLogger.trace("{}: {}", key.shortHex(), details.getStorage().get(key).shortHex()));
        int level = program.getCallDeep();
        String contract = Hex.toHexString(program.getOwnerAddress().getLast20Bytes());
        String internalSteps = String.format("%4s", Integer.toHexString(program.getPC())).replace(' ', '0').toUpperCase();
        dumpLogger.trace("{} | {} | #{} | {} : {} | {} | -{} | {}x32", level, contract, vmCounter, internalSteps, op, gasBefore, gasCost, memWords);
    }
}
Also used : Logger(org.slf4j.Logger) MsgType(org.ethereum.vm.MessageCall.MsgType) HashUtil(org.ethereum.crypto.HashUtil) Hex(org.spongycastle.util.encoders.Hex) LoggerFactory(org.slf4j.LoggerFactory) EMPTY_BYTE_ARRAY(org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY) RskAddress(co.rsk.core.RskAddress) ArrayList(java.util.ArrayList) Program(org.ethereum.vm.program.Program) List(java.util.List) VmConfig(co.rsk.config.VmConfig) ContractDetails(org.ethereum.db.ContractDetails) BigInteger(java.math.BigInteger) Stack(org.ethereum.vm.program.Stack) Collections(java.util.Collections) RskAddress(co.rsk.core.RskAddress) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) ContractDetails(org.ethereum.db.ContractDetails)

Example 19 with Program

use of org.ethereum.vm.program.Program in project rskj by rsksmart.

the class TransactionExecutor method finalization.

public void finalization() {
    if (!readyToExecute) {
        return;
    }
    // RSK if local call gas balances must not be changed
    if (localCall) {
        return;
    }
    logger.trace("Finalize transaction {} {}", toBI(tx.getNonce()), tx.getHash());
    cacheTrack.commit();
    // Should include only LogInfo's that was added during not rejected transactions
    List<LogInfo> notRejectedLogInfos = result.getLogInfoList().stream().filter(logInfo -> !logInfo.isRejected()).collect(Collectors.toList());
    TransactionExecutionSummary.Builder summaryBuilder = TransactionExecutionSummary.builderFor(tx).gasLeftover(mEndGas).logs(notRejectedLogInfos).result(result.getHReturn());
    if (result != null) {
        // Accumulate refunds for suicides
        result.addFutureRefund((long) result.getDeleteAccounts().size() * GasCost.SUICIDE_REFUND);
        long gasRefund = Math.min(result.getFutureRefund(), result.getGasUsed() / 2);
        RskAddress addr = tx.isContractCreation() ? tx.getContractAddress() : tx.getReceiveAddress();
        mEndGas = mEndGas.add(BigInteger.valueOf(gasRefund));
        summaryBuilder.gasUsed(toBI(result.getGasUsed())).gasRefund(toBI(gasRefund)).deletedAccounts(result.getDeleteAccounts()).internalTransactions(result.getInternalTransactions());
        ContractDetails cdetails = track.getContractDetails(addr);
        if (cdetails != null) {
            summaryBuilder.storageDiff(cdetails.getStorage());
        }
        if (result.getException() != null) {
            summaryBuilder.markAsFailed();
        }
    }
    logger.trace("Building transaction execution summary");
    TransactionExecutionSummary summary = summaryBuilder.build();
    // Refund for gas leftover
    track.addBalance(tx.getSender(), summary.getLeftover().add(summary.getRefund()));
    logger.trace("Pay total refund to sender: [{}], refund val: [{}]", tx.getSender(), summary.getRefund());
    // Transfer fees to miner
    Coin summaryFee = summary.getFee();
    // TODO: REMOVE THIS WHEN THE LocalBLockTests starts working with REMASC
    if (config.isRemascEnabled()) {
        logger.trace("Adding fee to remasc contract account");
        track.addBalance(PrecompiledContracts.REMASC_ADDR, summaryFee);
    } else {
        track.addBalance(coinbase, summaryFee);
    }
    this.paidFees = summaryFee;
    if (result != null) {
        logger.trace("Processing result");
        logs = notRejectedLogInfos;
        result.getCodeChanges().forEach((key, value) -> track.saveCode(new RskAddress(key), value));
        // Traverse list of suicides
        result.getDeleteAccounts().forEach(address -> track.delete(new RskAddress(address)));
    }
    if (listener != null) {
        listener.onTransactionExecuted(summary);
    }
    logger.trace("tx listener done");
    if (config.vmTrace() && program != null && result != null) {
        ProgramTrace trace = program.getTrace().result(result.getHReturn()).error(result.getException());
        String txHash = tx.getHash().toHexString();
        try {
            saveProgramTraceFile(config, txHash, trace);
            if (listener != null) {
                listener.onVMTraceCreated(txHash, trace);
            }
        } catch (IOException e) {
            String errorMessage = String.format("Cannot write trace to file: %s", e.getMessage());
            panicProcessor.panic("executor", errorMessage);
            logger.error(errorMessage);
        }
    }
    logger.trace("tx finalization done");
}
Also used : Arrays(java.util.Arrays) LoggerFactory(org.slf4j.LoggerFactory) EMPTY_BYTE_ARRAY(org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY) RskAddress(co.rsk.core.RskAddress) EthereumListenerAdapter(org.ethereum.listener.EthereumListenerAdapter) Coin(co.rsk.core.Coin) ArrayUtils.isEmpty(org.apache.commons.lang3.ArrayUtils.isEmpty) ContractDetails(org.ethereum.db.ContractDetails) BlockchainConfig(org.ethereum.config.BlockchainConfig) BigInteger(java.math.BigInteger) VMUtils.saveProgramTraceFile(org.ethereum.vm.VMUtils.saveProgramTraceFile) ProgramInvoke(org.ethereum.vm.program.invoke.ProgramInvoke) PanicProcessor(co.rsk.panic.PanicProcessor) Logger(org.slf4j.Logger) IOException(java.io.IOException) BlockStore(org.ethereum.db.BlockStore) EthereumListener(org.ethereum.listener.EthereumListener) Collectors(java.util.stream.Collectors) BIUtil(org.ethereum.util.BIUtil) ArrayUtils.getLength(org.apache.commons.lang3.ArrayUtils.getLength) ReceiptStore(org.ethereum.db.ReceiptStore) Program(org.ethereum.vm.program.Program) ProgramTrace(org.ethereum.vm.trace.ProgramTrace) List(java.util.List) VmConfig(co.rsk.config.VmConfig) org.ethereum.vm(org.ethereum.vm) ProgramResult(org.ethereum.vm.program.ProgramResult) ProgramInvokeFactory(org.ethereum.vm.program.invoke.ProgramInvokeFactory) RskSystemProperties(co.rsk.config.RskSystemProperties) Constants(org.ethereum.config.Constants) Coin(co.rsk.core.Coin) ProgramTrace(org.ethereum.vm.trace.ProgramTrace) RskAddress(co.rsk.core.RskAddress) IOException(java.io.IOException) ContractDetails(org.ethereum.db.ContractDetails)

Example 20 with Program

use of org.ethereum.vm.program.Program in project rskj by rsksmart.

the class VMExecutionTest method swapnTwentiethItem.

@Test
public void swapnTwentiethItem() {
    Program program = executeCode("PUSH1 0x01 PUSH1 0x02 PUSH1 0x03 PUSH1 0x04 PUSH1 0x05 PUSH1 0x06 PUSH1 0x07 PUSH1 0x08 PUSH1 0x09 PUSH1 0x0a PUSH1 0x0b PUSH1 0x0c PUSH1 0x0d PUSH1 0x0e PUSH1 0x0f PUSH1 0x10 PUSH1 0x11 PUSH1 0x12 PUSH1 0x13 PUSH1 0x14 PUSH1 0x12 SWAPN", 22);
    Stack stack = program.getStack();
    Assert.assertEquals(20, stack.size());
    Assert.assertEquals(new DataWord(1), stack.peek());
    Assert.assertEquals(new DataWord(20), stack.get(0));
    for (int k = 1; k < 19; k++) Assert.assertEquals(new DataWord(k + 1), stack.get(k));
}
Also used : Program(org.ethereum.vm.program.Program) DataWord(org.ethereum.vm.DataWord) Stack(org.ethereum.vm.program.Stack) Test(org.junit.Test)

Aggregations

Program (org.ethereum.vm.program.Program)37 Test (org.junit.Test)27 RskAddress (co.rsk.core.RskAddress)14 DataWord (org.ethereum.vm.DataWord)13 Stack (org.ethereum.vm.program.Stack)13 Coin (co.rsk.core.Coin)12 BigInteger (java.math.BigInteger)12 Repository (org.ethereum.core.Repository)10 ProgramInvokeMockImpl (org.ethereum.vm.program.invoke.ProgramInvokeMockImpl)9 Ignore (org.junit.Ignore)9 BlockchainConfig (org.ethereum.config.BlockchainConfig)7 AccountState (org.ethereum.core.AccountState)5 ProgramInvoke (org.ethereum.vm.program.invoke.ProgramInvoke)4 ContractDetails (org.ethereum.db.ContractDetails)3 VM (org.ethereum.vm.VM)3 RskSystemProperties (co.rsk.config.RskSystemProperties)2 VmConfig (co.rsk.config.VmConfig)2 IOException (java.io.IOException)2 List (java.util.List)2 EMPTY_BYTE_ARRAY (org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY)2