Corda 学习

R3 Corda: 升级 CorDapp(非平台版本升级)- C

2018-09-08  本文已影响0人  李甲川

原文地址:https://docs.corda.net/upgrading-cordapps.html#contract-and-state-versioning

这里有两种类型的 contract/state 升级:

  1. 隐式的升级:使用约束(constraints)允许提前对于 contract 开发多种实现
  2. 显式的升级:创建一个特殊的更新合约的 transaction然后使用升级合约 flows 来获得 state 的所有参与者的签名

这里我们会关注显式的升级。

在显式的升级中,contracts 和 state 可以按照任何的方式来变化,这些变化仅仅在 state 的所有参与者对这个升级都同意的条件下才会生效。下边是可能的更新组合:

使用一个特殊日子(flag-day) 的方式来更新 state 或者 contract 非常简单:

更新流程

编写新的 state 和 contract 定义

由更新 contract 和/或 state 定义开始。对于如何更新 states,并没有任何的限制。但是更新 contracts 必须要实现 UpgradedContract 接口。接口定义如下:

interface UpgradedContract<in OldState : ContractState, out NewState : ContractState> : Contract {
    val legacyContract: ContractClassName
    fun upgrade(state: OldState): NewState
}

upgrade 方法描述了旧的 state 类型是如何更新成新的 state 类型的。如果 state 没有更新的话,那可以给旧的和新的 state 类型参数使用相同的 state 类型。

新的 contract 默认只能够更新在白名单中的已有的 states。如果使用了 hash 或者其他的约束类型话,新的 contract 必须要实现 UpgradedContractWithLegacyConstraint,并且需要显式地指明是哪种约束:

interface UpgradedContractWithLegacyConstraint<in OldState : ContractState, out NewState : ContractState> : UpgradedContract<OldState, NewState> {
    val legacyContractConstraint: AttachmentConstraint
}

比如,如果是 hash 约束的话,那么原始的 JAR 文件的 hash 需要被提供:

override val legacyContractConstraint: AttachmentConstraint
    get() = HashAttachmentConstraint(SecureHash.parse("E02BD2B9B010BBCE49C0D7C35BECEF2C79BEB2EE80D902B54CC9231418A4FA0C"))

升级授权 Authorising

如果新的 states 和 contracts 已经被放到了所有节点的 classpath 下之后,下一步就是每个节点去运行 ContractUpgradeFlow.Authorise flow。这个 flow 会带有一个需要更新的 StateAndRef 的 state,还有一个对新的 contract 的引用,这个 contract 必须要实现 UpgradedContract 接口。

在任何时间,节点的管理员都可以通过运行 ContractUpgradeFlow.Deauthorise flow 来不通过一个 contract 的升级。

执行升级

当所有的节点都执行完了授权流程后,必须要选择一个参与节点通过 ContractUpgradeFlow.Initiate flow 来初始对每个 state 对象的更新。这个 flow 有这样的特点:

class Initiate<OldState : ContractState, out NewState : ContractState>(
    originalState: StateAndRef<OldState>,
    newContractClass: Class<out UpgradedContract<OldState, NewState>>
) : AbstractStateReplacementFlow.Instigator<OldState, NewState, Class<out UpgradedContract<OldState, NewState>>>(originalState, newContractClass)

这个 flow 是 AbstractStateReplacementFlow 的子类(sub-class),它也可以用来对不需要更新 contract 的 state 对象进行更新。

当 flow 成功结束后,所有参与节点的旧的 state 对象应该被更新为升级过的 state 对象了,他们也会指向新的 contract code。

需要注意的点

Contract 更新 flows 的能力

编写新的 states 和 contracts

对于旧的 contract code JAR 文件

当前,所有的参与节点必须要在节点的 classpath 中保留旧的 state 和 contract 定义,因为在验证 transactions 的时候,他们始终会被要求验证以前使用的旧版本的 state 和 contract。

你需要注意可能的 classpath 冲突。如果你还保留着旧版本的 JAR 文件的话,请确保新版本的不会包含同样名字的类(比如在 Kotlin 中文件级别的声明会被放在一个名字在文件名后边的静态类中)

权限 Permissioning

流程 Logistics

上一篇 下一篇

猜你喜欢

热点阅读