hyperledger-archives / fabric

THIS IS A READ-ONLY historic repository. Current development is at https://gerrit.hyperledger.org/r/#/admin/projects/fabric . pull requests not accepted
https://gerrit.hyperledger.org/
Apache License 2.0
1.17k stars 1.01k forks source link

Chaincode life-cycle #1127

Open binhn opened 8 years ago

binhn commented 8 years ago

A chaincode starts with deploy then invokes and queries. At some point, it might need to be upgraded. And it will be eventually terminated (out of service).

Upgrading is the most interesting as it involves code and data (state).

Assuming we have a system chaincode #938 to manage life-cycle (called uber chaincode), so deploy, invoke, query, upgrade, and terminate are functions of this uber chaincode, then upgrade would be an Invoke transaction with parameter points to the new code of the chaincode to be upgraded. Uber chaincode can deploy the new code and run the Init function to migrate any data necessary. The new chaincode will have a different ID than the one that it is upgrading. Uber chaincode then names #1077 the new chaincode with the same name as the one that it is upgrading, which will assume all the transactions targeted for the old version of the chaincode.

ghaskins commented 8 years ago

I would argue that in addition to all of the above, we should have provisions for the old chaincode to vote (possibly via subsequent human/transaction interaction) on whether it will permit itself to be upgraded.

Consider the scenario where a chaincode implements a contract whose terms have been agreed upon by two parties. Those parties may want to explicitly approve of any update to the code as that might involve changes to the terms (inadvertent or otherwise). The workflow might look something like as follows:

Roles: Deployer, CounterPartyA, CounterPartyB Entities: OldCode, NewCode, EventBus, Peer

Deployer: Peer.Deploy(OldCode) -> Address CounterParty[A|B]: Peer.Decompose(Address) -> {codehash: Hash(OldCode).. } CounterParty[A|B]: Check codehash against set of auditied/approved code CounterParty[A|B]: Peer.Invoke(FunctionFoo, Address) ... Deployer: OldCode.ProposeUpgrade(Address, NewCode) OldCode: Event(UpgradeRequested, NewCode) CounterPartyA: reviews NewCode CounterPartyA: Peer.Invoke(FunctionApproveUpgrade, Address) ... CounterPartyB: Peer.Invoke(FunctionApproveUpgrade, Address) OldCode: Event(UpgradeApproved) Peer: NewCode.CommitUpgrade(OldState) Peer: OldCode.Terminate()

I am thinking that the default implementation of ProposeUpgrade just says "yes", or at least says yes without requiring an async approval.

muralisrini commented 8 years ago

Can we split this up into two parts ? Deploy, Invoke, Query (already there) Upgrade (not there)

binhn commented 8 years ago

@muralisrini basically this is about upgrade and terminate, but it may require additional data in deploy to enable the life-cycle. I would keep this together and multiple people can work on it. @srderson @manish-sethi

kletkeman commented 8 years ago

A few thoughts on our requirements for IoT contract upgrades. Includes a short intro to our current thinking on IoT contracts. And ends with several questions on how to subsume the data without incurring a copy. I thought I had understood the statement "names #1077 the new chaincode with the same name", but I realized that alias != UUID and so state may require a copy, which takes too much time with large datasets. Anyway ... at the least, this is my chip in to this discussion.

Upgrade Requirements for IoT Contracts

kletkeman commented 8 years ago

#1217 is needed for fast upgrades

adecaro commented 8 years ago

@binhn I see many potential threats here. One among the others is related to access control. Then, who can terminate a chiancode? How do we ensure that someone who has requested the update cannot repudiate such a request? And so on...

Of course, there are answers these questions. A proper design is needed to take in account the security aspects :)