Replies: 4 comments 1 reply
-
A couple of considerations.
|
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Beta Was this translation helpful? Give feedback.
0 replies
-
Comments on the above:
Other questions / comments:
|
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
arc: 6
title: Program Upgradability
authors: @ProvableHQ
discussion: link
topic: Protocol
status: Draft
created: 2025-04-16
Abstract
As the Aleo ecosystem matures, it is apparent that applications will need to be upgraded over their lifetime. The Aleo Virtual Machine (AVM) provides a method for program-driven upgrades. This method, while sound, has properties that may be undesirable for some applications. This proposal offers a new method for program upgrades that seeks to be timely and cost-effective, while preventing fragmentation of application state.
Goals
We propose a system for program upgrades with the following properties:
function
orfinalize
struct
s,record
s, ormapping
s but cannot modify or remove existing ones.function
s andclosure
sfunction
’sinput
andoutput
interfacefinalize
’sinput
interfaceclosure
. This is because a change in a closure would invalidate all dependent proving and verifying keys.struct
s,record
s, ormapping
simport
struct
record
mapping
closure
function
finalize
constructor
Design
At a high-level, our proposed design introduces constructors and operands so that users can programmatically define upgrades with the above design goals in mind.
Operands
The Aleo Virtual Machine will support the following new operands:
<PROGRAM_ID>/checksum
<PROGRAM_ID>/edition
<PROGRAM_ID>/program_owner
These specific operands can only be used in off-chain AND on-chain contexts.
Checksum
checksum
is defined as the SHA3-256 hash of the program string.finalize
scope.[u8; 32u32]
and is optionally declared in aDeployment
transaction.checksum
is NOT defined in aDeployment
.checksum
is defined in aDeployment
.Edition
edition
denotes the version of a program.finalize
scope.u16
literal and is explicitly declared in aDeployment
transaction.edition
must be0
when a program is first deployed and must be incremented by 1 on each upgrade.Program Owner
program_owner
is the address that deployed the program.finalize
scope.address
and is optionally declared in aDeployment
transaction.program_owner
is NOT defined in aDeployment
.program_owner
is defined in aDeployment
.Constructors
Programs can define constructors which are immutable (they cannot be upgraded) sequences of code that are always run on-chain as part of a deployment or upgrade. Here is an example:
In this example, the constructor checks that its
edition
is always zero, ensuring that the program cannot be upgraded.Additionally, constructors have the following rules:
A core idea of this design is to allow developers to define rich instantiation and upgrade logic that suits their needs. Refer to the Usage section for more examples.
Verifying a Deployment
To support upgrades, deployments are checked using the additional rules:
None
None
constructor
or any of the new operands.Some
and that it matches the program.Some
and that it matches the transactionconstructor
edition
is zero (N::EDITION
), then check that:Process
Process
Changes to the VM and DB
In order to ensure that upgrades are correct and preserve existing state, we also require that:
Cost
A
constructor
uses the same cost model as on-chain execution, with a multiplier. Currently, this multiplier is set to 100.Implementation
The tracking issue for the implementation can be found here.
Security & Compliance
Protocol
The protocol must ensure that:
Application
Upgrades are a powerful mechanism for improving program usability and management. However, mutability fundamentally introduces new risks for users and dependent applications.
Mutable applications can be modified in malicious ways. For example, a developer can modify program logic to introduce a vulnerability or freeze the function. They could even introduce a new function to drain funds.
In the general case, there is not much a user can do. Users should validate that applications are written correctly and build trust in developers. Developers can demonstrate good intent to users by relying on governance mechanisms or restrictions to what an upgrade can do. Developers can use the upgrade mechanism to “ossify” a program by setting the authority to a “null” value, like the zero address. Ultimately, these are only mitigations and the burden falls on the user to do due-diligence.
Dependent programs have some defenses available to them. In Usage, we detail a mechanism where upgrades must be explicitly approved. This allows developers to fix dependent programs and issue a migration when a dependent makes a divergent change. It is worth noting that protocols like Sui do not atomically apply upgrades; the dependent application defaults to the old logic until the developer issues an upgrade. This option, while mitigating risks of malicious upgrades, prevents security patches or critical features from being applied immediately, which can be an issue.
Developers also need to be mindful of the fact that constructors are immutable. This means that a bug in the constructor logic cannot be fixed by rolling out a new upgrade. Developers should take special care and perform security audits.
The protocol provides some application security by requiring that all executions contains signatures over the checksums of the programs they intend to execute. This reduces the likelihood that a malicious developer front-runs an execution with an upgrade that a user did not know about.
Audits
Audits have been completed and their findings are addressed in this PR: ProvableHQ/snarkVM#2758.
The reports will be made public.
Usage
In this section, we detail how constructors and metadata declarations can be used to implement a variety of upgrades.
Not Upgradable
Goal. Define a program that cannot be upgraded.
Anyone Can Upgrade
Goal. Define a program that anyone can upgrade.
Fix Dependency
Goal. Require that a dependent program is on a specific version.
Important. If using this pattern, we recommend you make your program upgradable, in case your function is locked due to a dependency upgrade.
Remove Upgradability
Goal. Allow a developer to lock a program from future upgrades.
Important. Note that this pattern can be generalized to support ‘toggle-able’ upgrades.
Admin-Driven Upgrades
Goal. Define a program that only an authorized admin can upgrade.
Important. Note that the admin account can NEVER be changed. This pattern should be used IFF the private key associated with the admin is properly secured.
Content-Locked Upgrades
Goal. Define a program that can only be upgraded to a program with some specific contents.
This helps ensure that an upgrade has some pre-determined logic.
Configurable Admin-Driven Upgrades
Goal. Define a program that only an authorized admin can upgrade, with the option to swap admins and declare programs upfront.
This pattern combines the ideas behind Content-Locked Upgrades with the notion of an administrator.
Vote-Driven Upgrades
Goal. Define a program that can only be upgraded by an approving vote from a governance contract. \
Time-Locked Upgrades
Goal. Define a program that can only be upgraded after a specific block height.
To Developers
To Reviewers
Beta Was this translation helpful? Give feedback.
All reactions