💸

XRPLのPayChan機能で1000件の支払いを処理

2024/05/14に公開

XRP Ledgerとは

XRP Ledger(XRPL)は、2012年にローンチしたオープンソースのブロックチェーンネットワークです。XRP Ledgerの最大の特徴は、その迅速な取引処理能力と低い手数料です。これにより、ネットワークの参加者が効率的に資金を移動させることができます。

XRPLではプロトコルネイティブに機能を提供することで、DEXやNFTなどの機能だけでなく、ペイメントチャネルなどの決済向けの高度な機能を開発者にとってもユーザにとっても安全に提供しています

Payment Channel

Payment Channelは、XRP Ledgerのスマートコントラクト機能の一つです。Payment Channelを利用することで、支払いをオフレジャーで行うことができます。これにより、支払いの処理を高速化し、手数料を削減することができます。

https://xrpl.org/ja/docs/concepts/payment-types/payment-channels/

Payment Channelによる支払いは大まかに次のような流れで行われます。

  1. Channelの作成 (公開鍵の指定と資金の入金)
  2. 送金者による支払い情報への署名
  3. 受取人による支払い情報の検証 (この時点でオフレジャーでの送金は完了したとみなされます)
  4. Channelからの資金の引き出し (オンレジャー上での処理)

Payment Channelについての基礎的な内容はこちらの記事をご覧ください。

https://zenn.dev/tequ/articles/xrpl-try-paymentchannel

コード

import { Client, Wallet, signPaymentChannelClaim, verifyPaymentChannelClaim, xrpToDrops } from 'xrpl'

import BigNumber from 'bignumber.js'

const client = new Client('wss://testnet.xrpl-labs.com')

const signature = Wallet.generate()
;(async () => {
  await client.connect()
  const alice = (await client.fundWallet()).wallet
  const bob = (await client.fundWallet()).wallet

  // create channel
  await client.submitAndWait(
    {
      TransactionType: 'PaymentChannelCreate',
      Account: alice.address,
      Destination: bob.address,
      Amount: xrpToDrops(50),
      SettleDelay: 86400,
      PublicKey: signature.publicKey,
    },
    { wallet: alice },
  )

  // ChannelIDの取得
  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

  let paychanSignature = ''

  console.time()
  for (let i = 1; i <= 1000; i++) {
    const amount = BigNumber(0.05).multipliedBy(i).toString()
    // 送金人: オフレジャー支払いへの署名
    paychanSignature = signPaymentChannelClaim(channel_id, amount, signature.privateKey)

    // 受取人: オフレジャー支払い情報の検証
    if (!verifyPaymentChannelClaim(channel_id, amount, paychanSignature, signature.publicKey)) {
      throw new Error('Invalid signature')
    }
  }
  console.timeEnd()

  const response2 = await client.submitAndWait(
    {
      TransactionType: 'PaymentChannelClaim',
      Account: bob.address,
      Channel: channel_id,
      Balance: xrpToDrops(50),
      Amount: xrpToDrops(50),
      Signature: paychanSignature,
      PublicKey: signature.publicKey,
    },
    { wallet: bob },
  )
  console.log(response2.result)

  await client.disconnect()
})()

この記事のコアとなるコードは次の箇所です。

  for (let i = 1; i <= 1000; i++) {
    const amount = BigNumber(0.05).multipliedBy(i).toString()
    // 送金人: オフレジャー支払いへの署名
    paychanSignature = signPaymentChannelClaim(channel_id, amount, signature.privateKey)

    // 受取人: オフレジャー支払い情報の検証
    if (!verifyPaymentChannelClaim(channel_id, amount, paychanSignature, signature.publicKey)) {
      throw new Error('Invalid signature')
    }
  }

署名(sign)と検証(verify)で送金処理を行っていることがわかります。

これには支払いのチャネルを表すID(channel_id)とそのチャネルでの合計送金額(amount)、署名のための秘密鍵(privateKey)、検証のための公開鍵(publicKey)が必要です。

注意すべきなのは、送金額はその1送金の金額を表すものではなく、そのチャネルでの合計送金額を表すものであることです。

この1000回の処理は筆者のローカル環境ではおよそ1.6秒程度で完了しましたが、2011年の研究ではEd25519署名を利用した場合コモディティハードウェアで1秒間に署名を100,000回生成、70,000回検証が可能であると報告されています。

実用例

XRP LedgerのこのPayment Channel機能を活用したプロジェクトとしてDhaliがあります。
このプロジェクトはAPIをマネタイズするためのプラットフォームで、APIの利用者がAPIの利用料を支払うためにXRP LedgerのPayment Channel機能を利用します。

Discussion