Skip to content

Commit e91c53a

Browse files
rootulpclaude
andcommitted
fix(standalone): use SDK genesis provider to handle AppGenesis format
The standalone binary was failing to start with the error: "invalid 64-bit integer encoding '1', expected string" This was caused by using node.DefaultGenesisDocProviderFunc which reads the genesis file directly as CometBFT's GenesisDoc format, but the SDK's init command generates an AppGenesis file where InitialHeight is an int64 (serialized as a JSON integer) rather than a string. This commit adds a custom getGenDocProvider function that: 1. Reads the genesis file using the SDK's AppGenesisFromFile 2. Converts it to CometBFT's GenesisDoc using ToGenesisDoc() This matches the pattern used by the multiplexer binary in multiplexer/internal/utils.go:GetGenDocProvider. Closes #164 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3ec7eee commit e91c53a

File tree

2 files changed

+91
-1
lines changed

2 files changed

+91
-1
lines changed

cmd/celestia-appd/cmd/start_command_standalone.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/cometbft/cometbft/proxy"
2020
"github.com/cometbft/cometbft/rpc/client/local"
2121
coregrpc "github.com/cometbft/cometbft/rpc/grpc"
22+
cmttypes "github.com/cometbft/cometbft/types"
2223
db "github.com/cosmos/cosmos-db"
2324
"github.com/cosmos/cosmos-sdk/client"
2425
"github.com/cosmos/cosmos-sdk/server"
@@ -28,6 +29,7 @@ import (
2829
servercmtlog "github.com/cosmos/cosmos-sdk/server/log"
2930
servertypes "github.com/cosmos/cosmos-sdk/server/types"
3031
"github.com/cosmos/cosmos-sdk/telemetry"
32+
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
3133
"golang.org/x/sync/errgroup"
3234
"google.golang.org/grpc"
3335
"google.golang.org/grpc/credentials/insecure"
@@ -173,7 +175,7 @@ func startCometNode(svrCtx *server.Context, appInstance servertypes.Application)
173175
privVal,
174176
nodeKey,
175177
proxy.NewLocalClientCreator(cmtApp),
176-
node.DefaultGenesisDocProviderFunc(cfg),
178+
getGenDocProvider(cfg),
177179
cmtcfg.DefaultDBProvider,
178180
node.DefaultMetricsProvider(cfg.Instrumentation),
179181
servercmtlog.CometLoggerWrapper{Logger: svrCtx.Logger},
@@ -341,3 +343,16 @@ func openDB(rootDir string, backendType db.BackendType) (db.DB, error) {
341343
dataDir := filepath.Join(rootDir, "data")
342344
return db.NewDB("application", backendType, dataDir)
343345
}
346+
347+
// getGenDocProvider returns a function that loads the genesis document from file.
348+
// This uses the SDK's AppGenesis format and converts it to CometBFT's GenesisDoc,
349+
// which properly handles the type conversion (e.g., InitialHeight as int64 vs string).
350+
func getGenDocProvider(cfg *cmtcfg.Config) func() (*cmttypes.GenesisDoc, error) {
351+
return func() (*cmttypes.GenesisDoc, error) {
352+
appGenesis, err := genutiltypes.AppGenesisFromFile(cfg.GenesisFile())
353+
if err != nil {
354+
return nil, err
355+
}
356+
return appGenesis.ToGenesisDoc()
357+
}
358+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//go:build !multiplexer
2+
3+
package cmd
4+
5+
import (
6+
"os"
7+
"path/filepath"
8+
"testing"
9+
"time"
10+
11+
cmtcfg "github.com/cometbft/cometbft/config"
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func TestGetGenDocProvider(t *testing.T) {
17+
// Create a temporary directory for the test
18+
tempDir := t.TempDir()
19+
configDir := filepath.Join(tempDir, "config")
20+
require.NoError(t, os.MkdirAll(configDir, 0o755))
21+
22+
// Create a genesis file in SDK AppGenesis format (with InitialHeight as integer)
23+
genesisFile := filepath.Join(configDir, "genesis.json")
24+
// This is the format that the SDK's init command generates
25+
genesisContent := `{
26+
"app_name": "celestia-appd",
27+
"app_version": "test",
28+
"genesis_time": "2024-01-01T00:00:00Z",
29+
"chain_id": "test-chain",
30+
"initial_height": 1,
31+
"app_hash": null,
32+
"app_state": {},
33+
"consensus": {
34+
"validators": [],
35+
"params": {
36+
"block": {"max_bytes": "22020096", "max_gas": "-1"},
37+
"evidence": {"max_age_num_blocks": "100000", "max_age_duration": "172800000000000", "max_bytes": "1048576"},
38+
"validator": {"pub_key_types": ["ed25519"]},
39+
"version": {"app": "0"},
40+
"abci": {"vote_extensions_enable_height": "0"}
41+
}
42+
}
43+
}`
44+
require.NoError(t, os.WriteFile(genesisFile, []byte(genesisContent), 0o644))
45+
46+
// Create a CometBFT config pointing to the temp directory
47+
cfg := cmtcfg.DefaultConfig()
48+
cfg.SetRoot(tempDir)
49+
50+
// Get the genesis doc provider and call it
51+
provider := getGenDocProvider(cfg)
52+
genDoc, err := provider()
53+
54+
// Verify no error occurred (this would fail with the old DefaultGenesisDocProviderFunc
55+
// because it can't handle InitialHeight as an integer)
56+
require.NoError(t, err)
57+
58+
// Verify the genesis doc was parsed correctly
59+
assert.Equal(t, "test-chain", genDoc.ChainID)
60+
assert.Equal(t, int64(1), genDoc.InitialHeight)
61+
assert.Equal(t, time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), genDoc.GenesisTime)
62+
}
63+
64+
func TestGetGenDocProvider_FileNotFound(t *testing.T) {
65+
// Create a CometBFT config pointing to a non-existent directory
66+
cfg := cmtcfg.DefaultConfig()
67+
cfg.SetRoot("/non/existent/path")
68+
69+
// Get the genesis doc provider and call it
70+
provider := getGenDocProvider(cfg)
71+
_, err := provider()
72+
73+
// Verify an error occurred
74+
assert.Error(t, err)
75+
}

0 commit comments

Comments
 (0)