EOS系统智能合约升级

用eosio.msig合约间接升级

Cleos目前提供工具来与osio.msig合约的交互,但它不提供一个方便的接口来实现自定义交易。

因此,目前很难提出一个具有多个动作的原生交易(例如eosio::setcode,然后再eosio::setabi)。

eosio.msig方法的优点在于,它使得协调变得更容易,并且不会对签名集合设置严格的时间限制(小于9小时)。

eosio.msig方法的缺点是要求发起者有足够的RAM来提交交易,而目前cleos又没有方便的工具来使用它,比如像原生系统升级所必需的定制交易。

所以目前,建议采用直接的方法升级系统合约。

直接升级(避免使用eosio.msig合约)

前21个区块生产者(超级节点)中的每一个都应该做以下工作:

1.获取当前系统合约以供以后比较(主哈希和ABI在主网区块链上会有所不同):

1
2
3
4
$ programs/cleos/cleos get code -c original_system_contract.wast -a original_system_contract.abi eosio
code hash: cc0ffc30150a07c487d8247a484ce1caf9c95779521d8c230040c2cb0e2a3a60
saving wast to original_system_contract.wast
saving abi to original_system_contract.abi

2.生成升级系统合约的未签名交易:

1
$ programs/cleos/cleos set contract -s -j -d eosio contracts/eosio.system | tail -n +4 > upgrade_system_contract_trx.json

生成的文件的前几行应该类似于(除了expiration, ref_block_numref_block_prefix,应该不同外):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"expiration": "2018-06-15T22:17:10",
"ref_block_num": 4552,
"ref_block_prefix": 511016679,
"max_net_usage_words": 0,
"max_cpu_usage_ms": 0,
"delay_sec": 0,
"context_free_actions": [],
"actions": [{
"account": "eosio",
"name": "setcode",
"authorization": [{
"actor": "eosio",
"permission": "active"
}
],

最后几行应该是:

1
2
3
4
5
6
     }
],
"transaction_extensions": [],
"signatures": [],
"context_free_data": []
}

应该选择一个超级节点来引导升级过程。这个超级节点应该使用他们生成的upgrade_system_contract_trx.json,将其重命名为upgrade_system_contract_official_trx.json,并执行以下操作:

3.修改upgrade_system_contract_official_trx.json中的expiration时间戳到未来足够大的时间,以提供足够的时间来收集所有必要的签名,但不超过交易生成时间9小时。此外,请记住,如果不超过当前时间1小时,交易将不被接受到区块链中。

4.将upgrade_system_contract_official_trx.json文件传递到所有其他21个超级节点。

然后,前21个超级节点中的每一个都应该做如下操作:

5.将生成的upgrade_system_contract_official_trx.json文件与主网区块链提供的upgrade_system_contract_official_trx.json进行比较。唯一的区别应该是expiration,ref_block_num,ref_block_prefix,例如:

1
2
3
4
5
6
7
8
9
$ diff upgrade_system_contract_official_trx.json upgrade_system_contract_trx.json
2,4c2,4
< "expiration": "2018-06-15T22:17:10",
< "ref_block_num": 4552,
< "ref_block_prefix": 511016679,
---
> "expiration": "2018-06-15T21:20:39",
> "ref_block_num": 4972,
> "ref_block_prefix": 195390844,

6.如果比较好,则每个区块生产者应该继续用必要的密钥来签署官方升级交易,以满足他们的active许可。如果区块生产者在其区块生成帐户的active许可中只有一个密钥(即“active密钥”),那么它们只需要使用该active密钥生成一个签名。此签名过程可以离线进行,以获得更好的安全性。

首先,区块生产者应收集所有必要的信息。假设生产者active密钥对是EOS5kBmh5kfo6c6pwB8j77vrznoAaygzoYvBsgLyMMmQ9B6j83i9c, 5JjpkhxAmEfynDgSn7gmEKEVcBqJTtu6HiQFf4AVgGv5A89LfG3。区块生产者需要它们的active私钥5JjpkhxAmEfynDgSn7gmEKEVcBqJTtu6HiQFf4AVgGv5A89LfG3(在这个例子中是这个值),upgrade_system_contract_official_trx.jsonchain_idd0242fb30b71b82df9966d10ff6d09e4f5eb6be7ba85fd78f796937f1959315e(在这个例子中是这个值),可以通过cleos get info获得相关信息。

然后,在一台安全的计算机上,生产者可以签署交易(超级节点将需要在粘贴他们的私人密钥时,进行提示):

1
2
3
4
5
6
$ programs/cleos/cleos sign --chain-id d0242fb30b71b82df9966d10ff6d09e4f5eb6be7ba85fd78f796937f1959315e upgrade_system_contract_trx.json | tail -n 5
private key: "signatures": [
"SIG_K1_JzABB9gzDGwUHaRmox68UNcfxMVwMnEXqqS1MvtsyUX8KGTbsZ5aZQZjHD5vREQa5BkZ7ft8CceLBLAj8eZ5erZb9cHuy5"
],
"context_free_data": []
}

确保使用chain_id将交易提交到实际主网区块链,而不是上面提供的示例的chain_id

输出应该包括签名(在这种情况下)SIGIKK1JZABB9GZDGXHUMMOXQUVXQMVXQS1MVTYXUX8KGTBZZ55AZQZJHD5VRQA5BKZ7FT8CCELBAJA8EZ5ErZB99CUY5,然后超级节点应该发送给生产者。

当超级节点收集到15个生产者签名时,超级节点应做以下工作:

7.复制upgrade_system_contract_official_trx.json,然后调用upgrade_system_contract_official_trx_signed.json,修改upgrade_system_contract_official_trx_signed.json,因此签名字段包括所有15个收集的签名。所以upgrade_system_contract_official_trx_signed.json尾部应该看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cat upgrade_system_contract_official_trx_signed.json | tail -n 20
"transaction_extensions": [],
"signatures": [
"SIG_K1_JzABB9gzDGwUHaRmox68UNcfxMVwMnEXqqS1MvtsyUX8KGTbsZ5aZQZjHD5vREQa5BkZ7ft8CceLBLAj8eZ5erZb9cHuy5",
"SIG_K1_Kj7XJxnPQSxEXZhMA8uK3Q1zAxp7AExzsRd7Xaa7ywcE4iUrhbVA3B6GWre5Ctgikb4q4CeU6Bvv5qmh9uJjqKEbbjd3sX",
"SIG_K1_KbE7qyz3A9LoQPYWzo4e6kg5ZVojQVAkDKuufUN2EwVUqtFhtjmGoC6QPQqLi8J7ftiysBp52wJBPjtNQUfZiGpGMsnZ1f",
"SIG_K1_KdQsE7ahHA9swE9SDGg4oF6XahpgHmZfEgQAy9KPBLd9HuwrF6c8m6jz43zizK2oo32Ejg1DYuMfoEvJgVfXo81jsqTHvA",
"SIG_K1_K6228Hi2z1WabgVdf5bk2UdKyyDSVFwkMaagTn9oLVDV8rCX7aQcjY94c39ah2CkLTsTEqzTPAYknJ8m2m9B7npPkHaFzc",
"SIG_K1_Jzdx75hBCA2WSaXgrupmrNbcQocUCsP8r1BKkPXMreiAKPZDwX9J3G8fS1HhyqWjc7FbukwZf8sVRdS3wKbJVpytqXe7Nn",
"SIG_K1_KW7Qu2SdPD3zuQKh2ziFLzn9QbKqeMpeiemULky5Bbg1Mst6ijbCX3k2AVFGNFLkNLA36PM1WAT5oipzu1B1K7ymRxTx1Z",
"SIG_K1_KXJf1KZNpz73YFKKE7u6jFgsQ8XcX3yA7rDX6ZmG1Qfnc9FLLmT1WViv4bwcPbxaEYfR6SNWfk5cCR9eao2si1soqkXq92",
"SIG_K1_JynjkHFT5UFGDpEcqdriXTzCGCwS36Xztq4UAWQHLQgRUZT2YFoLhUcc87kvUteqCUGVxsmSbfgWv1KLy24voKN4Qs5zTe",
"SIG_K1_JxhfCaGBhuNShpDHn7j1CryG3iSebvfi7FUnJsfkXNTiwLyq2NDBkeakwjCMWFbzr6qqWuMDLjfXbzdtU17f1wCXMjKSgk",
"SIG_K1_KcMSz89QG1ZRFNrXc69R63d5KXbJA8CBjNPYv1VEA3TRfjqVYuhyaHpGXQN4RSKDq4ygr3UTRYBQQVutkJnR6zZ4Ssgd7R",
"SIG_K1_JuxT6bhUAbDs6Q2ppuKyKauduvbaJLxvh4gBH4e4A9yRhvUBT7w3DcvMyhdaor27Kbu29jnqhTbvXcb57QqKWQDpboLv7e",
"SIG_K1_K8BuFYpCiC5FhpVK8ZAzc3VUg7vz6WwLoWBrGN6nnuqUjngGqvHp3UxDVzcwhqccHdv8kdPXvF6G1NszwF1dd3wjCrHBYw",
"SIG_K1_KfH5ZirPwDk1RQKvJv2AGPfsJyPXvXLegZ7LvcPmRtjtMiErs1STXLNT8kiBfhZr4xkWRA5NR1kMF3d49DFMJiB2iWMXJc",
"SIG_K1_KjJB8jtcqpVe3r5jouFiAa9wJeYqoLMh5xrUV6kBF6UWfbYjimMWBJWz2ZPomGDsk7JtdUESVrYj1AhYbdp3X48KLm5Cev"
],
"context_free_data": []
}

8.提交签名交易到区块链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ programs/cleos/cleos push transaction upgrade_system_contract_official_trx_signed.json
{
"transaction_id": "202888b32e7a0f9de1b8483befac8118188c786380f6e62ced445f93fb2b1041",
"processed": {
"id": "202888b32e7a0f9de1b8483befac8118188c786380f6e62ced445f93fb2b1041",
"receipt": {
"status": "executed",
"cpu_usage_us": 4909,
"net_usage_words": 15124
},
"elapsed": 4909,
"net_usage": 120992,
"scheduled": false,
"action_traces": [{
...

如果你得到下面的错误提示信息:

1
2
Error 3090003: provided keys, permissions, and delays do not satisfy declared authorizations
Ensure that you have the related private keys inside your wallet and your wallet is unlocked.

这意味着所提供的签名中至少有一个是不对的。这可能是因为生产者签署了错误的交易,使用了错误的私钥,或者使用了错误的chainid

如果得到如下错误消息:

1
2
Error 3090002: irrelevant signature included
Please remove the unnecessary signature from your transaction!

这意味着不必要的签名包括在内。如果有21个active生产者,则只需要来自这21个active生产者的15个签名。

如果得到如下错误消息:

1
2
Error 3040006: Transaction Expiration Too Far
Please decrease the expiration time of your transaction!

这意味着在提交的截止时间超过当前时间1小时,你需要等待一段时间才能被允许提交交易。

如果得到如下错误消息:

1
2
Error 3040005: Expired Transaction
Please increase the expiration time of your transaction!

这意味着已签署的交易的截止时间已经过去,整个过程必须从步骤1重新启动,再来一遍(汗汗汗):

假设交易成功执行,那么每个人都可以验证新智能合约是否已就位:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ programs/cleos/cleos get code -c new_system_contract.wast -a new_system_contract.abi eosio
code hash: 9fd195bc5a26d3cd82ae76b70bb71d8ce83dcfeb0e5e27e4e740998fdb7b98f8
saving wast to new_system_contract.wast
saving abi to new_system_contract.abi
$ diff original_system_contract.abi new_system_contract.abi
584,592d583
< },{
< "name": "deferred_trx_id",
< "type": "uint32"
< },{
< "name": "last_unstake_time",
< "type": "time_point_sec"
< },{
< "name": "unstaking",
< "type": "asset"

另:《EOS智能合约与DApp开发入门》教程已经上线,爱学习等不及的可以抓紧体验一下:

EOS教程

本教程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用React和EOS的各知识点完成一个便签DApp的开发。

  • 以太坊教程,主要介绍智能合约与dapp应用开发,适合入门。
  • 以太坊开发,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • web3j教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和事件等内容。
  • C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和事件等。
  • python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。

汇智网原创翻译,转载请标明出处。原文