Search in sources :

Example 1 with ProgramInvoke

use of org.ethereum.vm.program.invoke.ProgramInvoke 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 2 with ProgramInvoke

use of org.ethereum.vm.program.invoke.ProgramInvoke 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 3 with ProgramInvoke

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

the class Program method createContract.

@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
public void createContract(DataWord value, DataWord memStart, DataWord memSize) {
    if (getCallDeep() == MAX_DEPTH) {
        stackPushZero();
        return;
    }
    RskAddress senderAddress = new RskAddress(getOwnerAddress());
    Coin endowment = new Coin(value.getData());
    if (isNotCovers(getStorage().getBalance(senderAddress), endowment)) {
        stackPushZero();
        return;
    }
    // [1] FETCH THE CODE FROM THE MEMORY
    byte[] programCode = memoryChunk(memStart.intValue(), memSize.intValue());
    if (isLogEnabled) {
        logger.info("creating a new contract inside contract run: [{}]", senderAddress);
    }
    // actual gas subtract
    long gasLimit = getRemainingGas();
    spendGas(gasLimit, "internal call");
    // [2] CREATE THE CONTRACT ADDRESS
    byte[] nonce = getStorage().getNonce(senderAddress).toByteArray();
    byte[] newAddressBytes = HashUtil.calcNewAddr(getOwnerAddress().getLast20Bytes(), nonce);
    RskAddress newAddress = new RskAddress(newAddressBytes);
    if (byTestingSuite()) {
        // This keeps track of the contracts created for a test
        getResult().addCallCreate(programCode, EMPTY_BYTE_ARRAY, gasLimit, value.getNoLeadZeroesData());
    }
    // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
    if (!byTestingSuite()) {
        getStorage().increaseNonce(senderAddress);
    }
    Repository track = getStorage().startTracking();
    // In case of hashing collisions, check for any balance before createAccount()
    if (track.isExist(newAddress)) {
        Coin oldBalance = track.getBalance(newAddress);
        track.createAccount(newAddress);
        track.addBalance(newAddress, oldBalance);
    } else {
        track.createAccount(newAddress);
    }
    // [4] TRANSFER THE BALANCE
    track.addBalance(senderAddress, endowment.negate());
    Coin newBalance = Coin.ZERO;
    if (!byTestingSuite()) {
        newBalance = track.addBalance(newAddress, endowment);
    }
    // [5] COOK THE INVOKE AND EXECUTE
    InternalTransaction internalTx = addInternalTx(nonce, getGasLimit(), senderAddress, RskAddress.nullAddress(), endowment, programCode, "create");
    ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(this, new DataWord(newAddressBytes), getOwnerAddress(), value, gasLimit, newBalance, null, track, this.invoke.getBlockStore(), byTestingSuite());
    ProgramResult programResult = ProgramResult.empty();
    // reset return buffer right before the call
    returnDataBuffer = null;
    if (isNotEmpty(programCode)) {
        VM vm = new VM(config, precompiledContracts);
        Program program = new Program(config, precompiledContracts, blockchainConfig, programCode, programInvoke, internalTx);
        vm.play(program);
        programResult = program.getResult();
    }
    if (programResult.getException() != null || programResult.isRevert()) {
        if (isLogEnabled) {
            logger.debug("contract run halted by Exception: contract: [{}], exception: [{}]", newAddress, programResult.getException());
        }
        if (internalTx == null) {
            throw new NullPointerException();
        }
        internalTx.reject();
        programResult.rejectInternalTransactions();
        programResult.rejectLogInfos();
        track.rollback();
        stackPushZero();
        if (programResult.getException() != null) {
            return;
        } else {
            returnDataBuffer = result.getHReturn();
        }
    } else {
        // 4. CREATE THE CONTRACT OUT OF RETURN
        byte[] code = programResult.getHReturn();
        int codeLength = getLength(code);
        long storageCost = (long) codeLength * GasCost.CREATE_DATA;
        long afterSpend = programInvoke.getGas() - storageCost - programResult.getGasUsed();
        if (afterSpend < 0) {
            programResult.setException(ExceptionHelper.notEnoughSpendingGas("No gas to return just created contract", storageCost, this));
        } else if (codeLength > Constants.getMaxContractSize()) {
            programResult.setException(ExceptionHelper.tooLargeContractSize(Constants.getMaxContractSize(), codeLength));
        } else {
            programResult.spendGas(storageCost);
            track.saveCode(newAddress, code);
        }
        track.commit();
        getResult().addDeleteAccounts(programResult.getDeleteAccounts());
        getResult().addLogInfos(programResult.getLogInfoList());
        // IN SUCCESS PUSH THE ADDRESS INTO THE STACK
        stackPush(new DataWord(newAddressBytes));
    }
    // 5. REFUND THE REMAIN GAS
    long refundGas = gasLimit - programResult.getGasUsed();
    if (refundGas > 0) {
        refundGas(refundGas, "remain gas from the internal call");
        if (isGasLogEnabled) {
            gasLogger.info("The remaining gas is refunded, account: [{}], gas: [{}] ", Hex.toHexString(getOwnerAddress().getLast20Bytes()), refundGas);
        }
    }
}
Also used : Coin(co.rsk.core.Coin) ProgramInvoke(org.ethereum.vm.program.invoke.ProgramInvoke) Repository(org.ethereum.core.Repository) RskAddress(co.rsk.core.RskAddress)

Example 4 with ProgramInvoke

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

the class Program method executeCode.

public boolean executeCode(MessageCall msg, RskAddress contextAddress, Coin contextBalance, InternalTransaction internalTx, Repository track, byte[] programCode, RskAddress senderAddress, byte[] data) {
    // reset return buffer right before the call
    returnDataBuffer = null;
    ProgramResult childResult = null;
    ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(this, new DataWord(contextAddress.getBytes()), msg.getType() == MsgType.DELEGATECALL ? getCallerAddress() : getOwnerAddress(), msg.getType() == MsgType.DELEGATECALL ? getCallValue() : msg.getEndowment(), limitToMaxLong(msg.getGas()), contextBalance, data, track, this.invoke.getBlockStore(), byTestingSuite());
    VM vm = new VM(config, precompiledContracts);
    Program program = new Program(config, precompiledContracts, blockchainConfig, programCode, programInvoke, internalTx);
    vm.play(program);
    childResult = program.getResult();
    getTrace().merge(program.getTrace());
    getResult().merge(childResult);
    boolean childCallSuccessful = true;
    if (childResult.getException() != null || childResult.isRevert()) {
        if (isGasLogEnabled) {
            gasLogger.debug("contract run halted by Exception: contract: [{}], exception: [{}]", contextAddress, childResult.getException());
        }
        internalTx.reject();
        childResult.rejectInternalTransactions();
        childResult.rejectLogInfos();
        track.rollback();
        // and we only do that when the call is successful or there's a REVERT operation.
        if (childResult.getException() != null) {
            return false;
        }
        childCallSuccessful = false;
    } else {
        // 4. THE FLAG OF SUCCESS IS ONE PUSHED INTO THE STACK
        track.commit();
    }
    // 3. APPLY RESULTS: childResult.getHReturn() into out_memory allocated
    byte[] buffer = childResult.getHReturn();
    int offset = msg.getOutDataOffs().intValue();
    int size = msg.getOutDataSize().intValue();
    memorySaveLimited(offset, buffer, size);
    returnDataBuffer = buffer;
    // 5. REFUND THE REMAIN GAS
    BigInteger refundGas = msg.getGas().value().subtract(toBI(childResult.getGasUsed()));
    if (isPositive(refundGas)) {
        // Since the original gas transferred was < Long.MAX_VALUE then the refund
        // also fits in a long.
        // SUICIDE refunds 24.000 and SSTORE clear refunds 15.000 gas.
        // The accumulated refund can not exceed half the gas used
        // for the current context (i.e. the initial call)
        // Therefore, the regundGas also fits in a long.
        refundGas(refundGas.longValue(), "remaining gas from the internal call");
        if (isGasLogEnabled) {
            gasLogger.info("The remaining gas refunded, account: [{}], gas: [{}] ", senderAddress, refundGas.toString());
        }
    }
    return childCallSuccessful;
}
Also used : ProgramInvoke(org.ethereum.vm.program.invoke.ProgramInvoke) BigInteger(java.math.BigInteger)

Example 5 with ProgramInvoke

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

the class TestRunner method runTestCase.

public List<String> runTestCase(TestCase testCase) {
    logger.info("\n***");
    logger.info(" Running test case: [" + testCase.getName() + "]");
    logger.info("***\n");
    List<String> results = new ArrayList<>();
    logger.info("--------- PRE ---------");
    Repository repository = loadRepository(new RepositoryImpl(config).startTracking(), testCase.getPre());
    try {
        /* 2. Create ProgramInvoke - Env/Exec */
        Env env = testCase.getEnv();
        Exec exec = testCase.getExec();
        Logs logs = testCase.getLogs();
        byte[] address = exec.getAddress();
        byte[] origin = exec.getOrigin();
        byte[] caller = exec.getCaller();
        byte[] balance = ByteUtil.bigIntegerToBytes(repository.getBalance(new RskAddress(exec.getAddress())).asBigInteger());
        byte[] gasPrice = exec.getGasPrice();
        byte[] gas = exec.getGas();
        byte[] callValue = exec.getValue();
        byte[] msgData = exec.getData();
        byte[] lastHash = env.getPreviousHash();
        byte[] coinbase = env.getCurrentCoinbase();
        long timestamp = ByteUtil.byteArrayToLong(env.getCurrentTimestamp());
        long number = ByteUtil.byteArrayToLong(env.getCurrentNumber());
        byte[] difficulty = env.getCurrentDifficulty();
        byte[] gaslimit = env.getCurrentGasLimit();
        // Origin and caller need to exist in order to be able to execute
        if (repository.getAccountState(new RskAddress(origin)) == null)
            repository.createAccount(new RskAddress(origin));
        if (repository.getAccountState(new RskAddress(caller)) == null)
            repository.createAccount(new RskAddress(caller));
        ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue, msgData, lastHash, coinbase, timestamp, number, 0, difficulty, gaslimit, repository, new BlockStoreDummy(), true);
        /* 3. Create Program - exec.code */
        /* 4. run VM */
        VM vm = new VM(vmConfig, precompiledContracts);
        Program program = new Program(vmConfig, precompiledContracts, mock(BlockchainConfig.class), exec.getCode(), programInvoke, null);
        boolean vmDidThrowAnEception = false;
        Exception e = null;
        ThreadMXBean thread;
        Boolean oldMode;
        long startTime = 0;
        thread = ManagementFactory.getThreadMXBean();
        if (thread.isThreadCpuTimeSupported()) {
            oldMode = thread.isThreadCpuTimeEnabled();
            thread.setThreadCpuTimeEnabled(true);
            // in nanoseconds.
            startTime = thread.getCurrentThreadCpuTime();
        }
        try {
            vm.steps(program, Long.MAX_VALUE);
            ;
        } catch (RuntimeException ex) {
            vmDidThrowAnEception = true;
            e = ex;
        }
        if (startTime != 0) {
            long endTime = thread.getCurrentThreadCpuTime();
            // de nano a micro.
            long deltaTime = (endTime - startTime) / 1000;
            logger.info("Time elapsed [uS]: " + Long.toString(deltaTime));
        }
        try {
            saveProgramTraceFile(config, testCase.getName(), program.getTrace());
        } catch (IOException ioe) {
            vmDidThrowAnEception = true;
            e = ioe;
        }
        if (testCase.getPost().size() == 0) {
            if (vmDidThrowAnEception != true) {
                String output = "VM was expected to throw an exception";
                logger.info(output);
                results.add(output);
            } else
                logger.info("VM did throw an exception: " + e.toString());
        } else {
            if (vmDidThrowAnEception) {
                String output = "VM threw an unexpected exception: " + e.toString();
                logger.info(output, e);
                results.add(output);
                return results;
            }
            this.trace = program.getTrace();
            logger.info("--------- POST --------");
            /* 5. Assert Post values */
            for (RskAddress addr : testCase.getPost().keySet()) {
                AccountState accountState = testCase.getPost().get(addr);
                long expectedNonce = accountState.getNonceLong();
                Coin expectedBalance = accountState.getBalance();
                byte[] expectedCode = accountState.getCode();
                boolean accountExist = (null != repository.getAccountState(addr));
                if (!accountExist) {
                    String output = String.format("The expected account does not exist. key: [ %s ]", addr);
                    logger.info(output);
                    results.add(output);
                    continue;
                }
                long actualNonce = repository.getNonce(addr).longValue();
                Coin actualBalance = repository.getBalance(addr);
                byte[] actualCode = repository.getCode(addr);
                if (actualCode == null)
                    actualCode = "".getBytes();
                if (expectedNonce != actualNonce) {
                    String output = String.format("The nonce result is different. key: [ %s ],  expectedNonce: [ %d ] is actualNonce: [ %d ] ", addr, expectedNonce, actualNonce);
                    logger.info(output);
                    results.add(output);
                }
                if (!expectedBalance.equals(actualBalance)) {
                    String output = String.format("The balance result is different. key: [ %s ],  expectedBalance: [ %s ] is actualBalance: [ %s ] ", addr, expectedBalance.toString(), actualBalance.toString());
                    logger.info(output);
                    results.add(output);
                }
                if (!Arrays.equals(expectedCode, actualCode)) {
                    String output = String.format("The code result is different. account: [ %s ],  expectedCode: [ %s ] is actualCode: [ %s ] ", addr, Hex.toHexString(expectedCode), Hex.toHexString(actualCode));
                    logger.info(output);
                    results.add(output);
                }
                // assert storage
                Map<DataWord, DataWord> storage = accountState.getStorage();
                for (DataWord storageKey : storage.keySet()) {
                    byte[] expectedStValue = storage.get(storageKey).getData();
                    ContractDetails contractDetails = program.getStorage().getContractDetails(accountState.getAddress());
                    if (contractDetails == null) {
                        String output = String.format("Storage raw doesn't exist: key [ %s ], expectedValue: [ %s ]", Hex.toHexString(storageKey.getData()), Hex.toHexString(expectedStValue));
                        logger.info(output);
                        results.add(output);
                        continue;
                    }
                    Map<DataWord, DataWord> testStorage = contractDetails.getStorage();
                    DataWord actualValue = testStorage.get(new DataWord(storageKey.getData()));
                    if (actualValue == null || !Arrays.equals(expectedStValue, actualValue.getData())) {
                        String output = String.format("Storage value different: key [ %s ], expectedValue: [ %s ], actualValue: [ %s ]", Hex.toHexString(storageKey.getData()), Hex.toHexString(expectedStValue), actualValue == null ? "" : Hex.toHexString(actualValue.getNoLeadZeroesData()));
                        logger.info(output);
                        results.add(output);
                    }
                }
                /* asset logs */
                List<LogInfo> logResult = program.getResult().getLogInfoList();
                Iterator<LogInfo> postLogs = logs.getIterator();
                int i = 0;
                while (postLogs.hasNext()) {
                    LogInfo expectedLogInfo = postLogs.next();
                    LogInfo foundLogInfo = null;
                    if (logResult.size() > i) {
                        foundLogInfo = logResult.get(i);
                    }
                    if (foundLogInfo == null) {
                        String output = String.format("Expected log [ %s ]", expectedLogInfo.toString());
                        logger.info(output);
                        results.add(output);
                    } else {
                        if (!Arrays.equals(expectedLogInfo.getAddress(), foundLogInfo.getAddress())) {
                            String output = String.format("Expected address [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getAddress()), Hex.toHexString(foundLogInfo.getAddress()));
                            logger.info(output);
                            results.add(output);
                        }
                        if (!Arrays.equals(expectedLogInfo.getData(), foundLogInfo.getData())) {
                            String output = String.format("Expected data [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getData()), Hex.toHexString(foundLogInfo.getData()));
                            logger.info(output);
                            results.add(output);
                        }
                        if (!expectedLogInfo.getBloom().equals(foundLogInfo.getBloom())) {
                            String output = String.format("Expected bloom [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getBloom().getData()), Hex.toHexString(foundLogInfo.getBloom().getData()));
                            logger.info(output);
                            results.add(output);
                        }
                        if (expectedLogInfo.getTopics().size() != foundLogInfo.getTopics().size()) {
                            String output = String.format("Expected number of topics [ %d ], found [ %d ]", expectedLogInfo.getTopics().size(), foundLogInfo.getTopics().size());
                            logger.info(output);
                            results.add(output);
                        } else {
                            int j = 0;
                            for (DataWord topic : expectedLogInfo.getTopics()) {
                                byte[] foundTopic = foundLogInfo.getTopics().get(j).getData();
                                if (!Arrays.equals(topic.getData(), foundTopic)) {
                                    String output = String.format("Expected topic [ %s ], found [ %s ]", Hex.toHexString(topic.getData()), Hex.toHexString(foundTopic));
                                    logger.info(output);
                                    results.add(output);
                                }
                                ++j;
                            }
                        }
                    }
                    ++i;
                }
            }
            // TODO: assert that you have no extra accounts in the repository
            // TODO:  -> basically the deleted by suicide should be deleted
            // TODO:  -> and no unexpected created
            List<org.ethereum.vm.CallCreate> resultCallCreates = program.getResult().getCallCreateList();
            // assert call creates
            for (int i = 0; i < testCase.getCallCreateList().size(); ++i) {
                org.ethereum.vm.CallCreate resultCallCreate = null;
                if (resultCallCreates != null && resultCallCreates.size() > i) {
                    resultCallCreate = resultCallCreates.get(i);
                }
                CallCreate expectedCallCreate = testCase.getCallCreateList().get(i);
                if (resultCallCreate == null && expectedCallCreate != null) {
                    String output = String.format("Missing call/create invoke: to: [ %s ], data: [ %s ], gas: [ %s ], value: [ %s ]", Hex.toHexString(expectedCallCreate.getDestination()), Hex.toHexString(expectedCallCreate.getData()), Long.toHexString(expectedCallCreate.getGasLimit()), Hex.toHexString(expectedCallCreate.getValue()));
                    logger.info(output);
                    results.add(output);
                    continue;
                }
                boolean assertDestination = Arrays.equals(expectedCallCreate.getDestination(), resultCallCreate.getDestination());
                if (!assertDestination) {
                    String output = String.format("Call/Create destination is different. Expected: [ %s ], result: [ %s ]", Hex.toHexString(expectedCallCreate.getDestination()), Hex.toHexString(resultCallCreate.getDestination()));
                    logger.info(output);
                    results.add(output);
                }
                boolean assertData = Arrays.equals(expectedCallCreate.getData(), resultCallCreate.getData());
                if (!assertData) {
                    String output = String.format("Call/Create data is different. Expected: [ %s ], result: [ %s ]", Hex.toHexString(expectedCallCreate.getData()), Hex.toHexString(resultCallCreate.getData()));
                    logger.info(output);
                    results.add(output);
                }
                boolean assertGasLimit = expectedCallCreate.getGasLimit() == resultCallCreate.getGasLimit();
                if (!assertGasLimit) {
                    String output = String.format("Call/Create gasLimit is different. Expected: [ %s ], result: [ %s ]", Long.toHexString(expectedCallCreate.getGasLimit()), Long.toHexString(resultCallCreate.getGasLimit()));
                    logger.info(output);
                    results.add(output);
                }
                boolean assertValue = Arrays.equals(expectedCallCreate.getValue(), resultCallCreate.getValue());
                if (!assertValue) {
                    String output = String.format("Call/Create value is different. Expected: [ %s ], result: [ %s ]", Hex.toHexString(expectedCallCreate.getValue()), Hex.toHexString(resultCallCreate.getValue()));
                    logger.info(output);
                    results.add(output);
                }
            }
            // assert out
            byte[] expectedHReturn = testCase.getOut();
            byte[] actualHReturn = EMPTY_BYTE_ARRAY;
            if (program.getResult().getHReturn() != null) {
                actualHReturn = program.getResult().getHReturn();
            }
            if (!Arrays.equals(expectedHReturn, actualHReturn)) {
                String output = String.format("HReturn is different. Expected hReturn: [ %s ], actual hReturn: [ %s ]", Hex.toHexString(expectedHReturn), Hex.toHexString(actualHReturn));
                logger.info(output);
                results.add(output);
            }
            // assert gas
            BigInteger expectedGas = new BigInteger(1, testCase.getGas());
            BigInteger actualGas = new BigInteger(1, gas).subtract(BigInteger.valueOf(program.getResult().getGasUsed()));
            if (validateGasUsed)
                if (!expectedGas.equals(actualGas)) {
                    String output = String.format("Gas remaining is different. Expected gas remaining: [ %s ], actual gas remaining: [ %s ]", expectedGas.toString(), actualGas.toString());
                    logger.info(output);
                    results.add(output);
                }
        /*
                 * end of if(testCase.getPost().size() == 0)
                 */
        }
        return results;
    } finally {
    // repository.close();
    }
}
Also used : DataWord(org.ethereum.vm.DataWord) ProgramInvokeImpl(org.ethereum.vm.program.invoke.ProgramInvokeImpl) ProgramInvoke(org.ethereum.vm.program.invoke.ProgramInvoke) Coin(co.rsk.core.Coin) RskAddress(co.rsk.core.RskAddress) ThreadMXBean(java.lang.management.ThreadMXBean) Program(org.ethereum.vm.program.Program) LogInfo(org.ethereum.vm.LogInfo) IOException(java.io.IOException) IOException(java.io.IOException) Repository(org.ethereum.core.Repository) BlockchainConfig(org.ethereum.config.BlockchainConfig) RepositoryImpl(co.rsk.db.RepositoryImpl) VM(org.ethereum.vm.VM) BigInteger(java.math.BigInteger)

Aggregations

ProgramInvoke (org.ethereum.vm.program.invoke.ProgramInvoke)5 Coin (co.rsk.core.Coin)4 RskAddress (co.rsk.core.RskAddress)4 BigInteger (java.math.BigInteger)3 BlockchainConfig (org.ethereum.config.BlockchainConfig)3 Program (org.ethereum.vm.program.Program)3 Repository (org.ethereum.core.Repository)2 RepositoryImpl (co.rsk.db.RepositoryImpl)1 IOException (java.io.IOException)1 ThreadMXBean (java.lang.management.ThreadMXBean)1 ContractDetails (org.ethereum.db.ContractDetails)1 DataWord (org.ethereum.vm.DataWord)1 LogInfo (org.ethereum.vm.LogInfo)1 VM (org.ethereum.vm.VM)1 ProgramInvokeImpl (org.ethereum.vm.program.invoke.ProgramInvokeImpl)1