EOS のアカウント・ロール・権限　応用編

EOS のアカウント・ロール・権限　上級編として、eosio.msig コントラクトを使ってマルチサインをやってみます。

[EOS のアカウント・ロール・権限　上級編](https://qiita.com/blueplanet/items/80c864d806110c3652af)　で下記のような権限を設定しました。

```json
{
  "threshold": 2,
  "keys": [],
  "accounts": [
    {
      "permission": {
        "actor": "alice",
        "permission": "active"
      },
      "weight": 1
    },
    {
      "permission": {
        "actor": "bob",
        "permission": "active"
      },
      "weight": 1
    },
    {
      "permission": {
        "actor": "carol",
        "permission": "active"
      },
      "weight": 2
    }
  ]
}
```

`carol` アカウントの場合は、自分１人で `trans` の権限で送金トランザクションを発行出来ますが、
`bob` と `alice` の場合は、マルチサインで二人ともサインしないとトランザクション発行できません。
今回は、このマルチサインのやり方を説明します。

### 注意
上記内容を使って、`cleos set account permission testuser` を実行する時、よく下記のエラーになります。

```shell
Error Details:
Authority failed validation! ensure that keys, accounts, and waits are sorted and that the threshold is valid and satisfiable!
```

ポイントとしては、上記エラーメッセージにかかれていますが、`accounts`に指定する各アカウント名はアルファベット順で並べておく必要があるところです。

山本さんの記事が参考になりました。 [EOSのMulti-sigアカウントについて - atcoin engineering blog](https://atcoin.hatenablog.com/entry/2018/09/21/221826) 

## マルチサインの流れ
**前提：`eosio.msig` を利用するため、ローカル環境でまだデプロイしてない場合はまずデプロイする必要がある**

1. やりたいことを提案する。提案する時は、実際の操作権限がなく、全く関係ないアカウントても大丈夫です
2. 提案をレビューする。これも提案コードとアカウントを分かっていれば、どのアカウントもみえます
3. やりたいことの権限を持っているアカウントが提案を承認する
4. 承認する重みが閾値以上になっていれば、提案を実行できるようになるので、権限あるアカウントで実行する

## `eosio.msig` をデプロイする

```shell
// eosio.msig アカウント作成
$ cleos create account eosio eosio.msig EOS7bKBnxtQMXWkffYesa7Fh6dY5QHFY8PiskXW3HnvG8XYbihtKQ
executed transaction: 6bb87aa1b18d91a3dbbf6c28e79d6b83a360c3e5f70036ea7238e2370d540bdd  200 bytes  3082 us
#         eosio <= eosio::newaccount            {"creator":"eosio","name":"eosio.msig","owner":{"threshold":1,"keys":[{"key":"EOS7bKBnxtQMXWkffYesa7...
warning: transaction executed locally, but may not be confirmed by the network yet         ]

// コントラクトをデプロイする
$ cd ~/dev/eos_contracts/eosio.contracts/eosio.msig
$ eosio-cpp -o eosio.msig.wasm src/eosio.msig.cpp -I=include --abigen
$ cleos set contract eosio.msig /eos_contracts/eosio.contracts/eosio.msig
Reading WASM from /eos_contracts/eosio.contracts/eosio.msig/eosio.msig.wasm...
Publishing contract...
executed transaction: 45617b8857ade28c975c708f8e7aa84b2e5dc3d5b0c7ea00b2fa9c87963af23c  9800 bytes  23587 us
#         eosio <= eosio::setcode               {"account":"eosio.msig","vmtype":0,"vmversion":0,"code":"0061736d0100000001a7011a60047f7e7e7f0060027...
#         eosio <= eosio::setabi                {"account":"eosio.msig","abi":"0e656f73696f3a3a6162692f312e30001006616374696f6e0004076163636f756e740...
warning: transaction executed locally, but may not be confirmed by the network yet         ]
```

## マルチサインコントラクトを使う
下記の流れでやってみます

- `ted` アカウントから、`testuser` アカウント向けに、`100 EOS` を請求するように提案する
    - `bob` と `alice` にサインしてもらうようにする
- `bob` が提案をレビューして、承認する
- `alice` が提案をレビューして、承認する
- `alice` が提案を実行する

### 現状確認

```shell
# 一回権限を確認しておく
$ cleos get account testuser
created: 2018-12-02T20:46:24.000
permissions:
     owner     1:    1 EOS7Uzo6MoGi2PcF6CG269PzNRbTZuRwgmgUFwTU9NhRNCPoXZdzW
        active     1:    1 EOS7PFNHZh3FbeHtSkwAqoQ2yCTzqZktzzuSWQCTBgfTE2RVZLoEj
           trans     2:    1 alice@active, 1 bob@active, 2 carol@active

# 残高確認
# ted アカウントはまだ残高がないので、空表示
$ cleos get currency balance eosio.token ted
$ cleos get currency balance eosio.token testuser
9689.0000 EOS
```

### ted から提案する

```shell
$ cleos multisig propose trans2ted '[{"actor": "alice", "permission": "active"},{"actor": "bob", "permission": "active"}]' '[{"actor": "testuser", "permission": "trans"}]' eosio.token transfer '{"from":"testuser", "to":"ted", "quantity":"100.0000 EOS", "memo":"transfer to ted 100 EOS"}' -p ted@active
executed transaction: 64e8425294c852b6875c9d6da63e6cdcf31b54056e3e34342dc781216cbdc3a4  248 bytes  4944 us
#    eosio.msig <= eosio.msig::propose          {"proposer":"ted","proposal_name":"trans2ted","requested":[{"actor":"alice","permission":"active"},{...
warning: transaction executed locally, but may not be confirmed by the network yet         ]
```

### bob から承認する

```shell
# bob から ted アカウントの trans2ted 提案をレビューする
$ cleos multisig review ted trans2ted
{
  "proposal_name": "trans2ted",
  "packed_transaction": "3b0f0b5c000000000000000000000100a6823403ea3055000000572d3ccdcd0100000057619db1ca00000000003ccdcd3800000057619db1ca00000000000092ca40420f000000000004454f5300000000177472616e7366657220746f207465642031303020454f5300",
  "transaction": {
    "expiration": "2018-12-08T00:24:27",
    "ref_block_num": 0,
    "ref_block_prefix": 0,
    "max_net_usage_words": 0,
    "max_cpu_usage_ms": 0,
    "delay_sec": 0,
    "context_free_actions": [],
    "actions": [{
        "account": "eosio.token",
        "name": "transfer",
        "authorization": [{
            "actor": "testuser",
            "permission": "trans"
          }
        ],
        "data": {
          "from": "testuser",
          "to": "ted",
          "quantity": "100.0000 EOS",
          "memo": "transfer to ted 100 EOS"
        },
        "hex_data": "00000057619db1ca00000000000092ca40420f000000000004454f5300000000177472616e7366657220746f207465642031303020454f53"
      }
    ],
    "transaction_extensions": []
  }
}

# 承認する
$ cleos multisig approve ted trans2ted '{"actor":"bob", "permission":"active"}' -p bob@active
executed transaction: cd1c9634069d7c097c67d7acb822f614a8532d7633c24f1e2d64df729aaa7bf0  128 bytes  1874 us
#    eosio.msig <= eosio.msig::approve          {"proposer":"ted","proposal_name":"trans2ted","level":{"actor":"bob","permission":"active"}}
warning: transaction executed locally, but may not be confirmed by the network yet         ]
```

### alice から承認する

```shell
# レビューは省略
# 承認する
$ cleos multisig approve ted trans2ted '{"actor":"alice", "permission":"active"}' -p alice@active
executed transaction: 36e639942ca60539529bf901eed276b28e76575e4bc445bcb0f22b2eefa1ca95  128 bytes  3297 us
#    eosio.msig <= eosio.msig::approve          {"proposer":"ted","proposal_name":"trans2ted","level":{"actor":"alice","permission":"active"}}
warning: transaction executed locally, but may not be confirmed by the network yet         ]
```

### alice から実行する
```shell
# 実行する
$ cleos multisig exec ted trans2ted -p alice@active
executed transaction: 1598a4df13e696c354e716f51eaf09bbdc1c85da7fbb636a1362af6a2badcc44  160 bytes  4647 us
#    eosio.msig <= eosio.msig::exec             {"proposer":"ted","proposal_name":"trans2ted","executer":"alice"}
warning: transaction executed locally, but may not be confirmed by the network yet         ]

# 結果確認
$ cleos get currency balance eosio.token ted
100.0000 EOS
$ cleos get currency balance eosio.token testuser
9589.0000 EOS
```

## まとめ
権限を複数アカウントに付与することで、マルチサインで実行できるので、うまく活用できれば、よりセキュリティが高いサービスが展開できそうですね。