Genesis合约

部署和升级合约

应该重点关注一个数据结构,SmartContractRegistration:

message SmartContractRegistration {
    // The category of contract code(0: C#).
    sint32 category = 1;
    // The byte array of the contract code.
    bytes code = 2;
    // The hash of the contract code.
    Hash code_hash = 3;
    // Whether it is a system contract.
    bool is_system_contract = 4;
    // The version of the current contract.
    int32 version = 5;
}

其中的code字段,正是存储合约代码的地方。不过每一个SmartContractRegistration实体,并不是跟合约一一对应的,其存储结构为:

public MappedState<Hash, SmartContractRegistration> SmartContractRegistrations { get; set; }

SmartContractRegistration实体通过合约代码的哈希值进行存取。事实上也只有部署合约的时候写入一次。与线上运行的合约一一对应的数据结构是ContractInfo:

message ContractInfo
{
    // The serial number of the contract.
    int64 serial_number = 1;
    // The author of the contract, this is the person who deployed the contract.
    aelf.Address author = 2;C#
    // The category of contract code(0: C#).
    sint32 category = 3;
    // The hash of the contract code.
    aelf.Hash code_hash = 4;
    // Whether it is a system contract.
    bool is_system_contract = 5;
    // The version of the current contract.
    int32 version = 6;
}

其存储结构为:

通过ContractInfo的code_hash字段,不难猜出:

  1. 当试图获取合约代码的时候,是先读取ContractInfo的code_hash,随后从State.SmartContractRegistrations里读到合约代码本身。

  2. 升级合约,实际上就是替换ContractInfo的code_hash

合约地址的计算

合约地址实际上是通过一个随着合约部署数量递增的字段计算出来的:

其计算过程位于DeploySmartContract方法中:

  • aelf每条链的合约地址都不一样。

  • 合约地址与合约代码无关,只跟它在这条链部署的顺序有关。

    • 因此在脚手架中测试新写的合约的时候,新的合约总是固定的地址。

合约部署和升级过程

当前的pipeline是首先Propose,生成一个议会提案,当超过2/3的BP同意部署/升级以后,释放一个新的提案请求代码检查,最后在代码检查通过后,才会通过释放代码检查的提案实现真正的合约部署/升级。

详情见:aelf主网合约部署流程

Last updated