Skip to content

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
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -203,6 +203,11 @@ public boolean eip145() {
return false;
}

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

@Override
public String toString() {
return getClass().getSimpleName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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
Expand Up @@ -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
Expand Up @@ -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));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
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
Expand Up @@ -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;
Expand Down Expand Up @@ -169,6 +170,10 @@ public int getREFUND_SSTORE() {
return REFUND_SSTORE;
}

public int getREUSE_SSTORE() {
return REUSE_SSTORE;
}

public int getCREATE() {
return CREATE;
}
Expand Down
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
Expand Up @@ -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();
Expand Down
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
Expand Up @@ -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();
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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();
}
Expand Down
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
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 6b87540

Please sign in to comment.