Skip to content

Commit 9bfd4b8

Browse files
core/vm: enable EIP-3855 (PUSH0)
1 parent 394d36f commit 9bfd4b8

File tree

6 files changed

+57
-2
lines changed

6 files changed

+57
-2
lines changed

core/vm/analysis.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ func codeBitmap(code []byte) bitvec {
4343
for pc := uint64(0); pc < uint64(len(code)); {
4444
op := OpCode(code[pc])
4545

46-
if op >= PUSH1 && op <= PUSH32 {
46+
if op == PUSH0 {
47+
// PUSH0 doesn't read any bytes, just increment pc
48+
pc++
49+
} else if op >= PUSH1 && op <= PUSH32 {
4750
numbits := op - PUSH1 + 1
4851
pc++
4952
for ; numbits >= 8; numbits -= 8 {

core/vm/eips.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ func EnableEIP(eipNum int, jt *JumpTable) error {
3737
enable1344(jt)
3838
case 1153:
3939
enable1153(jt)
40+
case 3855:
41+
enable3855(jt)
4042
default:
4143
return fmt.Errorf("undefined eip %d", eipNum)
4244
}
@@ -151,3 +153,15 @@ func opTstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
151153
interpreter.evm.StateDB.SetTransientState(contract.Address(), key, val)
152154
return nil, nil
153155
}
156+
157+
// enable3855 applies EIP-3855 (PUSH0 opcode)
158+
// - Adds PUSH0 opcode that pushes the value 0 onto the stack
159+
func enable3855(jt *JumpTable) {
160+
jt[PUSH0] = operation{
161+
execute: opPush0,
162+
constantGas: GasQuickStep,
163+
minStack: minStack(0, 1),
164+
maxStack: maxStack(0, 1),
165+
valid: true,
166+
}
167+
}

core/vm/instructions.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,13 @@ func makeLog(size int) executionFunc {
955955
}
956956
}
957957

958+
// opPush0 pushes the value 0 onto the stack
959+
func opPush0(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
960+
stack.push(interpreter.intPool.getZero())
961+
*pc++
962+
return nil, nil
963+
}
964+
958965
// opPush1 is a specialized version of pushN
959966
func opPush1(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
960967
var (

core/vm/interpreter.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
111111
default:
112112
jt = frontierInstructionSet
113113
}
114+
// Enable epoch-based EIPs
115+
epochBasedEIPs := []int{}
116+
if evm.ChainConfig().IsEIP3855(evm.EpochNumber) {
117+
epochBasedEIPs = append(epochBasedEIPs, 3855)
118+
}
119+
// Enable all epoch-based EIPs
120+
for _, eip := range epochBasedEIPs {
121+
if err := EnableEIP(eip, &jt); err != nil {
122+
utils.Logger().Error().Int("eip", eip).Err(err).Msg("Epoch-based EIP activation failed")
123+
}
124+
}
125+
// Enable manually specified extra EIPs
114126
for i, eip := range cfg.ExtraEips {
115127
if err := EnableEIP(eip, &jt); err != nil {
116128
// Disable it, so caller can check if it's activated or not

core/vm/opcodes.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type OpCode byte
2626
// IsPush specifies if an opcode is a PUSH opcode.
2727
func (op OpCode) IsPush() bool {
2828
switch op {
29-
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
29+
case PUSH0, PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
3030
return true
3131
}
3232
return false
@@ -121,6 +121,7 @@ const (
121121
JUMPDEST
122122
TLOAD // 0x5c
123123
TSTORE // 0x5d
124+
PUSH0 = 0x5f
124125
)
125126

126127
// 0x60 range.
@@ -301,6 +302,7 @@ var opCodeToString = map[OpCode]string{
301302
JUMPDEST: "JUMPDEST",
302303
TLOAD: "TLOAD",
303304
TSTORE: "TSTORE",
305+
PUSH0: "PUSH0",
304306

305307
// 0x60 range - push.
306308
PUSH1: "PUSH1",
@@ -468,6 +470,7 @@ var stringToOp = map[string]OpCode{
468470
"JUMPDEST": JUMPDEST,
469471
"TLOAD": TLOAD,
470472
"TSTORE": TSTORE,
473+
"PUSH0": PUSH0,
471474
"PUSH1": PUSH1,
472475
"PUSH2": PUSH2,
473476
"PUSH3": PUSH3,

internal/params/config.go

Lines changed: 16 additions & 0 deletions
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+
EIP3855Epoch: EpochTBD,
8687
}
8788

8889
// TestnetChainConfig contains the chain parameters to run a node on the harmony test network.
@@ -133,6 +134,7 @@ var (
133134
TestnetExternalEpoch: big.NewInt(3044),
134135
IsOneSecondEpoch: EpochTBD,
135136
EIP2537PrecompileEpoch: EpochTBD,
137+
EIP3855Epoch: EpochTBD,
136138
}
137139
// PangaeaChainConfig contains the chain parameters for the Pangaea network.
138140
// All features except for CrossLink are enabled at launch.
@@ -183,6 +185,7 @@ var (
183185
TestnetExternalEpoch: EpochTBD,
184186
IsOneSecondEpoch: EpochTBD,
185187
EIP2537PrecompileEpoch: EpochTBD,
188+
EIP3855Epoch: EpochTBD,
186189
}
187190

188191
// PartnerChainConfig contains the chain parameters for the Partner network.
@@ -285,6 +288,7 @@ var (
285288
TestnetExternalEpoch: EpochTBD,
286289
IsOneSecondEpoch: EpochTBD,
287290
EIP2537PrecompileEpoch: EpochTBD,
291+
EIP3855Epoch: EpochTBD,
288292
}
289293

290294
// LocalnetChainConfig contains the chain parameters to run for local development.
@@ -335,6 +339,7 @@ var (
335339
TestnetExternalEpoch: EpochTBD,
336340
IsOneSecondEpoch: big.NewInt(4),
337341
EIP2537PrecompileEpoch: EpochTBD,
342+
EIP3855Epoch: EpochTBD,
338343
}
339344

340345
// AllProtocolChanges ...
@@ -388,6 +393,7 @@ var (
388393
big.NewInt(0),
389394
big.NewInt(0),
390395
big.NewInt(0), // EIP2537PrecompileEpoch
396+
big.NewInt(0), // EIP3855Epoch
391397
}
392398

393399
// TestChainConfig ...
@@ -441,6 +447,7 @@ var (
441447
big.NewInt(0),
442448
big.NewInt(0),
443449
big.NewInt(0), // EIP2537PrecompileEpoch
450+
big.NewInt(0), // EIP3855Epoch
444451
}
445452

446453
// TestRules ...
@@ -571,6 +578,9 @@ type ChainConfig struct {
571578
// EIP2537PrecompileEpoch is the first epoch to support the EIP-2537 precompiles
572579
EIP2537PrecompileEpoch *big.Int `json:"eip2537-precompile-epoch,omitempty"`
573580

581+
// EIP3855Epoch is the first epoch to support EIP-3855 (PUSH0 opcode)
582+
EIP3855Epoch *big.Int `json:"eip3855-epoch,omitempty"`
583+
574584
// ChainIdFixEpoch is the first epoch to return ethereum compatible chain id by ChainID() op code
575585
ChainIdFixEpoch *big.Int `json:"chain-id-fix-epoch,omitempty"`
576586

@@ -865,6 +875,12 @@ func (c *ChainConfig) IsEIP2537Precompile(epoch *big.Int) bool {
865875
return isForked(c.EIP2537PrecompileEpoch, epoch)
866876
}
867877

878+
// IsEIP3855 determines whether EIP-3855 (PUSH0 opcode)
879+
// is available in the EVM
880+
func (c *ChainConfig) IsEIP3855(epoch *big.Int) bool {
881+
return isForked(c.EIP3855Epoch, epoch)
882+
}
883+
868884
// IsChainIdFix returns whether epoch is either equal to the ChainId Fix fork epoch or greater.
869885
func (c *ChainConfig) IsChainIdFix(epoch *big.Int) bool {
870886
return isForked(c.ChainIdFixEpoch, epoch)

0 commit comments

Comments
 (0)