Skip to content

Commit 6fda51a

Browse files
tac0turtletac0turtleManav-Aggarwal
authored
chore: cleanup chainid duplicate (#2510)
<!-- Please read and fill out this form before submitting your PR. Please make sure you have reviewed our contributors guide before submitting your first PR. NOTE: PR titles should follow semantic commits: https://www.conventionalcommits.org/en/v1.0.0/ --> ## Overview This pr removes chainid from the config making the chainid in the genesis file the single source of truth, since the genesis file is small and wont hold much data then it makes sense to require it when starting a node --------- Co-authored-by: tac0turtle <[email protected]> Co-authored-by: Manav Aggarwal <[email protected]>
1 parent 99dcd69 commit 6fda51a

28 files changed

+247
-108
lines changed

apps/evm/single/cmd/init.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,10 @@ func InitCmd() *cobra.Command {
5555
}
5656

5757
// get chain ID or use default
58-
chainID, _ := cmd.Flags().GetString(rollconf.FlagChainID)
59-
if chainID == "" {
60-
chainID = "evolve-test"
58+
chainID, err := cmd.Flags().GetString(rollgenesis.ChainIDFlag)
59+
if err != nil {
60+
return fmt.Errorf("error reading chain ID flag: %w", err)
6161
}
62-
6362
// Initialize genesis without app state
6463
err = rollgenesis.CreateGenesis(homePath, chainID, 1, proposerAddress)
6564
genesisPath := rollgenesis.GenesisPath(homePath)
@@ -85,6 +84,7 @@ func InitCmd() *cobra.Command {
8584

8685
// Add flags to the command
8786
rollconf.AddFlags(initCmd)
87+
initCmd.Flags().String(rollgenesis.ChainIDFlag, "rollkit-test", "chain ID")
8888

8989
return initCmd
9090
}

apps/evm/single/cmd/run.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/evstack/ev-node/core/execution"
1818
rollcmd "github.com/evstack/ev-node/pkg/cmd"
1919
"github.com/evstack/ev-node/pkg/config"
20+
genesispkg "github.com/evstack/ev-node/pkg/genesis"
2021
"github.com/evstack/ev-node/pkg/p2p"
2122
"github.com/evstack/ev-node/pkg/p2p/key"
2223
"github.com/evstack/ev-node/pkg/store"
@@ -49,7 +50,13 @@ var RunCmd = &cobra.Command{
4950
return err
5051
}
5152

52-
singleMetrics, err := single.DefaultMetricsProvider(nodeConfig.Instrumentation.IsPrometheusEnabled())(nodeConfig.ChainID)
53+
genesisPath := filepath.Join(filepath.Dir(nodeConfig.ConfigPath()), "genesis.json")
54+
genesis, err := genesispkg.LoadGenesis(genesisPath)
55+
if err != nil {
56+
return fmt.Errorf("failed to load genesis: %w", err)
57+
}
58+
59+
singleMetrics, err := single.DefaultMetricsProvider(nodeConfig.Instrumentation.IsPrometheusEnabled())(genesis.ChainID)
5360
if err != nil {
5461
return err
5562
}
@@ -59,7 +66,7 @@ var RunCmd = &cobra.Command{
5966
logger,
6067
datastore,
6168
&daJrpc.DA,
62-
[]byte(nodeConfig.ChainID),
69+
[]byte(genesis.ChainID),
6370
nodeConfig.Node.BlockTime.Duration,
6471
singleMetrics,
6572
nodeConfig.Node.Aggregator,
@@ -73,12 +80,12 @@ var RunCmd = &cobra.Command{
7380
return err
7481
}
7582

76-
p2pClient, err := p2p.NewClient(nodeConfig, nodeKey, datastore, logger, nil)
83+
p2pClient, err := p2p.NewClient(nodeConfig.P2P, nodeKey.PrivKey, datastore, genesis.ChainID, logger, nil)
7784
if err != nil {
7885
return err
7986
}
8087

81-
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, node.NodeOptions{})
88+
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, genesis, node.NodeOptions{})
8289
},
8390
}
8491

apps/grpc/single/cmd/init.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ This will create the necessary configuration structure in the specified root dir
5757
}
5858

5959
// get chain ID or use default
60-
chainID, _ := cmd.Flags().GetString(rollconf.FlagChainID)
61-
if chainID == "" {
62-
chainID = "grpc-test-chain"
60+
chainID, err := cmd.Flags().GetString(rollgenesis.ChainIDFlag)
61+
if err != nil {
62+
return err
6363
}
6464

6565
// Initialize genesis without app state
@@ -87,6 +87,7 @@ This will create the necessary configuration structure in the specified root dir
8787

8888
// Add configuration flags
8989
rollconf.AddFlags(initCmd)
90+
initCmd.Flags().String(rollgenesis.ChainIDFlag, "grpc-test-chain", "chain ID")
9091

9192
return initCmd
9293
}

apps/grpc/single/cmd/run.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/evstack/ev-node/node"
1313
rollcmd "github.com/evstack/ev-node/pkg/cmd"
1414
"github.com/evstack/ev-node/pkg/config"
15+
rollgenesis "github.com/evstack/ev-node/pkg/genesis"
1516
"github.com/evstack/ev-node/pkg/p2p"
1617
"github.com/evstack/ev-node/pkg/p2p/key"
1718
"github.com/evstack/ev-node/pkg/store"
@@ -56,8 +57,14 @@ The execution client must implement the Evolve execution gRPC interface.`,
5657
return err
5758
}
5859

60+
// Load genesis
61+
genesis, err := rollgenesis.LoadGenesis(rollgenesis.GenesisPath(nodeConfig.RootDir))
62+
if err != nil {
63+
return err
64+
}
65+
5966
// Create metrics provider
60-
singleMetrics, err := single.DefaultMetricsProvider(nodeConfig.Instrumentation.IsPrometheusEnabled())(nodeConfig.ChainID)
67+
singleMetrics, err := single.DefaultMetricsProvider(nodeConfig.Instrumentation.IsPrometheusEnabled())(genesis.ChainID)
6168
if err != nil {
6269
return err
6370
}
@@ -68,7 +75,7 @@ The execution client must implement the Evolve execution gRPC interface.`,
6875
logger,
6976
datastore,
7077
&daJrpc.DA,
71-
[]byte(nodeConfig.ChainID),
78+
[]byte(genesis.ChainID),
7279
nodeConfig.Node.BlockTime.Duration,
7380
singleMetrics,
7481
nodeConfig.Node.Aggregator,
@@ -84,13 +91,13 @@ The execution client must implement the Evolve execution gRPC interface.`,
8491
}
8592

8693
// Create P2P client
87-
p2pClient, err := p2p.NewClient(nodeConfig, nodeKey, datastore, logger, nil)
94+
p2pClient, err := p2p.NewClient(nodeConfig.P2P, nodeKey.PrivKey, datastore, genesis.ChainID, logger, nil)
8895
if err != nil {
8996
return err
9097
}
9198

9299
// Start the node
93-
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, node.NodeOptions{})
100+
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, genesis, node.NodeOptions{})
94101
},
95102
}
96103

apps/testapp/cmd/init.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ func InitCmd() *cobra.Command {
5555
}
5656

5757
// get chain ID or use default
58-
chainID, _ := cmd.Flags().GetString(rollconf.FlagChainID)
59-
if chainID == "" {
60-
chainID = "evolve-test"
58+
chainID, err := cmd.Flags().GetString(rollgenesis.ChainIDFlag)
59+
if err != nil {
60+
return fmt.Errorf("error reading chain ID flag: %w", err)
6161
}
6262

6363
// Initialize genesis without app state
@@ -85,6 +85,7 @@ func InitCmd() *cobra.Command {
8585

8686
// Add flags to the command
8787
rollconf.AddFlags(initCmd)
88+
initCmd.Flags().String(rollgenesis.ChainIDFlag, "rollkit-test", "chain ID")
8889

8990
return initCmd
9091
}

apps/testapp/cmd/run.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/evstack/ev-node/da/jsonrpc"
1212
"github.com/evstack/ev-node/node"
1313
rollcmd "github.com/evstack/ev-node/pkg/cmd"
14+
genesispkg "github.com/evstack/ev-node/pkg/genesis"
1415
"github.com/evstack/ev-node/pkg/p2p"
1516
"github.com/evstack/ev-node/pkg/p2p/key"
1617
"github.com/evstack/ev-node/pkg/store"
@@ -75,12 +76,18 @@ var RunCmd = &cobra.Command{
7576
}
7677
}
7778

79+
genesisPath := filepath.Join(filepath.Dir(nodeConfig.ConfigPath()), "genesis.json")
80+
genesis, err := genesispkg.LoadGenesis(genesisPath)
81+
if err != nil {
82+
return fmt.Errorf("failed to load genesis: %w", err)
83+
}
84+
7885
sequencer, err := single.NewSequencer(
7986
ctx,
8087
logger,
8188
datastore,
8289
&daJrpc.DA,
83-
[]byte(nodeConfig.ChainID),
90+
[]byte(genesis.ChainID),
8491
nodeConfig.Node.BlockTime.Duration,
8592
singleMetrics,
8693
nodeConfig.Node.Aggregator,
@@ -89,11 +96,11 @@ var RunCmd = &cobra.Command{
8996
return err
9097
}
9198

92-
p2pClient, err := p2p.NewClient(nodeConfig, nodeKey, datastore, logger, p2p.NopMetrics())
99+
p2pClient, err := p2p.NewClient(nodeConfig.P2P, nodeKey.PrivKey, datastore, genesis.ChainID, logger, p2p.NopMetrics())
93100
if err != nil {
94101
return err
95102
}
96103

97-
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, node.NodeOptions{})
104+
return rollcmd.StartNode(logger, cmd, executor, sequencer, &daJrpc.DA, p2pClient, datastore, nodeConfig, genesis, node.NodeOptions{})
98105
},
99106
}

apps/testapp/kv/kvexecutor.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,16 @@ import (
1616
var (
1717
genesisInitializedKey = ds.NewKey("/genesis/initialized")
1818
genesisStateRootKey = ds.NewKey("/genesis/stateroot")
19+
finalizedHeightKey = ds.NewKey("/finalizedHeight")
1920
// Define a buffer size for the transaction channel
2021
txChannelBufferSize = 10000
22+
// reservedKeys defines the set of keys that should be excluded from state root calculation
23+
// and protected from transaction modifications
24+
reservedKeys = map[ds.Key]bool{
25+
genesisInitializedKey: true,
26+
genesisStateRootKey: true,
27+
finalizedHeightKey: true,
28+
}
2129
)
2230

2331
// KVExecutor is a simple key-value store backed by go-datastore that implements the Executor interface
@@ -70,9 +78,9 @@ func (k *KVExecutor) computeStateRoot(ctx context.Context) ([]byte, error) {
7078
if result.Error != nil {
7179
return nil, fmt.Errorf("error iterating query results: %w", result.Error)
7280
}
73-
// Exclude reserved genesis keys from the state root calculation
81+
// Exclude reserved keys from the state root calculation
7482
dsKey := ds.NewKey(result.Key)
75-
if dsKey.Equal(genesisInitializedKey) || dsKey.Equal(genesisStateRootKey) {
83+
if reservedKeys[dsKey] {
7684
continue
7785
}
7886
keys = append(keys, result.Key)
@@ -200,7 +208,7 @@ func (k *KVExecutor) ExecuteTxs(ctx context.Context, txs [][]byte, blockHeight u
200208
}
201209
dsKey := ds.NewKey(key)
202210
// Prevent writing reserved keys via transactions
203-
if dsKey.Equal(genesisInitializedKey) || dsKey.Equal(genesisStateRootKey) {
211+
if reservedKeys[dsKey] {
204212
return nil, 0, fmt.Errorf("transaction attempts to modify reserved key: %s", key)
205213
}
206214
err = batch.Put(ctx, dsKey, []byte(value))
@@ -240,7 +248,7 @@ func (k *KVExecutor) SetFinal(ctx context.Context, blockHeight uint64) error {
240248
return errors.New("invalid blockHeight: cannot be zero")
241249
}
242250

243-
return k.db.Put(ctx, ds.NewKey("/finalizedHeight"), []byte(fmt.Sprintf("%d", blockHeight)))
251+
return k.db.Put(ctx, finalizedHeightKey, []byte(fmt.Sprintf("%d", blockHeight)))
244252
}
245253

246254
// InjectTx adds a transaction to the mempool channel.

apps/testapp/kv/kvexecutor_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,92 @@ func TestSetFinal(t *testing.T) {
172172
t.Error("Expected error for blockHeight 0, got nil")
173173
}
174174
}
175+
176+
func TestReservedKeysExcludedFromAppHash(t *testing.T) {
177+
exec, err := NewKVExecutor(t.TempDir(), "testdb")
178+
if err != nil {
179+
t.Fatalf("Failed to create KVExecutor: %v", err)
180+
}
181+
ctx := context.Background()
182+
183+
// Initialize chain to set up genesis state (this writes genesis reserved keys)
184+
_, _, err = exec.InitChain(ctx, time.Now(), 1, "test-chain")
185+
if err != nil {
186+
t.Fatalf("Failed to initialize chain: %v", err)
187+
}
188+
189+
// Add some application data
190+
txs := [][]byte{
191+
[]byte("user/key1=value1"),
192+
[]byte("user/key2=value2"),
193+
}
194+
_, _, err = exec.ExecuteTxs(ctx, txs, 1, time.Now(), []byte(""))
195+
if err != nil {
196+
t.Fatalf("Failed to execute transactions: %v", err)
197+
}
198+
199+
// Compute baseline state root
200+
baselineStateRoot, err := exec.computeStateRoot(ctx)
201+
if err != nil {
202+
t.Fatalf("Failed to compute baseline state root: %v", err)
203+
}
204+
205+
// Write to finalizedHeight (a reserved key)
206+
err = exec.SetFinal(ctx, 5)
207+
if err != nil {
208+
t.Fatalf("Failed to set final height: %v", err)
209+
}
210+
211+
// Verify finalizedHeight was written
212+
finalizedHeightExists, err := exec.db.Has(ctx, finalizedHeightKey)
213+
if err != nil {
214+
t.Fatalf("Failed to check if finalizedHeight exists: %v", err)
215+
}
216+
if !finalizedHeightExists {
217+
t.Error("Expected finalizedHeight to exist in database")
218+
}
219+
220+
// State root should be unchanged (reserved keys excluded from calculation)
221+
stateRootAfterReservedKeyWrite, err := exec.computeStateRoot(ctx)
222+
if err != nil {
223+
t.Fatalf("Failed to compute state root after writing reserved key: %v", err)
224+
}
225+
226+
if string(baselineStateRoot) != string(stateRootAfterReservedKeyWrite) {
227+
t.Errorf("State root changed after writing reserved key:\nBefore: %s\nAfter: %s",
228+
string(baselineStateRoot), string(stateRootAfterReservedKeyWrite))
229+
}
230+
231+
// Verify state root contains only user data, not reserved keys
232+
stateRootStr := string(stateRootAfterReservedKeyWrite)
233+
if !strings.Contains(stateRootStr, "user/key1:value1") ||
234+
!strings.Contains(stateRootStr, "user/key2:value2") {
235+
t.Errorf("State root should contain user data: %s", stateRootStr)
236+
}
237+
238+
// Verify reserved keys are NOT in state root
239+
for key := range reservedKeys {
240+
keyStr := key.String()
241+
if strings.Contains(stateRootStr, keyStr) {
242+
t.Errorf("State root should NOT contain reserved key %s: %s", keyStr, stateRootStr)
243+
}
244+
}
245+
246+
// Verify that adding user data DOES change the state root
247+
moreTxs := [][]byte{
248+
[]byte("user/key3=value3"),
249+
}
250+
_, _, err = exec.ExecuteTxs(ctx, moreTxs, 2, time.Now(), stateRootAfterReservedKeyWrite)
251+
if err != nil {
252+
t.Fatalf("Failed to execute more transactions: %v", err)
253+
}
254+
255+
finalStateRoot, err := exec.computeStateRoot(ctx)
256+
if err != nil {
257+
t.Fatalf("Failed to compute final state root: %v", err)
258+
}
259+
260+
if string(baselineStateRoot) == string(finalStateRoot) {
261+
t.Error("Expected state root to change after adding user data")
262+
}
263+
}

block/manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ func (m *Manager) execValidate(lastState types.State, header *types.SignedHeader
818818

819819
// AppHash should match the last state's AppHash
820820
if !bytes.Equal(header.AppHash, lastState.AppHash) {
821-
return fmt.Errorf("appHash mismatch in delayed execution mode: expected %x, got %x", lastState.AppHash, header.AppHash)
821+
return fmt.Errorf("appHash mismatch in delayed execution mode: expected %x, got %x at height %d", lastState.AppHash, header.AppHash, header.Height())
822822
}
823823

824824
return nil

block/publish_block_p2p_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func setupBlockManager(t *testing.T, ctx context.Context, workDir string, mainKV
178178
}
179179

180180
logger := zerolog.Nop()
181-
p2pClient, err := p2p.NewClient(nodeConfig, nodeKey, mainKV, logger, p2p.NopMetrics())
181+
p2pClient, err := p2p.NewClient(nodeConfig.P2P, nodeKey.PrivKey, mainKV, genesisDoc.ChainID, logger, p2p.NopMetrics())
182182
require.NoError(t, err)
183183

184184
// Start p2p client before creating sync service

0 commit comments

Comments
 (0)