見出し画像

【Jaguar's Blog 12】Symbol KYC Required Mosaic

この記事は2024年1月24日にNEM/Symgolのコア開発者Jaguar氏によって投稿された記事「Symbol KYC Required Mosaic」をChatGPTを用いて翻訳したものです。


Symbolでは、事前承認されたアカウント間でのみ送信可能なモザイクを作成することができます。これを可能にする主要な機能は、モザイクの制限です。この記事では、この機能を使用してモザイクをKYCを通過したアカウントにのみ制限する方法について探っていきます。

まず最初に、Symbol SDKを使用してSymbolトランザクションを送信する方法に関するこの記事を確認してください。この記事では、prepare_and_send_transaction関数を使用して、例を簡略化します。


モザイク - Background

デフォルトでは、モザイクはモザイクの所有者との間でのみ送受信できます。これは一部のケースで十分であるかもしれませんが、他の場合には制限があります。Symbolでは、モザイクの動作を定義する共通のトークンのパラダイムをモザイクフラグとして定義しています。モザイクが作成されると、対応するフラグを設定することでこれらの動作を採用できます。利用可能なモザイクフラグは以下の通りです:

  • SUPPLY_MUTABLE: モザイクは、モザイクの作成者が部分的な供給しか所有していない場合でも、供給の変更をサポートします。

  • TRANSFERABLE: モザイクは、任意のアカウント間での転送をサポートします。

  • RESTRICTABLE: モザイクは、モザイクの作成者によって構成されたカスタム制限をサポートします。

  • REVOKABLE: モザイクは、モザイクの作成者によるトークンの取り消しをサポートします。

制限

Symbolには、セキュリティトークンを考慮して作成されたモザイクの制限と呼ばれる機能があります。モザイクの制限は、次の2つの部分で構成されています:

  1. グローバル制限は、モザイクを保有するすべてのアカウントによって満たされる必要がある制約を定義します。

  2. アドレス制限は、アカウントにキーと値のペアを設定し、グローバル制限を満たすために使用できます。

モザイクのグローバル制限は、自己言及的であるか、任意のモザイクを指すことができます。後者の場合、共通の属性を一度だけ定義して再利用できます。例えば、KYCプロバイダーはモザイクを作成し、モザイクのアドレス制限を使用してKYCの結果を割り当てることができます。KYCアカウントに制限されたい任意のモザイクは、その単一のリストを参照できます。

セットアップ

この記事では、2つのモザイクを作成します:

  1. 制限されているモザイク。すべてのKYCアカウント間で自由な転送を行いたいので、転送可能である必要があります。非KYCアカウントによって保有されることを制限したいので、restrictable である必要があります。

  2. KYC Mosaic は、アドレス制限を維持するために使用されるモザイクです。このモザイクに関連するアドレス制限を使用してKYCの結果を定義したいので、restrictable である必要があります。

モザイクを作成して送信するためのヘルパー関数をいくつか書いてみよう:

async def create_mosaic(facade, signer_key_pair, nonce, inital_supply, flags=0):
    embedded_transactions = [
        facade.transaction_factory.create_embedded({
            'type': 'mosaic_definition_transaction_v1',
            'signer_public_key': signer_key_pair.public_key,
            'nonce': nonce,
            'divisibility': 0,
            'flags': flags
        }),
        facade.transaction_factory.create_embedded({
            'type': 'mosaic_supply_change_transaction_v1',
            'signer_public_key': signer_key_pair.public_key,
            'mosaic_id': generate_mosaic_id(facade.network.public_key_to_address(signer_key_pair.public_key), nonce),
            'delta': inital_supply,
            'action': 'increase'
        })
    ]

    merkle_hash = facade.hash_embedded_transactions(embedded_transactions)

    await prepare_and_send_transaction(facade, signer_key_pair, {
        'type': 'aggregate_complete_transaction_v2',
        'signer_public_key': signer_key_pair.public_key,
        'transactions_hash': merkle_hash,
        'transactions': embedded_transactions
    })

async def send_mosaic(facade, signer_key_pair, mosaic_id, recipient_address, amount):
    await prepare_and_send_transaction(facade, signer_key_pair, {
        'type': 'transfer_transaction_v1',
        'recipient_address': recipient_address,
        'mosaics': [
            {'mosaic_id': mosaic_id, 'amount': amount}
        ]
    })

次に、いくつかのアカウントを用意し、2つのモザイクを作成しよう:

facade = SymbolFacade('testnet')
    (signer_key_pair, signer_address) = get_test_account(facade, 1, 'signer')
    (recipient_key_pair, recipient_address) = get_test_account(facade, 2, 'recipient')
    (_, other_address) = get_test_account(facade, 3, 'other')

    nonce = 51
    await create_mosaic(facade, signer_key_pair, nonce, 100000, 'transferable restrictable')
    await create_mosaic(facade, signer_key_pair, nonce + 1, 1000, 'restrictable')

この段階では、主要なモザイクはまだ制約が設定されていないため、完全に転送可能です。モザイクの所有者(署名者)から受信者アカウントにモザイクを送信できます。その受信者アカウントは、モザイクの所有者と直接やり取りしない第三のアカウントにモザイクを送信できます。

mosaic_id = generate_mosaic_id(facade.network.public_key_to_address(signer_key_pair.public_key), nonce)
    await send_mosaic(facade, signer_key_pair, mosaic_id, recipient_address, 10)
    await send_mosaic(facade, recipient_key_pair, mosaic_id, signer_address, 5)
    await send_mosaic(facade, recipient_key_pair, mosaic_id, other_address, 3)

制限の例

まず、KYCモザイクのグローバル・モザイク制限(reference_mosaic_id)を作成する必要があります:

  reference_mosaic_id = generate_mosaic_id(facade.network.public_key_to_address(signer_key_pair.public_key), nonce + 1)
    await prepare_and_send_transaction(facade, signer_key_pair, {
        'type': 'mosaic_global_restriction_transaction_v1',

        'mosaic_id': reference_mosaic_id,
        'restriction_key': 1,
        'previous_restriction_value': 0,
        'new_restriction_value': 1,
        'previous_restriction_type': 'none',
        'new_restriction_type': 'ge'
    })

`restriction_key` は、KYCモザイクにスコープを定義したローカルな識別子です。前述の値は、これが新しい制約であるため、0(restriction_value)およびnone(restriction_type)でなければなりません。新しい制約の値は、1(restriction_value)およびge(restriction_type)に設定されています。これは転送可能なモザイクとして使用する意図がないため、値は実際には重要ではありません。

次に、受信者アカウントのアドレスモザイク制限を設定します:

    await prepare_and_send_transaction(facade, signer_key_pair, {
        'type': 'mosaic_address_restriction_transaction_v1',

        'mosaic_id': reference_mosaic_id,
        'restriction_key': 1,
        'previous_restriction_value': 0xFFFFFFFFFFFFFFFF,
        'new_restriction_value': 1,
        'target_address': recipient_address
    })

`restriction_key` は、グローバルモザイク制約を作成する際に使用されたものと一致しなければなりません。前述の値は以前に未設定だったため、0xFFFFFFFFFFFFFFFFである必要があります。新しい値は1に設定されていますが、符号なし64ビットの任意の値が有効です。最後に、`target_address` を使用してそれを受信者アカウントに関連付けます。

現実のシナリオでは、KYCプロバイダーはアカウントがKYCをパスまたは失敗するに従って、アドレスモザイク制約を設定していくでしょう。その結果、多くのアカウントに設定されることになります。この例では、単一のアカウントにのみ設定しています。

最後に、制限したいモザイクにグローバルモザイク制限を作成します:

    await prepare_and_send_transaction(facade, signer_key_pair, {
        'type': 'mosaic_global_restriction_transaction_v1',

        'mosaic_id': mosaic_id,
        'reference_mosaic_id': reference_mosaic_id,
        'restriction_key': 1,
        'previous_restriction_value': 0,
        'new_restriction_value': 1,
        'previous_restriction_type': 'none',
        'new_restriction_type': 'ge'
    })

重要なのは、`reference_mosaic_id` がKYCモザイクに設定され、`restriction_key` が以前に使用されたものと一致していることです。これがモザイクアドレス制約を複数のモザイク間で共有できるようにする仕組みです。この規則により、モザイクはアドレス制約が1以上(ge)のアカウントに制約されます。

ℹ️ `new_restriction_value` および `new_restriction_type` は、任意の有効な値である必要があります。これらは、KYCモザイクのモザイクグローバル制約で使用された値と一致する必要はありません。

さて、制限を設定したので、実際に使ってみよう:

   await send_mosaic(facade, signer_key_pair, mosaic_id, recipient_address, 10)
   await send_mosaic(facade, signer_key_pair, mosaic_id, other_address, 5)

受信者アカウントには適切なアドレス制約値が設定されているため、最初の転送は成功します。他のアカウントには設定されていないため、転送は Failure_RestrictionMosaic_Account_Unauthorized エラーで失敗します。注意すべきは、送信者(モザイクの作成者)でさえも制約を無視して資格のないアカウントにモザイクを送信することはできないということです。これは私たちが達成しようとしていたことです!

Postscript

実際の実装では、KYCプロバイダーがアカウントの身元を確認する責任があります。プロバイダーは、単一の `restriction_key` を使用して、権限レベルに応じて異なる値を設定できます。例えば、より高い数値はより徹底した検証を示すかもしれません。また、KYCプロバイダーは複数の `restriction_key` を使用してさまざまな種類の識別を示すこともできます。この決定は完全にKYCプロバイダーに任されています。

その後、モザイクの作成者は、自身のモザイクに適切な制約を選択できます。複数のモザイクグローバル制約が定義できます。これらすべてが満たされる必要があり、転送が許可されます。

この記事が気に入ったらサポートをしてみませんか?