Skip to content

Commit

Permalink
Merge branch 'master' into fmacleal/addition_transient_storage_opcodes
Browse files Browse the repository at this point in the history
  • Loading branch information
fmacleal committed Dec 17, 2024
2 parents b730550 + d072012 commit d0ccf35
Show file tree
Hide file tree
Showing 28 changed files with 2,973 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public enum ConsensusRule {
RSKIP428("rskip428"),
RSKIP434("rskip434"),
RSKIP438("rskip438"),
RSKIP445("rskip445"), // From EIP-5656 MCOPY instruction
RSKIP446("rskip446") ,// Transient storage opcodes addition implementing EIP-1153
RSKIP454("rskip454")
;
Expand Down
4 changes: 4 additions & 0 deletions rskj-core/src/main/java/org/ethereum/vm/OpCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,10 @@ public enum OpCode {
* (0x5b)
*/
JUMPDEST(0x5b, 0, 0, SPECIAL_TIER),
/**
* (0x5e) Memory copying instruction
*/
MCOPY(0x5e, 3, 0, VERY_LOW_TIER),

/**
* (0x5c) Load word from transient storage at address
Expand Down
13 changes: 9 additions & 4 deletions rskj-core/src/main/java/org/ethereum/vm/OpCodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
* Created by Sergio on 07/07/2016.
*/
public class OpCodes {

private OpCodes() {

}

/**
* Halts execution (0x00)
*/
Expand Down Expand Up @@ -320,6 +325,10 @@ public class OpCodes {
* (0x5b)
*/
static final byte OP_JUMPDEST =0x5b ;
/**
* (0x5e)
*/
public static final byte OP_MCOPY = 0x5e;
/**
* (0x5c)
*/
Expand Down Expand Up @@ -667,8 +676,4 @@ public class OpCodes {
* later deletion
*/
static final byte OP_SUICIDE =(byte)0xff;

private OpCodes() {

}
}
44 changes: 44 additions & 0 deletions rskj-core/src/main/java/org/ethereum/vm/VM.java
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,25 @@ private long computeDataCopyGas() {
return calcMemGas(oldMemSize, newMemSize, copySize);
}

private long computeMemoryCopyGas() {
DataWord length = stack.get(stack.size() - 3);
DataWord src = stack.get(stack.size() - 2);
DataWord dst = stack.peek();

long copySize = Program.limitToMaxLong(length);
checkSizeArgument(copySize);

DataWord offset = dst;
if (src.value().compareTo(dst.value()) > 0) {
offset = src;
}

long newMemSize = memNeeded(offset, copySize);

// Note: 3 additional units are added outside because of the "Very Low Tier" configuration
return calcMemGas(oldMemSize, newMemSize, copySize);
}

protected void doCODESIZE() {
if (computeGas) {
if (op == OpCode.EXTCODESIZE) {
Expand Down Expand Up @@ -1491,6 +1510,25 @@ protected void doJUMPDEST()
program.step();
}

protected void doMCOPY() {
if (computeGas) {
gasCost = GasCost.add(gasCost, computeMemoryCopyGas());
spendOpCodeGas();
}

// EXECUTION PHASE
DataWord dst = program.stackPop();
DataWord src = program.stackPop();
DataWord length = program.stackPop();

if (isLogEnabled) {
hint = "dst: " + dst + " src: " + src + " length: " + length;
}

program.memoryCopy(dst.intValueSafe(), src.intValueSafe(), length.intValueSafe());
program.step();
}

protected void doCREATE(){
if (program.isStaticCall() && program.getActivations().isActive(RSKIP91)) {
throw Program.ExceptionHelper.modificationException(program);
Expand Down Expand Up @@ -2064,6 +2102,12 @@ protected void executeOpcode() {
break;
case OpCodes.OP_JUMPDEST: doJUMPDEST();
break;
case OpCodes.OP_MCOPY:
if (!activations.isActive(RSKIP445)) {
throw Program.ExceptionHelper.invalidOpCode(program);
}
doMCOPY();
break;
case OpCodes.OP_CREATE: doCREATE();
break;
case OpCodes.OP_CREATE2:
Expand Down
4 changes: 4 additions & 0 deletions rskj-core/src/main/java/org/ethereum/vm/program/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,10 @@ public byte[] memoryChunk(int offset, int size) {
return memory.read(offset, size);
}

public void memoryCopy(int dst, int src, int length) {
memorySave(dst, memoryChunk(src, length));
}

/**
* Allocates extra memory in the program for
* a specified size, calculated from a given offset
Expand Down
165 changes: 83 additions & 82 deletions rskj-core/src/main/resources/expected.conf
Original file line number Diff line number Diff line change
Expand Up @@ -20,88 +20,89 @@ blockchain = {
lovell700 = <height>
}
consensusRules = {
areBridgeTxsPaid = <hardforkName>
rskip85 = <hardforkName>
rskip87 = <hardforkName>
rskip88 = <hardforkName>
rskip89 = <hardforkName>
rskip90 = <hardforkName>
rskip91 = <hardforkName>
rskip92 = <hardforkName>
rskip97 = <hardforkName>
rskip98 = <hardforkName>
rskip103 = <hardforkName>
rskip106 = <hardforkName>
rskip110 = <hardforkName>
rskip119 = <hardforkName>
rskip120 = <hardforkName>
rskip122 = <hardforkName>
rskip123 = <hardforkName>
rskip124 = <hardforkName>
rskip125 = <hardforkName>
rskip126 = <hardforkName>
rskip132 = <hardforkName>
rskip134 = <hardforkName>
rskip136 = <hardforkName>
rskip137 = <hardforkName>
rskip140 = <hardforkName>
rskip143 = <hardforkName>
rskip146 = <hardforkName>
rskip150 = <hardforkName>
rskip151 = <hardforkName>
rskip152 = <hardforkName>
rskip156 = <hardforkName>
rskipUMM = <hardforkName>
rskip153 = <hardforkName>
rskip169 = <hardforkName>
rskip170 = <hardforkName>
rskip171 = <hardforkName>
rskip174 = <hardforkName>
rskip176 = <hardforkName>
rskip179 = <hardforkName>
rskip180 = <hardforkName>
rskip181 = <hardforkName>
rskip185 = <hardforkName>
rskip186 = <hardforkName>
rskip191 = <hardforkName>
rskip197 = <hardforkName>
rskip199 = <hardforkName>
rskip200 = <hardforkName>
rskip201 = <hardforkName>
rskip203 = <hardforkName>
rskip218 = <hardforkName>
rskip219 = <hardforkName>
rskip220 = <hardforkName>
rskip252 = <hardforkName>
rskip271 = <hardforkName>
rskip284 = <hardforkName>
rskip290 = <hardforkName>
rskip293 = <hardforkName>
rskip294 = <hardforkName>
rskip297 = <hardforkName>
rskip351 = <hardforkName>
rskip144 = <hardforkName>
rskip326 = <hardforkName>
rskip353 = <hardforkName>
rskip357 = <hardforkName>
rskip374 = <hardforkName>
rskip375 = <hardforkName>
rskip376 = <hardforkName>
rskip377 = <hardforkName>
rskip379 = <hardforkName>
rskip383 = <hardforkName>
rskip385 = <hardforkName>
rskip398 = <hardforkName>
rskip400 = <hardforkName>
rskip412 = <hardforkName>
rskip415 = <hardforkName>
rskip417 = <hardforkName>
rskip427 = <hardforkName>
rskip428 = <hardforkName>
rskip434 = <hardforkName>
rskip438 = <hardforkName>
rskip446 = <hardforkName>
rskip454 = <hardforkName>
areBridgeTxsPaid = <hardforkName>
rskip85 = <hardforkName>
rskip87 = <hardforkName>
rskip88 = <hardforkName>
rskip89 = <hardforkName>
rskip90 = <hardforkName>
rskip91 = <hardforkName>
rskip92 = <hardforkName>
rskip97 = <hardforkName>
rskip98 = <hardforkName>
rskip103 = <hardforkName>
rskip106 = <hardforkName>
rskip110 = <hardforkName>
rskip119 = <hardforkName>
rskip120 = <hardforkName>
rskip122 = <hardforkName>
rskip123 = <hardforkName>
rskip124 = <hardforkName>
rskip125 = <hardforkName>
rskip126 = <hardforkName>
rskip132 = <hardforkName>
rskip134 = <hardforkName>
rskip136 = <hardforkName>
rskip137 = <hardforkName>
rskip140 = <hardforkName>
rskip143 = <hardforkName>
rskip146 = <hardforkName>
rskip150 = <hardforkName>
rskip151 = <hardforkName>
rskip152 = <hardforkName>
rskip156 = <hardforkName>
rskipUMM = <hardforkName>
rskip153 = <hardforkName>
rskip169 = <hardforkName>
rskip170 = <hardforkName>
rskip171 = <hardforkName>
rskip174 = <hardforkName>
rskip176 = <hardforkName>
rskip179 = <hardforkName>
rskip180 = <hardforkName>
rskip181 = <hardforkName>
rskip185 = <hardforkName>
rskip186 = <hardforkName>
rskip191 = <hardforkName>
rskip197 = <hardforkName>
rskip199 = <hardforkName>
rskip200 = <hardforkName>
rskip201 = <hardforkName>
rskip203 = <hardforkName>
rskip218 = <hardforkName>
rskip219 = <hardforkName>
rskip220 = <hardforkName>
rskip252 = <hardforkName>
rskip271 = <hardforkName>
rskip284 = <hardforkName>
rskip290 = <hardforkName>
rskip293 = <hardforkName>
rskip294 = <hardforkName>
rskip297 = <hardforkName>
rskip351 = <hardforkName>
rskip144 = <hardforkName>
rskip326 = <hardforkName>
rskip353 = <hardforkName>
rskip357 = <hardforkName>
rskip374 = <hardforkName>
rskip375 = <hardforkName>
rskip376 = <hardforkName>
rskip377 = <hardforkName>
rskip379 = <hardforkName>
rskip383 = <hardforkName>
rskip385 = <hardforkName>
rskip398 = <hardforkName>
rskip400 = <hardforkName>
rskip412 = <hardforkName>
rskip415 = <hardforkName>
rskip417 = <hardforkName>
rskip427 = <hardforkName>
rskip428 = <hardforkName>
rskip434 = <hardforkName>
rskip438 = <hardforkName>
rskip445 = <hardforkName>
rskip446 = <hardforkName>
rskip454 = <hardforkName>
}
}
gc = {
Expand Down
1 change: 1 addition & 0 deletions rskj-core/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ blockchain = {
rskip428 = lovell700
rskip434 = arrowhead631
rskip438 = lovell700
rskip445 = lovell700
rskip446 = lovell700
rskip454 = lovell700
}
Expand Down
46 changes: 46 additions & 0 deletions rskj-core/src/test/java/co/rsk/vm/VMExecutionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,10 @@ private Program executeCodeWithActivationConfig(String code, int nsteps, Activat
return executeCodeWithActivationConfig(compiler.compile(code), nsteps, activations);
}

private Program executeCodeWithActivationConfig(String code, DataWord[] stack, int nsteps, ActivationConfig.ForBlock activations) {
return executeCodeWithActivationConfig(compiler.compile(code), stack, nsteps, activations);
}

private Program executeCodeWithActivationConfig(byte[] code, int nsteps, ActivationConfig.ForBlock activations) {
VM vm = new VM(vmConfig, precompiledContracts);
Program program = new Program(vmConfig, precompiledContracts, blockFactory, activations, code, invoke,null, new HashSet<>(), new BlockTxSignatureCache(new ReceivedTxSignatureCache()));
Expand All @@ -881,6 +885,21 @@ private Program executeCodeWithActivationConfig(byte[] code, int nsteps, Activat
return program;
}

private Program executeCodeWithActivationConfig(byte[] code, DataWord[] stack, int nsteps, ActivationConfig.ForBlock activations) {
VM vm = new VM(vmConfig, precompiledContracts);
Program program = new Program(vmConfig, precompiledContracts, blockFactory, activations, code, invoke,null, new HashSet<>(), new BlockTxSignatureCache(new ReceivedTxSignatureCache()));

for (DataWord element : stack) {
program.stackPush(element);
}

for (int k = 0; k < nsteps; k++) {
vm.step(program);
}

return program;
}

private Program playCodeWithActivationConfig(String code, ActivationConfig.ForBlock activations) {
return playCodeWithActivationConfig(compiler.compile(code), activations);
}
Expand Down Expand Up @@ -947,4 +966,31 @@ private void executeBASEFEE(ActivationConfig.ForBlock activations) {
// See ProgramInvokeMockImpl.getMinimumGasPrice()
Assertions.assertEquals(DataWord.valueFromHex("000000000000000000000000000000000000000000000000000003104e60a000"), stack.peek());
}

@Test
void testMCOPY_WhenActive_ExecutesAsExpected() {
ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class);
when(activations.isActive(RSKIP445)).thenReturn(true);

executeMCOPY(activations);
}

@Test
void testMCOPY_WhenInactive_ExecutesAsExpected() {
ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class);
when(activations.isActive(RSKIP445)).thenReturn(false);

Assertions.assertThrows(Program.IllegalOperationException.class, () -> {
executeMCOPY(activations);
});
}

private void executeMCOPY(ActivationConfig.ForBlock activations) {
DataWord[] stackValues = {DataWord.ZERO, DataWord.ZERO, DataWord.ZERO};
Program program = executeCodeWithActivationConfig("MCOPY", stackValues, 1, activations);
Stack stack = program.getStack();

Assertions.assertEquals(0, stack.size());
}

}
Loading

0 comments on commit d0ccf35

Please sign in to comment.