🎣

XRPL HooksのState機能を試す

2023/06/26に公開

XRPレジャー とは

XRPレジャーはBitcoinやEthereumなどと同じ分散型のパブリックブロックチェーンです。ビットコインの初期コントリビュータを含む3人の開発者により2012年に開発され、PoWやPoSとは異なる独自のコンセンサスアルゴリズムが用いられています。

XRPレジャーではトランザクションはプロトコルネイティブであり、開発者が個別にNFTやDEXなどを機能を構築することなく、利用することができます。

Hooks

XRPLを使ったプロダクトの開発者はNFTやDEXなどで用意された多くのパラメータなどを利用することができますが、独自のロジックを実装することは出来ませんでした。

2021年に開発が発表されたXRPレジャーにスマートコントラクト機能を実装するHooksでは、開発者が独自のロジックを実装することが可能となります。

https://hooks.xrpl.org

各コントラクトをHookと呼び、その中ではトランザクションを拒否したり、別のトランザクションを送信したり、またはStateを使った状態の管理を行うことが可能です。

Hooksは2023年6月にセキュリティ監査に合格しており、今後Hooks用のサイドチェーンのリリースが予定されています。

State機能

XRPL HooksではEVMをはじめとした他のスマートコントラクトと同様にStateを保持することが可能です。
State情報はレジャー上に公開されているため、他のアカウントなどからの参照が可能となっています。

https://xrpl-hooks.readme.io/docs/state-management

Stateは同一アカウントの同一ネームスペースのHook内で共有されるため、前述の条件であれば複数のHookからStateの操作を行うことが可能です。
ネームスペース外のHookからStateを操作するためにForeign Stateという機能がありますが、ここでは割愛します。

https://xrpl-hooks.readme.io/docs/namespaces

他のオブジェクトと同様、アカウントに設定したHookがStateを保有するためには準備金が必要となります。

Stateのサイズ

Stateはkey-valueの形式で保存され、key32バイト固定valueバリデータによるガバナンス投票で決定されます。現在稼働中のHooksテストネットでは128バイトに設定されています。

試してみる

Hooksを触ったことがない場合は、まず以下の記事を読むことをお勧めします。

https://zenn.dev/tequ/articles/xrpl-hooks-starter

以降はこの記事と同様にhook-api-examples/starterディレクトリ内で作業を行うこととします。

https://github.com/XRPL-Labs/hookscript

今回は、Stateの追加・削除を試すため、以下のようなHookを作成します

  • 送信したXRPの額が奇数の場合、Stateを追加・更新
  • 偶数の場合、Stateを削除

以下が作成したHookのコードです。
解説の都合上、100XRP以上のPaymentではロジックは走らないようにしています。

function hook(reserved: i32) {
  if (Tx.TransactionType != TransactionType.Payment)
    accept("Allowing non-Payment transaction.");
  const amount = Tx.Amount;
  if (amount.drops > 100000000) {
    accept("Allowing over 100XRP Payment.");
  }
  const accid = Tx.Account.toString();

  const xrpAmount = <u8>(amount.drops / 1000000);

  let buffer = new ByteArray(1);
  buffer[0] = xrpAmount;
  let value_view = new ByteView(buffer, 0, buffer.length);
  
  if (xrpAmount % 2 === 1) {
    LocalState.setItem(accid, value_view);
  } else {
    LocalState.removeItem(accid);
  }
  accept();
}

パートごとに解説します。

ここではPaymentトランザクション以外のトランザクションでは以降の処理を行わずにスキップしたり、100XRP以上の送金の場合にスキップしています。

  if (Tx.TransactionType != TransactionType.Payment)
    accept("Allowing non-Payment transaction.");
  const amount = Tx.Amount;
  if (amount.drops > 100000000) {
    accept("Allowing over 100XRP Payment.");
  }
  const accid = Tx.Account.toString;

トランザクション情報に含まれるAmountフィールドがdrop単位であるため、XRP単位に変換しています。
u8型であり0~254までの値を格納できます。
その値をByteView型のオブジェクトへ格納します。

  const xrpAmount = <u8>(amount.drops / 1000000);

  let buffer = new ByteArray(1);
  buffer[0] = xrpAmount;
  let value_view = new ByteView(buffer, 0, buffer.length);

XRPの値ごとに処理を分けます。
Hooks向けのAssemblyScriptライブラリではLocalStateを利用しState操作を行うことができます。

  • LocalState.getItem(key)
  • LocalState.setItem(key,value)
  • LocalState.removeItem(key)

LocalStateの内部ではstateファンクションやstate_setファンクションを呼び出しています。

https://xrpl-hooks.readme.io/reference/state

https://xrpl-hooks.readme.io/reference/state_set

  if (xrpAmount % 2 === 1) {
    LocalState.setItem(accid, value_view);
  } else {
    LocalState.removeItem(accid);
  }
  accept();

実行結果

Stateの作成

21XRPの送金を行った結果、HookStateオブジェクトが作成されました。

keyはアカウントID(rから始まるアドレスではなくバイナリデータ)、valueは21の16進数値である15が設定されています。

1

https://hooks-testnet.xrpl.org/transactions/3AC908CAABE40F7B88E5A71CDA16B6E1D7878CFCFB06FC8513E88DBB59C6DB08/raw

Stateの更新

99XRPの送金を行った結果、HookStateオブジェクトが更新されました。

keyを表すHookStateKeyはそのまま、HookStateDataフィールドが更新されています。

2

https://hooks-testnet.xrpl.org/transactions/6253C347EA1EAFE315C3E780D3C20BBB953226A312EBC165F7A42CB31430ED23/raw

別のアカウントからの送金

先ほどとは別のアカウントから送金しました。

送金元アカウントを表すHookStateKeyが異なるStateが新規に作成されました。

3

https://hooks-testnet.xrpl.org/transactions/AAB89E1B68EF7A9FDECB0831F3AD7A9ED850211FE64E28D87EDBE208AD271AA1/raw

Stateの削除

2XRPの送金を行った結果、送金元アカウントに紐づくHookStateオブジェクトが削除されました。

4

まとめ

スマートコントラクトを使う上でState機能は当然無くてはならないものです。
AssemblyScriptライブラリはまだまだ開発段階であるため、粗い部分も多いですが、今後のアップデートに期待です。

XRPL Labsにより今後Hooksサイドチェーンのローンチも発表されており、このライブラリも整備されていくことでしょう。

興味を持たれた方はXRPL開発者のDiscordチャンネルへ是非お越しください!
日本語チャンネルもありますので、英語ができなくても大丈夫です!
https://xrpldevs.org

Discussion