Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1173 from ethereum/feature/eip-1283
Browse files Browse the repository at this point in the history
Feature/eip 1283
  • Loading branch information
mkalinin authored Sep 10, 2018
2 parents a8a8613 + 53098a6 commit 6b87540
Showing 15 changed files with 387 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -175,4 +175,10 @@ String validateTransactionChanges(BlockStore blockStore, Block curBlock, Transac
* EXTCODEHASH opcode
*/
boolean eip1052();

/**
* EIP 1283: https://eips.ethereum.org/EIPS/eip-1283
* Net gas metering for SSTORE without dirty maps
*/
boolean eip1283();
}
Original file line number Diff line number Diff line change
@@ -203,6 +203,11 @@ public boolean eip145() {
return false;
}

@Override
public boolean eip1283() {
return false;
}

@Override
public String toString() {
return getClass().getSimpleName();
Original file line number Diff line number Diff line change
@@ -43,4 +43,9 @@ public boolean eip1052() {
public boolean eip145() {
return true;
}

@Override
public boolean eip1283() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -191,4 +191,9 @@ public boolean eip145() {
public boolean eip1052() {
return false;
}

@Override
public boolean eip1283() {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -235,4 +235,10 @@ void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccou
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails);

Repository getSnapshotTo(byte[] root);

/**
* Clones repository so changes made to this repository are
* not reflected in its clone.
*/
Repository clone();
}
Original file line number Diff line number Diff line change
@@ -396,7 +396,7 @@ public TransactionExecutionSummary finalization() {
// Accumulate refunds for suicides
result.addFutureRefund(result.getDeleteAccounts().size() * config.getBlockchainConfig().
getConfigForBlock(currentBlock.getNumber()).getGasCost().getSUICIDE_REFUND());
long gasRefund = Math.min(result.getFutureRefund(), getGasUsed() / 2);
long gasRefund = Math.min(Math.max(0, result.getFutureRefund()), getGasUsed() / 2);
byte[] addr = tx.isContractCreation() ? tx.getContractAddress() : tx.getReceiveAddress();
m_endGas = m_endGas.add(BigInteger.valueOf(gasRefund));

Original file line number Diff line number Diff line change
@@ -230,6 +230,14 @@ public String dumpStateTrie() {
throw new RuntimeException("Not supported");
}

/**
* As tests only implementation this hack is pretty sufficient
*/
@Override
public Repository clone() {
return parent.startTracking();
}

class ContractDetailsImpl implements ContractDetails {
private byte[] address;

Original file line number Diff line number Diff line change
@@ -134,6 +134,11 @@ public Repository getSnapshotTo(byte[] root) {
return new RepositoryRoot(stateDS, root);
}

@Override
public Repository clone() {
return getSnapshotTo(getRoot());
}

@Override
public synchronized String dumpStateTrie() {
return ((TrieImpl) stateTrie).dumpTrie();
Original file line number Diff line number Diff line change
@@ -201,6 +201,11 @@ public Repository getSnapshotTo(byte[] root) {
return blockchain.getRepository().getSnapshotTo(root);
}

@Override
public Repository clone() {
return getSnapshotTo(getRoot());
}

@Override
public int getStorageSize(byte[] addr) {
return blockchain.getRepository().getStorageSize(addr);
5 changes: 5 additions & 0 deletions ethereumj-core/src/main/java/org/ethereum/vm/GasCost.java
Original file line number Diff line number Diff line change
@@ -51,6 +51,7 @@ public class GasCost {
private final int SET_SSTORE = 20000;
private final int RESET_SSTORE = 5000;
private final int REFUND_SSTORE = 15000;
private final int REUSE_SSTORE = 200;
private final int CREATE = 32000;

private final int JUMPDEST = 1;
@@ -169,6 +170,10 @@ public int getREFUND_SSTORE() {
return REFUND_SSTORE;
}

public int getREUSE_SSTORE() {
return REUSE_SSTORE;
}

public int getCREATE() {
return CREATE;
}
58 changes: 47 additions & 11 deletions ethereumj-core/src/main/java/org/ethereum/vm/VM.java
Original file line number Diff line number Diff line change
@@ -241,18 +241,54 @@ public void step(Program program) {
}
break;
case SSTORE:
DataWord currentValue = program.getCurrentValue(stack.peek());
if (currentValue == null) currentValue = DataWord.ZERO;
DataWord newValue = stack.get(stack.size() - 2);
DataWord oldValue = program.storageLoad(stack.peek());
if (oldValue == null && !newValue.isZero())
gasCost = gasCosts.getSET_SSTORE();
else if (oldValue != null && newValue.isZero()) {
// todo: GASREFUND counter policy

// refund step cost policy.
program.futureRefundGas(gasCosts.getREFUND_SSTORE());
gasCost = gasCosts.getCLEAR_SSTORE();
} else
gasCost = gasCosts.getRESET_SSTORE();

if (blockchainConfig.eip1283()) { // Net gas metering for SSTORE
if (newValue.equals(currentValue)) {
gasCost = gasCosts.getREUSE_SSTORE();
} else {
DataWord origValue = program.getOriginalValue(stack.peek());
if (origValue == null) origValue = DataWord.ZERO;
if (currentValue.equals(origValue)) {
if (origValue.isZero()) {
gasCost = gasCosts.getSET_SSTORE();
} else {
gasCost = gasCosts.getCLEAR_SSTORE();
if (newValue.isZero()) {
program.futureRefundGas(gasCosts.getREFUND_SSTORE());
}
}
} else {
gasCost = gasCosts.getREUSE_SSTORE();
if (!origValue.isZero()) {
if (currentValue.isZero()) {
program.futureRefundGas(-gasCosts.getREFUND_SSTORE());
} else if (newValue.isZero()) {
program.futureRefundGas(gasCosts.getREFUND_SSTORE());
}
}
if (origValue.equals(newValue)) {
if (origValue.isZero()) {
program.futureRefundGas(gasCosts.getSET_SSTORE() - gasCosts.getREUSE_SSTORE());
} else {
program.futureRefundGas(gasCosts.getCLEAR_SSTORE() - gasCosts.getREUSE_SSTORE());
}
}
}
}
} else { // Before EIP-1283 cost calculation
if (currentValue.isZero() && !newValue.isZero())
gasCost = gasCosts.getSET_SSTORE();
else if (!currentValue.isZero() && newValue.isZero()) {
// refund step cost policy.
program.futureRefundGas(gasCosts.getREFUND_SSTORE());
gasCost = gasCosts.getCLEAR_SSTORE();
} else {
gasCost = gasCosts.getRESET_SSTORE();
}
}
break;
case SLOAD:
gasCost = gasCosts.getSLOAD();
18 changes: 18 additions & 0 deletions ethereumj-core/src/main/java/org/ethereum/vm/program/Program.java
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ public class Program {
private Stack stack;
private Memory memory;
private Storage storage;
private Repository originalRepo;
private byte[] returnDataBuffer;

private ProgramResult result = new ProgramResult();
@@ -136,6 +137,7 @@ public Program(byte[] codeHash, byte[] ops, ProgramInvoke programInvoke, Transac
traceListener = new ProgramTraceListener(config.vmTrace());
this.memory = setupProgramListener(new Memory());
this.stack = setupProgramListener(new Stack());
this.originalRepo = programInvoke.getRepository().clone();
this.storage = setupProgramListener(new Storage(programInvoke));
this.trace = new ProgramTrace(config, programInvoke);
this.blockchainConfig = config.getBlockchainConfig().getConfigForBlock(programInvoke.getNumber().longValue());
@@ -793,6 +795,22 @@ public DataWord storageLoad(DataWord key) {
return getStorage().getStorageValue(getOwnerAddress().getLast20Bytes(), key);
}

/**
* @return current Storage data for key
*/
public DataWord getCurrentValue(DataWord key) {
return getStorage().getStorageValue(getOwnerAddress().getLast20Bytes(), key);
}

/*
* Original storage value at the beginning of current frame execution
* For more info check EIP-1283 https://eips.ethereum.org/EIPS/eip-1283
* @return Storage data at the beginning of Program execution
*/
public DataWord getOriginalValue(DataWord key) {
return originalRepo.getStorageValue(getOwnerAddress().getLast20Bytes(), key);
}

public DataWord getPrevHash() {
return invoke.getPrevHash();
}
10 changes: 10 additions & 0 deletions ethereumj-core/src/main/java/org/ethereum/vm/program/Storage.java
Original file line number Diff line number Diff line change
@@ -45,6 +45,11 @@ public Storage(ProgramInvoke programInvoke) {
this.repository = programInvoke.getRepository();
}

private Storage(Repository repository, DataWord address) {
this.repository = repository;
this.address = address;
}

@Override
public void setProgramListener(ProgramListener listener) {
this.programListener = listener;
@@ -224,6 +229,11 @@ public Repository getSnapshotTo(byte[] root) {
throw new UnsupportedOperationException();
}

@Override
public Repository clone() {
return new Storage(repository.getSnapshotTo(getRoot()), address);
}

@Override
public int getStorageSize(byte[] addr) {
return repository.getStorageSize(addr);
Original file line number Diff line number Diff line change
@@ -77,6 +77,11 @@ public Repository getSnapshotTo(byte[] root) {
return new IterableTestRepository(src.getSnapshotTo(root), this);
}

@Override
public Repository clone() {
return new IterableTestRepository(src.clone(), this);
}

@Override
public AccountState createAccount(byte[] addr) {
addAccount(addr);
Loading

0 comments on commit 6b87540

Please sign in to comment.