poc-7 gas adjustments:
+ EXP new cost + Transaction data new cost + mem data copy size cost + small fixes
This commit is contained in:
parent
883ca6e5dc
commit
1f22e1e9f9
|
@ -150,6 +150,7 @@ public class AccountState {
|
|||
accountState.setNonce(this.getNonce());
|
||||
accountState.setCodeHash(this.getCodeHash());
|
||||
accountState.setStateRoot(this.getStateRoot());
|
||||
accountState.setDirty(false);
|
||||
|
||||
return accountState;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.ethereum.manager.WorldManager;
|
|||
import org.ethereum.net.BlockQueue;
|
||||
import org.ethereum.net.server.ChannelManager;
|
||||
import org.ethereum.util.AdvancedDeviceUtils;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.vm.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -321,14 +320,17 @@ public class BlockchainImpl implements Blockchain {
|
|||
int i = 0;
|
||||
long totalGasUsed = 0;
|
||||
for (Transaction tx : block.getTransactionsList()) {
|
||||
stateLogger.debug("apply block: [{}] tx: [{}] ", block.getNumber(), i);
|
||||
stateLogger.info("apply block: [{}] tx: [{}] ", block.getNumber(), i);
|
||||
|
||||
TransactionReceipt receipt = applyTransaction(block, tx);
|
||||
totalGasUsed += receipt.getCumulativeGasLong();
|
||||
receipt.setCumulativeGas(totalGasUsed);
|
||||
|
||||
track.commit();
|
||||
|
||||
receipt.setPostTxState(repository.getRoot());
|
||||
stateLogger.info("executed block: [{}] tx: [{}] \n state: [{}]", block.getNumber(), i,
|
||||
Hex.toHexString(repository.getRoot()));
|
||||
|
||||
if(block.getNumber() >= CONFIG.traceStartBlock())
|
||||
repository.dumpState(block, totalGasUsed, i++, tx.getHash());
|
||||
|
@ -552,8 +554,8 @@ public class BlockchainImpl implements Blockchain {
|
|||
}
|
||||
trackTx.commit();
|
||||
} else {
|
||||
// REFUND GASDEBIT EXCEPT FOR FEE (500 + 5*TXDATA)
|
||||
long dataCost = tx.getData() == null ? 0: tx.getData().length * GasCost.TXDATA;
|
||||
// REFUND GASDEBIT EXCEPT FOR FEE (500 + 5*TX_NO_ZERO_DATA)
|
||||
long dataCost = tx.getData() == null ? 0: tx.getData().length * GasCost.TX_NO_ZERO_DATA;
|
||||
gasUsed = GasCost.TRANSACTION + dataCost;
|
||||
|
||||
BigInteger refund = gasDebit.subtract(BigInteger.valueOf(gasUsed).multiply(gasPrice));
|
||||
|
|
|
@ -88,16 +88,15 @@ public class RepositoryImpl implements Repository {
|
|||
public void updateBatch(HashMap<ByteArrayWrapper, AccountState> stateCache,
|
||||
HashMap<ByteArrayWrapper, ContractDetails> detailsCache) {
|
||||
|
||||
WriteBatch writeBatch = detailsDB.getDb().createWriteBatch();
|
||||
for (ByteArrayWrapper hash : detailsCache.keySet()) {
|
||||
|
||||
ContractDetails contractDetails = detailsCache.get(hash);
|
||||
|
||||
if (contractDetails.isDeleted())
|
||||
writeBatch.delete(hash.getData());
|
||||
detailsDB.delete(hash.getData());
|
||||
else{
|
||||
if (contractDetails.isDirty())
|
||||
writeBatch.put(hash.getData(), contractDetails.getEncoded());
|
||||
detailsDB.put(hash.getData(), contractDetails.getEncoded());
|
||||
}
|
||||
|
||||
if (contractDetails.isDirty() || contractDetails.isDeleted()){
|
||||
|
@ -110,7 +109,6 @@ public class RepositoryImpl implements Repository {
|
|||
contractDetails.setDeleted(false);
|
||||
contractDetails.setDirty(false);
|
||||
}
|
||||
detailsDB.getDb().write(writeBatch);
|
||||
|
||||
for (ByteArrayWrapper hash : detailsCache.keySet()) {
|
||||
|
||||
|
@ -119,8 +117,18 @@ public class RepositoryImpl implements Repository {
|
|||
if (accountState.isDeleted())
|
||||
worldState.delete(hash.getData());
|
||||
else{
|
||||
if (accountState.isDirty())
|
||||
if (accountState.isDirty()){
|
||||
worldState.update(hash.getData(), accountState.getEncoded());
|
||||
|
||||
if (logger.isDebugEnabled()){
|
||||
|
||||
logger.debug("update: [{}],nonce: [{}] balance: [{}]",
|
||||
Hex.toHexString(hash.getData()),
|
||||
accountState.getNonce(),
|
||||
accountState.getBalance());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
accountState.setDeleted(false);
|
||||
|
|
|
@ -126,10 +126,12 @@ public class RepositoryTrack implements Repository {
|
|||
accountState = createAccount(addr);
|
||||
}
|
||||
|
||||
logger.trace("adding to balance addr: [{}], balance: [{}], delta: [{}]", Hex.toHexString(addr),
|
||||
accountState.getBalance(), value);
|
||||
BigInteger newBalance = accountState.addToBalance(value);
|
||||
|
||||
return accountState.addToBalance(value);
|
||||
logger.trace("adding to balance addr: [{}], balance: [{}], delta: [{}]", Hex.toHexString(addr),
|
||||
newBalance, value);
|
||||
|
||||
return newBalance;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -188,6 +190,8 @@ public class RepositoryTrack implements Repository {
|
|||
public void commit() {
|
||||
logger.debug("commit changes");
|
||||
repository.updateBatch(cacheAccounts, cacheDetails);
|
||||
cacheAccounts.clear();
|
||||
cacheDetails.clear();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -231,12 +231,24 @@ public class ByteUtil {
|
|||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public static int firstNonZeroByte(byte[] data){
|
||||
int firstNonZero = -1;
|
||||
int i = 0;
|
||||
for (; i < data.length; ++i) {
|
||||
if (data[i] != 0) {
|
||||
firstNonZero = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return firstNonZero;
|
||||
}
|
||||
|
||||
public static byte[] stripLeadingZeroes(byte[] data) {
|
||||
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
int firstNonZero = 0;
|
||||
int firstNonZero = firstNonZeroByte(data);
|
||||
int i = 0;
|
||||
for (; i < data.length; ++i) {
|
||||
if (data[i] != 0) {
|
||||
|
|
|
@ -302,4 +302,10 @@ public class DataWord implements Comparable<DataWord> {
|
|||
this.data[31 - i] = mask;
|
||||
}
|
||||
}
|
||||
|
||||
public int bytesOccupied(){
|
||||
int firstNonZero = ByteUtil.firstNonZeroByte(data);
|
||||
if (firstNonZero == -1) return 0;
|
||||
return 31 - firstNonZero + 1;
|
||||
}
|
||||
}
|
|
@ -20,8 +20,10 @@ public class GasCost {
|
|||
public static int STOP = 0;
|
||||
/** Cost 0 gas */
|
||||
public static int SUICIDE = 0;
|
||||
/** Cost 100 gas */
|
||||
public static int SSTORE = 100;
|
||||
/** Cost 300 gas */
|
||||
public static int SSTORE = 300;
|
||||
/** Cost 100 gas */
|
||||
public static int RESET_SSTORE = 100;
|
||||
/** Cost 100 gas */
|
||||
public static int CREATE = 100;
|
||||
/** Cost 20 gas */
|
||||
|
@ -29,7 +31,9 @@ public class GasCost {
|
|||
/** Cost 1 gas */
|
||||
public static int MEMORY = 1;
|
||||
/** Cost 5 gas */
|
||||
public static int TXDATA = 5;
|
||||
public static int TX_NO_ZERO_DATA = 5;
|
||||
/** Cost 1 gas */
|
||||
public static int TX_ZERO_DATA = 1;
|
||||
/** Cost 500 gas */
|
||||
public static int TRANSACTION = 500;
|
||||
/** Cost 32 gas */
|
||||
|
@ -38,4 +42,12 @@ public class GasCost {
|
|||
public static int LOG_DATA_GAS = 1;
|
||||
/** Cost 32 gas */
|
||||
public static int LOG_TOPIC_GAS = 32;
|
||||
/** Cost 1 gas */
|
||||
public static int COPY_GAS = 1;
|
||||
/** Cost 1 gas */
|
||||
public static int EXP_GAS = 1;
|
||||
/** Cost 1 gas */
|
||||
public static int EXP_BYTE_GAS = 1;
|
||||
|
||||
|
||||
}
|
|
@ -19,8 +19,9 @@ public interface ProgramInvoke {
|
|||
public DataWord getDataSize();
|
||||
public DataWord getDataValue(DataWord indexData);
|
||||
public byte[] getDataCopy(DataWord offsetData, DataWord lengthData);
|
||||
public int countNonZeroData();
|
||||
|
||||
public DataWord getPrevHash();
|
||||
public DataWord getPrevHash();
|
||||
public DataWord getCoinbase();
|
||||
public DataWord getTimestamp();
|
||||
public DataWord getNumber();
|
||||
|
|
|
@ -31,8 +31,8 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
|||
private boolean byTestingSuite = false;
|
||||
private int callDeep = 0;
|
||||
|
||||
public ProgramInvokeImpl(DataWord address, DataWord origin, DataWord caller, DataWord balance,
|
||||
DataWord gasPrice, DataWord gas, DataWord callValue, byte[] msgData,
|
||||
public ProgramInvokeImpl(DataWord address, DataWord origin, DataWord caller, DataWord balance,
|
||||
DataWord gasPrice, DataWord gas, DataWord callValue, byte[] msgData,
|
||||
DataWord lastHash, DataWord coinbase, DataWord timestamp, DataWord number, DataWord difficulty,
|
||||
DataWord gaslimit, Repository repository, int callDeep) {
|
||||
|
||||
|
@ -182,6 +182,18 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
|||
return data;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int countNonZeroData(){
|
||||
|
||||
int counter = 0;
|
||||
for (int i = 0; i < msgData.length; ++i){
|
||||
|
||||
if (msgData[i] != 0) ++counter;
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
/* PREVHASH op */
|
||||
public DataWord getPrevHash() {
|
||||
return prevHash;
|
||||
|
|
|
@ -146,6 +146,18 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
|||
return new DataWord(prevHash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countNonZeroData(){
|
||||
|
||||
int counter = 0;
|
||||
for (int i = 0; i < msgData.length; ++i){
|
||||
|
||||
if (msgData[i] != 0) ++counter;
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DataWord getCoinbase() {
|
||||
byte[] coinBase = Hex.decode("E559DE5527492BCB42EC68D07DF0742A98EC3F1E");
|
||||
|
|
|
@ -76,6 +76,7 @@ public class ProgramResult {
|
|||
}
|
||||
|
||||
public void addLogInfos(List<LogInfo> logInfos){
|
||||
if (logInfos == null) return;
|
||||
if (this.logInfoList == null) logInfoList = new ArrayList<>();
|
||||
this.logInfoList.addAll(logInfos);
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ public class VM {
|
|||
|
||||
long oldMemSize = program.getMemSize();
|
||||
BigInteger newMemSize = BigInteger.ZERO;
|
||||
long copySize = 0;
|
||||
Stack<DataWord> stack = program.getStack();
|
||||
|
||||
String hint = "";
|
||||
|
@ -104,11 +105,12 @@ public class VM {
|
|||
DataWord newValue = stack.get(stack.size()-2);
|
||||
DataWord oldValue = program.storageLoad(stack.peek());
|
||||
if (oldValue == null && !newValue.isZero())
|
||||
gasCost = GasCost.SSTORE * 2;
|
||||
gasCost = GasCost.SSTORE;
|
||||
else if (oldValue != null && newValue.isZero())
|
||||
gasCost = GasCost.SSTORE * 0;
|
||||
// todo: GASREFUND counter policy
|
||||
System.currentTimeMillis();
|
||||
else
|
||||
gasCost = GasCost.SSTORE;
|
||||
gasCost = GasCost.RESET_SSTORE;
|
||||
break;
|
||||
case SLOAD:
|
||||
gasCost = GasCost.SLOAD;
|
||||
|
@ -135,12 +137,15 @@ public class VM {
|
|||
newMemSize = memNeeded(stack.peek(), stack.get(stack.size()-2));
|
||||
break;
|
||||
case CALLDATACOPY:
|
||||
copySize = stack.get(stack.size()-3).longValue();
|
||||
newMemSize = memNeeded(stack.peek(), stack.get(stack.size()-3));
|
||||
break;
|
||||
case CODECOPY:
|
||||
copySize = stack.get(stack.size()-3).longValue();
|
||||
newMemSize = memNeeded(stack.peek(), stack.get(stack.size()-3));
|
||||
break;
|
||||
case EXTCODECOPY:
|
||||
copySize = stack.get(stack.size()-4).longValue();
|
||||
newMemSize = memNeeded(stack.get(stack.size()-2), stack.get(stack.size()-4));
|
||||
break;
|
||||
case CALL: case CALLCODE:
|
||||
|
@ -167,7 +172,12 @@ public class VM {
|
|||
GasCost.LOG_DATA_GAS * stack.get(stack.size()-2).longValue();
|
||||
|
||||
break;
|
||||
case EXP:
|
||||
|
||||
DataWord exp = stack.get(stack.size()-2);
|
||||
int bytesOccupied = exp.bytesOccupied();
|
||||
gasCost = (bytesOccupied == 0) ? 0 : GasCost.EXP_GAS + GasCost.EXP_BYTE_GAS * bytesOccupied;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -176,7 +186,7 @@ public class VM {
|
|||
// Avoid overflows
|
||||
if(newMemSize.compareTo(MAX_GAS) == 1)
|
||||
throw program.new OutOfGasException();
|
||||
|
||||
|
||||
// memory gas calc
|
||||
long memoryUsage = (newMemSize.longValue() + 31) / 32 * 32;
|
||||
if (memoryUsage > oldMemSize) {
|
||||
|
@ -186,6 +196,12 @@ public class VM {
|
|||
gasCost += memGas;
|
||||
}
|
||||
|
||||
if (copySize > 0){
|
||||
long copyGas = GasCost.COPY_GAS * (copySize + 31) / 32;
|
||||
gasCost += copyGas;
|
||||
program.spendGas(copyGas, op.name() + " (copy usage)");
|
||||
}
|
||||
|
||||
// Log debugging line for VM
|
||||
if(program.getNumber().intValue() == CONFIG.dumpBlock())
|
||||
this.dumpLine(op, gasBefore, gasCost+callGas, memWords, program);
|
||||
|
@ -750,7 +766,7 @@ public class VM {
|
|||
hint = logInfo.toString();
|
||||
|
||||
program.getResult().addLogInfo(logInfo);
|
||||
|
||||
program.step();
|
||||
} break;
|
||||
case MLOAD:{
|
||||
DataWord addr = program.stackPop();
|
||||
|
@ -820,9 +836,12 @@ public class VM {
|
|||
|
||||
if (!cond.isZero()) {
|
||||
int nextPC = pos.intValue(); // possible overflow
|
||||
if (nextPC != 0 && program.getOp(nextPC-1) != OpCode.JUMPDEST.val())
|
||||
if (nextPC != 0 && program.getOp(nextPC) != OpCode.JUMPDEST.val())
|
||||
throw program.new BadJumpDestinationException();
|
||||
|
||||
// todo: in case destination is not JUMPDEST, check if prev was strict push
|
||||
// todo: in EP: (ii) If a jump is preceded by a push, no jumpdest required;
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "~> " + nextPC;
|
||||
|
||||
|
@ -977,7 +996,12 @@ public class VM {
|
|||
// charged by CALL op
|
||||
if (program.invokeData.byTransaction()) {
|
||||
program.spendGas(GasCost.TRANSACTION, "TRANSACTION");
|
||||
program.spendGas(GasCost.TXDATA * program.invokeData.getDataSize().intValue(), "DATA");
|
||||
int dataSize = program.invokeData.getDataSize().intValue();
|
||||
int nonZeroesVals = program.invokeData.countNonZeroData();
|
||||
int zeroVals = dataSize - nonZeroesVals;
|
||||
|
||||
program.spendGas(GasCost.TX_NO_ZERO_DATA * nonZeroesVals, "DATA");
|
||||
program.spendGas(GasCost.TX_ZERO_DATA * zeroVals, "DATA");
|
||||
}
|
||||
|
||||
while(!program.isStopped())
|
||||
|
|
|
@ -254,6 +254,34 @@ public class BlockTest {
|
|||
assertArrayEquals(root, worldManager.getRepository().getRoot());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScenario4() throws URISyntaxException, IOException {
|
||||
|
||||
BlockchainImpl blockchain = (BlockchainImpl)worldManager.getBlockchain();
|
||||
|
||||
URL scenario1 = ClassLoader
|
||||
.getSystemResource("blockload/scenario4.dmp");
|
||||
|
||||
File file = new File(scenario1.toURI());
|
||||
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
|
||||
|
||||
byte[] root = Genesis.getInstance().getStateRoot();
|
||||
for(String blockRLP : strData){
|
||||
Block block = new Block(
|
||||
Hex.decode(blockRLP));
|
||||
logger.info("sending block.hash: {}", Hex.toHexString( block.getHash() ));
|
||||
blockchain.tryToConnect(block);
|
||||
root = block.getStateRoot();
|
||||
}
|
||||
|
||||
logger.info("asserting root state is: {}", Hex.toHexString( root ));
|
||||
|
||||
//expected root: dedd258f4cee2d1b45f137a2a74a2052e14a6d7fe1b1184be0a6adcec6a1d1d3
|
||||
assertEquals(Hex.toHexString(root),
|
||||
Hex.toHexString(worldManager.getRepository().getRoot()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testUncleValidGenerationGap() {
|
||||
|
|
|
@ -208,4 +208,35 @@ public class ByteUtilTest {
|
|||
System.out.println(System.currentTimeMillis() - start2 + "ms to reach: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(4, counter2)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void firstNonZeroByte_1() {
|
||||
|
||||
byte[] data = Hex.decode("0000000000000000000000000000000000000000000000000000000000000000");
|
||||
int result = ByteUtil.firstNonZeroByte(data);
|
||||
|
||||
assertEquals(-1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void firstNonZeroByte_2() {
|
||||
|
||||
byte[] data = Hex.decode("0000000000000000000000000000000000000000000000000000000000332211");
|
||||
int result = ByteUtil.firstNonZeroByte(data);
|
||||
|
||||
assertEquals(29, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void firstNonZeroByte_3() {
|
||||
|
||||
byte[] data = Hex.decode("2211009988776655443322110099887766554433221100998877665544332211");
|
||||
int result = ByteUtil.firstNonZeroByte(data);
|
||||
|
||||
assertEquals(0, result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1738,13 +1738,14 @@ public class VMTest {
|
|||
public void testJUMPI_1() {
|
||||
|
||||
VM vm = new VM();
|
||||
program = new Program(Hex.decode("60016006575B60CC"), invoke);
|
||||
program = new Program(Hex.decode("60016005575B60CC"), invoke);
|
||||
String s_expected = "00000000000000000000000000000000000000000000000000000000000000CC";
|
||||
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
assertEquals(s_expected, Hex.toHexString(program.getStack().peek().getData()).toUpperCase());
|
||||
}
|
||||
|
@ -1824,7 +1825,7 @@ public class VMTest {
|
|||
public void testJUMPDEST_2() {
|
||||
|
||||
VM vm = new VM();
|
||||
program = new Program(Hex.decode("60236001600a5760015b600255"), invoke);
|
||||
program = new Program(Hex.decode("6023600160095760015b600255"), invoke);
|
||||
|
||||
String s_expected_key = "0000000000000000000000000000000000000000000000000000000000000002";
|
||||
String s_expected_val = "0000000000000000000000000000000000000000000000000000000000000023";
|
||||
|
@ -1835,7 +1836,8 @@ public class VMTest {
|
|||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
vm.step(program);
|
||||
|
||||
DataWord key = new DataWord(Hex.decode(s_expected_key));
|
||||
DataWord val = program.getResult().getRepository().getStorageValue(invoke.getOwnerAddress().getNoLeadZeroesData(), key);
|
||||
|
||||
|
@ -2342,7 +2344,10 @@ public class VMTest {
|
|||
vm.step(program);
|
||||
|
||||
DataWord item1 = program.stackPop();
|
||||
long gas = program.getResult().getGasUsed();
|
||||
|
||||
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
|
||||
assertEquals(4, gas);
|
||||
}
|
||||
|
||||
@Test // EXP OP
|
||||
|
@ -2357,12 +2362,34 @@ public class VMTest {
|
|||
vm.step(program);
|
||||
|
||||
DataWord item1 = program.stackPop();
|
||||
long gas = program.getResult().getGasUsed();
|
||||
|
||||
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
|
||||
assertEquals(2, gas);
|
||||
}
|
||||
|
||||
@Test(expected=StackTooSmallException.class) // EXP OP mal
|
||||
@Test // EXP OP
|
||||
public void testEXP_3() {
|
||||
|
||||
VM vm = new VM();
|
||||
program = new Program(Hex.decode("61112260010a"), invoke);
|
||||
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000001";
|
||||
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
DataWord item1 = program.stackPop();
|
||||
long gas = program.getResult().getGasUsed();
|
||||
|
||||
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
|
||||
assertEquals(5, gas);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected=StackTooSmallException.class) // EXP OP mal
|
||||
public void testEXP_4() {
|
||||
|
||||
VM vm = new VM();
|
||||
program = new Program(Hex.decode("621234560a"), invoke);
|
||||
try {
|
||||
|
@ -2465,7 +2492,9 @@ public class VMTest {
|
|||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
long gas = program.getResult().getGasUsed();
|
||||
assertEquals(m_expected_1, Hex.toHexString(program.getMemory().array()).toUpperCase());
|
||||
assertEquals(6, gas);
|
||||
}
|
||||
|
||||
@Test // CODECOPY OP
|
||||
|
@ -2482,7 +2511,9 @@ public class VMTest {
|
|||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
long gas = program.getResult().getGasUsed();
|
||||
assertEquals(m_expected_1, Hex.toHexString(program.getMemory().array()).toUpperCase());
|
||||
assertEquals(10 , gas);
|
||||
}
|
||||
|
||||
@Test // CODECOPY OP
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue