From 3c860c38c86b5b9aa2b035be9026e698c481c238 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Wed, 21 Aug 2024 22:45:14 -0400 Subject: [PATCH 1/7] fix: state sync --- app/app.go | 24 ++++++++++++++++++++ scripts/arabica.sh | 56 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/mocha.sh | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100755 scripts/arabica.sh create mode 100755 scripts/mocha.sh diff --git a/app/app.go b/app/app.go index 134da07ea5..a5c7802880 100644 --- a/app/app.go +++ b/app/app.go @@ -570,6 +570,7 @@ func (app *App) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain // mountKeysAndInit mounts the keys for the provided app version and then // invokes baseapp.Init(). func (app *App) mountKeysAndInit(appVersion uint64) { + app.BaseApp.Logger().Debug(fmt.Sprintf("mounting KV stores for app version %v", appVersion)) app.MountKVStores(app.versionedKeys(appVersion)) // Invoke load latest version for it's side-effect of invoking baseapp.Init() @@ -784,3 +785,26 @@ func (app *App) InitializeAppVersion(ctx sdk.Context) { app.SetAppVersion(ctx, appVersion) } } + +// OfferSnapshot is a wrapper around the baseapp's OfferSnapshot method. It is +// needed to mount stores for the appropriate app version. +func (app *App) OfferSnapshot(req abci.RequestOfferSnapshot) abci.ResponseOfferSnapshot { + if app.IsSealed() { + // If the app is sealed, keys have already been mounted so this can + // delegate to the baseapp's OfferSnapshot. + return app.BaseApp.OfferSnapshot(req) + } + + if app.upgradeHeightV2 == 0 { + app.Logger().Debug("v2 upgrade height not set, assuming app version 2") + app.mountKeysAndInit(v2) + } else if req.Snapshot.Height >= uint64(app.upgradeHeightV2) { + app.Logger().Debug("snapshot height is greater than or equal to upgrade height, assuming app version 2") + app.mountKeysAndInit(v2) + } else { + app.Logger().Debug("snapshot height is less than upgrade height, assuming app version 1") + app.mountKeysAndInit(v1) + } + + return app.BaseApp.OfferSnapshot(req) +} diff --git a/scripts/arabica.sh b/scripts/arabica.sh new file mode 100755 index 0000000000..5c19bd6c8c --- /dev/null +++ b/scripts/arabica.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +# Stop script execution if an error is encountered +set -o errexit +# Stop script execution if an undefined variable is used +set -o nounset + +CHAIN_ID="arabica-11" +NODE_NAME="node-name" +SEEDS="827583022cc6ce65cf762115642258f937c954cd@validator-1.celestia-arabica-11.com:26656,74e42b39f512f844492ff09e30af23d54579b7bc@validator-2.celestia-arabica-11.com:26656,00d577159b2eb1f524ef9c37cb389c020a2c38d2@validator-3.celestia-arabica-11.com:26656,b2871b6dc2e18916d07264af0e87c456c2bba04f@validator-4.celestia-arabica-11.com:26656" +RPC="https://rpc.celestia-arabica-11.com:443" + +CELESTIA_APP_HOME="${HOME}/.celestia-app" +CELESTIA_APP_VERSION=$(celestia-appd version 2>&1) + +echo "celestia-app home: ${CELESTIA_APP_HOME}" +echo "celestia-app version: ${CELESTIA_APP_VERSION}" +echo "" + +# Ask the user for confirmation before deleting the existing celestia-app home +# directory. +read -p "Are you sure you want to delete: $CELESTIA_APP_HOME? [y/n] " response + +# Check the user's response +if [ "$response" != "y" ]; then + # Exit if the user did not respond with "y" + echo "You must delete $CELESTIA_APP_HOME to continue." + exit 1 +fi + +echo "Deleting $CELESTIA_APP_HOME..." +rm -r "$CELESTIA_APP_HOME" + +echo "Initializing config files..." +celestia-appd init ${NODE_NAME} --chain-id ${CHAIN_ID} > /dev/null 2>&1 # Hide output to reduce terminal noise + +echo "Settings seeds in config.toml..." +sed -i.bak -e "s/^seeds *=.*/seeds = \"$SEEDS\"/" $CELESTIA_APP_HOME/config/config.toml + +# LATEST_HEIGHT=$(curl -s $RPC/block | jq -r .result.block.header.height); +BLOCK_HEIGHT=1751700 +TRUST_HASH=$(curl -s "$RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash) + +echo "Block height: $BLOCK_HEIGHT" +echo "Trust hash: $TRUST_HASH" +echo "Enabling state sync in config.toml..." +sed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\1true| ; \ +s|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\1\"$RPC,$RPC\"| ; \ +s|^(trust_height[[:space:]]+=[[:space:]]+).*$|\1$BLOCK_HEIGHT| ; \ +s|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\1\"$TRUST_HASH\"|" $HOME/.celestia-app/config/config.toml + +echo "Downloading genesis file..." +celestia-appd download-genesis ${CHAIN_ID} + +echo "Starting celestia-appd..." +celestia-appd start --v2-upgrade-height 1751707 diff --git a/scripts/mocha.sh b/scripts/mocha.sh new file mode 100755 index 0000000000..bb14207cf8 --- /dev/null +++ b/scripts/mocha.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +# Stop script execution if an error is encountered +set -o errexit +# Stop script execution if an undefined variable is used +set -o nounset + +CHAIN_ID="mocha-4" +NODE_NAME="node-name" +SEEDS="ee9f90974f85c59d3861fc7f7edb10894f6ac3c8@seed-mocha.pops.one:26656,258f523c96efde50d5fe0a9faeea8a3e83be22ca@seed.mocha-4.celestia.aviaone.com:20279,5d0bf034d6e6a8b5ee31a2f42f753f1107b3a00e@celestia-testnet-seed.itrocket.net:11656,7da0fb48d6ef0823bc9770c0c8068dd7c89ed4ee@celest-test-seed.theamsolutions.info:443" +RPC="https://celestia-testnet-rpc.itrocket.net:443" + +CELESTIA_APP_HOME="${HOME}/.celestia-app" +CELESTIA_APP_VERSION=$(celestia-appd version 2>&1) + +echo "celestia-app home: ${CELESTIA_APP_HOME}" +echo "celestia-app version: ${CELESTIA_APP_VERSION}" +echo "" + +# Ask the user for confirmation before deleting the existing celestia-app home +# directory. +read -p "Are you sure you want to delete: $CELESTIA_APP_HOME? [y/n] " response + +# Check the user's response +if [ "$response" != "y" ]; then + # Exit if the user did not respond with "y" + echo "You must delete $CELESTIA_APP_HOME to continue." + exit 1 +fi + +echo "Deleting $CELESTIA_APP_HOME..." +rm -r "$CELESTIA_APP_HOME" + +echo "Initializing config files..." +celestia-appd init ${NODE_NAME} --chain-id ${CHAIN_ID} > /dev/null 2>&1 # Hide output to reduce terminal noise + +echo "Settings seeds in config.toml..." +sed -i.bak -e "s/^seeds *=.*/seeds = \"$SEEDS\"/" $CELESTIA_APP_HOME/config/config.toml + +LATEST_HEIGHT=$(curl -s $RPC/block | jq -r .result.block.header.height); +BLOCK_HEIGHT=$((LATEST_HEIGHT - 2000)); \ +TRUST_HASH=$(curl -s "$RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash) + +echo "Block height: $BLOCK_HEIGHT" +echo "Trust hash: $TRUST_HASH" +echo "Enabling state sync in config.toml..." +sed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\1true| ; \ +s|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\1\"$RPC,$RPC\"| ; \ +s|^(trust_height[[:space:]]+=[[:space:]]+).*$|\1$BLOCK_HEIGHT| ; \ +s|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\1\"$TRUST_HASH\"|" $HOME/.celestia-app/config/config.toml + +echo "Downloading genesis file..." +celestia-appd download-genesis ${CHAIN_ID} > /dev/null 2>&1 # Hide output to reduce terminal noise + +echo "Starting celestia-appd..." +celestia-appd start --v2-upgrade-height 2585031 From 041314db89ad587d604bed4cd843b808c060f274 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Wed, 21 Aug 2024 23:12:30 -0400 Subject: [PATCH 2/7] fix: lint --- app/app.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/app.go b/app/app.go index a5c7802880..884d40c11d 100644 --- a/app/app.go +++ b/app/app.go @@ -798,13 +798,16 @@ func (app *App) OfferSnapshot(req abci.RequestOfferSnapshot) abci.ResponseOfferS if app.upgradeHeightV2 == 0 { app.Logger().Debug("v2 upgrade height not set, assuming app version 2") app.mountKeysAndInit(v2) - } else if req.Snapshot.Height >= uint64(app.upgradeHeightV2) { + return app.BaseApp.OfferSnapshot(req) + } + + if req.Snapshot.Height >= uint64(app.upgradeHeightV2) { app.Logger().Debug("snapshot height is greater than or equal to upgrade height, assuming app version 2") app.mountKeysAndInit(v2) - } else { - app.Logger().Debug("snapshot height is less than upgrade height, assuming app version 1") - app.mountKeysAndInit(v1) + return app.BaseApp.OfferSnapshot(req) } + app.Logger().Debug("snapshot height is less than upgrade height, assuming app version 1") + app.mountKeysAndInit(v1) return app.BaseApp.OfferSnapshot(req) } From 393574adafa8bb13f004c7211a40e65b0b793bd3 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Thu, 22 Aug 2024 01:00:02 -0400 Subject: [PATCH 3/7] v0 unit test --- app/app_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/app/app_test.go b/app/app_test.go index a991981d41..953b5fcf63 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -6,7 +6,13 @@ import ( "github.com/celestiaorg/celestia-app/v2/app" "github.com/celestiaorg/celestia-app/v2/app/encoding" "github.com/celestiaorg/celestia-app/v2/x/minfee" + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/snapshots" + snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" tmdb "github.com/tendermint/tm-db" ) @@ -47,6 +53,45 @@ func TestNew(t *testing.T) { }) } +func TestOfferSnapshot(t *testing.T) { + logger := log.NewNopLogger() + db := tmdb.NewMemDB() + traceStore := &NoopWriter{} + invCheckPeriod := uint(1) + encodingConfig := encoding.MakeConfig(app.ModuleEncodingRegisters...) + upgradeHeight := int64(0) + appOptions := NoopAppOptions{} + snapshotOption := getSnapshotOption(t) + app := app.New(logger, db, traceStore, invCheckPeriod, encodingConfig, upgradeHeight, appOptions, snapshotOption) + + t.Run("should return ACCEPT", func(t *testing.T) { + request := abci.RequestOfferSnapshot{ + Snapshot: &abci.Snapshot{ + Height: 0x1b07ec, + Format: 0x2, + Chunks: 0x1, + Hash: []uint8{0xaf, 0xa5, 0xe, 0x16, 0x45, 0x4, 0x2e, 0x45, 0xd3, 0x49, 0xdf, 0x83, 0x2a, 0x57, 0x9d, 0x64, 0xc8, 0xad, 0xa5, 0xb, 0x65, 0x1b, 0x46, 0xd6, 0xc3, 0x85, 0x6, 0x51, 0xd7, 0x45, 0x8e, 0xb8}, + Metadata: []uint8{0xa, 0x20, 0xaf, 0xa5, 0xe, 0x16, 0x45, 0x4, 0x2e, 0x45, 0xd3, 0x49, 0xdf, 0x83, 0x2a, 0x57, 0x9d, 0x64, 0xc8, 0xad, 0xa5, 0xb, 0x65, 0x1b, 0x46, 0xd6, 0xc3, 0x85, 0x6, 0x51, 0xd7, 0x45, 0x8e, 0xb8}, + }, + AppHash: []byte("apphash"), + } + want := abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ACCEPT} + got := app.OfferSnapshot(request) + assert.Equal(t, want, got) + }) +} + +func getSnapshotOption(t *testing.T) func(*baseapp.BaseApp) { + snapshotDir := t.TempDir() + snapshotDB, err := sdk.NewLevelDB("metadata", t.TempDir()) + require.NoError(t, err) + snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir) + require.NoError(t, err) + interval := uint64(10) + keepRecent := uint32(10) + return baseapp.SetSnapshot(snapshotStore, snapshottypes.NewSnapshotOptions(interval, keepRecent)) +} + // NoopWriter is a no-op implementation of a writer. type NoopWriter struct{} From 3cd3cb99c1b7c9cf7081c9605d0144af13e18b63 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Thu, 22 Aug 2024 01:02:47 -0400 Subject: [PATCH 4/7] fix: lint --- app/app_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index 953b5fcf63..c9fb31c1dc 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -9,7 +9,6 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/snapshots" snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" @@ -83,7 +82,7 @@ func TestOfferSnapshot(t *testing.T) { func getSnapshotOption(t *testing.T) func(*baseapp.BaseApp) { snapshotDir := t.TempDir() - snapshotDB, err := sdk.NewLevelDB("metadata", t.TempDir()) + snapshotDB, err := tmdb.NewDB("metadata", tmdb.GoLevelDBBackend, t.TempDir()) require.NoError(t, err) snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir) require.NoError(t, err) From 211dae5a0e495b439530e6af38b861d74248451e Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Thu, 22 Aug 2024 15:51:16 +0200 Subject: [PATCH 5/7] update the app version after completing state sync --- app/app.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app/app.go b/app/app.go index 884d40c11d..b8cb2bfe4e 100644 --- a/app/app.go +++ b/app/app.go @@ -167,6 +167,9 @@ type App struct { // upgradeHeightV2 is used as a coordination mechanism for the height-based // upgrade from v1 to v2. upgradeHeightV2 int64 + // HACK: remove this once we have a better way to handle versioning while + // state syncing + stateSyncVersion uint64 // MsgGateKeeper is used to define which messages are accepted for a given // app version. MsgGateKeeper *ante.MsgVersioningGateKeeper @@ -519,11 +522,17 @@ func (app *App) Info(req abci.RequestInfo) abci.ResponseInfo { if err != nil { panic(err) } - appVersion := app.GetAppVersionFromParamStore(ctx) - if appVersion > 0 { - app.SetAppVersion(ctx, appVersion) + // Info get's called after state sync is complete. Here + // we check for this case and set the app version accordingly. + if app.stateSyncVersion > 0 { + app.SetAppVersion(ctx, app.stateSyncVersion) } else { - app.SetAppVersion(ctx, v1) + appVersion := app.GetAppVersionFromParamStore(ctx) + if appVersion > 0 { + app.SetAppVersion(ctx, appVersion) + } else { + app.SetAppVersion(ctx, v1) + } } } @@ -798,12 +807,14 @@ func (app *App) OfferSnapshot(req abci.RequestOfferSnapshot) abci.ResponseOfferS if app.upgradeHeightV2 == 0 { app.Logger().Debug("v2 upgrade height not set, assuming app version 2") app.mountKeysAndInit(v2) + app.stateSyncVersion = v2 return app.BaseApp.OfferSnapshot(req) } if req.Snapshot.Height >= uint64(app.upgradeHeightV2) { app.Logger().Debug("snapshot height is greater than or equal to upgrade height, assuming app version 2") app.mountKeysAndInit(v2) + app.stateSyncVersion = v2 return app.BaseApp.OfferSnapshot(req) } From 0f6fa8436a5cd88536cd656e0fd06b80562d0038 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Thu, 22 Aug 2024 09:51:35 -0400 Subject: [PATCH 6/7] describe scripts --- scripts/arabica.sh | 3 +++ scripts/mocha.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/scripts/arabica.sh b/scripts/arabica.sh index 5c19bd6c8c..831c785245 100755 --- a/scripts/arabica.sh +++ b/scripts/arabica.sh @@ -1,5 +1,8 @@ #!/bin/sh +# This script starts a consensus node on Arabica and state syncs to the tip of +# the chain. + # Stop script execution if an error is encountered set -o errexit # Stop script execution if an undefined variable is used diff --git a/scripts/mocha.sh b/scripts/mocha.sh index bb14207cf8..d64921b2a8 100755 --- a/scripts/mocha.sh +++ b/scripts/mocha.sh @@ -1,5 +1,8 @@ #!/bin/sh +# This script starts a consensus node on Mocha and state syncs to the tip of the +# chain. + # Stop script execution if an error is encountered set -o errexit # Stop script execution if an undefined variable is used From 39ae6c9615cc7852951a2385d77839a06a135f88 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Thu, 22 Aug 2024 16:11:42 +0200 Subject: [PATCH 7/7] Revert "update the app version after completing state sync" This reverts commit 211dae5a0e495b439530e6af38b861d74248451e. --- app/app.go | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/app/app.go b/app/app.go index b8cb2bfe4e..884d40c11d 100644 --- a/app/app.go +++ b/app/app.go @@ -167,9 +167,6 @@ type App struct { // upgradeHeightV2 is used as a coordination mechanism for the height-based // upgrade from v1 to v2. upgradeHeightV2 int64 - // HACK: remove this once we have a better way to handle versioning while - // state syncing - stateSyncVersion uint64 // MsgGateKeeper is used to define which messages are accepted for a given // app version. MsgGateKeeper *ante.MsgVersioningGateKeeper @@ -522,17 +519,11 @@ func (app *App) Info(req abci.RequestInfo) abci.ResponseInfo { if err != nil { panic(err) } - // Info get's called after state sync is complete. Here - // we check for this case and set the app version accordingly. - if app.stateSyncVersion > 0 { - app.SetAppVersion(ctx, app.stateSyncVersion) + appVersion := app.GetAppVersionFromParamStore(ctx) + if appVersion > 0 { + app.SetAppVersion(ctx, appVersion) } else { - appVersion := app.GetAppVersionFromParamStore(ctx) - if appVersion > 0 { - app.SetAppVersion(ctx, appVersion) - } else { - app.SetAppVersion(ctx, v1) - } + app.SetAppVersion(ctx, v1) } } @@ -807,14 +798,12 @@ func (app *App) OfferSnapshot(req abci.RequestOfferSnapshot) abci.ResponseOfferS if app.upgradeHeightV2 == 0 { app.Logger().Debug("v2 upgrade height not set, assuming app version 2") app.mountKeysAndInit(v2) - app.stateSyncVersion = v2 return app.BaseApp.OfferSnapshot(req) } if req.Snapshot.Height >= uint64(app.upgradeHeightV2) { app.Logger().Debug("snapshot height is greater than or equal to upgrade height, assuming app version 2") app.mountKeysAndInit(v2) - app.stateSyncVersion = v2 return app.BaseApp.OfferSnapshot(req) }