XRP Ledgerのペイメントチャネルを触ってみる
XRP Ledger とは
XRP LedgerはBitcoinやEthereumなどと同じ分散型のパブリックブロックチェーンです。PoWやPoSとは異なる独自のコンセンサスアルゴリズム(Proof of Association)が用いられています。
EVMによるスマートコントラクトは搭載しておらず、スマートトランザクタ(プロトコルネイティブで提供されている機能)を拡張することで進化し続けています。
DEXやNFTなどの機能だけでなく、エスくローやペイメントチャネル等の決済向けの高度な機能も備わっています。
ペイメントチャネル機能
ペイメントチャネルとは、送金の一部をオフチェーンにおいて処理し、後にオンレジャーでまとめて処理することで、オンレジャーでの処理コストを削減できる機能です。
XRP Ledgerの3~5秒のファイナリティを待つことなく、秒間数千~数万件の送金処理を可能とします。
XRP Ledgerメインネットではペイメントチャネル機能は2017年3月に有効化され利用可能となりました。
ペイメントチャネルに関するレジャーオブジェクト
次のPayChannel
オブジェクトを使いペイメントチャネルの情報が表現されます。
例えばペイメントチャネルの送信元と送信先、ペイメントチャネルで利用可能なXRP残高、送信済みのXRP残高、署名に利用する公開鍵などの情報があります。
ペイメントチャネルに関するトランザクションの種類
以下のようなトランザクションを利用することでペイメントチャネルが利用可能となっています。
PaymentChannelCreate
ペイメントチャネルを作成し、チャネルに資金を提供するトランザクションです。
PaymentChannelFund
送信者がチャネルに追加の資金を提供するトランザクションです。
PaymentChannelClaim
受信者がチャネルから資金を請求するトランザクションです。送信者からオフチェーンで送信された署名情報を利用して請求を行います。
また、いくつかの条件に応じて送信者、受信者またはそれ以外の第三者によりペイメントチャネルを閉じることができます。
1. ペイメントチャネルを作成する
ペイメントチャネルを作成します。
import { Wallet, Client, xrpToDrops, signPaymentChannelClaim, verifyPaymentChannelClaim, PaymentChannelClaimFlags } from 'xrpl'
const client = new Client("wss://testnet.xrpl-labs.com")
const alice = Wallet.fromSeed('sEdVSH8WdY2na2kGWhytNbEti8ZEMkB') // testnet account
const bob = Wallet.fromSeed('sEdVh9tvzFuhxEc8uXhyyMdopG3sNtt') // testnet account
const signature = Wallet.generate()
await client.connect()
// create channel
await client.submitAndWait({
TransactionType: "PaymentChannelCreate",
Account: alice.address,
Destination: bob.address,
Amount: xrpToDrops(1), // ペイメントチャネルの利用資金として1XRPを設定
SettleDelay: 86400, // 24 * 60 * 60 チャネルに資金がある場合でも86400秒(=1日)後にチャネルを閉じることが可能になる
PublicKey: signature.publicKey, // オフレジャーでの署名に利用する公開鍵
}, { wallet: alice })
2. ペイメントチャネルのIDを取得
account_channels
メソッドを使ってペイメントチャネルのIDを取得します。
const response = await client.request({
command: 'account_channels',
account: alice.address,
})
console.log(response.result.channels[0].channel_id)
const channel_id = response.result.channels[0].channel_id
PaymentChannelCreate
トランザクションのメタデータ(PayChannel
オブジェクトのLedgerIndex
フィールド)から取得する方法もあります。
3. オフレジャーで署名を作成する。
ペイメントチャネルで利用する送金の署名を作成します。
xrpl.jsのsignPaymentChannelClaim
を利用するとペイメントチャネル向けの署名が簡単に作成できます。
第二引数は送金するXRPの量です。drop建の量ではなくXRP建の量での指定が必要であることに注意してください。
const paychanSignature = signPaymentChannelClaim(channel_id, '1', signature.privateKey)
console.log(paychanSignature)
この署名情報は送信者によって作成され、PaymentChannelCreate
トランザクションで設定して公開鍵に紐付く秘密鍵によって署名されなければいけません。
署名したデータはその他必要なデータとともに受信者へ送信する必要があります。
4. 署名を検証する。
送金の受取人は送信者から署名情報などを受け取った後、その署名情報が正しいかどうかを検証する必要があります。
検証には2パターンの方法があります。
verifyPaymentChannelClaim
メソッドを利用する
パターン 1. xrpl.jsの対象となるチャネルID、送金されるXRPの量、署名情報、公開鍵を指定して検証を行います。
signPaymentChannelClaim
と同じくXRP建の量での指定が必要です。
const verified = verifyPaymentChannelClaim(channel_id, '1', paychanSignature, signature.publicKey)
channel_verify
を利用する
パターン 2. rippledのパブリックメソッドパターン1と指定する情報は代わりませんが、ノードとの通信が発生するため、パターン1に比べ遅延が発生します。
他のプログラム言語を使っており、検証メソッドがない場合などはこのメソッドを利用することが有効かもしれません。
const channelVerifyResponse = await client.request({
command: 'channel_verify',
amount: xrpToDrops(1),
channel_id,
public_key: signature.publicKey,
signature: paychanSignature
})
const verified = channelVerifyResponse.result.signature_verified
5. 資金を請求する
PaymentChannelClaim
トランザクションを利用してペイメントチャネルから資金を請求します。
これは送金の受取人または送金人により実行可能です。
Balance
フィールドには、このチャンネルでこれまで請求したXRPの額をdropで指定します。(今回の請求額を含む)
Amount
フィールドには、このトランザクションで請求するXRPの額をdropで指定します。この額はSigunature
フィールドによって署名された額と一致している必要があります。
送金人はSigunature
やPublicKey
フィールドを指定することなく資金を送金できます。
const response2 = await client.submitAndWait({
TransactionType: "PaymentChannelClaim",
Account: bob.address,
Channel: channel_id,
Balance: xrpToDrops(1),
Amount: xrpToDrops(1),
Signature: paychanSignature,
PublicKey: signature.publicKey,
}, { wallet: bob })
console.log(response2.result)
6. ペイメントチャネルに資金を追加する
PaymentChannelFund
トランザクションを利用してペイメントチャネルに資金を追加できます。
await client.submitAndWait({
TransactionType: "PaymentChannelFund",
Account: alice.address,
Channel: channel_id,
Amount: xrpToDrops(1),
}, { wallet: alice })
7. チャネルを閉じる
PaymentChannelClaim
トランザクションはペイメントチャネルを閉じる場合にも利用できます。
Flags
フィールドにtfClose
を指定することでペイメントチャネルを閉じることができます。
const response3 = await client.submitAndWait({
TransactionType: "PaymentChannelClaim",
Account: bob.address,
Channel: channel_id,
Flags: PaymentChannelClaimFlags.tfClose,
}, { wallet: bob })
console.log(response3.result)
まとめ
XRP Ledgerではコントラクト開発を行うことなく、組み込みの機能でペイメントチャネルを利用可能です。
これによりコントラクトリスクを最小限に抑え、安く安全にペイメントチャネルを利用できます。
今回はJavaScriptライブライxrpl.jsを利用してペイメントチャネルを作成し、資金を追加し、資金を請求し、チャネルを閉じる方法を紹介しました。他にもPython向けのライブラリやJava向けのライブラリなども存在しているため、お好きな言語で試してみてください。
興味を持たれた方はXRP Ledger開発者のDiscordチャンネルへ是非お越しください!
日本語チャンネルもありますので、英語ができなくても大丈夫です!
Discussion