Contract Upgrades #1642
Replies: 2 comments 4 replies
-
[WIP] Decoupling code and accounts(diagram below is a WIP, it needs a couple of updates) ConceptsState
Logic
Actions
|
Beta Was this translation helpful? Give feedback.
-
My initial thoughts were outlined in #1578 and I'll repost here. My design looks at contract upgrades from a contract <-> host function level rather than at the action level. This means, we don't need any additional actions to support this design(not saying this is bad or good). Currently, a contract's state space is prefixed by its address. flowchart TD
State(Global State)
ContractA("Contract A Address")
ContractB("Contract B Address")
ContractC("Contract C Address")
StateA("Contract A State Space")
StateB("Contract B State Space")
StateC("Contract C State Space")
State --> ContractA
State --> ContractB
State --> ContractC
ContractA --> StateA
ContractB --> StateB
ContractC --> StateC
style State stroke:#f9f,stroke-width:4px
style ContractA stroke:#bbf,stroke-width:2px
style ContractB stroke:#bbf,stroke-width:2px
style ContractC stroke:#bbf,stroke-width:2px
style StateA stroke:#bfb,stroke-width:2px
style StateB stroke:#bfb,stroke-width:2px
style StateC stroke:#bfb,stroke-width:2px
The state space of a contract should be decoupled with its code. This way, contracts would have much greater flexibility in interacting with state, and offer a very clean and explicit interface for managing state access and ownership. StateSpace would become a property of contracts, with their own read/write/own permissions. Initially every contract would be instantiated with it's own state space, but would be able to move access and control as it pleases. flowchart TD
State(State)
Space1("State Space 0x1a2b")
Space2("State Space 0x3c4d")
Space3("State Space 0x5e6f")
State --> Space1
State --> Space2
State --> Space3
style State stroke:#f9f,stroke-width:4px
style Space1 stroke:#bbf,stroke-width:2px
style Space2 stroke:#bbf,stroke-width:2px
style Space3 stroke:#bbf,stroke-width:2px
classDiagram
%% Defining the classes
class ContractA {
StateSpace: 0x1a2b
}
class ContractB {
StateSpace: 0x3c4d
}
class ContractC {
StateSpace: 0x5e6f
}
class ContractD {
StateSpace: nil
}
class StateSpace {
owner: Address
writers: map[Address]bool
statePrefix: []byte
}
This design gives contracts much more flexibility regarding state access as contracts can share state and move ownership. A A lightweight implementation of this would expose one additional host function extern fn set_state_access(access: AccessControl)
enum AccessControl {
// gives `contract` write access to this contracts StateSpace
// calling contract must have ownership of its StateSpace
Write(Contract)
// moves ownership to `contract`,
// calling contract must have ownership,
Own(Contract)
// removes all access `contract` has to calling contract
Remove(Contract)
// delegates access control to `contract`
Delegate(Contract)
} Upgrading contracts are quite easy. Contract A
pub fn upgrade(new: Address) {
// validate caller & other logic...
// change owner
set_state_access(AccessControl::own(address))
}
Contract B
pub fn init(contractA: Address) {
// Allow contractA to move ownership to ContractB
set_state_access(AccessControl::delegate(contractA))
} In this example, |
Beta Was this translation helpful? Give feedback.
-
As is apparent on multiple blockchains and blockchain-frameworks, there is demand for upgradeable contracts.
What is an upgradeable contract?
Nothing precludes a smart-contract author from deploying a new contract and calling the new contract version-(n + 1), but what happens when another contract has hardcoded its address? That other contract is calling old code and needs to also release version-(n + 1). It's untenable to have to release a new contract every time a "parent" contract is updated (dependent-contract calls parent-contract).
Existing Solutions
Since the problem seems to relate to the calling code and the address of the contract, it's not surprising that the general community has centered around a type of proxy pattern. There are two types of proxies:
It seems that with the benefit of hindsight, the community of blockchain builders seems to be converging on building the proxy into protocol itself.
Proposals to follow...
Beta Was this translation helpful? Give feedback.
All reactions