二者間によるデプロイへの複数署名(マルチシグ)

Casperネットワークにあるアカウントは、他のアカウントを紐づけて、デプロイへのマルチシグを許可もしくは強制する仕組みをつくれます。 

このワークフローでは、Casperネットワーク上のアカウントがどの様にデプロイへの署名と送信の行程を二者間のマルチシグで行うのか、をお伝えします。

下記を前提としています。

  1. 必要なセットアップを終えている
  2. Casperのコマンドラインクライアントを使用している
  3. メインの公開鍵MA)Hexとアソシエイト(関連)鍵の公開鍵AA)Hexを保持している
  4. 有効なノードアドレス(node-address)を取得している
  5. Casperネットワークにデプロイ済みのスマートコントラクトがある

メインアカウントの設定

注意:間違ったアカウント設定は、アカウントの機能不全や利用不可な状態を引き起こしかねません。まず初めに、アカウントへのいかなる変更も、まずはテスト環境であるテストネット上で実行してみることをお勧めします。それから、メインネットなどのライブ環境にて動かすとよいでしょう。

各アカウントには、associated_keys(関連鍵)フィールドがあり、アカウントアドレスのリストと各アソシエイト(関連)アカウントのweight(ウエイト)を表記しています。アカウントは、associated_keys(関連鍵)フィールドにアカウントアドレスを追加することで関連付けられます。

Casperネットワーク上のアカウントは、紐づいている関連鍵にweight(ウエイト)を割り当てます。単一の鍵でデプロイに署名、もしくはアカウントのステート変更を行う場合、weight(ウエイト)は必ず設定した閾値以上である必要があります。閾値は、アカウントのaction_thersholds(アクション閾値)としてラベル付けされます。

Casperネットワーク上の各アカウントには、デプロイ送信の許可やアカウントの管理を行える、2つのアクション閾値が設けられています。各閾値には、単一の鍵もしくは鍵の組み合わせに割り当てる最低weight(ウエイト)数を定義しており、下記のいずれかとなります。

  1. ネットワークへのデプロイ送信:デプロイ(deployment)閾値によって定義
  2. 関連鍵(associated keys)action_thresholds の変更:key_management(鍵の管理)によって定義

Casperネットワーク上のアカウントにマルチシグを強いる方法としては、メインの鍵と関連鍵の組み合わせのweight(ウエイト)が、デプロイ閾値以上でなくてはなりません。このやり方を実現するには、デプロイ(deployment閾値の半分のweight(ウエイト)数を各鍵に割り当てる必要があります。

コードの説明

メインアカウントのコンテキスト内で実行されるセッションコードを使うことができます。下記は、WASMにコンパイルされ、デプロイとしてネットワークに送信する際のコードです。

注意:下記コントラクトのサンプルは、特定のアカウント設定のセットアップであり、通常の使用目的で作成されたコントラクトではありません。

#![no_main]
use casper_contract::{
    contract_api::{account, runtime},
    unwrap_or_revert::UnwrapOrRevert,
};
use casper_types::account::{AccountHash, ActionType, Weight};

const ASSOCIATED_ACCOUNT: &str = "deployment-account";

#[no_mangle]
pub extern "C" fn call() {
    // Account hash for the account to be associated.
    let deployment_account: AccountHash = runtime::get_named_arg(ASSOCIATED_ACCOUNT);

    // Add the CA key to half the deployment threshold (i.e 1)
    account::add_associated_key(deployment_account, Weight::new(1)).unwrap_or_revert();

    // Deployment threshold <= Key management threshold.
    // Therefore update the key management threshold value.
    account::set_action_threshold(ActionType::KeyManagement, Weight::new(2)).unwrap_or_revert();

    // Set the deployment threshold to 2, enforcing multi-sig to send deploys.
    account::set_action_threshold(ActionType::Deployment, Weight::new(2)).unwrap_or_revert();
}

コントラクトは、主に下記2つのステップに従い、マルチシグの仕組みをお持ちのアカウントで実行させます。

  1. アカウントに関連鍵(AA)を追加します
  2. デプロイ(deployment閾値を2に上げ、デプロイ送信に必要なweight(ウエイト)を、アカウントとその関連鍵に平等に分割します。

デプロイのアクション閾値は、key management(鍵管理)のアクション閾値以上に設定できません。既定値として、アクション閾値は1に設定されています。

コードの実行

アカウントの状態は、デプロイを送信しWASMを実行することで変更され、それが、関連アカウント AA(アソシエイトアカウント)アドレスと紐づきます。

このガイドにおいては、スマートコントラクトは作成済みであり既にGithubのレポジトリに格納されています。そのレポジトリには、WASMの生成を行うコントラクトのコンパイルに必要なビルドコマンドと一緒にMakefileも保存されています。

git clone https://github.com/casper-ecosystem/two-party-multi-sig
cd two-party-multi-sig

下記コマンドを実行して、コントラクトのビルドしてください。

make build-contract

下記パス上に、コンパイルしたWASMが格納されます。

target/wasm32-unknown-unknown/release/contract.wasm

Casperのコマンドラインクライアントは、コンパイルしたWASMをネットワークに送信して実行する際に使用されます。

casper-client put-deploy \
--node-address http://<peer-ip-address>:7777/rpc \
--secret-key <secret-key-MA>.pem \
--chain-name casper-test \
--payment-amount 2500000000 \
--session-path <path-to-contract-wasm> \
--session-arg "deployment-account:account_hash='account-hash-<hash-AA>'"
  1. node-address – ネットワーク上のノードのIPアドレス
  2. secret-key – メインアカウント(MA)の秘密鍵が保存されているファイル名
  3. chain-name – デプロイの送信先となるネットワークのチェーン名(この例では、テストネットを使用)
  4. payment-amount – デプロイのコスト
  5. session-path – コントラクトWASMへのパス
  6. session-argdeployment-accountのラベルの付いた引数として、コントラクトが関連アカウント(AA)のアカウントハッシュを引用。コマンドラインクライアントにて、–session-argフラグを使ったこの引数を渡すこともできます。

重要なレスポンスフィールド:

  • “result”.”deploy_hash” – 転送の追加情報を確認する際に必要となる、実行済みデプロイのアドレス

補足:実行ステータス情報をクエリ時の出力で返された deploy_hash は保存しておいてください。

実行ステータスとアカウントステータスの確認

Casperブロックチェーン上でのアカウント設定はマークルツリーに格納され、ブロックチェーンのグローバルステートのスナップショットでもあります。対象のブロックと祖先ブロック内でデプロイ(転送を含む)を実行することで、そのブロックのグローバルステートの代替アセット(リプレゼンテーション)は計算されます。特定のステート(状態)を識別しているマークルツリーのルートノードは、ステートルートハッシュ(state_root_hash)と呼ばれ、実行されたブロック全てに格納されています。

ご自分のアカウント設定が正しく行われているかを確認するには、ご自分のデプロイが含まれているブロックと紐づいている state_root_hash が必要となります。state_root_hash の取得方法は、下記のとおりです。

  1. デプロイの実行ステータスの確認とそのデプロイを持つブロックハッシュの取得
  2. 対象のデプロイを持つブロックのクエリ(紐づいているstate_root_hashを取得する為) 

state_root_hash と対象のアカウントをネットワークにクエリする為のメインアカウントの hex-encoded-public-key を使用し、設定状況を確認します。

casper-client query-state \
--node-address http://<peer-ip-address>:7777/rpc \
--state-root-hash <state-root-hash-from-block> \
--key <hex-encoded-public-key-MA>


出力サンプル

{
    "id": 1126043166167626077,
    "jsonrpc": "2.0",
    "result": {
        "api_version": "1.0.0",
        "merkle_proof": "2226 chars",
        "stored_value": {
            "Account": {
                "account_hash": "account-hash-dc88a1819381c5ebbc3432e5c1d94df18cdcd7253b85259eeebe0ec8661bb84a",
                "action_thresholds": {
                    "deployment": 2,
                    "key_management": 2
                },
                "associated_keys": [
                    {
                        "account_hash": "account-hash-12dee9fe535bfd8fd335fce1ba1f972f26bb60029a303b310d85419357d18f51",
                        "weight": 1
                    },
                    {
                        "account_hash": "account-hash-dc88a1819381c5ebbc3432e5c1d94df18cdcd7253b85259eeebe0ec8661bb84a",
                        "weight": 1
                    }
                ],
                "main_purse": "uref-74b20e9722d3f087f9dc431e9f0fcc6a803c256e005fa45b64a101512001cb78-007",
                "named_keys": []
            }
        }
    }
}

上記の例では、アソシエイトキー(associated keys)セクション内にリストアップされているアカウントアドレスをご覧いただけます。各鍵毎に、weight(ウエイト)1が割り当てられています。それは、デプロイ(deployment閾値が2に設定されており、どのアカウントも単独ではデプロイへの署名も送信もできません。よって、メインアカウントからのデプロイ送信には、必要な閾値に達する必要があり、その為に各アカウントの秘密鍵で署名をする必要があります。