diff --git a/app/app.go b/app/app.go index ecba661020..b13e8f7f3f 100644 --- a/app/app.go +++ b/app/app.go @@ -280,7 +280,7 @@ func New( ), ) - app.SignalKeeper = signal.NewKeeper(appCodec, keys[signaltypes.StoreKey], app.StakingKeeper, appconsts.UpgradeHeightDelay()) + app.SignalKeeper = signal.NewKeeper(appCodec, keys[signaltypes.StoreKey], app.StakingKeeper) app.IBCKeeper = ibckeeper.NewKeeper( appCodec, @@ -458,7 +458,7 @@ func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.R func (app *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { res := app.manager.EndBlock(ctx, req) currentVersion := app.AppVersion() - // For v1 only we upgrade using a agreed upon height known ahead of time + // For v1 only we upgrade using an agreed upon height known ahead of time if currentVersion == v1 { // check that we are at the height before the upgrade if req.Height == app.upgradeHeightV2-1 { @@ -480,6 +480,8 @@ func (app *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo app.SignalKeeper.ResetTally(ctx) } } + res.Timeouts.TimeoutCommit = appconsts.GetTimeoutCommit(currentVersion) + res.Timeouts.TimeoutPropose = appconsts.GetTimeoutPropose(currentVersion) return res } @@ -535,11 +537,15 @@ func (app *App) Info(req abci.RequestInfo) abci.ResponseInfo { if resp.AppVersion > 0 && !app.IsSealed() { app.mountKeysAndInit(resp.AppVersion) } + + resp.Timeouts.TimeoutPropose = appconsts.GetTimeoutPropose(resp.AppVersion) + resp.Timeouts.TimeoutCommit = appconsts.GetTimeoutCommit(resp.AppVersion) + return resp } // InitChain implements the ABCI interface. This method is a wrapper around -// baseapp's InitChain so we can take the app version and setup the multicommit +// baseapp's InitChain so that we can take the app version and setup the multicommit // store. // // Side-effect: calls baseapp.Init() @@ -558,6 +564,8 @@ func (app *App) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain app.SetInitialAppVersionInConsensusParams(ctx, appVersion) app.SetAppVersion(ctx, appVersion) } + res.Timeouts.TimeoutCommit = appconsts.GetTimeoutCommit(appVersion) + res.Timeouts.TimeoutPropose = appconsts.GetTimeoutPropose(appVersion) return res } diff --git a/app/default_overrides.go b/app/default_overrides.go index fbb53f7441..9e0b5dd382 100644 --- a/app/default_overrides.go +++ b/app/default_overrides.go @@ -267,8 +267,8 @@ func DefaultConsensusConfig() *tmcfg.Config { cfg.Mempool.MaxTxsBytes = 39_485_440 cfg.Mempool.Version = "v1" // prioritized mempool - cfg.Consensus.TimeoutPropose = appconsts.TimeoutPropose - cfg.Consensus.TimeoutCommit = appconsts.TimeoutCommit + cfg.Consensus.TimeoutPropose = appconsts.GetTimeoutPropose(appconsts.LatestVersion) + cfg.Consensus.TimeoutCommit = appconsts.GetTimeoutCommit(appconsts.LatestVersion) cfg.Consensus.SkipTimeoutCommit = false cfg.TxIndex.Indexer = "null" diff --git a/app/module/configurator_test.go b/app/module/configurator_test.go index ed504c9ac3..a93713938a 100644 --- a/app/module/configurator_test.go +++ b/app/module/configurator_test.go @@ -37,7 +37,7 @@ func TestConfigurator(t *testing.T) { stateStore.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, db) require.NoError(t, stateStore.LoadLatestVersion()) - keeper := signal.NewKeeper(config.Codec, storeKey, nil, 0) + keeper := signal.NewKeeper(config.Codec, storeKey, nil) require.NotNil(t, keeper) upgradeModule := signal.NewAppModule(keeper) manager, err := module.NewManager([]module.VersionedModule{ diff --git a/app/test/upgrade_test.go b/app/test/upgrade_test.go index ab188e01ac..4c2677c8e0 100644 --- a/app/test/upgrade_test.go +++ b/app/test/upgrade_test.go @@ -37,6 +37,10 @@ func TestAppUpgradeV3(t *testing.T) { if testing.Short() { t.Skip("skipping TestAppUpgradeV3 in short mode") } + + appconsts.OverrideUpgradeHeightDelayStr = "1" + defer func() { appconsts.OverrideUpgradeHeightDelayStr = "" }() + testApp, genesis := SetupTestAppWithUpgradeHeight(t, 3) upgradeFromV1ToV2(t, testApp) @@ -88,6 +92,10 @@ func TestAppUpgradeV3(t *testing.T) { Height: 3, }) require.Equal(t, v2.Version, endBlockResp.ConsensusParamUpdates.Version.AppVersion) + require.Equal(t, appconsts.GetTimeoutCommit(v2.Version), + endBlockResp.Timeouts.TimeoutCommit) + require.Equal(t, appconsts.GetTimeoutPropose(v2.Version), + endBlockResp.Timeouts.TimeoutPropose) testApp.Commit() require.NoError(t, signer.IncrementSequence(testnode.DefaultValidatorAccountName)) @@ -98,18 +106,22 @@ func TestAppUpgradeV3(t *testing.T) { // brace yourselfs, this part may take a while initialHeight := int64(4) - for height := initialHeight; height < initialHeight+appconsts.DefaultUpgradeHeightDelay; height++ { + for height := initialHeight; height < initialHeight+appconsts.UpgradeHeightDelay(v2.Version); height++ { + appVersion := v2.Version _ = testApp.BeginBlock(abci.RequestBeginBlock{ Header: tmproto.Header{ Height: height, - Version: tmversion.Consensus{App: 2}, + Version: tmversion.Consensus{App: appVersion}, }, }) endBlockResp = testApp.EndBlock(abci.RequestEndBlock{ - Height: 3 + appconsts.DefaultUpgradeHeightDelay, + Height: 3 + appconsts.UpgradeHeightDelay(v2.Version), }) + require.Equal(t, appconsts.GetTimeoutCommit(appVersion), endBlockResp.Timeouts.TimeoutCommit) + require.Equal(t, appconsts.GetTimeoutPropose(appVersion), endBlockResp.Timeouts.TimeoutPropose) + _ = testApp.Commit() } require.Equal(t, v3.Version, endBlockResp.ConsensusParamUpdates.Version.AppVersion) @@ -129,7 +141,7 @@ func TestAppUpgradeV3(t *testing.T) { _ = testApp.BeginBlock(abci.RequestBeginBlock{ Header: tmproto.Header{ ChainID: genesis.ChainID, - Height: initialHeight + appconsts.DefaultUpgradeHeightDelay, + Height: initialHeight + appconsts.UpgradeHeightDelay(v3.Version), Version: tmversion.Consensus{App: 3}, }, }) @@ -139,7 +151,10 @@ func TestAppUpgradeV3(t *testing.T) { }) require.Equal(t, abci.CodeTypeOK, deliverTxResp.Code, deliverTxResp.Log) - _ = testApp.EndBlock(abci.RequestEndBlock{}) + respEndBlock := testApp.EndBlock(abci. + RequestEndBlock{Height: initialHeight + appconsts.UpgradeHeightDelay(v3.Version)}) + require.Equal(t, appconsts.GetTimeoutCommit(v3.Version), respEndBlock.Timeouts.TimeoutCommit) + require.Equal(t, appconsts.GetTimeoutPropose(v3.Version), respEndBlock.Timeouts.TimeoutPropose) } // TestAppUpgradeV2 verifies that the all module's params are overridden during an @@ -271,7 +286,10 @@ func SetupTestAppWithUpgradeHeight(t *testing.T, upgradeHeight int64) (*app.App, // assert that the chain starts with version provided in genesis infoResp := testApp.Info(abci.RequestInfo{}) - require.EqualValues(t, app.DefaultInitialConsensusParams().Version.AppVersion, infoResp.AppVersion) + appVersion := app.DefaultInitialConsensusParams().Version.AppVersion + require.EqualValues(t, appVersion, infoResp.AppVersion) + require.EqualValues(t, appconsts.GetTimeoutCommit(appVersion), infoResp.Timeouts.TimeoutCommit) + require.EqualValues(t, appconsts.GetTimeoutPropose(appVersion), infoResp.Timeouts.TimeoutPropose) supportedVersions := []uint64{v1.Version, v2.Version, v3.Version} require.Equal(t, supportedVersions, testApp.SupportedVersions()) @@ -286,7 +304,11 @@ func upgradeFromV1ToV2(t *testing.T, testApp *app.App) { Height: 2, Version: tmversion.Consensus{App: 1}, }}) - testApp.EndBlock(abci.RequestEndBlock{Height: 2}) + endBlockResp := testApp.EndBlock(abci.RequestEndBlock{Height: 2}) + require.Equal(t, appconsts.GetTimeoutCommit(v1.Version), + endBlockResp.Timeouts.TimeoutCommit) + require.Equal(t, appconsts.GetTimeoutPropose(v1.Version), + endBlockResp.Timeouts.TimeoutPropose) testApp.Commit() require.EqualValues(t, 2, testApp.AppVersion()) } diff --git a/go.mod b/go.mod index 5c9de33eb4..7ad4054fc1 100644 --- a/go.mod +++ b/go.mod @@ -260,5 +260,5 @@ replace ( github.com/cosmos/ledger-cosmos-go => github.com/cosmos/ledger-cosmos-go v0.12.4 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tendermint/tendermint => github.com/celestiaorg/celestia-core v1.42.0-tm-v0.34.35 + github.com/tendermint/tendermint => github.com/celestiaorg/celestia-core v1.43.0-tm-v0.34.35 ) diff --git a/go.sum b/go.sum index f5df8c2707..22fd80bf43 100644 --- a/go.sum +++ b/go.sum @@ -317,8 +317,8 @@ github.com/celestiaorg/bittwister v0.0.0-20231213180407-65cdbaf5b8c7 h1:nxplQi8w github.com/celestiaorg/bittwister v0.0.0-20231213180407-65cdbaf5b8c7/go.mod h1:1EF5MfOxVf0WC51Gb7pJ6bcZxnXKNAf9pqWtjgPBAYc= github.com/celestiaorg/blobstream-contracts/v3 v3.1.0 h1:h1Y4V3EMQ2mFmNtWt2sIhZIuyASInj1a9ExI8xOsTOw= github.com/celestiaorg/blobstream-contracts/v3 v3.1.0/go.mod h1:x4DKyfKOSv1ZJM9NwV+Pw01kH2CD7N5zTFclXIVJ6GQ= -github.com/celestiaorg/celestia-core v1.42.0-tm-v0.34.35 h1:bWy5XOgeuuSLe0Lc/htL9/QLEURBjA1JTvEko6bEBhg= -github.com/celestiaorg/celestia-core v1.42.0-tm-v0.34.35/go.mod h1:/fK0n3ps09t5uErBQe1QZbrE81L81MNUzWpFyWQLDT0= +github.com/celestiaorg/celestia-core v1.43.0-tm-v0.34.35 h1:L4GTm+JUXhB0a/nGPMq6jEqqe6THuYSQ8m2kUCtZYqw= +github.com/celestiaorg/celestia-core v1.43.0-tm-v0.34.35/go.mod h1:bFr0lAGwaJ0mOHSBmib5/ca5pbBf1yKWGPs93Td0HPw= github.com/celestiaorg/cosmos-sdk v1.25.0-sdk-v0.46.16 h1:f+fTe7GGk0/qgdzyqB8kk8EcDf9d6MC22khBTQiDXsU= github.com/celestiaorg/cosmos-sdk v1.25.0-sdk-v0.46.16/go.mod h1:07Z8HJqS8Rw4XlZ+ok3D3NM/X/in8mvcGLvl0Zb5wrA= github.com/celestiaorg/go-square v1.1.1 h1:Cy3p8WVspVcyOqHM8BWFuuYPwMitO1pYGe+ImILFZRA= diff --git a/local_devnet/docker-compose.yml b/local_devnet/docker-compose.yml index 15c0a38704..1cf768d53d 100644 --- a/local_devnet/docker-compose.yml +++ b/local_devnet/docker-compose.yml @@ -6,6 +6,7 @@ services: container_name: core0 build: context: .. + dockerfile: ./docker/Dockerfile expose: - "26660" # for prometheus ports: @@ -31,6 +32,7 @@ services: container_name: core1 build: context: .. + dockerfile: ./docker/Dockerfile expose: - "26660" # for prometheus depends_on: @@ -59,6 +61,7 @@ services: container_name: core2 build: context: .. + dockerfile: ./docker/Dockerfile expose: - "26660" # for prometheus depends_on: @@ -87,6 +90,7 @@ services: container_name: core3 build: context: .. + dockerfile: ./docker/Dockerfile expose: - "26660" # for prometheus depends_on: diff --git a/pkg/appconsts/consensus_consts.go b/pkg/appconsts/consensus_consts.go index c26e4078eb..43aa335f93 100644 --- a/pkg/appconsts/consensus_consts.go +++ b/pkg/appconsts/consensus_consts.go @@ -3,8 +3,6 @@ package appconsts import "time" const ( - TimeoutPropose = time.Second * 10 - TimeoutCommit = time.Second * 11 // GoalBlockTime is the target time interval between blocks. Since the block // interval isn't enforced at consensus, the real block interval isn't // guaranteed to exactly match GoalBlockTime. GoalBlockTime is currently targeted diff --git a/pkg/appconsts/global_consts.go b/pkg/appconsts/global_consts.go index ca73aa8fee..ce6f7d71ee 100644 --- a/pkg/appconsts/global_consts.go +++ b/pkg/appconsts/global_consts.go @@ -1,8 +1,6 @@ package appconsts import ( - "strconv" - "github.com/celestiaorg/go-square/v2/share" "github.com/celestiaorg/rsmt2d" "github.com/tendermint/tendermint/pkg/consts" @@ -26,11 +24,6 @@ const ( // BondDenom defines the native staking denomination BondDenom = "utia" - - // DefaultUpgradeHeightDelay is the number of blocks after a quorum has been - // reached that the chain should upgrade to the new version. Assuming a block - // interval of 12 seconds, this is 7 days. - DefaultUpgradeHeightDelay = int64(7 * 24 * 60 * 60 / 12) // 7 days * 24 hours * 60 minutes * 60 seconds / 12 seconds per block = 50,400 blocks. ) var ( @@ -51,18 +44,6 @@ var ( SupportedShareVersions = share.SupportedShareVersions ) -// UpgradeHeightDelay returns the delay in blocks after a quorum has been reached that the chain should upgrade to the new version. -func UpgradeHeightDelay() int64 { - if OverrideUpgradeHeightDelayStr != "" { - parsedValue, err := strconv.ParseInt(OverrideUpgradeHeightDelayStr, 10, 64) - if err != nil { - panic("Invalid OverrideUpgradeHeightDelayStr value") - } - return parsedValue - } - return DefaultUpgradeHeightDelay -} - // HashLength returns the length of a hash in bytes. func HashLength() int { return hashLength diff --git a/pkg/appconsts/v1/app_consts.go b/pkg/appconsts/v1/app_consts.go index 72b040f819..873d3ec18a 100644 --- a/pkg/appconsts/v1/app_consts.go +++ b/pkg/appconsts/v1/app_consts.go @@ -1,7 +1,15 @@ package v1 +import "time" + const ( Version uint64 = 1 SquareSizeUpperBound int = 128 SubtreeRootThreshold int = 64 + TimeoutPropose = time.Second * 10 + TimeoutCommit = time.Second * 11 + // UpgradeHeightDelay is the number of blocks after a quorum has been + // reached that the chain should upgrade to the new version. Assuming a block + // interval of 12 seconds, this is 7 days. + UpgradeHeightDelay = int64(7 * 24 * 60 * 60 / 12) // 7 days * 24 hours * 60 minutes * 60 seconds / 12 seconds per block = 50,400 blocks. ) diff --git a/pkg/appconsts/v2/app_consts.go b/pkg/appconsts/v2/app_consts.go index d5829e84c5..d02a97079b 100644 --- a/pkg/appconsts/v2/app_consts.go +++ b/pkg/appconsts/v2/app_consts.go @@ -1,7 +1,15 @@ package v2 +import "time" + const ( Version uint64 = 2 SquareSizeUpperBound int = 128 SubtreeRootThreshold int = 64 + TimeoutPropose = time.Second * 10 + TimeoutCommit = time.Second * 11 + // UpgradeHeightDelay is the number of blocks after a quorum has been + // reached that the chain should upgrade to the new version. Assuming a block + // interval of 12 seconds, this is 7 days. + UpgradeHeightDelay = int64(7 * 24 * 60 * 60 / 12) // 7 days * 24 hours * 60 minutes * 60 seconds / 12 seconds per block = 50,400 blocks. ) diff --git a/pkg/appconsts/v3/app_consts.go b/pkg/appconsts/v3/app_consts.go index 4b65941de1..3f9279518d 100644 --- a/pkg/appconsts/v3/app_consts.go +++ b/pkg/appconsts/v3/app_consts.go @@ -1,5 +1,7 @@ package v3 +import "time" + const ( Version uint64 = 3 SquareSizeUpperBound int = 128 @@ -7,4 +9,10 @@ const ( TxSizeCostPerByte uint64 = 10 GasPerBlobByte uint32 = 8 MaxTxSize int = 2097152 // 2 MiB in bytes + TimeoutPropose = time.Millisecond * 3500 + TimeoutCommit = time.Millisecond * 4200 + // UpgradeHeightDelay is the number of blocks after a quorum has been + // reached that the chain should upgrade to the new version. Assuming a block + // interval of 12 seconds, this is 7 days. + UpgradeHeightDelay = int64(7 * 24 * 60 * 60 / 6) // 7 days * 24 hours * 60 minutes * 60 seconds / 6 seconds per block = 100,800 blocks. ) diff --git a/pkg/appconsts/versioned_consts.go b/pkg/appconsts/versioned_consts.go index 1eb40deb83..2455e87791 100644 --- a/pkg/appconsts/versioned_consts.go +++ b/pkg/appconsts/versioned_consts.go @@ -2,7 +2,10 @@ package appconsts import ( "strconv" + "time" + v1 "github.com/celestiaorg/celestia-app/v3/pkg/appconsts/v1" + v2 "github.com/celestiaorg/celestia-app/v3/pkg/appconsts/v2" v3 "github.com/celestiaorg/celestia-app/v3/pkg/appconsts/v3" ) @@ -52,3 +55,45 @@ var ( DefaultTxSizeCostPerByte = TxSizeCostPerByte(LatestVersion) DefaultGasPerBlobByte = GasPerBlobByte(LatestVersion) ) + +func GetTimeoutPropose(v uint64) time.Duration { + switch v { + case v1.Version: + return v1.TimeoutPropose + case v2.Version: + return v2.TimeoutPropose + default: + return v3.TimeoutPropose + } +} + +func GetTimeoutCommit(v uint64) time.Duration { + switch v { + case v1.Version: + return v1.TimeoutCommit + case v2.Version: + return v2.TimeoutCommit + default: + return v3.TimeoutCommit + } +} + +// UpgradeHeightDelay returns the delay in blocks after a quorum has been reached that the chain should upgrade to the new version. +func UpgradeHeightDelay(v uint64) int64 { + if OverrideUpgradeHeightDelayStr != "" { + parsedValue, err := strconv.ParseInt(OverrideUpgradeHeightDelayStr, 10, 64) + if err != nil { + panic("Invalid OverrideUpgradeHeightDelayStr value") + } + return parsedValue + } + switch v { + case v1.Version: + return v1.UpgradeHeightDelay + case v2.Version: + return v2.UpgradeHeightDelay + default: + return v3.UpgradeHeightDelay + + } +} diff --git a/test/e2e/benchmark/benchmark.go b/test/e2e/benchmark/benchmark.go index bc4503d61d..5af7b8539e 100644 --- a/test/e2e/benchmark/benchmark.go +++ b/test/e2e/benchmark/benchmark.go @@ -22,6 +22,8 @@ type BenchmarkTest struct { manifest *Manifest } +// NewBenchmarkTest wraps around testnet.New to create a new benchmark test. +// It may modify genesis consensus parameters based on manifest. func NewBenchmarkTest(name string, manifest *Manifest) (*BenchmarkTest, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -52,7 +54,7 @@ func NewBenchmarkTest(name string, manifest *Manifest) (*BenchmarkTest, error) { } // SetupNodes creates genesis nodes and tx clients based on the manifest. -// There will be manifest.Validators validators and manifest.TxClients tx clients. +// There will be manifest.Validators many validators and manifest.TxClients many tx clients. // Each tx client connects to one validator. If TxClients are fewer than Validators, some validators will not have a tx client. func (b *BenchmarkTest) SetupNodes() error { ctx := context.Background() diff --git a/test/e2e/benchmark/manifest.go b/test/e2e/benchmark/manifest.go index 64b319fcc8..b212ff85c4 100644 --- a/test/e2e/benchmark/manifest.go +++ b/test/e2e/benchmark/manifest.go @@ -80,6 +80,8 @@ type Manifest struct { GovMaxSquareSize int64 DisableBBR bool + + GenesisAppVersion uint64 } func (m *Manifest) GetGenesisModifiers() []genesis.Modifier { @@ -88,6 +90,7 @@ func (m *Manifest) GetGenesisModifiers() []genesis.Modifier { blobParams := blobtypes.DefaultParams() blobParams.GovMaxSquareSize = uint64(m.GovMaxSquareSize) + modifiers = append(modifiers, genesis.SetBlobParams(ecfg.Codec, blobParams)) return modifiers @@ -96,6 +99,7 @@ func (m *Manifest) GetGenesisModifiers() []genesis.Modifier { func (m *Manifest) GetConsensusParams() *tmproto.ConsensusParams { cparams := app.DefaultConsensusParams() cparams.Block.MaxBytes = m.MaxBlockBytes + cparams.Version.AppVersion = m.GenesisAppVersion return cparams } diff --git a/test/e2e/major_upgrade_v3.go b/test/e2e/major_upgrade_v3.go index f82fae2804..35cb79b045 100644 --- a/test/e2e/major_upgrade_v3.go +++ b/test/e2e/major_upgrade_v3.go @@ -7,16 +7,18 @@ import ( "time" "github.com/celestiaorg/celestia-app/v3/app" + "github.com/celestiaorg/celestia-app/v3/pkg/appconsts" v2 "github.com/celestiaorg/celestia-app/v3/pkg/appconsts/v2" v3 "github.com/celestiaorg/celestia-app/v3/pkg/appconsts/v3" "github.com/celestiaorg/celestia-app/v3/test/e2e/testnet" "github.com/celestiaorg/knuu/pkg/knuu" + tmtypes "github.com/tendermint/tendermint/types" ) func MajorUpgradeToV3(logger *log.Logger) error { testName := "MajorUpgradeToV3" numNodes := 4 - upgradeHeightV3 := int64(10) + upgradeHeightV3 := int64(40) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -37,12 +39,8 @@ func MajorUpgradeToV3(logger *log.Logger) error { defer testNet.Cleanup(ctx) - // HACKHACK: use a version of celestia-app built from a commit on this PR. - // This can be removed after the PR is merged to main and we override the - // upgrade height delay to one block in a new Docker image. - version := "1a20c01" - - logger.Println("Running major upgrade to v3 test", "version", version) + latestVersion, err := testnet.GetLatestVersion() + testnet.NoError("failed to get latest version", err) consensusParams := app.DefaultConsensusParams() consensusParams.Version.AppVersion = v2.Version // Start the test on v2 @@ -51,13 +49,13 @@ func MajorUpgradeToV3(logger *log.Logger) error { preloader, err := testNet.NewPreloader() testnet.NoError("failed to create preloader", err) - err = preloader.AddImage(ctx, testnet.DockerImageName(version)) + err = preloader.AddImage(ctx, testnet.DockerImageName(latestVersion)) testnet.NoError("failed to add image", err) defer func() { _ = preloader.EmptyImages(ctx) }() logger.Println("Creating genesis nodes") for i := 0; i < numNodes; i++ { - err := testNet.CreateGenesisNode(ctx, version, 10000000, 0, testnet.DefaultResources, true) + err := testNet.CreateGenesisNode(ctx, latestVersion, 10000000, 0, testnet.DefaultResources, true) testnet.NoError("failed to create genesis node", err) } @@ -68,7 +66,7 @@ func MajorUpgradeToV3(logger *log.Logger) error { upgradeHeightV3: v3.Version, } - err = testNet.CreateTxClient(ctx, "txsim", version, 1, "100-2000", 100, testnet.DefaultResources, endpoints[0], upgradeSchedule) + err = testNet.CreateTxClient(ctx, "txsim", latestVersion, 1, "100-2000", 100, testnet.DefaultResources, endpoints[0], upgradeSchedule) testnet.NoError("failed to create tx client", err) logger.Println("Setting up testnet") @@ -76,16 +74,18 @@ func MajorUpgradeToV3(logger *log.Logger) error { logger.Println("Starting testnet") testnet.NoError("Failed to start testnet", testNet.Start(ctx)) - timer := time.NewTimer(10 * time.Minute) + timer := time.NewTimer(20 * time.Minute) defer timer.Stop() ticker := time.NewTicker(3 * time.Second) defer ticker.Stop() logger.Println("waiting for upgrade") + + // wait for the upgrade to complete + var upgradedHeight int64 for _, node := range testNet.Nodes() { client, err := node.Client() testnet.NoError("failed to get client", err) - upgradeComplete := false lastHeight := int64(0) for !upgradeComplete { @@ -97,6 +97,9 @@ func MajorUpgradeToV3(logger *log.Logger) error { testnet.NoError("failed to get header", err) if resp.Header.Version.App == v3.Version { upgradeComplete = true + if upgradedHeight == 0 { + upgradedHeight = resp.Header.Height + } } logger.Printf("height %v", resp.Header.Height) lastHeight = resp.Header.Height @@ -104,5 +107,84 @@ func MajorUpgradeToV3(logger *log.Logger) error { } } + // check if the timeouts are set correctly + rpcNode := testNet.Nodes()[0] + client, err := rpcNode.Client() + testnet.NoError("failed to get client", err) + + startHeight := upgradeHeightV3 - 5 + endHeight := upgradedHeight + 5 + + type versionDuration struct { + dur time.Duration + block *tmtypes.Block + } + + blockSummaries := make([]versionDuration, 0, endHeight-startHeight) + var prevBlockTime time.Time + + for h := startHeight; h < endHeight; h++ { + resp, err := client.Block(ctx, &h) + testnet.NoError("failed to get header", err) + blockTime := resp.Block.Time + + if h == startHeight { + if resp.Block.Version.App != v2.Version { + return fmt.Errorf("expected start height %v was app version 2", startHeight) + } + prevBlockTime = blockTime + continue + } + + blockDur := blockTime.Sub(prevBlockTime) + prevBlockTime = blockTime + blockSummaries = append(blockSummaries, versionDuration{dur: blockDur, block: resp.Block}) + } + + preciseUpgradeHeight := 0 + multipleRounds := 0 + for _, b := range blockSummaries { + + // check for the precise upgrade height and skip, as the block time + // won't match due to the off by 1 nature of the block time. + if b.block.Version.App == v3.Version && preciseUpgradeHeight == 0 { + preciseUpgradeHeight = int(b.block.Height) + continue + } + + // don't test heights with multiple rounds as the times are off and fail + // later if there are too many + if b.block.LastCommit.Round > 0 { + multipleRounds++ + continue + } + + if b.dur < appconsts.GetTimeoutCommit(b.block.Version.App) { + return fmt.Errorf( + "block was too fast for corresponding version: version %v duration %v upgrade height %v height %v", + b.block.Version.App, + b.dur, + preciseUpgradeHeight, + b.block.Height, + ) + } + + // check if the time decreased for v3 + if b.block.Version.App == v3.Version && b.dur > appconsts.GetTimeoutCommit(b.block.Version.App)+5 { + return fmt.Errorf( + "block was too slow for corresponding version: version %v duration %v upgrade height %v height %v", + b.block.Version.App, + b.dur, + preciseUpgradeHeight, + b.block.Height, + ) + } + + } + + if multipleRounds > 2 { + return fmt.Errorf("too many multiple rounds for test to be reliable: %d", multipleRounds) + } + return nil } diff --git a/test/e2e/simple.go b/test/e2e/simple.go index 2a25c46e2b..8dab0278eb 100644 --- a/test/e2e/simple.go +++ b/test/e2e/simple.go @@ -12,7 +12,7 @@ import ( "github.com/celestiaorg/knuu/pkg/knuu" ) -// This test runs a simple testnet with 4 validators. It submits both MsgPayForBlobs +// E2ESimple runs a simple testnet with 4 validators. It submits both MsgPayForBlobs // and MsgSends over 30 seconds and then asserts that at least 10 transactions were // committed. func E2ESimple(logger *log.Logger) error { diff --git a/test/e2e/testnet/testnet.go b/test/e2e/testnet/testnet.go index 5b73daf596..7cc74fb011 100644 --- a/test/e2e/testnet/testnet.go +++ b/test/e2e/testnet/testnet.go @@ -376,6 +376,7 @@ func (t *Testnet) WaitToSync(ctx context.Context) error { genesisNodes = append(genesisNodes, node) } } + for _, node := range genesisNodes { log.Info().Str("name", node.Name).Msg( "waiting for node to sync") @@ -410,18 +411,18 @@ func (t *Testnet) WaitToSync(ctx context.Context) error { // For that, use WaitToSync. func (t *Testnet) StartNodes(ctx context.Context) error { genesisNodes := make([]*Node, 0) + // identify genesis nodes for _, node := range t.nodes { if node.StartHeight == 0 { genesisNodes = append(genesisNodes, node) } - } - // start genesis nodes asynchronously - for _, node := range genesisNodes { + err := node.StartAsync(ctx) if err != nil { return fmt.Errorf("node %s failed to start: %w", node.Name, err) } } + log.Info().Msg("create endpoint proxies for genesis nodes") // wait for instances to be running for _, node := range genesisNodes { diff --git a/test/e2e/testnet/txsimNode.go b/test/e2e/testnet/txsimNode.go index bfa21da875..c63062598b 100644 --- a/test/e2e/testnet/txsimNode.go +++ b/test/e2e/testnet/txsimNode.go @@ -78,10 +78,13 @@ func CreateTxClient( fmt.Sprintf("--blob %d", blobSequences), fmt.Sprintf("--blob-amounts %d", blobsPerSeq), fmt.Sprintf("--blob-sizes %s", blobRange), - fmt.Sprintf("--upgrade-schedule %s", stringifyUpgradeSchedule(upgradeSchedule)), fmt.Sprintf("--blob-share-version %d", share.ShareVersionZero), } + if len(upgradeSchedule) > 0 { + args = append(args, fmt.Sprintf("--upgrade-schedule %s", stringifyUpgradeSchedule(upgradeSchedule))) + } + if err := instance.Build().SetArgs(args...); err != nil { return nil, err } diff --git a/test/txsim/run_test.go b/test/txsim/run_test.go index 4a922f15a1..d4cbdf22ba 100644 --- a/test/txsim/run_test.go +++ b/test/txsim/run_test.go @@ -170,6 +170,8 @@ func TestTxSimUpgrade(t *testing.T) { WithFundedAccounts("txsim-master") cctx, _, grpcAddr := testnode.NewNetwork(t, cfg) + require.NoError(t, cctx.WaitForNextBlock()) + // updrade to v3 at height 20 sequences := []txsim.Sequence{ txsim.NewUpgradeSequence(v3.Version, 20), diff --git a/test/util/genesis/genesis.go b/test/util/genesis/genesis.go index 83eab54250..f0fadf0b59 100644 --- a/test/util/genesis/genesis.go +++ b/test/util/genesis/genesis.go @@ -73,7 +73,7 @@ func NewDefaultGenesis() *Genesis { return g } -// WithModifier adds a genesis modifier to the genesis. +// WithModifiers adds a genesis modifier to the genesis. func (g *Genesis) WithModifiers(ops ...Modifier) *Genesis { g.genOps = append(g.genOps, ops...) return g @@ -97,7 +97,7 @@ func (g *Genesis) WithGenesisTime(genesisTime time.Time) *Genesis { return g } -// WithAccounts adds the given validators to the genesis. +// WithValidators adds the given validators to the genesis. func (g *Genesis) WithValidators(vals ...Validator) *Genesis { for _, val := range vals { err := g.NewValidator(val) @@ -180,7 +180,7 @@ func (g *Genesis) AddValidator(val Validator) error { return nil } -// Creates a new validator account and adds it to the genesis. +// NewValidator creates a new validator account and adds it to the genesis. func (g *Genesis) NewValidator(val Validator) error { // Add the validator's genesis account if err := g.NewAccount(val.KeyringAccount); err != nil { diff --git a/test/util/testnode/app_wrapper.go b/test/util/testnode/app_wrapper.go new file mode 100644 index 0000000000..e885f4c4ed --- /dev/null +++ b/test/util/testnode/app_wrapper.go @@ -0,0 +1,21 @@ +package testnode + +import ( + "time" + + "github.com/celestiaorg/celestia-app/v3/app" + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +// wrapEndBlocker overrides the app's endblocker to set the timeout commit to a +// different value for testnode. +func wrapEndBlocker(app *app.App, timeoutCommit time.Duration) func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { + endBlocker := func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { + resp := app.EndBlocker(ctx, req) + resp.Timeouts.TimeoutCommit = timeoutCommit + return resp + } + + return endBlocker +} diff --git a/test/util/testnode/config.go b/test/util/testnode/config.go index 7062735a4c..0ec6e7920e 100644 --- a/test/util/testnode/config.go +++ b/test/util/testnode/config.go @@ -174,7 +174,7 @@ func DefaultTendermintConfig() *tmconfig.Config { func DefaultAppCreator() srvtypes.AppCreator { return func(_ log.Logger, _ tmdb.DB, _ io.Writer, _ srvtypes.AppOptions) srvtypes.Application { encodingConfig := encoding.MakeConfig(app.ModuleEncodingRegisters...) - return app.New( + app := app.New( log.NewNopLogger(), tmdb.NewMemDB(), nil, // trace store @@ -184,13 +184,15 @@ func DefaultAppCreator() srvtypes.AppCreator { simapp.EmptyAppOptions{}, baseapp.SetMinGasPrices(fmt.Sprintf("%v%v", appconsts.DefaultMinGasPrice, app.BondDenom)), ) + app.SetEndBlocker(wrapEndBlocker(app, time.Millisecond*30)) + return app } } func CustomAppCreator(minGasPrice string) srvtypes.AppCreator { return func(_ log.Logger, _ tmdb.DB, _ io.Writer, _ srvtypes.AppOptions) srvtypes.Application { encodingConfig := encoding.MakeConfig(app.ModuleEncodingRegisters...) - return app.New( + app := app.New( log.NewNopLogger(), tmdb.NewMemDB(), nil, // trace store @@ -200,6 +202,8 @@ func CustomAppCreator(minGasPrice string) srvtypes.AppCreator { simapp.EmptyAppOptions{}, baseapp.SetMinGasPrices(minGasPrice), ) + app.SetEndBlocker(wrapEndBlocker(app, time.Millisecond*0)) + return app } } diff --git a/test/util/testnode/network.go b/test/util/testnode/network.go index 4c0421c895..eab7384c91 100644 --- a/test/util/testnode/network.go +++ b/test/util/testnode/network.go @@ -33,6 +33,7 @@ func NewNetwork(t testing.TB, config *Config) (cctx Context, rpcAddr, grpcAddr s }) cctx = NewContext(ctx, config.Genesis.Keyring(), config.TmConfig, config.Genesis.ChainID, config.AppConfig.API.Address) + cctx.tmNode = tmNode cctx, stopNode, err := StartNode(tmNode, cctx) require.NoError(t, err) diff --git a/test/util/testnode/node_interaction_api.go b/test/util/testnode/node_interaction_api.go index 162840c819..a5c175e86d 100644 --- a/test/util/testnode/node_interaction_api.go +++ b/test/util/testnode/node_interaction_api.go @@ -22,6 +22,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" tmconfig "github.com/tendermint/tendermint/config" tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/node" rpctypes "github.com/tendermint/tendermint/rpc/core/types" ) @@ -33,6 +34,7 @@ type Context struct { goContext context.Context client.Context apiAddress string + tmNode *node.Node } func NewContext(goContext context.Context, keyring keyring.Keyring, tmConfig *tmconfig.Config, chainID, apiAddress string) Context { diff --git a/x/blobstream/integration_test.go b/x/blobstream/integration_test.go index a8f19bf4b6..7bb03a49ee 100644 --- a/x/blobstream/integration_test.go +++ b/x/blobstream/integration_test.go @@ -46,6 +46,8 @@ func (s *BlobstreamIntegrationSuite) SetupSuite() { cctx, _, _ := testnode.NewNetwork(t, cfg) s.ecfg = encoding.MakeConfig(app.ModuleEncodingRegisters...) s.cctx = cctx + + require.NoError(t, s.cctx.WaitForBlocks(10)) } func (s *BlobstreamIntegrationSuite) TestBlobstream() { diff --git a/x/signal/integration_test.go b/x/signal/integration_test.go index 23b8158dd2..c3dd2419dd 100644 --- a/x/signal/integration_test.go +++ b/x/signal/integration_test.go @@ -77,7 +77,7 @@ func TestUpgradeIntegration(t *testing.T) { require.False(t, shouldUpgrade) require.EqualValues(t, 0, version) - ctx = ctx.WithBlockHeight(ctx.BlockHeight() + appconsts.DefaultUpgradeHeightDelay) + ctx = ctx.WithBlockHeight(ctx.BlockHeight() + appconsts.UpgradeHeightDelay(version)) shouldUpgrade, version = app.SignalKeeper.ShouldUpgrade(ctx) require.True(t, shouldUpgrade) diff --git a/x/signal/keeper.go b/x/signal/keeper.go index 0a23d93119..3ee13a9708 100644 --- a/x/signal/keeper.go +++ b/x/signal/keeper.go @@ -5,6 +5,7 @@ import ( "encoding/binary" sdkmath "cosmossdk.io/math" + "github.com/celestiaorg/celestia-app/v3/pkg/appconsts" "github.com/celestiaorg/celestia-app/v3/x/signal/types" "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" @@ -41,10 +42,6 @@ type Keeper struct { // stakingKeeper is used to fetch validators to calculate the total power // signalled to a version. stakingKeeper StakingKeeper - - // upgradeHeightDelayBlocks is the number of blocks after a quorum has been - // reached that the chain should upgrade to the new version - upgradeHeightDelayBlocks int64 } // NewKeeper returns a signal keeper. @@ -52,13 +49,11 @@ func NewKeeper( binaryCodec codec.BinaryCodec, storeKey storetypes.StoreKey, stakingKeeper StakingKeeper, - upgradeHeightDelayBlocks int64, ) Keeper { return Keeper{ - binaryCodec: binaryCodec, - storeKey: storeKey, - stakingKeeper: stakingKeeper, - upgradeHeightDelayBlocks: upgradeHeightDelayBlocks, + binaryCodec: binaryCodec, + storeKey: storeKey, + stakingKeeper: stakingKeeper, } } @@ -109,7 +104,7 @@ func (k *Keeper) TryUpgrade(ctx context.Context, _ *types.MsgTryUpgrade) (*types } upgrade := types.Upgrade{ AppVersion: version, - UpgradeHeight: sdkCtx.BlockHeader().Height + k.upgradeHeightDelayBlocks, + UpgradeHeight: sdkCtx.BlockHeader().Height + appconsts.UpgradeHeightDelay(version), } k.setUpgrade(sdkCtx, upgrade) } diff --git a/x/signal/keeper_test.go b/x/signal/keeper_test.go index 71627a8417..f79d1c3884 100644 --- a/x/signal/keeper_test.go +++ b/x/signal/keeper_test.go @@ -69,7 +69,7 @@ func TestGetVotingPowerThreshold(t *testing.T) { t.Run(tc.name, func(t *testing.T) { config := encoding.MakeConfig(app.ModuleEncodingRegisters...) stakingKeeper := newMockStakingKeeper(tc.validators) - k := signal.NewKeeper(config.Codec, nil, stakingKeeper, appconsts.DefaultUpgradeHeightDelay) + k := signal.NewKeeper(config.Codec, nil, stakingKeeper) got := k.GetVotingPowerThreshold(sdk.Context{}) assert.Equal(t, tc.want, got, fmt.Sprintf("want %v, got %v", tc.want.String(), got.String())) }) @@ -183,7 +183,7 @@ func TestTallyingLogic(t *testing.T) { require.False(t, shouldUpgrade) // should be false because upgrade height hasn't been reached. require.Equal(t, uint64(0), version) - ctx = ctx.WithBlockHeight(ctx.BlockHeight() + appconsts.DefaultUpgradeHeightDelay) + ctx = ctx.WithBlockHeight(ctx.BlockHeight() + appconsts.UpgradeHeightDelay(version)) shouldUpgrade, version = upgradeKeeper.ShouldUpgrade(ctx) require.True(t, shouldUpgrade) // should be true because upgrade height has been reached. @@ -426,7 +426,7 @@ func TestGetUpgrade(t *testing.T) { got, err := upgradeKeeper.GetUpgrade(ctx, &types.QueryGetUpgradeRequest{}) require.NoError(t, err) assert.Equal(t, v2.Version, got.Upgrade.AppVersion) - assert.Equal(t, appconsts.DefaultUpgradeHeightDelay, got.Upgrade.UpgradeHeight) + assert.Equal(t, appconsts.UpgradeHeightDelay(v2.Version), got.Upgrade.UpgradeHeight) }) } @@ -452,7 +452,7 @@ func setup(t *testing.T) (signal.Keeper, sdk.Context, *mockStakingKeeper) { ) config := encoding.MakeConfig(app.ModuleEncodingRegisters...) - upgradeKeeper := signal.NewKeeper(config.Codec, signalStore, mockStakingKeeper, appconsts.DefaultUpgradeHeightDelay) + upgradeKeeper := signal.NewKeeper(config.Codec, signalStore, mockStakingKeeper) return upgradeKeeper, mockCtx, mockStakingKeeper }