【Hyperledger Aries】Aries Cloud Agent – PythonにおけるMultitenant/Endorse機能を試す

SSI

こんにちは。GMOグローバルサイン・ホールディングスCTO室で分散型IDの研究開発をしている神沼@t_kanumaです。

この記事ではHyperledger Ariesの実装の1種であるACA-Py(Aries Cloud Agent – Python)に最近追加された機能である以下の2つのモードを試してみます。

  1. Multitenantモード
  2. Endorserモード

Hyperledger AriesおよびACA-Pyについての詳細は省きますが、端的にいうとACA-PyはDockerコンテナ上のPythonプロセスです。詳細は拙著ではありますが、以下の記事をご参照ください。

また当記事ではローカルに環境を構築します。
以下の拙著の内容を前提にしていますので軽く目を通した上でお進みください。

利用するOSSのバージョンはこの拙著と同様です。

  • ACA-Py: 0.7.3
  • von-network: 1.7.2

では、新モードを1つずつ試してみます。

1. Multitenantモード

概要

ACA-Pyのデフォルトモードでは、1つのACA-Pyインスタンス(プロセス)で扱えるEntityの数は1つです。このMultitenantモードではその文字通り、1つのACA-Pyインスタンスで複数のEntity(=テナント)を扱うことができます。 以下、デフォルトモードとMultitenantモードの差を表した図です。

以下、ポイントです。

  • WalletとWallet内のPairwise DID、およびWebhook(別名コントローラー – 開発者が個々に実装が必要なアプリ部分)はテナントごとに独立して作成することができます。テナントごとにWebhook先を指定することができるため、デフォルトモードで別々に建てた時と同様に、テナントごとにコントローラーのビジネスロジックを構築できます。
  • Admin API/DIDComm Endpointはデフォルトモードの時と同様にACA-Py全体で1つです。MultitenantモードではACA-Py内部に各テナントの共通設定などを持つBase Walletが内在します。このBase Walletがメッセージをテナントに適切にルーティングします。
  • Admin APIの呼び出しにおいては、各テナントごとに割り当てるJWTをリクエストヘッダーに含めることで、Base Walletは特定テナントにルーティングすることができます。
  • DIDCommでの他エージェントとのやりとりにおいては、テナントからの要求を元に、Base Walletが他エージェントとのコネクションのためのPairwise DIDを生成します。Base WalletはPairwise DIDとテナントの紐付けができるわけで、結果、特定テナントにルーティングすることができます。

試してみる

マルチテナントモードでACA-PyをIssuerとして起動し、以下のテナントの挙動を確認してみます。

  • Issuerとして振る舞えないこと。
  • 他エージェントとテナント間のメッセージのやりとり(別のACA-Pyからテナントにメッセージを送信する。)

Admin API呼び出しのポイント

先にAdmin API呼び出しのポイントを挙げます。

  • 各API Endpointの呼び出しに対して、対応するTenantに対する認可と識別のために、それぞれのTenantに紐づくJWTをリクエストヘッダーに含めることが必須です。
  • ただしTenantを作成したり削除したりするEndpoint(URLのPathに/multitenancy/が入る)においては、JWTは不要です。

(1) 開発用Ledger(von-network)の起動

詳細は、前述の拙著(c)をご参照ください。

(2) Multitenantモードでのaca-pyの起動

基本的な部分は、拙著(c)のdocker-compose.ymlと.envファイルをご確認ください。
今回、以下の3つのMultitenant用の起動パラメーターを追加します。

--multitenant
--multitenant-admin
--jwt-secret ${MULTITENANT_JWT_SECRET}
  • multitenant: multitenantモードでaca-pyを起動します。
  • multitenant-admin: Admin APIの中のmultitenantに関するEndpointを利用可能にします。
  • jwt-secret: Admin API呼び出しの認可のために、テナントごとにJWTが発行されます。このパラメーターは各JWTの署名鍵です。

(3) MultitenantのためのAdmin API Endpointの確認

aca-pyを起動後、Swagger UIから確認します。
以下の5つのEndpoint + HTTPメソッドの組み合わせを用意していることがわかります。

(4) Base Walletの存在確認 / デフォルトモードの様にACA-Pyインスタンス単位での振る舞いができないことの確認

まずPostgreSQLコンテナを覗き、Base WalletのDBが生成されていることを確認します。

次に、Admin APIからACA-Pyインスタンス全体としてのWalletを取得してみます。デフォルトモードではこの時点で既にIndy Ledgerに記録されているPublic DIDを保持するWalletが生成されています。

# request
curl -X 'GET' \
  'http://localhost:8031/wallet/did' \
  -H 'accept: application/json'
# response
401: Unauthorized

上記からMultitenantモードでは、(前述の5つのMultitenant用のEndpoint以外では)テナントを識別するトークンを付与し認可をパスしなければAdmin APIを利用できないことがわかります。つまりは、デフォルトモードのようにACA-Pyインスタンス全体として外部とやり取りするWalletは存在せず、デフォルトモードとMutitenantモードは相互排他的だということがわかります。

(5) テナントの未生成確認

Admin API上からテナント(別名Sub Wallet)がまだ1つも作られていないことを確認します。

# request
curl -X 'GET' \
  'http://localhost:8031/multitenancy/wallets' \
  -H 'accept: application/json'
# response
{
  "results": []
}

(6) Webhookの構築

任意の技術で任意の場所に、POSTを受け付けるEndpoint”<Webhookのコンテキストルート>/topic/basicmessages”を持つAPIを用意します。詳細は割愛します。

(7) 新規テナント(Sub Wallet)の生成

# テナント生成のリクエスト
curl -X 'POST' \
  'http://localhost:8031/multitenancy/wallet' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "key_management_mode": "managed",
  "label": "issuer-dev-tenant-1",
  "wallet_dispatch_type": "default",
  "wallet_key": "foobarbaz",
  "wallet_name": "issuer-dev-tenant-1-wallet",
  "wallet_type": "indy",
  "wallet_webhook_urls": [
    "<WebhookのコンテキストルートまでのURL (e.g. http://localhost:8080/webhook)>"
  ]
}'

以下、生成されたテナントの内容です

# テナント作成のレスポンス
{
  "created_at": "2022-04-22T04:20:13.260009Z",
  "key_management_mode": "managed",
  "wallet_id": "48589c75-718d-4451-bad9-8dee90f80897",
  "updated_at": "2022-04-22T04:20:13.260009Z",
  "settings": {
    "wallet.type": "indy",
    "wallet.name": "issuer-dev-tenant-1-wallet",
    "wallet.webhook_urls": [
        "<WebhookのコンテキストルートまでのURL (e.g. http://localhost:8080/webhook)>"
    ],
    "wallet.dispatch_type": "default",
    "default_label": "issuer-dev-tenant-1",
    "wallet.id": "48589c75-718d-4451-bad9-8dee90f80897"
  },
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3YWxsZXRfaWQiOiI0ODU4OWM3NS03MThkLTQ0NTEtYmFkOS04ZGVlOTBmODA4OTcifQ.B3lSjsiy3IZmk9IdhYw5rXvD_-qcEm8N__z4LZyeTXo"
}

リクエストの内容を見ると、テナント単位で複数のWebhookを指定できることがわかります。
またレスポンスの内容を見るとテナントを識別するJWTが含まれていることがわかります。
ここでJWTをデコードしてみます。

PayloadとしてはWallet IDのみです。Base WalletはこのWallet IDにより特定のテナント(Sub Wallet)に適切にルーティングしているわけです。またACA-Py起動時にjwt-secretパラメータに指定した値で署名されていることもわかります。(今回の値は”thisissecret”)

またこの時点でのPostgreSQLを確認します。Sub Wallet用のDBが作成されていることがわかります。

(8) Issuerとして振る舞えないことの確認

以下を確認します。

  • 作成したテナントにPubilc DIDが紐づいていないことを確認する。
  • Ledger上にTransaction(SCHEMA)を作成できないことを確認する。

まずデフォルトモードを対象としたWalletに関するEndpointを叩きます。

# request
curl -X 'GET' \
  'http://localhost:8031/wallet/did' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3YWxsZXRfaWQiOiI0ODU4OWM3NS03MThkLTQ0NTEtYmFkOS04ZGVlOTBmODA4OTcifQ.B3lSjsiy3IZmk9IdhYw5rXvD_-qcEm8N__z4LZyeTXo'
# response
{
  "results": []
}

Multitenantモード用Endpointのそれとは異なり、Walletは無いことになっています。

次にテナントに紐づけられたPublic DIDがあるか確認します。

# Request
curl -X 'GET' \
  'http://localhost:8031/wallet/did/public' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3YWxsZXRfaWQiOiI0ODU4OWM3NS03MThkLTQ0NTEtYmFkOS04ZGVlOTBmODA4OTcifQ.B3lSjsiy3IZmk9IdhYw5rXvD_-qcEm8N__z4LZyeTXo'

# Response
{
  "result": null
}

Public DIDは紐付けられていないことがわかります。

ここから、デフォルトモードなら可能なTransaction(SCHEMAレコード)の作成を試みます。

# request
curl -X 'POST' \
  'http://localhost:8031/schemas' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3YWxsZXRfaWQiOiI0ODU4OWM3NS03MThkLTQ0NTEtYmFkOS04ZGVlOTBmODA4OTcifQ.B3lSjsiy3IZmk9IdhYw5rXvD_-qcEm8N__z4LZyeTXo' \
  -H 'Content-Type: application/json' \
  -d '{
  "attributes": [
    "age"
  ],
  "schema_name": "test",
  "schema_version": "1.0"
}'
# response
400: Cannot publish schema without a public DID.

当然の帰結ではありますが、Agentに紐づけられたPublic DIDが存在しないため、Transactionが生成できません。(これはCredential Definitionでも同様だと考えます。)

以上のことから、MultitenantモードではテナントはPublic DIDを保持することができず(言い換えれば、Pairwise DIDのみ保持する。)、それゆえにIssuerとして機能することはできないという結論に至りました。

(9) 別Agentとのメッセージ交換

まずテナントとP2P通信する、デフォルトモードの別のACA-Pyを起動し、Invitationを作成します。(詳細は割愛します)

次に、以下の様にテナント側でInvitationを受け入れて、Connectionを張ります。

# request
curl -X 'POST' \
  'http://localhost:8031/connections/receive-invitation' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3YWxsZXRfaWQiOiI1MjJlY2RhOS0xODMzLTQ1MDEtODVkOS1hN2U2MmU1M2E3NjMifQ.Z_NSSseJJUdMKJTbKM-zJ2Ljg8ix52UXPTbCA7anSZc' \
  -H 'Content-Type: application/json' \
  -d '{
    "@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation",
    "@id": "3a73aeb8-9f54-4fc1-afd7-9f6317b8a8cc",
    "label": "another acapy",
    "serviceEndpoint": "http://172.19.0.4:8040",
    "recipientKeys": [
      "G1yLskBGLHzq636Yj7NEJ6ra11azZgi3KSovnhQPQNow"
    ]
  }'
# response
{
  "updated_at": "2022-05-02T06:52:26.349915Z",
  "connection_id": "7013799d-ca99-4e89-bcf6-22d3225fdfea",
  "rfc23_state": "request-sent",
  "request_id": "e89c5265-b5d4-4c30-ab30-77bb4da062db",
  "routing_state": "none",
  "invitation_key": "G1yLskBGLHzq636Yj7NEJ6ra11azZgi3KSovnhQPQNow",
  "invitation_mode": "once",
  "accept": "auto",
  "created_at": "2022-05-02T06:52:26.198863Z",
  "their_role": "inviter",
  "their_label": "another acapy",
  "invitation_msg_id": "3a73aeb8-9f54-4fc1-afd7-9f6317b8a8cc",
  "state": "request",
  "connection_protocol": "connections/1.0",
  "my_did": "5RAuChZ4WLLSzZvmGcBCnw"
}

別ACA-Pyからテナントにメッセージを送信します。

curl -X 'POST' \
  'http://localhost:8041/connections/ccc32a2f-e8e5-4444-a896-ade8a8074db8/send-message' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "content": "Hello Tenant"
}'

最後にテナントに紐づくWebhookで受信したメッセージを確認します。今回はWebhookにAWS(API Gateway + Lambda)を使いました。処理としてはLambdaの中でHTTPリクエストをロギングしているだけです。CloudWatch Logsにてログを確認します。


(省略)

テナントに向けたメッセージの送信を確認できました。

ユースケースとメリット

同一企業内、または環境内に複数のVerifierを構築したい時に有用だと考えます。
デフォルトモードでVerifierごとにACA-Pyを立てることに比べてインフラの管理が楽になる、またインフラコストを改善できると考えます。

まとめ

上記ユースケースに該当する状況で、Verifierとして利用するなら効果的だと考えます。

私の今回の検証では、テナントはPublic DIDに紐づけることができない、結果Issuerとして利用することができないという結論に至りました。(公式DocumentにはIssuerとして使えるとも使えないとも書かれてはいません。)
この部分に関しては、今後も状況を見守りたいと考えます。

2. Endorserモード

前提: AuthorとEndorserロール

Indyにおいて、IssuerはLedgerにTransactionを保管するわけですが、そのIssuerに付与されるロールには、AuthorとEndorserの2種類があります。EndorserロールはLedgerにTransactionを書き込める権限を持ちます。一方、Authorはその権限を持ちません。

書き込みの流れとしては、まずAuthorはEndorserに署名依頼を出します。そして、Endorserが署名して書き込みます。もしくは、署名したTransactionを一旦Authorに返却し、AuthorがLedgerに書き込むこともできます。(正確にはSteward(Ledgerノード運用者)に書き込みリクエストを出す。)

EndorserのPublic DIDは予めLedgerに登録されているため、Stewardは署名の検証をすることができ、最終的にLedgerに書き込めるわけです。

例示: Sovrin

具体例として、現時点で最大規模と思われるIndy Ledger、Sovrin Networkにおける内容を例示します。Sovrinは、Issuerに対しTransaction AuthorTransaction Endorserというロールを用意しています。下の2つのリンク先の図にあるように、Public Write AccessにはTransaction Authorロールだけで十分ですが、Permissioned Write AccessにはTransaction Endorserロールが必要です。

(なお、SovrinにおいてはPubic Write Accessで書き込めるタイプのTransactionは現状、用意されていないため、そのの書き込みには自身がEndorserになるか、自身はAuthorとして他のEndorserに署名してもらう必要があります。)

Sovrinでは、Webフォームを通した申請をした上で費用を払うことで、Transaction Endorserになることができます。

デフォルトモードとの違い

デフォルトモードでACA-Pyを起動したとしても、それにEndorserロールを付与することは可能です。例えば、von-networkを使ったローカル開発においては、Issuerは自身のPublic DID登録の際に、ロールを指定することができます。前述の拙著においては、ロールにEndorserを指定していることを見てもらえると思います。そうすることで、その後自身のSchemaやCredential DefinitionなどのTransactionを書き込めるわけです。(言い換えれば、自分自身に対しEndorseしていると言えると思います。)

このように起動モードには関係なくEndorserになることは可能です。ただし、デフォルトモードかつEndorserロールの場合、自身のTransaction書き込みは可能ですが、他AgentからのEndorseの依頼、つまりAuthorからのTransactionに署名をすることはできないと考えます。そしてEndorserモードではそれが可能になるというわけです。

ユースケース

Multitenantモードと同様に、同一企業内または環境内に複数のIssuerを構築したい時に有用だと考えます。

例えば企業内に部署ごとにIssuer(ACA-Py)を建てたとします。この時それぞれのIssuerがSovinにてEndorserになるとコストがかさみます。このような場合は企業内に1つのEndorserとなるACA-Pyを建てた方が効率的です。

試してみる

まず上図の上半分の通り、ACA-PyのPublic DIDをAuthorロールでLedger上に作成し、Authorが自身のTransactionをLedgerに書き込むことができないことを確認します。

その次に、上図の下半分ように、Authorロールを付与したACA-PyとEndorserロールを付与したACA-Pyを用意し、Authorからの署名要求をEndorserが処理し、Authorが返却されたTransactionを書き込めることを確認します。

(1) 上図の上半分の検証

ここでは、デフォルトモードかつAuthorロールでIssuer(ACA-Py)を構築します。そしてTransactionの書き込みができないことを確認します。

まずvon-networkのUIからIndy LedgerにDIDを生成します。この時、RoleをEndorserではなくNoneに設定します。

LedgerにDIDが生成されたことを確認します。

次に上記のSEEDをパラメーターに含めてACA-Pyを起動します。
正常に起動すると、Endorserの時と同様にTransactionの1種(Type:ATTRIB)ができていることがわかります。

次にACA-PyのAdmin APIから別のTransaction(Type:Schema)を生成するエンドポイントを叩きます。

# request
curl -X 'POST' \
  'http://localhost:8031/schemas' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "attributes": [
    "name", "year","major"
  ],
  "schema_name": "graduation certificate",
  "schema_version": "1.0"
}'
# response
{
  "schema_id": "9NcSZTKydMbPNVrCP58SCb:2:graduation certificate:1.0",
  "schema": {
    "ver": "1.0",
    "id": "9NcSZTKydMbPNVrCP58SCb:2:graduation certificate:1.0",
    "name": "graduation certificate",
    "version": "1.0",
    "attrNames": [
      "major",
      "year",
      "name"
    ],
    "seqNo": null
  }
}

Admin API上はレスポンスコード200で成功したように見えますが、その後Ledgerを見てもTransactonは生成されていませんでした。ここでLedgerのログを確認すると、想定した通り、認可のエラーになっていることがわかりました。

node1_1 | 2022-04-25 05:19:09,047|WARNING|auth_request_validator.py|Request Request: {'reqId': 1650863948975850900, 'operation': {'data': {'attr_names': ['major', 'name', 'year'], 'name': 'graduation certificate', 'version': '1.0'}, 'type': '101'}, 'identifier': '9NcSZTKydMbPNVrCP58SCb', 'signature': '2usBiVYkDpsrEhgDeM49akZXwqkRBJchJtX4XA7ra5sCri9dRmRESqRXUTyNAGpGgTXHmk9ouNkeSfc7doT3c6zH', 'protocolVersion': 2} cannot be authorized by reason: Rule for this action is: 1 TRUSTEE signature is required OR 1 STEWARD signature is required OR 1 ENDORSER signature is required

node1_1 | 2022-04-25 05:19:09,048|WARNING|ordering_service.py|Node1:0 encountered exception UnauthorizedClientRequest('9NcSZTKydMbPNVrCP58SCb', 1650863948975850900, 'Rule for this action is: 1 TRUSTEE signature is required OR 1 STEWARD signature is required OR 1 ENDORSER signature is required\nFailed checks:\nConstraint: 1 TRUSTEE signature is required, Error: Not enough TRUSTEE signatures\nConstraint: 1 STEWARD signature is required, Error: Not enough STEWARD signatures\nConstraint: 1 ENDORSER signature is required, Error: Not enough ENDORSER signatures') while processing Request: {'reqId': 1650863948975850900, 'operation': {'data': {'attr_names': ['major', 'name', 'year'], 'name': 'graduation certificate', 'version': '1.0'}, 'type': '101'}, 'identifier': '9NcSZTKydMbPNVrCP58SCb', 'signature': '2usBiVYkDpsrEhgDeM49akZXwqkRBJchJtX4XA7ra5sCri9dRmRESqRXUTyNAGpGgTXHmk9ouNkeSfc7doT3c6zH', 'protocolVersion': 2}, will reject

(2) 上図の下半分の検証

メインパートです。以下、流れです。

  1. (後にEndorserロールに設定する)ACA-Pyを起動する。
  2. (後にAuthorロールに設定する)ACA-Pyを起動する。
  3. 通常のAgent間でのConnection生成と同様の手法で、ACA-Py間にConnectionを張る。
  4. 上記で生成したConnectionのコンテキスト上で、2つのACA-Pyそれぞれが自身の役割を設定する。
  5. Authorにて、Transaction(Schema)を作成するAdmin APIのエンドポイントを叩く。バックグラウンドで以下のフローが走る。
    1. AuthorがEndorserにTransactionの署名依頼を出す。
    2. Endorserが署名をして、TransactionをAuthorに返却する。
    3. AuthorがTransactionの書き込み依頼をLedgerに出す。
    4. Steward(Indy Node)が、Ledgerに登録されているEndorserPublic DIDから、署名を検証して、LedgerにTransactionを書き込む。
  6. AuthorのSchemaがLedgerに作成されていることを確認する。
1. (後にEndorserロールに設定する)ACA-Pyの起動

拙著内のdocker-compose.ymlに対し、以下のパラメーターを足します。

--auto-endorse-transactions

auto-endorser-transactionsはAuthorからのendorse依頼を無条件で自動的に処理します。このパラメーターを付けない場合、Authorからの依頼があったことをイベントとしてWebhookに通知します。そしてイベントを受けとったControllerはEndpoint “/transactions/{transaction_id}/endorse” を叩くことでendorserが完了します。

事前にvon-networkのUIからLedgerにEndorserロールでこのACA-PyのPublic DIDを作成しておいて、ACA-Pyを起動します。

2. (後にAuthorロールに設定する)ACA-Pyの起動

前述拙著内のdocker-compose.ymlに対し、以下のパラメーターを足します。

--auto-request-endorsement
--auto-write-transactions

auto-request-endorsementパラメーターを付与すると、AuthorがTransactionを作成するEndpointを叩いた際に、その裏で自動的にEndorserにendorseリクエストが飛ぶようになります。付与しない場合は、AuthorのControllerは、Transactionを作成するEndpointを叩いた際に取得できるTransaction IDをクエリパラメーターにして、Endpoint “/transactions/create-request”を明示的に叩くことで、Endorserにリクエストを飛ばすことができます。

auto-write-transactionsパラメータを付与すると、Endorserによる署名処理完了後に返却されるTransactionに対し、Authorが自動的にLedgerに書き込みをします。付与しない場合は、AuthorのControllerは明示的にEndpoint “/transactions/{tran_id}/write” を叩く必要があります。

このACA-Pyも下図のように、起動前にロールをNoneにしてLedgerにPublic DIDを作成しておきます。

3. ACA-Py間のConnectionの生成

割愛します。

4. 両ACA-Pyへのロール設定

まずAuthor側ACA-PyでEndpoint “set-endorser-role” を叩いて自身に対しAuthor役の設定をします。パスパラメーターにEndorserに対するConnection IDを指定しています。

# Request
curl -X 'POST' \
  'http://localhost:8041/transactions/d4c725e6-0414-4cd9-85f9-ddbf676f4116/set-endorser-role?transaction_my_job=TRANSACTION_AUTHOR' \
  -H 'accept: application/json' \
  -d ''

 # Reponse
{
  "transaction_my_job": "TRANSACTION_AUTHOR"
}

次にEndorser側で自身に対しEndorser役の設定をします。

# Request
 curl -X 'POST' \
  'http://localhost:8031/transactions/c79cd7c9-f492-4f45-86c2-f9149397e97c/set-endorser-role?transaction_my_job=TRANSACTION_ENDORSER' \
  -H 'accept: application/json' \
  -d ''

# Response
  {
  "transaction_their_job": "TRANSACTION_AUTHOR",
  "transaction_my_job": "TRANSACTION_ENDORSER"
}

最後に、Endpoint “set-endorser-info” でAuthor側からEndorserの情報を設定します。EndorserとのConnection IDをパスパラメーターに、およびEndorserのPublic DIDをクエリパラメーターに指定しています。

# Request
curl -X 'POST' \
  'http://localhost:8041/transactions/d4c725e6-0414-4cd9-85f9-ddbf676f4116/set-endorser-info?endorser_did=N5GgMcJAFK8o3J9eLXqPkg' \
  -H 'accept: application/json' \
  -d ''

# Response
  {
  "endorser_did": "N5GgMcJAFK8o3J9eLXqPkg",
  "endorser_name": null
}

ここまでで、Ledger上にTransactionを生成する準備ができました。

5. Schema作成

AuthorからSchema作成のEndpointを叩きます。
Endorserに対するConenction IDを指定します。

# Request
curl -X 'POST' \
  'http://localhost:8041/schemas?conn_id=d4c725e6-0414-4cd9-85f9-ddbf676f4116' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "attributes": [
    "name","department"
  ],
  "schema_name": "employee id",
  "schema_version": "1.4"
}'
# Response
{
  "txn": {
    "trace": false,
    "updated_at": "2022-04-27T07:24:58.546002Z",
    "_type": "http://didcomm.org/sign-attachment/%VER/signature-request",
    "meta_data": {
      "context": {
        "schema_id": "Ut4iiKexLtnEaBE68zpLLH:2:employee id:1.4",
        "schema_name": "employee id",
        "schema_version": "1.4",
        "attributes": [
          "name",
          "department"
        ]
      },
      "processing": {}
    },
    "transaction_id": "ba32de97-aa1b-4e30-a2a8-9caa5cef3974",
    "timing": {
      "expires_time": null
    },
    "state": "request_sent",
    "created_at": "2022-04-27T07:24:58.537944Z",
    "signature_response": [],
    "connection_id": "d4c725e6-0414-4cd9-85f9-ddbf676f4116",
    "messages_attach": [
      {
        "@id": "006b20d0-7e6f-46ea-bdf2-781cdffc80df",
        "mime-type": "application/json",
        "data": {
          "json": "{\"endorser\":\"N5GgMcJAFK8o3J9eLXqPkg\",\"identifier\":\"Ut4iiKexLtnEaBE68zpLLH\",\"operation\":{\"data\":{\"attr_names\":[\"department\",\"name\"],\"name\":\"employee id\",\"version\":\"1.4\"},\"type\":\"101\"},\"protocolVersion\":2,\"reqId\":1651044298503550856,\"signatures\":{\"Ut4iiKexLtnEaBE68zpLLH\":\"3UzHg7xniKtcP6LqRSPCQyKwARTGa7EzhfMnBtXMQHJzAvxWCyK2wjFP9wmuuEXNw4GD7KvV4AgyckcUP3W5efgn\"}}"
        }
      }
    ],
    "signature_request": [
      {
        "context": "did:sov",
        "method": "add-signature",
        "signature_type": "<requested signature type>",
        "signer_goal_code": "aries.transaction.endorse",
        "author_goal_code": "aries.transaction.ledger.write"
      }
    ],
    "formats": [
      {
        "attach_id": "006b20d0-7e6f-46ea-bdf2-781cdffc80df",
        "format": "dif/endorse-transaction/request@v1.0"
      }
    ]
  }
}
6. Ledger上のSchemaの確認

von-networkのUIから、AuthorによるTransactionを作成できたか確認してみます。

上記からEndorsermentが機能することを確認できました。

終わりに

簡単にではありますが、2つの新モードをそれぞれ試してみました。
どなたかのお役に立てたならば幸いです。