🎣

XRPLのスマコン機能「Hooks」を軽く触ってみる

2023/06/08に公開

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用のサイドチェーンのリリースが予定されています。

利用可能な言語

HooksはWebAssembly(WASM)バイナリであるため、多くの言語で利用することが可能です。

執筆時点ではC言語でフル機能を利用することが可能であり、AssemblyScript(TypeScriptのようなもの)でのライブラリ開発が進められています。

WASMであるため理論的にはRustやGoなどのさまざまな言語で開発が可能です。

スターター

Hooksのサンプルは以下のリポジトリで公開されています。

https://github.com/XRPL-Labs/hookscript/tree/main/hook-api-examples

今回はこの中のstarterを利用してHooksのコンパイルやデプロイなどを行ってみます。

hook-api-examples/starterで作業を行います。

パッケージのインストール

まずはパッケージのインストールを行います。

yarn install

コードの確認

starter.tsファイルがHooksのコード本体となります。

https://github.com/XRPL-Labs/hookscript/blob/main/hook-api-examples/starter/starter.ts

処理は何も行わず、トランザクションを許可するだけのコードとなっています。

コンパイル

上記のコードをコンパイルします。

yarn compile

次のような出力があれば成功です。

✨  Done in 0.80s.

starter.wasmファイルが作成されます。

デプロイ

コンパイルしたコードをHooksにデプロイします。
デプロイの前にデプロイ対象とするアカウントを取得しましょう。

次のサイトのHooks FacucetのGet Someボタンを押してアカウントを取得しましょう。
https://hooks-testnet-v3.xrpl-labs.com

表示されたsecretの値をメモしておいてください。

次のコマンドでデプロイを行います。

node deploy.js <取得したsecret>

次のような出力があり、engine_result'tesSuccess'であればデプロイ成功です。

paying 99020 drops to install hook of 198 bytes
{
  accepted: true,
  account_sequence_available: 3755605,
  account_sequence_next: 3755605,
  applied: true,
  broadcast: true,
  engine_result: 'tesSUCCESS',
  engine_result_code: 0,
  engine_result_message: 'The transaction was applied. Only final in a validated ledger.',
  kept: true,
  open_ledger_cost: '99010',
  queued: false,
  tx_blob: '120016210000535A2400394E546840000000000182CC732102F8AC1C2F62EDBFBC47A55DB00237A3FC68B322497A22E109B421A786C9C72EE37446304402200BCC7AAD9446A7A9759CEDA934FD49F19A0A508843FB61A9980DF1BACAA98F0B022023CFC812CD518C60085A9DE0764976E0184A84A5CE47EBD9E355EF9F4E5AC4B9811444C703152BE352AD4B349FBFBDD87AFE6235E0B9FBEE1014000022000000015014000000000000000000000000000000000000000000000000000000003E3FF5BE502011111111111111111111111111111111111111111111111111111111111111117BC1050061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60017F017E60027F7F017F02230303656E76057472616365000003656E7606616363657074000103656E76025F67000303020102050301000107110204686F6F6B0003066D656D6F727902000A2601240041A008419C0828020041004100410010001A41D00841CC08280200420010011A42000B0B350400418C080B012C004198080B1901000000110000004163636570742E633A2043616C6C65642E0041BC080B011C0041C8080B0101E1F1',
  tx_json: {
    Account: 'rfGCMeKtjEjY2XutXEuaJQf33Gr31daGFu',
    Fee: '99020',
    Hooks: [ [Object] ],
    NetworkID: 21338,
    Sequence: 3755604,
    SigningPubKey: '02F8AC1C2F62EDBFBC47A55DB00237A3FC68B322497A22E109B421A786C9C72EE3',
    TransactionType: 'SetHook',
    TxnSignature: '304402200BCC7AAD9446A7A9759CEDA934FD49F19A0A508843FB61A9980DF1BACAA98F0B022023CFC812CD518C60085A9DE0764976E0184A84A5CE47EBD9E355EF9F4E5AC4B9',
    hash: '337064A1209921702750978E3ECD55D0C26C45CCF0817B3771AC54C184AF60EF'
  },
  validated_ledger_index: 3755664
}
Shutting down...

出力内のhashを使ってトランザクションを確認してみます。
次のサイトの右上の検索欄にhashの値を入力して検索してみましょう。

https://hooks-testnet-v3-explorer.xrpl-labs.com

上の例では337064A1209921702750978E3ECD55D0C26C45CCF0817B3771AC54C184AF60EFがhashがhashの値です。

https://hooks-testnet-v3-explorer.xrpl-labs.com/tx/337064A1209921702750978E3ECD55D0C26C45CCF0817B3771AC54C184AF60EF

metaフィールドを確認するとHookオブジェクトが作成されていることが確認できます。

このままでは実際にデプロイしたHookの動作確認はできないため、少しだけコードを書き換えてみます。

hookが呼び出されたらrDADDYfnLvVY9FBnS8zFXhwYFHPuU5q2Skに1drops(=0.000001)を送信するコードです。

function hook(reserved: i32) {
  etxn_reserve(1)
  const acc_byte = util_accid('rDADDYfnLvVY9FBnS8zFXhwYFHPuU5q2Sk')
  const destination = new Account(acc_byte)
  emit({
    transactionType: TransactionType.Payment,
    destination,
    amount: Amount.fromDrops(1)
  })
  accept()
}

同様にコンパイルとデプロイを行います。

yarn compile
node deploy.js <取得したsecret>
デプロイ結果
{
  accepted: true,
  account_sequence_available: 3755611,
  account_sequence_next: 3755611,
  applied: true,
  broadcast: true,
  engine_result: 'tesSUCCESS',
  engine_result_code: 0,
  engine_result_message: 'The transaction was applied. Only final in a validated ledger.',
  kept: true,
  open_ledger_cost: '1795510',
  queued: false,
  tx_blob: '120016210000535A2400394E5A6840000000001B65C0732102F8AC1C2F62EDBFBC47A55DB00237A3FC68B322497A22E109B421A786C9C72EE374473045022100FC67E51A75F27841108CB6B7A403B8D240FA81EC9BFDFD74F517E2E96A58E64D02206DBB88615AB2DD0354A910E250DA909B5FC254E0F2F2291ECA84EF507738AF4F811444C703152BE352AD4B349FBFBDD87AFE6235E0B9FBEE1014000022000000015014000000000000000000000000000000000000000000000000000000003E3FF5BE502011111111111111111111111111111111111111111111111111111111111111117BCE460061736D0100000001250660027F7F017E60017F017E60037F7F7E017E60047F7F7F7F017E6000017E60027F7F017F02A0010A03656E760C6574786E5F72657365727665000103656E7608726F6C6C6261636B000203656E760A7574696C5F6163636964000303656E760A6C65646765725F736571000403656E760C686F6F6B5F6163636F756E74000003656E760C6574786E5F64657461696C73000003656E760D6574786E5F6665655F62617365000003656E7604656D6974000303656E7606616363657074000203656E76025F6700050302010105030100010606017F0141000B07110204686F6F6B000A066D656D6F727902000AA219019F1902017E067F410110002201420152044041A008419C08280200200142FF018342809680A8F7008410011A0B2300450440419C0924000B2300220041046A2202412C6A22033F00411074410F6A4170714B0440000B200324002000412C360200200241046B22004100360204200041003602082000410436020C20004114360210200241106A2200411441C00841BC0828020010022201421453044041A008419C08280200200142FF018342809680908B018410011A0B2300450440419C0924000B2300220241046A2203411C6A22043F00411074410F6A4170714B0440000B200424002002411C360200200341046B22024100360204200241003602082002410536020C20024104360210200341106A22022000360200200041146B280210411447044041A008419C08280200200041146B34021042FF018342808280F0008410011A0B2300450440419C0924000B2300220041046A220341EC016A22043F00411074410F6A4170714B0440000B20042400200041EC01360200200341046B22004100360204200041003602082000410636020C200041D001360210200341106A2200410036020020004100360204200041003602082000410036020C2000410036021020004100360214200041A0083602182000410036021C2000410036022020004100360224200041003602282000410036022C200041003A003020004100360234200041003602382000410036023C2000410036024020004100360244200041003602482000410036024C2000410036025020004100360254200041003602582000410036025C2000410036026020004100360264200041003602682000410036026C2000410036027020004100360274200041003B0178200041A00836027C2000410036028001200041003602840120004100360288012000410036028C012000410036029001200041003602940120004100360298012000410036029C01200041003602A001200041003602A401200041003602A801200041003602AC01200041003602B001200041003602B401200041003602B801200041003602BC01200041003602C001200041003602C401200041003A00C801200041003602CC0120004100360200200020023602042300450440419C0924000B2300220241046A2203411C6A22043F00411074410F6A4170714B0440000B200424002002411C360200200341046B22024100360204200241003602082002410436020C20024108360210200341106A220242003C0000200242003C0001200242003C0002200242003C0003200242003C0004200242003C0005200242003C0006200242013C00072300450440419C0924000B2300220341046A2204411C6A22053F00411074410F6A4170714B0440000B200524002003411C360200200441046B22034100360204200341003602082003410736020C20034104360210200441106A22032002360200200241146B280210410847047F200241146B2802104130470541000B044041A008419C08280200200241146B34021042FF018342808480D8008410011A0B200020033602082000410036020C20004100360210200041003602142000410036021C2000410036022020004100360224200041003602282000410036022C200041003A003020004100360234200041003602382000410036023C2000410036024020004100360244200041003602482000410036024C2000410036025020004100360254200041003602582000410036025C2000410036026020004100360264200041003602682000410036026C2000410036027020004100360274200041003B01782000410036028001200041003602840120004100360288012000410036028C012000410036029001200041003602940120004100360298012000410036029C01200041003602A001200041003602A401200041003602A801200041003602AC01200041003602B001200041003602B401200041003602B801200041003602BC01200041003602C001200041003602C401200041003A00C801200041003602CC0120002802082202450440000B41F80141A002200228020041146B2802104108461B220341106A220441FCFFFFFF034B0440000B2300450440419C0924000B2300220541046A2206200441136A41707141046B22046A22073F00411074410F6A4170714B0440000B2007240020052004360200200641046B22044100360204200441003602082004410436020C200420033602101003A721032300450440419C0924000B2300220441046A2205412C6A22073F00411074410F6A4170714B0440000B200724002004412C360200200541046B22044100360204200441003602082004410436020C20044114360210200541106A2204411410042201421452044041A008419C08280200200142FF01834280968080FE008410011A0B200641106A220541123A0000200541003A0001200541003A00022000280274418080808078722106200541036A220741223A0000200720064118763A0001200720064110763A0002200720064108763A0003200720063A0004200028020C2106200741056A220741233A0000200720064118763A0001200720064110763A0002200720064108763A0003200720063A0004200741056A220641243A0000200641003A0001200641003A0002200641003A0003200641003A000420002802102107200641056A2206412E3A0000200620074118763A0001200620074110763A0002200620074108763A0003200620073A0004200641056A220641203A00002006411A3A00012006200341016A22074118763A0002200620074110763A0003200620074108763A0004200620073A0005200641066A220641203A00002006411B3A00012006200341056A22034118763A0002200620034110763A0003200620034108763A0004200620033A0005200641066A2103200228020041146B280210410846047F20022802002102200341E1003A0000200320022D0000410F7141406B3A0001200320022D00013A0002200320022D00023A0003200320022D00033A0004200320022D00043A0005200320022D00053A0006200320022D00063A0007200320022D00073A0008200341096A0520022802002102200341E1003A0000200341016A22062002290300370300200641086A2206200241086A2202290300370300200641086A2206200241086A2202290300370300200641086A2206200241086A2202290300370300200641086A2206200241086A220229030037030020062002290308370308200341316A0B220241E8003A0000200242C0003C0001200242003C0002200242003C0003200242003C0004200242003C0005200242003C0006200242003C0007200242003C0008200241096A220341F3C2003B0100200342003703022003420037030A200342003703122003420037031A200341003A0022200341236A22034181013A0000200341143A0001200320042903003703022003200429030837030A2003200428021036021220002802042200450440000B20002802002104200341166A22004183013A0000200041143A0001200020042903003703022000200429030837030A20002004280210360212200541146B280210200041166A20056B22036B21042300450440419C0924000B2300220041046A2206412C6A22073F00411074410F6A4170714B0440000B200724002000412C360200200641046B22004100360204200041003602082000411136020C20004110360210200641106A2200200236020C20004504402300450440419C0924000B2300220041046A2202411C6A22063F00411074410F6A4170714B0440000B200624002000411C360200200241046B22004100360204200041003602082000410936020C2000410C360210200241106A21000B200020053602002000200336020420002004360208200028020020002802046A200028020810052201420053044041A008419C08280200200142FF01834280968080F5008410011A0B20002802002202200241146B28021010062201420053044041A008419C08280200200142FF018342809680B8F5008410011A0B200028020C220041E8003A000020002001423888423F8342407D3C00012000200142308842FF01833C00022000200142288842FF01833C00032000200142208842FF01833C00042000200142188842FF01833C00052000200142108842FF01833C00062000200142088842FF01833C00072000200142FF01833C00082300450440419C0924000B2300220041046A2203413C6A22043F00411074410F6A4170714B0440000B200424002000413C360200200341046B22004100360204200041003602082000410436020C20004120360210200341106A41202002200241146B28021010072201420053044041A008419C08280200200142FF018342809680B0EC008410011A0B41A008419C08280200420010081A42000B0B6A0600418C080B011C004198080B01010041AC080B013C0041B8080B2A0100000022000000724441444459666E4C7656593946426E53387A46586877594648507555357132536B0041EC080B012C0041F8080B17010000000F000000756E6578706563746564206E756C6CE1F1',
  tx_json: {
    Account: 'rfGCMeKtjEjY2XutXEuaJQf33Gr31daGFu',
    Fee: '1795520',
    Hooks: [ [Object] ],
    NetworkID: 21338,
    Sequence: 3755610,
    SigningPubKey: '02F8AC1C2F62EDBFBC47A55DB00237A3FC68B322497A22E109B421A786C9C72EE3',
    TransactionType: 'SetHook',
    TxnSignature: '3045022100FC67E51A75F27841108CB6B7A403B8D240FA81EC9BFDFD74F517E2E96A58E64D02206DBB88615AB2DD0354A910E250DA909B5FC254E0F2F2291ECA84EF507738AF4F',
    hash: '7DE7A6AFB5740314D7BBAC2750175BB324628F73DD6F7F06BE728DEE4FA2F92C'
  },
  validated_ledger_index: 3756560
}
Shutting down...

デプロイが成功したら、アカウントからトランザクションを送信してみましょう

node pay.js <取得したsecret> <送信するXRP> <宛先アドレス>の形式で入力します。

node pay.js <取得したsecret> 1 rJ8MSNPq9JLhRfGr1Z1xN7MjPbRFrQAgq5
実行結果
{
  accepted: true,
  account_sequence_available: 3755612,
  account_sequence_next: 3755612,
  applied: true,
  broadcast: true,
  engine_result: 'tesSUCCESS',
  engine_result_code: 0,
  engine_result_message: 'The transaction was applied. Only final in a validated ledger.',
  kept: true,
  open_ledger_cost: '1525',
  queued: false,
  tx_blob: '120000210000535A2400394E5B6140000000000F42406840000000000005FF732102F8AC1C2F62EDBFBC47A55DB00237A3FC68B322497A22E109B421A786C9C72EE374473045022100EDE64F008AC1F3765450415C2DE594C95A30C50B3F5FFD3B9D33332B42C2769702204D8B4F552232E5631BED85375A35CB4E9293DDCDEE6CD5F0F10348DEEF1DCB41811444C703152BE352AD4B349FBFBDD87AFE6235E0B98314C30DEA36B07AE7E21E36C143E5D4F50AE47F08B0',
  tx_json: {
    Account: 'rfGCMeKtjEjY2XutXEuaJQf33Gr31daGFu',
    Amount: '1000000',
    Destination: 'rJ8MSNPq9JLhRfGr1Z1xN7MjPbRFrQAgq5',
    Fee: '1535',
    NetworkID: 21338,
    Sequence: 3755611,
    SigningPubKey: '02F8AC1C2F62EDBFBC47A55DB00237A3FC68B322497A22E109B421A786C9C72EE3',
    TransactionType: 'Payment',
    TxnSignature: '3045022100EDE64F008AC1F3765450415C2DE594C95A30C50B3F5FFD3B9D33332B42C2769702204D8B4F552232E5631BED85375A35CB4E9293DDCDEE6CD5F0F10348DEEF1DCB41',
    hash: '2C9EDF33F892848364AF55E6F4293527ED63058AFA09D9E87D12E1C7430D140A'
  },
  validated_ledger_index: 3756562
}
Shutting down...

実行されたトランザクションを確認すると、EmittedTxnオブジェクトが作成されていることがわかります。

さらにアカウントのトランザクションを確認すると、EmittedTxnを使用してトランザクションが自動的に発行されていることがわかります。

rDADDYfnLvVY9FBnS8zFXhwYFHPuU5q2Skに対して1dropsが送金されていますね。

https://hooks-testnet-v3-explorer.xrpl-labs.com/tx/4EB7955D8791E2A9A761427EB6085DF433551C918FBDC96D3389F1B036C7E048

まとめ

今回の記事はHooksの基礎的な部分の説明でした。AssemblyScript用ライブラリのドキュメントはまだなく、手探りで実装している部分も多いですが、このように実際に動作するコードの作成・デプロイを行うことができています。

今後はHooksサイドチェーンのリリースも予定されており、Hooks関連の開発はさらに活発になっていくことでしょう。

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

Discussion