-
Notifications
You must be signed in to change notification settings - Fork 49
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
[Rolling upgrade] Create and deploy contract for synchronizing versions #308
Comments
Posting questions here to close comms loop on a convo I began with @m4ksio
and his responses:
I would imagine we want the ability to update versions in some admin resource in the interest of composability. E.g. the versioning process could conceivably be utilized by a future governance contract where the version is updated on consensus Regarding version representation, thinking I'll represent version by some struct and introduce conditions between version increments that are in line with semver as mentioned above. Current status: Prototyping in progress based on preliminary design docs |
So far, I have a contract interface that I'd like to post here for visibility and feedback. Fundamentally, the approach is to separate state of the contract from the task of administration. All ENs would know the contract address, and only need to concern themselves with maintaining the correct version and updating in time for a version rollover. At least for the time being, version updates could be handled by the Flow Service account or some other administrative account with checks around cooldown block height thresholds to provide ENs with sufficient notice of a coming update. Related events are emitted on updates to the height:table mapping. Here's the interface: /// This contract is used to defined block height and software version boundaries
/// for the software run by Execution Nodes.
pub contract ENVersionBeacon {
pub enum ENVersionUpdateAction: UInt8 {
pub case added
pub case deleted
pub case amended
}
/// Struct representing Execution Node software version
/// along with helper functions
pub struct ENVersion {
/// Compnents defining a semantic version
pub let major: UInt8
pub let minor: UInt8
pub let patch: UInt8
/// Oldest compatitible version with this version
///
/// Defining this can help with logic around updating before a target block is reached
/// Such behavior may be desireable in the event breaking changes are released
/// between versions
pub let oldestCompatibleVersion: ENVersion
init(major: UInt8, minor: UInt8, patch: UInt8, oldestCompatibleVersion: ENVersion)
/// Returns version in Semver format (e.g. v<major>.<minor>.<patch>)
/// as a String
pub fun toString(): String
/* Custom Comparators */
/// Returns true if ENVersion is greater than
/// passed ENVersion and false otherwise
pub fun greaterThan(_ other: ENVersion): Bool
/// Returns true if ENVersion is greater than or
/// equal to passed ENVersion and false otherwise
pub fun greaterThanOrEqualTo(_ other: ENVersion): Bool
/// Returns true if ENVersion is less than
/// passed ENVersion and false otherwise
pub fun lessThan(_ other: ENVersion): Bool
/// Returns true if ENVersion is less than or
/// equal to passed ENVersion and false otherwise
pub fun lessThanOrEqualTo(_ other: ENVersion): Bool
/// Returns true if ENVersion is equal to passed
/// ENVersion and false otherwise
pub fun equalTo(_ other: ENVersion): Bool
}
/// Event emitted any time a new version is added to the version table
pub event ENVersionTableUpdated(height: UInt64, version: ENVersion, action: ENVersionUpdateAction)
/// Event emitted any time the version cooldown period is updated
pub event ENVersionCooldownPeriodUpdated(newVersionCooldownPeriod: UInt64)
/// Canonical storage path for ENVersionKeeper
pub let ENVersionAdminStoragePath: StoragePath
/// Table dictating minimum version - {blockHeight: ENVersion}
access(contract) let versionTable: {UInt64: ENVersion}
/// Number of blocks between height at updating and target height for version rollover
access(contract) let versionCooldownPeriod: UInt64
/// Admin interface that manages the Execution Node versioning
/// maintained in this contract
pub resource interface ENVersionAdmin {
/// Update the minimum version to take effect at the given block height
pub fun addMinimumVersion(targetblockHeight: UInt64, version: ENVersion) {
pre {
targetblockHeight > getCurrentBlock().height + ENVersionAdmin.versionCooldownPeriod: "Target block height occurs too soon to update EN version"
}
emit EMVersionTableUpdated(height: targetblockHeight, version: version, action: ENVersionAction.added)
}
/// Deletes the entry in versionTable at the passed block height
/// Could be helpful in event of rollback
pub fun deleteBlockTargetVersionMapping(blockHeight: UInt64, version: ENVersion) {
pre {
targetblockHeight > getCurrentBlock().height + ENVersionAdmin.versionCooldownPeriod: "Target block height occurs too soon to update EN version"
}
emit EMVersionTableUpdated(height: targetblockHeight, version: version, action: ENVersionAction.deleted)
}
pub fun updateVersionCooldownPeriod(cooldownInBlocks: UInt64) {
emit ENVersionCooldownPeriodUpdated(newVersionCooldownPeriod: cooldownInBlocks)
}
}
/// Returns the current cooldown period within which ENs
/// can be assured version will not change
pub fun getVersionCooldownPeriod(): UInt64
/// Function that returns that minimum current version based on the current
/// block height and version table mapping
pub fun getCurrentMinimumENVersion(): ENVersion
/// Returns a copy of the full historical versionTable
pub fun getVersionTable(): {ENVersion: UInt64}
/// Checks whether given version was compatible at the given block height
pub fun isCompatibleENVersion(blockHeight: UInt64, version: ENVersion): Bool
/// Returns
pub fun getNextVersion
init() {
self.versionTable = {}
self.ENVersionAdminStoragePath = /storage/ENVersionAdmin
self.account.save(<-create ENVersionAdmin(), to: self.ENVersionAdminStoragePath)
}
} |
@sisyphusSmiling Overall looks good to me. Some nitpick / Feedback -
|
Thank you both for the feedback. A couple clarifying points.
|
The Looks good otherwise. |
Few comments & questions
|
Re: @janezpodhostnik is there documentation I can refer to regarding version naming conventions, particularly relating to pre-releases? Re: @bluesign
|
Posting an update on progress here: I've finished working on the contract and scripts and have been working on JavaScript tests as I'm not familiar with Go. Due to some dependency issues in the Planning on having these issues sorted and a PR up on Monday or Tuesday of next week |
Made some progress a debug call yesterday to get beyond the blocking issue in |
PR #310 was merged and should resolve this issue. |
In order to synchronise EN version switchover, as described in a design document height to version map is to be stored as part of service account, and thus available to every node in an uniform manner.
It should be designed with https://app.zenhub.com/workspace/o/onflow/flow-go/issues/3047
This includes first actually defining and designing the best approach to the problem, and then implementing it.
Requirements
The text was updated successfully, but these errors were encountered: