Skip to content

Commit e2a8ee6

Browse files
authored
core, internal, params: lisovoPro HF and version bump (#2055)
* core, internal, params: lisovoPro HF and version bump * core: add lisovoPro instructionset * core: lisovo-lisovoPro instructionset test
1 parent a2a67b7 commit e2a8ee6

File tree

10 files changed

+154
-7
lines changed

10 files changed

+154
-7
lines changed

builder/files/genesis-amoy.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"madhugiriProBlock": 29287400,
2828
"dandeliBlock": 31890000,
2929
"lisovoBlock": 33634700,
30+
"lisovoProBlock": 34062000,
3031
"skipValidatorByteCheck": [26160367, 26161087, 26171567, 26173743, 26175647],
3132
"stateSyncConfirmationDelay": {
3233
"0": 128

core/vm/contracts.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ var PrecompiledContractsPrague = PrecompiledContracts{
134134
common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{},
135135
common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{},
136136
common.BytesToAddress([]byte{0x09}): &blake2F{},
137-
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
138137
common.BytesToAddress([]byte{0x0b}): &bls12381G1Add{},
139138
common.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{},
140139
common.BytesToAddress([]byte{0x0d}): &bls12381G2Add{},
@@ -191,7 +190,6 @@ var PrecompiledContractsMadhugiri = PrecompiledContracts{
191190
common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{},
192191
common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{},
193192
common.BytesToAddress([]byte{0x09}): &blake2F{},
194-
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
195193
common.BytesToAddress([]byte{0x0b}): &bls12381G1Add{},
196194
common.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{},
197195
common.BytesToAddress([]byte{0x0d}): &bls12381G2Add{},
@@ -213,7 +211,6 @@ var PrecompiledContractsMadhugiriPro = PrecompiledContracts{
213211
common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{},
214212
common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{},
215213
common.BytesToAddress([]byte{0x09}): &blake2F{},
216-
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
217214
common.BytesToAddress([]byte{0x0b}): &bls12381G1Add{},
218215
common.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{},
219216
common.BytesToAddress([]byte{0x0d}): &bls12381G2Add{},
@@ -247,7 +244,30 @@ var PrecompiledContractsLisovo = PrecompiledContracts{
247244
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{eip7951: true},
248245
}
249246

247+
// PrecompiledContractsLisovoPro contains the set of pre-compiled Ethereum
248+
// contracts used in the LisovoPro release (bor HF).
249+
var PrecompiledContractsLisovoPro = PrecompiledContracts{
250+
common.BytesToAddress([]byte{0x01}): &ecrecover{},
251+
common.BytesToAddress([]byte{0x02}): &sha256hash{},
252+
common.BytesToAddress([]byte{0x03}): &ripemd160hash{},
253+
common.BytesToAddress([]byte{0x04}): &dataCopy{},
254+
common.BytesToAddress([]byte{0x05}): &bigModExp{eip2565: true, eip7823: true, eip7883: true},
255+
common.BytesToAddress([]byte{0x06}): &bn256AddIstanbul{},
256+
common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{},
257+
common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{},
258+
common.BytesToAddress([]byte{0x09}): &blake2F{},
259+
common.BytesToAddress([]byte{0x0b}): &bls12381G1Add{},
260+
common.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{},
261+
common.BytesToAddress([]byte{0x0d}): &bls12381G2Add{},
262+
common.BytesToAddress([]byte{0x0e}): &bls12381G2MultiExp{},
263+
common.BytesToAddress([]byte{0x0f}): &bls12381Pairing{},
264+
common.BytesToAddress([]byte{0x10}): &bls12381MapG1{},
265+
common.BytesToAddress([]byte{0x11}): &bls12381MapG2{},
266+
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{eip7951: true},
267+
}
268+
250269
var (
270+
PrecompiledAddressesLisovoPro []common.Address
251271
PrecompiledAddressesLisovo []common.Address
252272
PrecompiledAddressesMadhugiriPro []common.Address
253273
PrecompiledAddressesMadhugiri []common.Address
@@ -294,10 +314,15 @@ func init() {
294314
for k := range PrecompiledContractsLisovo {
295315
PrecompiledAddressesLisovo = append(PrecompiledAddressesLisovo, k)
296316
}
317+
for k := range PrecompiledContractsLisovoPro {
318+
PrecompiledAddressesLisovoPro = append(PrecompiledAddressesLisovoPro, k)
319+
}
297320
}
298321

299322
func activePrecompiledContracts(rules params.Rules) PrecompiledContracts {
300323
switch {
324+
case rules.IsLisovoPro:
325+
return PrecompiledContractsLisovoPro
301326
case rules.IsLisovo:
302327
return PrecompiledContractsLisovo
303328
case rules.IsMadhugiriPro:
@@ -331,6 +356,8 @@ func ActivePrecompiledContracts(rules params.Rules) PrecompiledContracts {
331356
// ActivePrecompiles returns the precompile addresses enabled with the current configuration.
332357
func ActivePrecompiles(rules params.Rules) []common.Address {
333358
switch {
359+
case rules.IsLisovoPro:
360+
return PrecompiledAddressesLisovoPro
334361
case rules.IsLisovo:
335362
return PrecompiledAddressesLisovo
336363
case rules.IsMadhugiriPro:

core/vm/contracts_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ func TestReinforceMultiClientPreCompilesTest(t *testing.T) {
535535
"IsMadhugiri",
536536
"IsMadhugiriPro",
537537
"IsLisovo",
538+
"IsLisovoPro",
538539
}
539540

540541
if len(actual) != len(expected) {
@@ -586,3 +587,39 @@ func TestLisovoCLZOpcode(t *testing.T) {
586587
t.Errorf("CLZ gas: got %d, want %d", postLisovo[CLZ].constantGas, GasFastStep)
587588
}
588589
}
590+
591+
// TestKZGPointEvaluationPrecompileRemoval verifies that the kzgPointEvaluation precompile
592+
// is present before LisovoPro and removed starting with LisovoPro.
593+
func TestKZGPointEvaluationPrecompileRemoval(t *testing.T) {
594+
t.Parallel()
595+
596+
kzgPointEvaluationAddr := common.BytesToAddress([]byte{0x0a})
597+
598+
// Test Lisovo: should have kzgPointEvaluation
599+
lisovoRules := params.Rules{
600+
IsLisovo: true,
601+
IsMadhugiriPro: true,
602+
IsMadhugiri: true,
603+
}
604+
lisovoPrecompiles := ActivePrecompiledContracts(lisovoRules)
605+
if _, exists := lisovoPrecompiles[kzgPointEvaluationAddr]; !exists {
606+
t.Error("kzgPointEvaluation (0x0a) should exist in Lisovo precompiles")
607+
}
608+
609+
// Verify it's the correct type
610+
if _, ok := lisovoPrecompiles[kzgPointEvaluationAddr].(*kzgPointEvaluation); !ok {
611+
t.Error("precompile at 0x0a should be kzgPointEvaluation type in Lisovo")
612+
}
613+
614+
// Test LisovoPro: should not have kzgPointEvaluation
615+
lisovoProRules := params.Rules{
616+
IsLisovoPro: true,
617+
IsLisovo: true,
618+
IsMadhugiriPro: true,
619+
IsMadhugiri: true,
620+
}
621+
lisovoProPrecompiles := ActivePrecompiledContracts(lisovoProRules)
622+
if _, exists := lisovoProPrecompiles[kzgPointEvaluationAddr]; exists {
623+
t.Error("kzgPointEvaluation (0x0a) should not exist in LisovoPro precompiles")
624+
}
625+
}

core/vm/evm.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
150150
evm.precompiles = activePrecompiledContracts(evm.chainRules)
151151

152152
switch {
153+
case evm.chainRules.IsLisovoPro:
154+
evm.table = &lisovoProInstructionSet
153155
case evm.chainRules.IsLisovo:
154156
evm.table = &lisovoInstructionSet
155157
case evm.chainRules.IsOsaka:

core/vm/jump_table.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ var (
6464
pragueInstructionSet = newPragueInstructionSet()
6565
osakaInstructionSet = newOsakaInstructionSet()
6666
lisovoInstructionSet = newLisovoInstructionSet()
67+
lisovoProInstructionSet = newLisovoProInstructionSet()
6768
)
6869

6970
// JumpTable contains the EVM opcodes supported at a given fork.
@@ -94,6 +95,12 @@ func newLisovoInstructionSet() JumpTable {
9495
return validate(instructionSet)
9596
}
9697

98+
func newLisovoProInstructionSet() JumpTable {
99+
instructionSet := newPragueInstructionSet()
100+
enable7939(&instructionSet) // EIP-7939 (CLZ opcode)
101+
return validate(instructionSet)
102+
}
103+
97104
func newOsakaInstructionSet() JumpTable {
98105
instructionSet := newPragueInstructionSet()
99106
enable7939(&instructionSet) // EIP-7939 (CLZ opcode)

core/vm/jump_table_export.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) {
2828
switch {
2929
// Note: geth only returns an error for the verkle-fork.
3030
// Return nil for other forks.
31+
case rules.IsLisovoPro:
32+
return newLisovoProInstructionSet(), nil
3133
case rules.IsLisovo:
3234
return newLisovoInstructionSet(), nil
3335
case rules.IsMadhugiriPro:

core/vm/jump_table_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package vm
1818

1919
import (
20+
"reflect"
2021
"testing"
2122

2223
"github.com/stretchr/testify/require"
@@ -35,3 +36,60 @@ func TestJumpTableCopy(t *testing.T) {
3536
require.Equal(t, uint64(100), deepCopy[SLOAD].constantGas)
3637
require.Equal(t, uint64(0), tbl[SLOAD].constantGas)
3738
}
39+
40+
// TestLisovoProMatchesLisovo verifies that lisovoPro instruction set is identical to lisovo
41+
func TestLisovoProMatchesLisovo(t *testing.T) {
42+
t.Parallel()
43+
44+
lisovo := newLisovoInstructionSet()
45+
lisovoPro := newLisovoProInstructionSet()
46+
47+
// Compare all 256 operations in the jump table
48+
for i := 0; i < 256; i++ {
49+
opLisovo := lisovo[i]
50+
opLisovoPro := lisovoPro[i]
51+
52+
// Both should be non-nil
53+
require.NotNil(t, opLisovo, "lisovo operation at index %d is nil", i)
54+
require.NotNil(t, opLisovoPro, "lisovoPro operation at index %d is nil", i)
55+
56+
// Compare all fields
57+
require.Equal(t, opLisovo.constantGas, opLisovoPro.constantGas,
58+
"constantGas mismatch at opcode %#x", i)
59+
require.Equal(t, opLisovo.minStack, opLisovoPro.minStack,
60+
"minStack mismatch at opcode %#x", i)
61+
require.Equal(t, opLisovo.maxStack, opLisovoPro.maxStack,
62+
"maxStack mismatch at opcode %#x", i)
63+
require.Equal(t, opLisovo.undefined, opLisovoPro.undefined,
64+
"undefined mismatch at opcode %#x", i)
65+
66+
// Compare function pointers using reflection
67+
require.Equal(t, reflect.ValueOf(opLisovo.execute).Pointer(),
68+
reflect.ValueOf(opLisovoPro.execute).Pointer(),
69+
"execute function mismatch at opcode %#x", i)
70+
71+
// Compare dynamicGas (can be nil)
72+
if opLisovo.dynamicGas == nil && opLisovoPro.dynamicGas == nil {
73+
// Both nil, ok
74+
} else if opLisovo.dynamicGas == nil || opLisovoPro.dynamicGas == nil {
75+
t.Errorf("dynamicGas nil mismatch at opcode %#x: lisovo=%v, lisovoPro=%v",
76+
i, opLisovo.dynamicGas == nil, opLisovoPro.dynamicGas == nil)
77+
} else {
78+
require.Equal(t, reflect.ValueOf(opLisovo.dynamicGas).Pointer(),
79+
reflect.ValueOf(opLisovoPro.dynamicGas).Pointer(),
80+
"dynamicGas function mismatch at opcode %#x", i)
81+
}
82+
83+
// Compare memorySize (can be nil)
84+
if opLisovo.memorySize == nil && opLisovoPro.memorySize == nil {
85+
// Both nil, ok
86+
} else if opLisovo.memorySize == nil || opLisovoPro.memorySize == nil {
87+
t.Errorf("memorySize nil mismatch at opcode %#x: lisovo=%v, lisovoPro=%v",
88+
i, opLisovo.memorySize == nil, opLisovoPro.memorySize == nil)
89+
} else {
90+
require.Equal(t, reflect.ValueOf(opLisovo.memorySize).Pointer(),
91+
reflect.ValueOf(opLisovoPro.memorySize).Pointer(),
92+
"memorySize function mismatch at opcode %#x", i)
93+
}
94+
}
95+
}

internal/cli/server/chains/amoy.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var amoyTestnet = &Chain{
4040
MadhugiriProBlock: big.NewInt(29287400),
4141
DandeliBlock: big.NewInt(31890000),
4242
LisovoBlock: big.NewInt(33634700),
43+
LisovoProBlock: big.NewInt(34062000),
4344
StateSyncConfirmationDelay: map[string]uint64{
4445
"0": 128,
4546
},

params/config.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ var (
344344
MadhugiriProBlock: big.NewInt(29287400),
345345
DandeliBlock: big.NewInt(31890000),
346346
LisovoBlock: big.NewInt(33634700),
347+
LisovoProBlock: big.NewInt(34062000),
347348
StateSyncConfirmationDelay: map[string]uint64{
348349
"0": 128,
349350
},
@@ -731,6 +732,7 @@ var (
731732
MadhugiriProBlock: big.NewInt(0),
732733
DandeliBlock: big.NewInt(0),
733734
LisovoBlock: big.NewInt(0),
735+
LisovoProBlock: big.NewInt(0),
734736
},
735737
}
736738

@@ -931,6 +933,7 @@ type BorConfig struct {
931933
MadhugiriProBlock *big.Int `json:"madhugiriProBlock"` // MadhugiriPro switch block (nil = no fork, 0 = already on madhugiriPro)
932934
DandeliBlock *big.Int `json:"dandeliBlock"` // Dandeli switch block (nil = no fork, 0 = already on dandeli)
933935
LisovoBlock *big.Int `json:"lisovoBlock"` // Lisovo switch block (nil = no fork, 0 = already on lisovo)
936+
LisovoProBlock *big.Int `json:"lisovoProBlock"` // LisovoPro switch block (nil = no fork, 0 = already on lisovoPro)
934937
}
935938

936939
// String implements the stringer interface, returning the consensus engine details.
@@ -998,6 +1001,10 @@ func (c *BorConfig) IsLisovo(number *big.Int) bool {
9981001
return isBlockForked(c.LisovoBlock, number)
9991002
}
10001003

1004+
func (c *BorConfig) IsLisovoPro(number *big.Int) bool {
1005+
return isBlockForked(c.LisovoProBlock, number)
1006+
}
1007+
10011008
// GetTargetGasPercentage returns the target gas percentage for gas limit calculation.
10021009
// After Lisovo hard fork, this value can be configured via CLI flags (stored in BorConfig at runtime).
10031010
// It validates the configured value and falls back to defaults if invalid or nil.
@@ -1134,6 +1141,9 @@ func (c *ChainConfig) Description() string {
11341141
if c.Bor.LisovoBlock != nil {
11351142
banner += fmt.Sprintf(" - Lisovo: #%-8v\n", c.Bor.LisovoBlock)
11361143
}
1144+
if c.Bor.LisovoProBlock != nil {
1145+
banner += fmt.Sprintf(" - Lisovo Pro: #%-8v\n", c.Bor.LisovoProBlock)
1146+
}
11371147
return banner
11381148
}
11391149

@@ -1771,6 +1781,7 @@ type Rules struct {
17711781
IsMadhugiri bool
17721782
IsMadhugiriPro bool
17731783
IsLisovo bool
1784+
IsLisovoPro bool
17741785
}
17751786

17761787
// Rules ensures c's ChainID is not nil.
@@ -1805,5 +1816,6 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, _ uint64) Rules {
18051816
IsMadhugiri: c.Bor != nil && c.Bor.IsMadhugiri(num),
18061817
IsMadhugiriPro: c.Bor != nil && c.Bor.IsMadhugiriPro(num),
18071818
IsLisovo: c.Bor != nil && c.Bor.IsLisovo(num),
1819+
IsLisovoPro: c.Bor != nil && c.Bor.IsLisovoPro(num),
18081820
}
18091821
}

params/version.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ import (
2323
)
2424

2525
const (
26-
VersionMajor = 2 // Major version component of the current release
27-
VersionMinor = 6 // Minor version component of the current release
28-
VersionPatch = 0 // Patch version component of the current release
29-
VersionMeta = "beta" // Version metadata to append to the version string
26+
VersionMajor = 2 // Major version component of the current release
27+
VersionMinor = 6 // Minor version component of the current release
28+
VersionPatch = 0 // Patch version component of the current release
29+
VersionMeta = "beta2" // Version metadata to append to the version string
3030
)
3131

3232
var (

0 commit comments

Comments
 (0)