-
Notifications
You must be signed in to change notification settings - Fork 344
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!: allow for hardcoded upgrade schedules #2583
Changes from 7 commits
53ccf5e
9536fe1
ef7a56f
44ef5fe
01edc6a
203ab86
9d47a20
fc7f857
86c9df2
390112b
f7048a7
c78f7a8
4f8ad61
68a7d44
dccd2b5
d82c2af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,23 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
package app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"fmt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"github.com/celestiaorg/celestia-app/x/upgrade" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
abci "github.com/tendermint/tendermint/abci/types" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
func (app *App) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sdkTx, err := app.txConfig.TxDecoder()(req.Tx) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if err == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if appVersion, ok := upgrade.IsUpgradeMsg(sdkTx.GetMsgs()); ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !IsSupported(appVersion) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
panic(fmt.Sprintf("network has upgraded to version %d which is not supported by this node. Please upgrade and restart", appVersion)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
app.SetProtocolVersion(appVersion) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// TODO: we may want to emit an event for this | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
evan-forbes marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return abci.ResponseDeliverTx{Code: abci.CodeTypeOK} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return app.BaseApp.DeliverTx(req) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since v1 nodes won't be running this, what will they do with this tx? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since we're setting the protocol version here, I think we have to be extra careful to never use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
They will just error and skip over it. In the following block they will panic (not sure if in cometbft or in app) because of the app version difference There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [non-blocking] I think de-indenting and following an exit early strategy makes the code easier to follow and easier to test. Additionally I think it reduces the chances of future changes causing bugs.
Suggested change
Now it's super clear that there are 4 test cases that need to be created.
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ import ( | |
"github.com/celestiaorg/celestia-app/pkg/shares" | ||
"github.com/celestiaorg/celestia-app/pkg/square" | ||
blobtypes "github.com/celestiaorg/celestia-app/x/blob/types" | ||
"github.com/celestiaorg/celestia-app/x/upgrade" | ||
"github.com/cosmos/cosmos-sdk/telemetry" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
abci "github.com/tendermint/tendermint/abci/types" | ||
|
@@ -66,19 +67,42 @@ func (app *App) ProcessProposal(req abci.RequestProcessProposal) (resp abci.Resp | |
|
||
// handle non-blob transactions first | ||
if !isBlobTx { | ||
_, has := hasPFB(sdkTx.GetMsgs()) | ||
msgs := sdkTx.GetMsgs() | ||
|
||
_, has := hasPFB(msgs) | ||
if has { | ||
// A non blob tx has a PFB, which is invalid | ||
logInvalidPropBlock(app.Logger(), req.Header, fmt.Sprintf("tx %d has PFB but is not a blob tx", idx)) | ||
return reject() | ||
} | ||
|
||
if appVersion, ok := upgrade.IsUpgradeMsg(msgs); ok { | ||
if idx != 0 { | ||
logInvalidPropBlock(app.Logger(), req.Header, fmt.Sprintf("upgrade message %d is not the first transaction", idx)) | ||
return reject() | ||
} | ||
|
||
if !IsSupported(appVersion) { | ||
logInvalidPropBlock(app.Logger(), req.Header, fmt.Sprintf("block proposes an unsupported app version %d", appVersion)) | ||
return reject() | ||
} | ||
Comment on lines
+79
to
+88
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a scenario where nodes running v1 that don't know how to parse this msg or have this logic vote for the proposal? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I thought about this. This was why I chose to wrap it as a tx rather than having it unparseable which would then be accepted. As a tx, it would fail the ante handler because there is no signature attached to it. Ideally I can write a test to check it out. |
||
|
||
// app version must always increase | ||
if appVersion <= app.GetBaseApp().AppVersion() { | ||
logInvalidPropBlock(app.Logger(), req.Header, fmt.Sprintf("block proposes an app version %d that is not greater than the current app version %d", appVersion, app.GetBaseApp().AppVersion())) | ||
return reject() | ||
} | ||
evan-forbes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// we don't need to pass this message through the ante handler | ||
continue | ||
} | ||
|
||
// we need to increment the sequence for every transaction so that | ||
// the signature check below is accurate. this error only gets hit | ||
// if the account in question doens't exist. | ||
sdkCtx, err = handler(sdkCtx, sdkTx, false) | ||
if err != nil { | ||
logInvalidPropBlockError(app.Logger(), req.Header, "failure to incrememnt sequence", err) | ||
logInvalidPropBlockError(app.Logger(), req.Header, "failure to increment sequence", err) | ||
return reject() | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,6 @@ import ( | |
"os" | ||
"path/filepath" | ||
|
||
"github.com/celestiaorg/celestia-app/pkg/appconsts" | ||
qgbcmd "github.com/celestiaorg/celestia-app/x/qgb/client" | ||
|
||
"github.com/celestiaorg/celestia-app/app" | ||
|
@@ -211,11 +210,6 @@ func NewAppServer(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts se | |
cache = store.NewCommitKVStoreCacheManager() | ||
} | ||
|
||
skipUpgradeHeights := make(map[int64]bool) | ||
for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) { | ||
skipUpgradeHeights[int64(h)] = true | ||
} | ||
|
||
pruningOpts, err := server.GetPruningOptionsFromFlags(appOpts) | ||
if err != nil { | ||
panic(err) | ||
|
@@ -234,10 +228,10 @@ func NewAppServer(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts se | |
} | ||
|
||
return app.New( | ||
logger, db, traceStore, true, skipUpgradeHeights, | ||
cast.ToString(appOpts.Get(flags.FlagHome)), | ||
logger, db, traceStore, true, | ||
cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)), | ||
encoding.MakeConfig(app.ModuleEncodingRegisters...), // Ideally, we would reuse the one created by NewRootCmd. | ||
nil, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what's your current preferred way to pass this in the future? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess the main question I have from your question is whether we want to allow node operators to be able to modify this in their app.toml config. Either way we will have some hardcoded value that gets ported in the binary. I'm just not sure yet whether that value is a default that can be overrided or a built-in value that can only be changed by switching to a different binary |
||
appOpts, | ||
baseapp.SetPruning(pruningOpts), | ||
baseapp.SetMinGasPrices(cast.ToString(appOpts.Get(server.FlagMinGasPrices))), | ||
|
@@ -249,9 +243,6 @@ func NewAppServer(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts se | |
baseapp.SetTrace(cast.ToBool(appOpts.Get(server.FlagTrace))), | ||
baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents))), | ||
baseapp.SetSnapshot(snapshotStore, snapshottypes.NewSnapshotOptions(cast.ToUint64(appOpts.Get(server.FlagStateSyncSnapshotInterval)), cast.ToUint32(appOpts.Get(server.FlagStateSyncSnapshotKeepRecent)))), | ||
func(b *baseapp.BaseApp) { | ||
b.SetProtocolVersion(appconsts.LatestVersion) | ||
}, | ||
Comment on lines
-252
to
-254
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. now that this is in init, will it still get called after rebooting? in the past we've had bugs where the chain-id was not set after rebooting because its supposed to be set during init There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [proposal for a future PR, no change needed] perhaps we should just make this a stateful value? its a one off benefit as it would only apply to v1, however it would guarantee nodes running v1 will hit an apphash error instead of ignoring txs that they don't know about. We'll probably hit one of those anyway, but this just guarantees it asap. The other benefit being that we never have to think about loading a consensus critical value into the application. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree. This is what later versions of the SDK have. Maybe we can add it in v2 as a migration |
||
) | ||
} | ||
|
||
|
@@ -263,13 +254,13 @@ func createAppAndExport( | |
encCfg.Codec = codec.NewProtoCodec(encCfg.InterfaceRegistry) | ||
var capp *app.App | ||
if height != -1 { | ||
capp = app.New(logger, db, traceStore, false, map[int64]bool{}, "", uint(1), encCfg, appOpts) | ||
capp = app.New(logger, db, traceStore, false, uint(1), encCfg, nil, appOpts) | ||
|
||
if err := capp.LoadHeight(height); err != nil { | ||
return servertypes.ExportedApp{}, err | ||
} | ||
} else { | ||
capp = app.New(logger, db, traceStore, true, map[int64]bool{}, "", uint(1), encCfg, appOpts) | ||
capp = app.New(logger, db, traceStore, true, uint(1), encCfg, nil, appOpts) | ||
} | ||
|
||
return capp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
syntax = "proto3"; | ||
package celestia.upgrade.v1; | ||
|
||
option go_package = "github.com/celestiaorg/celestia-app/x/upgrade"; | ||
|
||
// MsgPayForBlobs pays for the inclusion of a blob in the block. | ||
cmwaters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
message MsgVersionChange { | ||
// the new version to propose the change to | ||
cmwaters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
uint64 version = 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is meant to be done as the first transaction, should we just do this in BeginBlock?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be more complex as we would need to track all the different proposed blocks and match them with the one that eventually gets committed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be easier in finalize block because it can reside as part of the
preBlock
call back function