Skip to content

Conversation

@0xHansLee
Copy link
Contributor

This PR adds support for rolling upgrades via the UpgradeEntrypoint contract. The core implementation is mostly adapted from the signal module in Celestia. Instead of introducing a new module, the logic is integrated into the evmengine module, which is responsible for handling EVM-triggered upgrades. Since our upgrades are initiated from within the EVM and do not require validator quorum, we were able to adopt only the necessary parts of the signal module and implement them within evmengine for simplicity.

Functionally, this is very similar to how we previously supported rolling upgrades using Fork.

As you may know, in Cosmos SDK, a node must not upgrade its binary before the scheduled upgrade height, if the upgrade has already been registered in the upgrade keeper. This constraint prevents validators from upgrading early when the upgrade is pre-scheduled.

To address this, we can defer scheduling upgrade. When the UpgradeEntrypoint contract emits an upgrade event, the upgrade information is temporarily stored in the evmengine's state. The actual scheduling of the upgrade in the upgrade keeper is deferred until the block reaches the specified upgrade height. At that point, during the PreBlock phase, the upgrade is scheduled in upgrade keeper so that it can be applied within that same block.

issue: #149

@0xHansLee 0xHansLee force-pushed the hans/defer-upgrade-scheduling branch from 7562888 to 8cea7d7 Compare June 18, 2025 01:23
@stevemilk
Copy link

Am i able to sync from block 0 to chain tip using only the latest story binary with this feature?

@0xHansLee
Copy link
Contributor Author

Am i able to sync from block 0 to chain tip using only the latest story binary with this feature?

Good question. I tested that it synced well from the genesis, but not til the tip. Will test it and let you know. I will full sync from the genesis, so it might take some time.

@0xHansLee 0xHansLee force-pushed the hans/defer-upgrade-scheduling branch 2 times, most recently from 98d6a20 to 09afa00 Compare June 19, 2025 09:36
@0xHansLee
Copy link
Contributor Author

Removed to use upgrade-info.json when app starts up. Previously, the app just observed the latest upgrade because the file only stores the latest upgrade info. Instead, I changed to apply all store upgrades excepting skip ones to support backward-compatible binary that can replay from genesis.

Note: added to dump this upgrade-info.json after process the SoftwareUpgrade event which is emitted from EVM for the operator to use cosmovisor to change the binary at the exact height.

cc. @limengformal @lucas2brh

@ramtinms ramtinms requested a review from stevemilk July 21, 2025 23:57
@jdubpark
Copy link
Contributor

jdubpark commented Jul 22, 2025

Removed to use upgrade-info.json when app starts up. Previously, the app just observed the latest upgrade because the file only stores the latest upgrade info. Instead, I changed to apply all store upgrades excepting skip ones to support backward-compatible binary that can replay from genesis.

Note: added to dump this upgrade-info.json after process the SoftwareUpgrade event which is emitted from EVM for the operator to use cosmovisor to change the binary at the exact height.

Does Cosmovisor support multiple entries in upgrade-info.json?

@0xHansLee
Copy link
Contributor Author

Does Cosmovisor support multiple entries in upgrade-info.json?

No, they just support the single entry, the latest one.

Copy link
Contributor

@jdubpark jdubpark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the main purposes of Celestia's signal module is to await 4/5 majority signals for the next binary version (signal tx) before upgrading (upgrade tx). Thus, there's no "upgrade height," and nodes await the 4/5 signals. This ensures that the chain upgrades without halting, which happens when quorum on new binary is not met.

Just want to note that deferring the upgrade scheduling (this PR) doesn't achieve that purpose as it sets the upgrade height (from EL). This allows validators to swap the binary before the upgrade height, assuming the new binary is backward-compatible.

(But all current version upgrades have been triggered on EL by Story, so I suppose the above purpose of the original signal module doesn't matter much for some time.)

@0xHansLee
Copy link
Contributor Author

@jdubpark Thanks for the notes. Right. Since we trigger the upgrade from EL, quorum of validators for the upgrade is not needed for Story.

(But all current version upgrades have been triggered on EL by Story, so I suppose the above purpose of the original signal module doesn't matter much for some time.)

I expect we can make our upgrade process be more decentralized by improving our upgrade entry contract on EL.

@0xHansLee 0xHansLee force-pushed the hans/defer-upgrade-scheduling branch from 09afa00 to 6715e6f Compare July 22, 2025 07:13
Copy link

@ramtinms ramtinms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, just to confirm this doesn't have any impact to state sync of older blocks since genesis since we used different way of upgrading the network.

@0xHansLee
Copy link
Contributor Author

Looks good to me, just to confirm this doesn't have any impact to state sync of older blocks since genesis since we used different way of upgrading the network.

It should. But after finding a sync issue in v1.2.1, I have not tested again with the updated branch. I will test again to make sure this works for syncing blocks from the genesis.

@0xHansLee 0xHansLee merged commit 847a369 into main Jul 29, 2025
14 checks passed
@0xHansLee 0xHansLee deleted the hans/defer-upgrade-scheduling branch July 29, 2025 06:34
@github-actions
Copy link

Binary uploaded successfully 🎉

📦 Version Name: 1.3.2-unstable-847a369
📦 Download Source: AWS S3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants