Skip to content

Commit b3cf913

Browse files
committed
first draft
1 parent 6e29c6c commit b3cf913

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

FIPS/fip-actor-upgrades.md

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
---
2+
fip: "<to be assigned>" <!--keep the qoutes around the fip number, i.e: `fip: "0001"`-->
3+
title: Add support for upgradable actors
4+
author: Fridrik Asmundsson (@fridrik01), Steven Allen (@stebalien)
5+
discussions-to: https://github.com/filecoin-project/FIPs/discussions/396
6+
status: Draft
7+
type: Technical Core
8+
created: 2023-11-27
9+
---
10+
11+
## Simple Summary
12+
13+
This FIP introduces support for upgradable actors, enabling deployed actors to update their code while retaining their address, state, and balance.
14+
15+
## Abstract
16+
17+
This FIP proposes the integration of upgradable actors into the Filecoin network through the introduction of a new `upgrade_actor` syscall and an optional `upgrade` WebAssembly (WASM) entrypoint.
18+
19+
Upgradable actors provide a framework for seamlessly replacing deployed actor code, significantly enhancing the user experience when updating deployed actor code.
20+
21+
## Change Motivation
22+
23+
Currently, all actors on the Filecoin Network are immutable once deployed. To modify the underlying actor code, such as fixing a security bug, the following steps are required:
24+
1. Deploy a new actor with the corrected code.
25+
2. Migrate all state from the previous actor to the new one.
26+
3. Update all other actors interacting with the old actor to use the new actor.
27+
28+
By adding support for upgradable actors, deployed actors can easily upgrade their code and no longer need to go through the series of steps mentioned above.
29+
30+
This also simplifies the upgrade process for builtin actors. Currently, any changes made to the builtin actors require a network upgrade, a new Lotus version, and collaboration with the network to push the new version to production. This is a time consuming and manual process. However, with upgradable actors, we can instead deploy a new code to the builtin actors allowing the changes to be pushed to production almost instantly and does not require a new network upgrade or new Lotus version.
31+
32+
## Specification
33+
34+
Introducing support for actor upgrades involves the following changes to the FVM:
35+
36+
1. Adding a new `upgrade` WASM entrypoint, which actors must implement in order to be a valid upgrade target.
37+
2. Adding a new `upgrade_actor` syscall, enabling actors to upgrade themselves.
38+
39+
These changes are discussed in detail in the following sections.
40+
41+
### New upgrade WASM Entrypoint
42+
43+
We introduce a new optional `upgrade` WASM entrypoint. Deployed actors must implement this entrypoint to be a valid upgrade target. It is defined as follows:
44+
45+
```rust
46+
pub fn upgrade(params_id: u32, upgrade_info_id: u32) -> u32
47+
```
48+
49+
Parameters:
50+
- `params_id`: An IPLD block handle provided by the caller and sent to the upgrade receiver, or `0` for none.
51+
- `upgrade_info_id`: An IPLD block handle for an `UpgradeInfo` struct provided by the FVM runtime (defined below).
52+
53+
The single `u32` return value is an IPLD block handle, or `0` for none.
54+
55+
The `UpgradeInfo` struct is defined as follows:
56+
57+
```rust
58+
#[derive(Clone, Debug, Copy, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
59+
pub struct UpgradeInfo {
60+
// the old code cid we are upgrading from
61+
pub old_code_cid: Cid,
62+
}
63+
```
64+
65+
When a target actor's `upgrade` WASM entrypoint is called, it can make necessary state tree changes from the calling if needed to its actor code. The `UpgradeInfo` struct provided by the FVM runtime can be used to check what code CID its upgrading from. A successful return from the `upgrade` entrypoint instructs the FVM that it should proceed with the upgrade. The target actor can reject the upgrade by calling `sdk::vm::exit()`` before returning from the upgrade entrypoint.
66+
67+
### New upgrade_actor syscall
68+
69+
We introduce a new `upgrade_actor` syscall which calls the `upgrade` wasm entrypoint of the calling actor and then atomically replaces the code CID of the calling actor with the provided code CID. It is defined as follows:
70+
71+
```rust
72+
pub fn upgrade_actor(
73+
new_code_cid_off: *const u8,
74+
params: u32,
75+
) -> Result<Send>;
76+
```
77+
78+
Parameters:
79+
- `new_code_cid_off`: The code CID the calling actor should be replaced with.
80+
- `params`: The IPLD block handle passed, or `0` for none.
81+
82+
On successful upgrade, this syscall will not return. Instead, the current invocation will "complete" and the return value will be the block returned by the new code's `upgrade` endpoint. If the new code rejects the upgrade (calls `sdk::vm::exit()`) or performs an illegal operation, this syscall will return the exit code plus the error returned by the upgrade endpoint.
83+
84+
This syscall will:
85+
1. Validate that the pointers passed to the syscall are in-bounds.
86+
2. Validate that `new_code_cid_off` is a valid code CID.
87+
3. Validate that the calling actor is not currently executing in "read-only" mode. If so, the syscall fails with a "ReadOnly" (13) syscall error.
88+
4. Checks whether the calling actor is already on the call stack where it has previously been called on its `invoke` entrypoint (note that we allow calling `upgrade` recursively). If so, the syscall fails with a "Forbidden" (11) syscall error.
89+
5. Checks that we have space for storing the return block. If not, the syscall fails with a "LimitExceeded" (3) syscall error.
90+
6. Start a new Call Manager transaction:
91+
1. Validate that the calling actor has not been deleted. If so, the syscall fails with a "IllegalOperation" (2) syscall error.
92+
2. Update the actor in the state tree with the new `new_code_cid` keeping the same `state`, `sequence` and `balance`.
93+
3. Invoke the target actor's `upgrade` entrypoint.
94+
4. If the target actor does not implement the `upgrade` entrypoint, then return the syscall fails with a `ExitCode::SYS_INVALID_RECEIVER` exit code.
95+
5. If the target actor aborts the `upgrade` entrypoint by calling `sdk::vm::exit()`, the syscall fails with the provided exit code.
96+
7. Apply transaction, committing changes.
97+
8. Abort the calling actor and return the IPLD block from the `upgrade` entrypoint.
98+
99+
## Design Rationale
100+
101+
### Additional metadata syscall
102+
103+
We considered adding a new `get_old_code_cid` syscall to get the calling actors code CID. That has the benefit of keeping the `upgrade` entrypoint signature consistent with the `invoke` signature. We however rejected that as we felt the benefit didn't outweight the overhead of adding a new syscall. Furthermore, it did not provide the flexibility of passing in a IPLD handle for a `UpgradeInfo` struct where we can easily add more fields if required.
104+
105+
## Backwards Compatibility
106+
107+
Fully backwards compatibility is expected.
108+
109+
## Test Cases
110+
111+
Detailed test cases are provided with the implementation.
112+
113+
## Security Considerations
114+
115+
Upgradable actors pose potential security risks, as users can replace deployed actors' code. However, measures are in place to minimize these risks:
116+
117+
- Upgradable actors are opt-in by default, ensuring no impact on currently deployed actors.
118+
- Actors can only upgrade themselves, preventing one actor from upgrading another actor to a new version.
119+
- We reject re-entrant `upgrade_actor` syscalls, i.e., if some actor `A` is already on the call stack, no "deeper" instance of `A` should be able to call the upgrade syscall.
120+
121+
Detailed tests cover these security considerations and edge cases.
122+
123+
## Incentive Considerations
124+
125+
This FIP does not materially impact incentives in any way.
126+
127+
## Product Considerations
128+
129+
This FIP makes it possible to upgrade deployed actors, for example in cases where a bug or security concern was identified in the deployed code, allowing a simple safe way to addres such issues which significantly improves the user experience from how it is today.
130+
131+
## Implementation
132+
133+
https://github.com/filecoin-project/ref-fvm/pull/1866
134+
135+
## TODO
136+
137+
N/A
138+
139+
## Copyright
140+
141+
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

0 commit comments

Comments
 (0)