Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(statesync): extract app version from snapshot #3871

Merged
merged 18 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@ jobs:
**/**.go
go.mod
go.sum
- uses: golangci/golangci-lint-action@v6.0.1
- uses: golangci/golangci-lint-action@v6.1.0
with:
version: v1.57.0
version: v1.61.0
args: --timeout 10m
github-token: ${{ secrets.github_token }}
skip-pkg-cache: true
if: env.GIT_DIFF

# hadolint lints the Dockerfile
Expand Down
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ run:

linters:
enable:
- exportloopref
- copyloopvar
- gofumpt
- misspell
- nakedret
Expand Down
2 changes: 1 addition & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ archives:
checksum:
name_template: "checksums.txt"
snapshot:
name_template: "{{ incpatch .Version }}-next"
version_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# Separating the builder and runtime image allows the runtime image to be
# considerably smaller because it doesn't need to have Golang installed.
ARG BUILDER_IMAGE=docker.io/golang:1.22.6-alpine3.19
ARG BUILDER_IMAGE=docker.io/golang:1.23.1-alpine3.19
ARG RUNTIME_IMAGE=docker.io/alpine:3.19
ARG TARGETOS
ARG TARGETARCH
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ DOCKER_PROTO_BUILDER := docker run -v $(shell pwd):/workspace --workdir /workspa
PROJECTNAME=$(shell basename "$(PWD)")
HTTPS_GIT := https://github.com/celestiaorg/celestia-app.git
PACKAGE_NAME := github.com/celestiaorg/celestia-app/v2
GOLANG_CROSS_VERSION ?= v1.22.6
GOLANG_CROSS_VERSION ?= v1.23.1

# process linker flags
ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=celestia-app \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ node | | | |

### Source

1. [Install Go](https://go.dev/doc/install) 1.22.6
1. [Install Go](https://go.dev/doc/install) 1.23.1
1. Clone this repo
1. Install the celestia-app CLI

Expand Down
27 changes: 23 additions & 4 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ func setDefaultAppVersion(req abci.RequestInitChain) abci.RequestInitChain {
// mountKeysAndInit mounts the keys for the provided app version and then
// invokes baseapp.Init().
func (app *App) mountKeysAndInit(appVersion uint64) {
app.BaseApp.Logger().Info(fmt.Sprintf("mounting KV stores for app version %v", appVersion))
app.Logger().Info(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()
Expand Down Expand Up @@ -802,19 +802,38 @@ func (app *App) OfferSnapshot(req abci.RequestOfferSnapshot) abci.ResponseOfferS
return app.BaseApp.OfferSnapshot(req)
}

app.Logger().Info("offering snapshot", "height", req.Snapshot.Height, "app_version", req.AppVersion)
if req.AppVersion != 0 {
if !isSupportedAppVersion(req.AppVersion) {
app.Logger().Info("rejecting snapshot because unsupported app version", "app_version", req.AppVersion)
rootulp marked this conversation as resolved.
Show resolved Hide resolved
return abci.ResponseOfferSnapshot{
Result: abci.ResponseOfferSnapshot_REJECT,
}
}

app.Logger().Info("mounting keys for snapshot", "app_version", req.AppVersion)
app.mountKeysAndInit(req.AppVersion)
return app.BaseApp.OfferSnapshot(req)
}

// If the app version is not set in the snapshot, this falls back to inferring the app version based on the upgrade height.
if app.upgradeHeightV2 == 0 {
app.Logger().Debug("v2 upgrade height not set, assuming app version 2")
app.Logger().Info("v2 upgrade height not set, assuming app version 2")
app.mountKeysAndInit(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.Logger().Info("snapshot height is greater than or equal to upgrade height, assuming app version 2")
app.mountKeysAndInit(v2)
return app.BaseApp.OfferSnapshot(req)
}

app.Logger().Debug("snapshot height is less than upgrade height, assuming app version 1")
app.Logger().Info("snapshot height is less than upgrade height, assuming app version 1")
app.mountKeysAndInit(v1)
return app.BaseApp.OfferSnapshot(req)
}

func isSupportedAppVersion(appVersion uint64) bool {
return appVersion == v1 || appVersion == v2
}
54 changes: 41 additions & 13 deletions app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,23 +120,51 @@ func TestOfferSnapshot(t *testing.T) {
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"),
}

t.Run("should ACCEPT a valid snapshot", func(t *testing.T) {
app := app.New(logger, db, traceStore, invCheckPeriod, encodingConfig, upgradeHeight, appOptions, snapshotOption)
request := validSnapshot()
want := abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ACCEPT}
got := app.OfferSnapshot(request)
assert.Equal(t, want, got)
})
t.Run("should ACCEPT a snapshot with app version 1", func(t *testing.T) {
app := app.New(logger, db, traceStore, invCheckPeriod, encodingConfig, upgradeHeight, appOptions, snapshotOption)
request := validSnapshot()
request.AppVersion = 1
want := abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ACCEPT}
got := app.OfferSnapshot(request)
assert.Equal(t, want, got)
})
t.Run("should ACCEPT a snapshot with app version 2", func(t *testing.T) {
app := app.New(logger, db, traceStore, invCheckPeriod, encodingConfig, upgradeHeight, appOptions, snapshotOption)
request := validSnapshot()
request.AppVersion = 2
want := abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ACCEPT}
got := app.OfferSnapshot(request)
assert.Equal(t, want, got)
})
t.Run("should REJECT a snapshot with unsupported app version", func(t *testing.T) {
app := app.New(logger, db, traceStore, invCheckPeriod, encodingConfig, upgradeHeight, appOptions, snapshotOption)
request := validSnapshot()
request.AppVersion = 3 // unsupported app version
want := abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_REJECT}
got := app.OfferSnapshot(request)
assert.Equal(t, want, got)
})
}

func validSnapshot() abci.RequestOfferSnapshot {
return 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"),
}
}

func getSnapshotOption(t *testing.T) func(*baseapp.BaseApp) {
Expand Down
1 change: 0 additions & 1 deletion app/test/priority_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ func (s *PriorityTestSuite) TestPriorityByGasPrice() {
wg := &sync.WaitGroup{}
for _, accName := range s.accountNames {
wg.Add(1)
accName := accName // new variable per iteration
go func() {
defer wg.Done()
// ensure that it is greater than the min gas price
Expand Down
66 changes: 66 additions & 0 deletions app/test/state_sync_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package app_test

import (
"path/filepath"
"testing"

"github.com/celestiaorg/celestia-app/v2/app"
"github.com/celestiaorg/celestia-app/v2/app/encoding"
"github.com/celestiaorg/celestia-app/v2/test/util"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/snapshots"
snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
abcitypes "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
)

func TestOfferSnapshot(t *testing.T) {
t.Run("v1", func(t *testing.T) {
testApp := createTestApp(t)
request := createRequest()
request.AppVersion = 1
resp := testApp.OfferSnapshot(request)
assert.Equal(t, abcitypes.ResponseOfferSnapshot{Result: abcitypes.ResponseOfferSnapshot_ACCEPT}, resp)
})
t.Run("v2", func(t *testing.T) {
testApp := createTestApp(t)
request := createRequest()
request.AppVersion = 2
resp := testApp.OfferSnapshot(request)
assert.Equal(t, abcitypes.ResponseOfferSnapshot{Result: abcitypes.ResponseOfferSnapshot_ACCEPT}, resp)
})
}

func createTestApp(t *testing.T) *app.App {
db := dbm.NewMemDB()
config := encoding.MakeConfig(app.ModuleEncodingRegisters...)
upgradeHeight := int64(3)
snapshotDir := filepath.Join(t.TempDir(), "data", "snapshots")
snapshotDB, err := dbm.NewDB("metadata", dbm.GoLevelDBBackend, snapshotDir)
require.NoError(t, err)
snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir)
require.NoError(t, err)
baseAppOption := baseapp.SetSnapshot(snapshotStore, snapshottypes.NewSnapshotOptions(10, 10))
testApp := app.New(log.NewNopLogger(), db, nil, 0, config, upgradeHeight, util.EmptyAppOptions{}, baseAppOption)
require.NoError(t, err)
response := testApp.Info(abcitypes.RequestInfo{})
require.Equal(t, uint64(0), response.AppVersion)
return testApp
}

func createRequest() abcitypes.RequestOfferSnapshot {
return abcitypes.RequestOfferSnapshot{
Snapshot: &abcitypes.Snapshot{
Height: 0x290400,
Format: 0x2,
Chunks: 0x15,
Hash: []uint8{0xdd, 0x39, 0x7a, 0xb, 0xf7, 0x48, 0xb1, 0xb2, 0x40, 0x9a, 0x5f, 0x9, 0xd3, 0x59, 0x6f, 0x26, 0x85, 0x1f, 0x39, 0xb4, 0x69, 0x4e, 0x30, 0x45, 0x45, 0xc, 0x61, 0x65, 0x58, 0x19, 0xbd, 0x13},
Metadata: []uint8{0xa, 0x20, 0xe5, 0xd2, 0x9f, 0xa6, 0xad, 0xa9, 0xf5, 0x19, 0xb3, 0xd1, 0x60, 0xe4, 0x9d, 0x36, 0xfa, 0x85, 0x7c, 0x5, 0x1d, 0x63, 0xa6, 0x92, 0x12, 0xb5, 0xf8, 0x1e, 0x0, 0x78, 0x57, 0xef, 0xc9, 0xdb, 0xa, 0x20, 0x35, 0xcb, 0x42, 0xaa, 0x7e, 0x18, 0x1e, 0x2d, 0xb3, 0xf2, 0x60, 0xca, 0x42, 0xf8, 0xa9, 0x56, 0x17, 0x1, 0xdd, 0x2f, 0xdd, 0x3c, 0xb2, 0x24, 0x4, 0xc9, 0x1, 0xd4, 0x76, 0x50, 0xd3, 0xa5, 0xa, 0x20, 0xaf, 0xf9, 0xde, 0x28, 0x23, 0x3d, 0x5f, 0x5b, 0xb0, 0x2b, 0xb0, 0xb1, 0x2b, 0x40, 0xc4, 0xf6, 0xa7, 0xb4, 0xbc, 0x91, 0x20, 0xa5, 0x27, 0x59, 0x81, 0x68, 0x10, 0x2c, 0x8c, 0x90, 0x12, 0x66, 0xa, 0x20, 0xff, 0x15, 0x78, 0x38, 0xaf, 0x28, 0x9e, 0x9b, 0x9d, 0xf, 0x43, 0x9f, 0x81, 0x78, 0xc8, 0xe8, 0x33, 0x88, 0x4f, 0x60, 0x15, 0x82, 0x1f, 0x3b, 0x4b, 0x9d, 0xcb, 0xfe, 0xdd, 0x33, 0xab, 0x9d, 0xa, 0x20, 0x2c, 0xb7, 0x98, 0x72, 0x76, 0x74, 0x74, 0xad, 0xf4, 0x57, 0x80, 0xc, 0xbb, 0x8c, 0x38, 0xb3, 0xf4, 0x81, 0xdc, 0x5c, 0xa4, 0x6, 0xd1, 0x85, 0x90, 0xbb, 0x1b, 0x5d, 0xf2, 0x16, 0x4a, 0x14, 0xa, 0x20, 0x86, 0x54, 0xa6, 0x90, 0x55, 0x66, 0x28, 0x58, 0x5f, 0xaf, 0x96, 0xcb, 0xda, 0x1b, 0x5c, 0x12, 0x5a, 0xe0, 0x2b, 0x9f, 0x56, 0xaa, 0x0, 0x41, 0x95, 0x3, 0x95, 0xe3, 0xad, 0xb8, 0x49, 0x9e, 0xa, 0x20, 0xcb, 0x93, 0x9, 0xaf, 0xe, 0xfd, 0xf1, 0xa9, 0xe4, 0xd9, 0xb3, 0x63, 0x3b, 0x1e, 0xca, 0x85, 0x2c, 0xa3, 0xd8, 0x9a, 0x19, 0xfa, 0xe8, 0xea, 0xc6, 0xd4, 0x87, 0x44, 0x82, 0xcf, 0x1, 0x4c, 0xa, 0x20, 0x1d, 0x27, 0x30, 0x95, 0xd8, 0xf3, 0xd6, 0x2, 0xe0, 0x45, 0xc5, 0x30, 0x87, 0x30, 0xb9, 0x7e, 0x38, 0xee, 0x6a, 0xe1, 0xfe, 0x60, 0x5e, 0x58, 0xdf, 0x22, 0xf6, 0xf5, 0x13, 0xf6, 0xa1, 0xd6, 0xa, 0x20, 0x22, 0x47, 0x84, 0x25, 0x35, 0xf0, 0x11, 0xcd, 0x24, 0x26, 0x11, 0x9c, 0xde, 0x75, 0xff, 0x11, 0xe9, 0x12, 0xa1, 0xfc, 0xd1, 0x1, 0xe2, 0xf7, 0x4, 0xb0, 0x10, 0x2c, 0xd4, 0x18, 0xcf, 0x84, 0xa, 0x20, 0x9a, 0x85, 0xe9, 0x18, 0xc8, 0xdc, 0x3e, 0x38, 0x13, 0xe3, 0x97, 0x64, 0xbd, 0x4b, 0xb1, 0xc4, 0x47, 0x9e, 0x68, 0xa5, 0xf7, 0x32, 0x85, 0x56, 0x98, 0x25, 0x2f, 0x92, 0x9d, 0xdc, 0x4a, 0x2, 0xa, 0x20, 0xc2, 0xe0, 0xea, 0x18, 0xe2, 0x4c, 0x9c, 0x87, 0xbb, 0x88, 0xe8, 0x7, 0xb3, 0x99, 0x85, 0x4d, 0xda, 0x44, 0xd9, 0x3f, 0xa8, 0xb6, 0x21, 0xfb, 0xd7, 0x98, 0xe6, 0xe4, 0x55, 0x91, 0xd, 0x97, 0xa, 0x20, 0x37, 0x75, 0x7f, 0x7, 0xa6, 0x59, 0xe4, 0x4, 0x2, 0xb3, 0x8e, 0xb2, 0xfd, 0x81, 0x5a, 0x99, 0xce, 0x48, 0x2d, 0x39, 0xa6, 0xba, 0xe8, 0x26, 0xeb, 0xca, 0x8d, 0xae, 0x16, 0x21, 0x6d, 0xe0, 0xa, 0x20, 0x28, 0xa0, 0xb7, 0x37, 0xaa, 0x4c, 0x8c, 0x5, 0x25, 0x70, 0x96, 0x29, 0x2a, 0x1a, 0x60, 0x51, 0x9d, 0xd0, 0xc6, 0x32, 0x4c, 0x59, 0xc0, 0xf4, 0xb7, 0xad, 0x19, 0x21, 0xe, 0x20, 0x7, 0x50, 0xa, 0x20, 0x32, 0x32, 0x29, 0x6c, 0x7e, 0xfc, 0x8, 0x79, 0x24, 0x72, 0xfa, 0x69, 0x29, 0xe0, 0x1, 0xb8, 0xa3, 0xac, 0x90, 0x1b, 0x37, 0x96, 0x95, 0xff, 0x4e, 0xd2, 0xd0, 0xcf, 0x2a, 0xad, 0x44, 0xd3, 0xa, 0x20, 0xc9, 0x38, 0xe0, 0xaa, 0xa2, 0x9a, 0x69, 0xd3, 0xa6, 0xd3, 0x72, 0x7, 0xe6, 0xf6, 0xbb, 0x81, 0x42, 0x59, 0xf3, 0xae, 0x3d, 0xfc, 0xc0, 0x51, 0xe8, 0x2, 0x1c, 0x80, 0x3f, 0xc1, 0xf3, 0x38, 0xa, 0x20, 0x5a, 0xc1, 0x9b, 0x0, 0x8, 0x1e, 0xee, 0xd0, 0x5, 0x34, 0xc8, 0xfd, 0x22, 0x96, 0x7e, 0xa0, 0x9a, 0x60, 0x55, 0x84, 0x55, 0xbc, 0x1d, 0xef, 0xfe, 0xfd, 0xbe, 0xe6, 0x2e, 0x90, 0xce, 0xbc, 0xa, 0x20, 0x5d, 0x40, 0x89, 0xac, 0xdf, 0x90, 0x52, 0x70, 0xf9, 0xd, 0xab, 0x3d, 0x6d, 0xe3, 0xa8, 0x65, 0xa9, 0xe6, 0xdc, 0x6d, 0x72, 0x71, 0x38, 0x8d, 0x56, 0xaa, 0x22, 0xc, 0x46, 0xf2, 0xfd, 0x15, 0xa, 0x20, 0xab, 0x91, 0x4e, 0xb2, 0x97, 0x1d, 0xc0, 0xe6, 0x4d, 0x4b, 0x48, 0x1a, 0xbb, 0x39, 0x9f, 0xa2, 0xdc, 0x1, 0x7c, 0x8, 0xc5, 0xe8, 0x16, 0x2d, 0xce, 0xcd, 0xa2, 0xa7, 0x22, 0x30, 0x2b, 0xad, 0xa, 0x20, 0xf0, 0x96, 0x1d, 0x71, 0x7f, 0xa1, 0xc0, 0xab, 0xbf, 0xb8, 0x90, 0xf0, 0xe1, 0x64, 0x1f, 0x6e, 0xdd, 0xbd, 0xe9, 0xb8, 0xc2, 0xf6, 0xf0, 0x2e, 0x8c, 0x76, 0xf3, 0x1a, 0xfe, 0x40, 0x93, 0x70, 0xa, 0x20, 0x1c, 0x51, 0xe9, 0xdf, 0x1d, 0x6, 0x28, 0xdf, 0x17, 0xda, 0x75, 0xf7, 0x83, 0x4e, 0xe6, 0x6e, 0xf1, 0x73, 0xcf, 0x3a, 0x55, 0x90, 0xb4, 0x28, 0x15, 0x13, 0x9e, 0x79, 0x5d, 0xd1, 0xd0, 0x33, 0xa, 0x20, 0xf2, 0xd2, 0x2f, 0x94, 0x1a, 0xf9, 0x61, 0x25, 0xb5, 0xb0, 0x82, 0xf9, 0x80, 0x11, 0x29, 0xf0, 0x38, 0xda, 0xb9, 0xb9, 0xe2, 0x6, 0x7b, 0x6a, 0x15, 0x87, 0xc4, 0x1d, 0x54, 0x2e, 0xca, 0x27},
rootulp marked this conversation as resolved.
Show resolved Hide resolved
},
AppHash: []byte("apphash"),
AppVersion: 0, // unit tests will override this
}
}
2 changes: 1 addition & 1 deletion docker/Dockerfile_txsim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Stage 1: generate celestia-appd binary
FROM --platform=$BUILDPLATFORM docker.io/golang:1.22.6-alpine3.19 as builder
FROM --platform=$BUILDPLATFORM docker.io/golang:1.23.1-alpine3.19 as builder

ARG TARGETOS
ARG TARGETARCH
Expand Down
Loading
Loading