Skip to content

Commit d941d33

Browse files
initial version of eip-5656
1 parent c1bb07e commit d941d33

File tree

9 files changed

+78
-1
lines changed

9 files changed

+78
-1
lines changed

core/vm/eips.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
)
2727

2828
var activators = map[int]func(*JumpTable){
29+
5656: enable5656,
2930
3855: enable3855,
3031
3529: enable3529,
3132
3198: enable3198,
@@ -233,3 +234,15 @@ func opPush0(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
233234
scope.Stack.push(new(uint256.Int))
234235
return nil, nil
235236
}
237+
238+
// enable5656 applies EIP-5656 (MCOPY opcode)
239+
func enable5656(jt *JumpTable) {
240+
jt[MCOPY] = &operation{
241+
execute: opMcopy,
242+
constantGas: 0,
243+
dynamicGas: gasMcopy,
244+
minStack: minStack(3, 0),
245+
maxStack: maxStack(3, 0),
246+
memorySize: memoryMcopy,
247+
}
248+
}

core/vm/gas_table.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func memoryCopierGas(stackpos int) gasFunc {
8989
var (
9090
gasCallDataCopy = memoryCopierGas(2)
9191
gasCodeCopy = memoryCopierGas(2)
92+
gasMcopy = memoryCopierGas(2)
9293
gasExtCodeCopy = memoryCopierGas(3)
9394
gasReturnDataCopy = memoryCopierGas(2)
9495
)

core/vm/instructions.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,18 @@ func opMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
525525
return nil, nil
526526
}
527527

528+
func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
529+
var (
530+
dst = scope.Stack.pop()
531+
src = scope.Stack.pop()
532+
length = scope.Stack.pop()
533+
)
534+
// These values are checked for overflow during memory expansion calculation
535+
// (the memorySize function on the opcode).
536+
scope.Memory.Copy(dst.Uint64(), src.Uint64(), length.Uint64())
537+
return nil, nil
538+
}
539+
528540
func opSload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
529541
loc := scope.Stack.peek()
530542
hash := common.Hash(loc.Bytes32())

core/vm/interpreter.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
7878
// If jump table was not initialised we set the default one.
7979
if cfg.JumpTable == nil {
8080
switch {
81+
case evm.chainRules.IsEIP5656Mcopy:
82+
cfg.JumpTable = &eip5656InstructionSet
8183
case evm.chainRules.Is1153TransientStorage:
8284
cfg.JumpTable = &eip1153InstructionSet
8385
case evm.chainRules.IsIstanbul:

core/vm/jump_table.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ var (
5353
constantinopleInstructionSet = newConstantinopleInstructionSet()
5454
istanbulInstructionSet = newIstanbulInstructionSet()
5555
eip1153InstructionSet = eip1153TransientStorage()
56+
eip5656InstructionSet = eip5656Mcopy()
5657
//berlinInstructionSet = newBerlinInstructionSet()
5758
//londonInstructionSet = newLondonInstructionSet()
5859
//mergeInstructionSet = newMergeInstructionSet()
@@ -110,6 +111,13 @@ func newBerlinInstructionSet() JumpTable {
110111
return validate(instructionSet)
111112
}*/
112113

114+
// EIP 5656 MCOPY
115+
func eip5656Mcopy() JumpTable {
116+
instructionSet := eip1153TransientStorage()
117+
enable5656(&instructionSet) // MCOPY - https://eips.ethereum.org/EIPS/eip-5656
118+
return validate(instructionSet)
119+
}
120+
113121
// EIP 1153 Transient Storage
114122
func eip1153TransientStorage() JumpTable {
115123
instructionSet := newIstanbulInstructionSet()

core/vm/memory.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,17 @@ func (m *Memory) Data() []byte {
107107
return m.store
108108
}
109109

110+
// Copy copies data from the src position slice into the dst position.
111+
// The source and destination may overlap.
112+
// OBS: This operation assumes that any necessary memory expansion has already been performed,
113+
// and this method may panic otherwise.
114+
func (m *Memory) Copy(dst, src, len uint64) {
115+
if len == 0 {
116+
return
117+
}
118+
copy(m.store[dst:], m.store[src:src+len])
119+
}
120+
110121
// Print dumps the content of the memory.
111122
func (m *Memory) Print() {
112123
fmt.Printf("### mem %d bytes ###\n", len(m.store))

core/vm/memory_table.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ func memoryMStore(stack *Stack) (uint64, bool) {
4848
return calcMemSize64WithUint(stack.Back(0), 32)
4949
}
5050

51+
func memoryMcopy(stack *Stack) (uint64, bool) {
52+
mStart := stack.Back(0) // stack[0]: dest
53+
if stack.Back(1).Gt(mStart) {
54+
mStart = stack.Back(1) // stack[1]: source
55+
}
56+
return calcMemSize64(mStart, stack.Back(2))
57+
}
58+
5159
func memoryCreate(stack *Stack) (uint64, bool) {
5260
return calcMemSize64(stack.Back(1), stack.Back(2))
5361
}

core/vm/opcodes.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ const (
121121
JUMPDEST OpCode = 0x5b
122122
TLOAD OpCode = 0x5c
123123
TSTORE OpCode = 0x5d
124+
MCOPY OpCode = 0x5e
124125
PUSH0 OpCode = 0x5f
125126
)
126127

@@ -305,6 +306,7 @@ var opCodeToString = map[OpCode]string{
305306
JUMPDEST: "JUMPDEST",
306307
TLOAD: "TLOAD",
307308
TSTORE: "TSTORE",
309+
MCOPY: "MCOPY",
308310
PUSH0: "PUSH0",
309311

310312
// 0x60 range - push.
@@ -472,6 +474,7 @@ var stringToOp = map[string]OpCode{
472474
"PUSH0": PUSH0,
473475
"TLOAD": TLOAD,
474476
"TSTORE": TSTORE,
477+
"MCOPY": MCOPY,
475478
"PUSH1": PUSH1,
476479
"PUSH2": PUSH2,
477480
"PUSH3": PUSH3,

internal/params/config.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ var (
8383
HIP32Epoch: big.NewInt(2152), // 2024-10-31 13:02 UTC
8484
IsOneSecondEpoch: EpochTBD,
8585
EIP2537PrecompileEpoch: EpochTBD,
86+
EIP5656McopyEpoch: EpochTBD,
8687
}
8788

8889
// TestnetChainConfig contains the chain parameters to run a node on the harmony test network.
@@ -134,6 +135,7 @@ var (
134135
IsOneSecondEpoch: EpochTBD,
135136
EIP2537PrecompileEpoch: EpochTBD,
136137
EIP1153TransientStorageEpoch: big.NewInt(6280),
138+
EIP5656McopyEpoch: EpochTBD,
137139
}
138140
// PangaeaChainConfig contains the chain parameters for the Pangaea network.
139141
// All features except for CrossLink are enabled at launch.
@@ -184,6 +186,7 @@ var (
184186
TestnetExternalEpoch: EpochTBD,
185187
IsOneSecondEpoch: EpochTBD,
186188
EIP2537PrecompileEpoch: EpochTBD,
189+
EIP5656McopyEpoch: EpochTBD,
187190
}
188191

189192
// PartnerChainConfig contains the chain parameters for the Partner network.
@@ -236,6 +239,7 @@ var (
236239
IsOneSecondEpoch: big.NewInt(17436),
237240
EIP2537PrecompileEpoch: EpochTBD,
238241
EIP1153TransientStorageEpoch: big.NewInt(35626),
242+
EIP5656McopyEpoch: EpochTBD,
239243
}
240244

241245
// StressnetChainConfig contains the chain parameters for the Stress test network.
@@ -287,6 +291,7 @@ var (
287291
TestnetExternalEpoch: EpochTBD,
288292
IsOneSecondEpoch: EpochTBD,
289293
EIP2537PrecompileEpoch: EpochTBD,
294+
EIP5656McopyEpoch: EpochTBD,
290295
}
291296

292297
// LocalnetChainConfig contains the chain parameters to run for local development.
@@ -337,6 +342,7 @@ var (
337342
TestnetExternalEpoch: EpochTBD,
338343
IsOneSecondEpoch: big.NewInt(4),
339344
EIP2537PrecompileEpoch: EpochTBD,
345+
EIP5656McopyEpoch: EpochTBD,
340346
}
341347

342348
// AllProtocolChanges ...
@@ -391,6 +397,7 @@ var (
391397
big.NewInt(0),
392398
big.NewInt(0), // EIP2537PrecompileEpoch
393399
big.NewInt(0), // 1153 transient storage
400+
big.NewInt(0), // EIP5656McopyEpoch
394401
}
395402

396403
// TestChainConfig ...
@@ -445,6 +452,7 @@ var (
445452
big.NewInt(0),
446453
big.NewInt(0), // EIP2537PrecompileEpoch
447454
big.NewInt(0), // 1153 transient storage
455+
big.NewInt(0), // EIP5656McopyEpoch
448456
}
449457

450458
// TestRules ...
@@ -634,11 +642,14 @@ type ChainConfig struct {
634642

635643
// EIP2537PrecompileEpoch is the first epoch to support the EIP-2537 precompiles
636644
EIP1153TransientStorageEpoch *big.Int `json:"eip1153-transient-storage-epoch,omitempty"`
645+
646+
// EIP5656McopyEpoch is the first epoch to support the EIP-5656 MCOPY opcode
647+
EIP5656McopyEpoch *big.Int `json:"eip5656-mcopy-epoch,omitempty"`
637648
}
638649

639650
// String implements the fmt.Stringer interface.
640651
func (c *ChainConfig) String() string {
641-
return fmt.Sprintf("{ChainID: %v EthCompatibleChainID: %v EIP155: %v CrossTx: %v Staking: %v CrossLink: %v ReceiptLog: %v SHA3Epoch: %v StakingPrecompileEpoch: %v ChainIdFixEpoch: %v CrossShardXferPrecompileEpoch: %v EIP2537PrecompileEpoch: %v EIP1153TransientStorageEpoch: %v}",
652+
return fmt.Sprintf("{ChainID: %v EthCompatibleChainID: %v EIP155: %v CrossTx: %v Staking: %v CrossLink: %v ReceiptLog: %v SHA3Epoch: %v StakingPrecompileEpoch: %v ChainIdFixEpoch: %v CrossShardXferPrecompileEpoch: %v EIP2537PrecompileEpoch: %v EIP1153TransientStorageEpoch: %v EIP5656McopyEpoch: %v}",
642653
c.ChainID,
643654
c.EthCompatibleChainID,
644655
c.EIP155Epoch,
@@ -652,6 +663,7 @@ func (c *ChainConfig) String() string {
652663
c.CrossShardXferPrecompileEpoch,
653664
c.EIP2537PrecompileEpoch,
654665
c.EIP1153TransientStorageEpoch,
666+
c.EIP5656McopyEpoch,
655667
)
656668
}
657669

@@ -878,6 +890,11 @@ func (c *ChainConfig) IsEIP1153TransientStorage(epoch *big.Int) bool {
878890
return isForked(c.EIP1153TransientStorageEpoch, epoch)
879891
}
880892

893+
// IsEIP5656Mcopy determines whether EIP-5656 MCOPY opcode is available in the EVM
894+
func (c *ChainConfig) IsEIP5656Mcopy(epoch *big.Int) bool {
895+
return isForked(c.EIP5656McopyEpoch, epoch)
896+
}
897+
881898
// IsChainIdFix returns whether epoch is either equal to the ChainId Fix fork epoch or greater.
882899
func (c *ChainConfig) IsChainIdFix(epoch *big.Int) bool {
883900
return isForked(c.ChainIdFixEpoch, epoch)
@@ -1009,6 +1026,7 @@ type Rules struct {
10091026
IsValidatorCodeFix bool
10101027
IsYoloV2 bool
10111028
Is1153TransientStorage bool
1029+
IsEIP5656Mcopy bool
10121030
}
10131031

10141032
// Rules ensures c's ChainID is not nil.
@@ -1041,5 +1059,6 @@ func (c *ChainConfig) Rules(epoch *big.Int) Rules {
10411059
IsValidatorCodeFix: c.IsValidatorCodeFix(epoch),
10421060
IsEIP2537Precompile: c.IsEIP2537Precompile(epoch),
10431061
Is1153TransientStorage: c.IsEIP1153TransientStorage(epoch),
1062+
IsEIP5656Mcopy: c.IsEIP5656Mcopy(epoch),
10441063
}
10451064
}

0 commit comments

Comments
 (0)