はじめてのTapyrus

初めてTapryusを学ぶ方へ向けた、「Tapyrusとはなんたるか」「Tapyrusは何がいいのか」を解説する記事になります。記事中ではブロックチェーン、特にBitcoinの知識を前提としています。基礎的な内容については触れておりませんのでご注意ください。

記事の内容は tapyrus-core/doc/tapyrus/ 配下のドキュメント、特に getting_started.mdtechnical_overview.md を参考にしております。より正確かつ最新の情報は公式ソースを参照してください。

Tapyrusとは

任意のビジネスケース毎に独立したネットワークを構成・運用することができるブロックチェーン。各ネットワークは管理主体となるフェデレーション(連邦)をもち、ジェネシスブロック・集約公開鍵・ネットワークIDで識別される。また、一つのネットワークは「Signer Network」と「Tapyrus Network」の二つの層(後述)で構成される。

ブロックチェーンの分類

※公式の見解ではなく、個人の解釈であることに注意してください。

NIST による分類

NISTIR 8202

ブロックの発行は Signer Network にのみ許されるため、「許可型ブロックチェーン」に分類される。

Vitalik による分類

On Public and Private Blockchains

同様の理由により、「コンソーシアムブロックチェーン」に分類される。中でもブロックのルートハッシュと API を公開しており、一定の参照が可能であることから「ハイブリッド」な手法であると言える。

また、Tapyrus Network が完全にオープンである点、つまり参照権限がパブリックであることに留意することが必要であり、「不完全分権型(partially decentralized)」であると言える。

chaintope での表現

chaintope のサイトおよびレポジトリではしばしば「ハイブリッド型ブロックチェーン」という表現がされる。「単にプライベートとパブリックな特徴を併せ持つチェーン」をハイブリッドブロックチェーンと呼び、中でも「複数の利害関係者からなるコンソーシアム、ないしフェデレーションにより運営されるもの」をコンソーシアムチェーンと呼ぶ事例をを見かけることがあるが、筆者には明確で一般的な定義は確認できなかった。

コンセンサスアルゴリズム

Bitcoin における PoW では後述の問題があるとし、Tapyrus では PoA に近い、フェデレーションによる検証可能な閾値署名方式を用いたコンセンサスをとっている。公式では明確に「PoA」と行った表現はしていない。

既存チェーンの課題

Tapyrusの特徴を説明するために既存チェーンにおける課題点をおさらいする。

ファイナリティの欠如

一般に、ファイナリティとは「現金通貨の支払いにより債権債務問題が解決され、決済が完了する」といった、法的性質をもった「完了性」として使われる。

ファイナリティ(settlement finality)”とは、一般に「決済が無条件かつ取消不能となり、最終的に完了した状態」と定義され、我が国においては「決済完了性」と呼ばれる。 - 金融庁

しかし、ブロックチェーンにおいては、チェーンの「不可逆性」としてファイナリティという言葉が使われる。これら二つの概念は全くもって別のものであるという認識が重要である。

従来の Bitcoin などによる PoW ではファイナリティは存在せず、ブロックが徐々に繋がることにより再編成やチェーン分岐の可能性が小さくなり、確率的にファイナリティがもたらされる仕組みになっている。つまり既存チェーンにおいては分岐可能性は常に存在し、絶対的なファイナリティがもたらされることはなく、時間経過により確率的に分岐可能性が収束することによる「疑似的なファイナリティ」がもたらされるにすぎない。

このような「確率的ファイナリティ」においては以下の課題が挙げられる。

決済速度の低下

前述の通り、時間経過による確率の収束を待たなければ決済が成立したと見なすことができず、即時決済などに向かない。

トランザクションの不確定性

ブロックの再編成・チェーンの分岐が発生した場合、破棄されたブロック内に含まれるトランザクションは無効となり、決済は失敗に終わる。これは「時間経過により決済成功とみなした後」にも起こり得る事象であり、ファイナリティ欠如の最たるデメリットとも言える。

ボラティリティの低さ

ボラティリティとは「価値変動の度合い」を示す経済学用語である。ここでは各チェーンにおけるネイティブトークン(BTCやETHなど)のマーケット価格の揺れを指す。

多くのブロックチェーンでは大量のトランザクション処理要求などによるDos攻撃を防ぐため、トランザクションの実行に手数料を課している。この手数料は各チェーンのネイティブトークンで支払われることになるが、現在それらのマーケット価格の変動は非常に激しいものになっている。

例えばエンタープライズ向けなどにサービスを構築する際、手数料価格を含む実コストの予想が非常に困難となり、サービスの運用に支障をきたす可能性がある。また、外的要因によりネットワークを流れるトランザクション数が増加し、手数料が高騰(Ethereum におけるガス代高騰問題など)することも珍しくない。

チェーンのガバナンス

パブリックチェーンにおいて、ガバナンス主体としての管理者は存在しない。これはブロックチェーンにおける大きなメリットでもあるが、同時にデメリットにもなりうる。例えばコンセンサスに影響をもたらすような大きな機能拡張、または致命的な欠陥の修正において、コミュニティ内でうまく意見が合わず、結果ハードフォークなどの結果に繋がる例も過去には発生している。2017年には Bitcoin において、BIP49(SegWit)の導入に一部マイナーが反対し、実際に「Bitcoin Cash」としてハードフォークした事例がある。また、Ethereum における The DAO 事件では Ethereum コミュニティにより救済的なハードフォークが行われたが、これは当該事件に対する「特別な処置」でもあり、いわば「コミュニティからの神の手」である対に反対する一部派閥により、新たな分岐チェーン「Ethereum Classic」が誕生した。

このように明確な管理者が存在しないチェーンにおいて、その不在がしばしば問題となっている。

参照権限の有無

上記のような問題を解決するため、許可型ブロックチェーン「Hyperledger Fabric」が登場した。Hyperledger Fabricは参加者を限定した許可型のブロックチェーンであり、コンセンサスアルゴリズムにはPBFTが採用され、許可を得た参加者であるかをAPI層で任意に実装するなどで、トランザクション手数料の撤廃に成功している。またチェーン参加が許可型であることから許可主体によるガバナンスが取られ、上記のような課題は解決されている。

しかし、チェーン参加が許可型であると同時に、チェーン上のデータの参照権限も許可されたノードに限られる。つまり、オープンな台帳アクセスが提供されておらず、第三者による「データの正しさ」の証明が不可能である。

Tapyrus による解決「ブロックチェーン層の二層分割」

これら既存チェーンの課題に対する Tapyrus の解決を紹介する。

Tapyrus ではネットワークを Signer Network と Tapyrus Network の二層に分割することを提案・実装している。

Image in a image block
https://www.chaintope.com/chaintope-blockchain-protocol/

Signer Netwotk

ネットワークの利害関係者からなるフェデレーションにより運営される。Signer Network 内の各ノードはブロックの署名(Sign)を担当し、承認されたブロックを Tapyrus Network へ伝播する。これにより Tapyrus では確率的なファイナリティではなく、ブロック作成の時点で各トランザクションにファイナリティが与えられる。

Tapyrus Network

フェデレーション関係者のみで構成される Signer Network とは異なり、Tapyrus Network はオープンな台帳ネットワークとなる。ジェネシスブロックおよびネットワークIDにより誰でも Tapyrus Network に参加することが可能であり、Tapyrus Network 内の各ノードは自由にチェーン上のデータを参照することが可能である。

これら二層へ分割することで、各課題は以下のように解決される。

 ファイナリティ → Signer Network によるファイナリティの実現

 ガバナンス → フェデレーションによる Signer Network の運営

 参照権限 → 自由に参加可能な Tapyrus Network によるオープンな台帳ネットワークの実現

技術仕様

Tapyrusの技術的な仕様を紹介する。

ネットワーク構成

ネットワークは三種類のノードから構成される。

ノード目的
Tapyrus Signer最低3, 上限なしSigner Network を構築
Tapyrus Core最低1, 上限なしTapyrus Network を構築
Tapyrus Seeder最低1, 上限なしネットワークのDNSシーダー

また、ネットワークは以下のパラメータを持つ。

Network ID

ネットワークID。ネットワークを識別するものであり、独自である必要がある。

Network magic bytes

ネットワークマジックバイト。 マジックバイトはノード間通信時、送受信メッセージの接頭辞に付与され、ネットワークの識別子として機能する。マジックバイトはネットワークIDから計算され、16進数で表示される。

Genesis block

ジェネシスブロック。最初のブロック。Bitcoinとは異なりソースコード内には記載がなく、tapyrus-genesisというユーティリティを用いて生成される。ジェネシスブロックは Signer Network による署名が必要であり、各ノードはこれを外部ファイルとして保持する。ネットワークで独自である必要がある。

Aggregate public key

集約公開鍵。ジェネシスブロックに含まれる。各ノードがブロックを検証する際に用いる。

Signer Network

Signer Network は構築時に設定されたフェデレーションのメンバーで構築される。このフェデレーションメンバーは後からでも編集することが可能である。その際には新たな集約公開鍵が生成される。

ノードの役割は主に

  • Tapyrus Network で生成されたトランザクションを収集し検証する
  • 有効なトランザクションからブロックを生成作成し署名する
  • Tapyrus Nerwork へブロードキャストする

ことである。

ブロックの検証

Signer Network の作成したブロックの検証は、ブロックの proof が有効な署名かどうかを検証することで確認ができる。検証に用いるデータは以下。

  • ブロックの proof にセットされている署名データ
  • 署名対象のメッセージ m(ブロックヘッダーから proof を除外したデータの double-SHA256ハッシュ値)
  • 集約公開鍵(全 Signer の公開鍵を加算し、集約したもの)

上二つは検証対象のブロックから取得でき、また集約公開鍵は公開鍵の集約にすぎないため、Tapyrus Network の参加者全てがこれらについて参照可能である。つまり、誰でもブロックの正しさを独立して検証することができる。

閾値署名方式

先述の集約公開鍵に対応するものとして集約秘密鍵がある。しかし、集約秘密鍵の生成には全ての Signer の秘密鍵を知る必要があり、これはセキュリティ上望ましい手法とは言えない。そこで Tapyrus では分散Schnorr署名と(t, n)閾値署名方式を基に、「集約秘密鍵を生成することなく集約公開鍵に対して有効なSchnorr署名を作成する」方式をとっている。この方式では内部で「検証可能な秘密分散(Verifiable Secret Sharing: VSS)」を使用し、秘密分散法とSchnorr署名を組み合わせ、n人の Signer 中、閾値 t個の部分署名を集めると有効なSchnorr署名を完成させることができる閾値署名を提供する。これにより、全ての Signer の署名を収集する必要はなく、t個集めれば良いため、部分的な Signer の故障に対しても堅牢である。(ただし閾値を満たす必要はある)

また、閾値tは任意に設定することができるが、分母に対し過半数を超える値、もしくはビザンチン耐性を考慮した値が望ましい。

これにより生成されるSchnorr署名は、ネットワーク参加者から見ると単一のSchnorr署名であるため、署名検証コストは一定となる。

秘密分散

秘密分散とは、秘密情報を複数のメンバーに分散する方法。

Schnorr署名

Schnorr署名は、1990年にシュノアが提唱した離散対数問題の困難性に基づくデジタル署名であり、非対話ゼロ知識証明プロトコルであるSchnoorプロトコルをデジタル署名に応用したもの。2021年にはTaprootによりBitcoinへ正式に導入された。

ビザンチン耐性・ビザンチン将軍問題

不特定のノードが一時的に故障しその後復旧することがある、あるいは故意に嘘の情報を他のノードに伝える可能性があるという前提の上での合意問題。全ノード数を n , 結託した嘘つきノード数を f とした時、 3f≧n の場合には、ビザンチン将軍問題を解くいかなるアルゴリズムも存在しないことが証明されている。

Signer Network の処理フロー

各 Signer ノードはそれぞれの公開鍵で識別され、辞書順にインデックスが割り当てられる。

また、Signer がメッセージを交換し、一つのブロックを作成するまでの期間を「ラウンド」と呼び、各ラウンド毎にラウンドマスターが選出される。このラウンドマスターはSignerノードのインデックスを基に決定される。

各ラウンドの流れを以下に示す。(ラウンドマスターは「全Signer」に含まれる)

  1. ラウンドマスターが選出される
  2. ラウンドマスターは「候補ブロック(candidateblock)」を全Signerに送信する
  3. 全 Signer は「ブロックへ対するVSS(blockVSS)」をお互いに送信する
  4. ラウンドマスターは全 Signer に「ブロック参加(blockparticipants)」を送信する
  5. 全 Signer は「ブロックへの部分署名(blocksig)」をお互いに送信する
  6. ラウンドマスターは受け取った blocksig を基に「最終的な署名」を作成し Tapyrus Network にブロードキャストする
  7. ラウンドマスターは「完成したブロック(completedblock)」を全 Signer に送信する
Image in a image block
https://github.com/chaintope/tapyrus-signer#sequence-diagram

Tapyrus Network

Tapyrus Network は誰もが参加可能なブロックチェーンネットワークである。ネットワーク IDとジェネシスブロックさえ分かれば、tapyrusd を利用し接続可能。

ノードの役割は主に

  • 全てのオンチェーンデータの提供
  • トランザクションの発行、伝搬

Tapyrus のフルノード実装である Tapyrus Core は、Bitcoin Core をベースに作られている。

トークン

多くのトークンプロトコルは、オーバーレイプロトコルであるLayer2で実装されている。しかし、これら実装は「任意データをブロックチェーンに記録する機能」を用いており、これはLayer1におけるコンセンサスとして正しさを検証されない。

例えば Bitcoin におけるトークン「カラードコイン」を表現するプロトコルは複数存在し、Open Assets Protocol が主流である。しかし、Open Assets Protocol を通じて発行されたカラードコインは Bitcoin 単体ではカラードコインとして解釈することはできず、あくまで Open Assets Protocol を通して見た時に初めてカラードコインであると認識できる。これはウォレットの実装においても、仮に Open Assets Protocol を解釈しないウォレットにカラードコインが送られた場合、ウォレットは受信トークンをトークンと認識できず、ネイティブトークンであるBTCとして解釈する。またこの説明において、 “Bitcoin” がすなわち “Layer1” であり、”Open Assets Protocol” が “Layer2 プロトコル” である。

対して Tapyrus では Layer1 において、つまり外部のライブラリやプロトコル等に依存せず Tapyrus 単体での任意のトークンの発行・転送をサポートしている。

トークン仕様

Tapyrus では以下の3種類のトークンタイプが発行可能である。

  • Reissuable Token(再発行可能なファンジブルトークン)
  • Non-Reissuable Token(再発行不可能なファンジブルトークン)(一部ドキュメントでUnreissuable Tokenと表記される場合もある)
  • Non-Fungible Token(NFT)

上二つについてはFungible Tokenであり、複数枚の発行が可能である。

NFTについては、ERC721 のような「コントラクトを基にトークンを発行し、Metadata を付与する」といった考え方ではなく、特定のアドレスに対し一意なIDを持ったトークンが発行されるものである。

トークンを識別するために、Tapyrus Script にて OP_COLOR opcode が追加されている。OP_COLOR は Script 内に一つのみ含めることができ、OP_COLOR が出現するとスタックの一番上の要素が “COLOR識別子” として解釈され、その UTXO のコインは任意のトークンを示す。OP_COLOR のない Script はネイティブトークンとして解釈される。

つまり単に「OP_COLOR の有無」のみでネイティブトークンか否かを判断することができ、また後述の「COLOR識別子」によりトークンの識別が可能であるため、ノード/ウォレットはUTXO単体でトークンを解釈することが可能である。それにより、経由した使用済みTXOの全てを保持する必要がなくなり、軽量ノードなどにおいても容易にトークンを扱うことが可能である。

COLOR識別子

CCOLOR識別子は1バイトの「タイプ(TYPE)」と32バイトの「ペイロード(PAYLOAD)」で構成される。COLOR識別子の内容は以下表に示す通り。

タイプ定義ペイロード
0xC1Reissuable Token発行TXのインプットのscriptPubkeyのSHA256値
0xC2Non-Reissuable Token発行TXのインプットのOutPointのSHA256値
0xC3Non-Fungible Token発行TXのインプットのOutPointのSHA256値

「発行TXのインプットのOutPoint」

OutPointとは特定のTXOを指定するために利用されるデータ構造であり、TXID とインデックス番号から成る。つまり NRT, NFT におけるペイロードは発行時に利用した「TXID とインデックス番号」すなわち UTXO を基に造られることになり、UTXO はチェーンで一意であるためCOLOR識別子にも一意性がもたらされる。

また、COLOR識別子は、tapyrus-cli にてtokenを発行した際には color、Tapyrus の Ruby 実装であるtapyrusrbにおいては color_id と表記される。

以降では tapyrus-cli を用いた testnet での NFT 操作を交えて進める。

トークンの発行
インプット発行に使用するUTXO
アウトプットCOLOR識別子とOP_COLORを使ったscriptPubkeyを含むUTXO(トークン本体)
お釣りUTXO

トークン新規発行のトランザクションは、UTXO をインプットにセットしCOLOR識別子を導出、COLOR識別子と OP_COLOR を使った scriptPubkey をアウトプットにセットすることで作成される。またトークンの発行量はアウトプットにおいて value としてセットすることが可能であり、インプットに指定された UTXO で発生するお釣りは非トークンアウトプットが作成され、従来通り TPC で返却される。

# 手持ち $ tapyrus-cli listunspent [ { "txid": "3bc7c60867a3fe2e4c0b1be12cf930ee31f20e96c46028aa08071889e1f83c57", "vout": 0, "address": "1DZeRgPHQepFJrHiJLwvHibKY9XUtvTrKF", "token": "TPC", "amount": 1.00000000, "label": "", "scriptPubKey": "76a91489ce0fb90a30f9141cc2d2896fdd8e2252c1a61688ac", "confirmations": 219, "spendable": true, "solvable": true, "safe": true } ] # 発行 $ tapyrus-cli -conf=/etc/tapyrus/tapyrus.conf issuetoken 3 1 3bc7c60867a3fe2e4c0b1be12cf930ee31f20e96c46028aa08071889e1f83c57 0 { "color": "c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22", "txid": "153dfc29ce70d7c249fc382055a44deefa72a4c48ee20ec1e3fa8e0c3f9f3120" } # txの内容 { "txid": "153dfc29ce70d7c249fc382055a44deefa72a4c48ee20ec1e3fa8e0c3f9f3120", "hash": "36a0e2a144bca76365bc7717e32002a5f9c767ae9d084527e38c8b9d7a234e4e", "features": 1, "size": 257, "locktime": 187790, "vin": [ { "txid": "3bc7c60867a3fe2e4c0b1be12cf930ee31f20e96c46028aa08071889e1f83c57", "vout": 0, "scriptSig": { "asm": "304302206efe41c9968bf7edeac3c5c636806b82198626358cece9f4998841e693fcca49021f0096c08d46dcda64a2390fc6d95de0d6a3aa67225ded1744fbc3f856938bb1[ALL] 03f960211ba2f99001cfe168b2190c9eadc93f1e9504c629800228d38ce1b3cf78", "hex": "46304302206efe41c9968bf7edeac3c5c636806b82198626358cece9f4998841e693fcca49021f0096c08d46dcda64a2390fc6d95de0d6a3aa67225ded1744fbc3f856938bb1012103f960211ba2f99001cfe168b2190c9eadc93f1e9504c629800228d38ce1b3cf78" }, "sequence": 4294967294 } ], "vout": [ { "token": "c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22", "value": 1, "n": 0, "scriptPubKey": { "asm": "c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22 OP_COLOR OP_HASH160 29dc588b58a35145d7281c6ccdcf1d38794fcaf7 OP_EQUAL", "hex": "21c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22bca91429dc588b58a35145d7281c6ccdcf1d38794fcaf787", "reqSigs": 1, "type": "coloredscripthash", "addresses": [ "4ZyqgapFfb4Hz6HhgkXjFYMKUZoKjnc2RrsQ4gzQnpfafK4etwTsKeTNPAxKatXJ3whEEkPzKwjUeh3" ] } }, { "token": "TPC", "value": 0.99999742, "n": 1, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 62cfafe2c7062cb73929b0fb0b8ce44259dbfa04 OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a91462cfafe2c7062cb73929b0fb0b8ce44259dbfa0488ac", "reqSigs": 1, "type": "pubkeyhash", "addresses": [ "1A1U29dqTfqvuUfTCMGZGiaZFhFCzCf6o7" ] } } ] }

vout[0] の scriptPubkey asm において OP_COLOR opcode が Script 内に出現したことにより最上位要素がCOLOR識別子として解釈されている。

c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22 OP_COLOR ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ これ

トークンの転送
インプット移転対象のトークンを持つUTXO
手数料用UTXO(FeeProviderが自分の場合)
アウトプット送信先のアドレスに対して移転対象のトークンと同じCOLOR識別子とOP_COLOR opcodeを付与したUTXO(アドレスが書き換えられたトークン本体)
お釣りUTXO

トークン移転のトランザクションは、トークンを持つ UTXO をインプットにセットし、「送信先のアドレスに対してインプットのトークンと同じCOLOR識別子と OP_COLOR を付与」したアウトプットをセットする。インプット/アウトプット数やトークンの種類を複数指定することもできるが、トランザクション内で各トークンの総量が保存されている必要がある。

# 手持ち user@nodeA:$ tapyrus-cli -conf=/etc/tapyrus/tapyrus.conf listunspent [ { "txid": "153dfc29ce70d7c249fc382055a44deefa72a4c48ee20ec1e3fa8e0c3f9f3120", "vout": 0, "address": "4ZyqgapFfb4Hz6HhgkXjFYMKUZoKjnc2RrsQ4gzQnpfafK4etwTsKeTNPAxKatXJ3whEEkPzKwjUeh3", "token": "c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22", "amount": 1, "scriptPubKey": "21c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22bca91429dc588b58a35145d7281c6ccdcf1d38794fcaf787", "confirmations": 1, "spendable": true, "solvable": true, "safe": true }, { "txid": "153dfc29ce70d7c249fc382055a44deefa72a4c48ee20ec1e3fa8e0c3f9f3120", "vout": 1, "address": "1A1U29dqTfqvuUfTCMGZGiaZFhFCzCf6o7", "token": "TPC", "amount": 0.99999742, "scriptPubKey": "76a91462cfafe2c7062cb73929b0fb0b8ce44259dbfa0488ac", "confirmations": 1, "spendable": true, "solvable": true, "safe": true } ] # 受け取り先アドレスを生成 # getnewaddressコマンドの第三引数に受け取るTokenのCOLOR識別子を指定する必要がある # 第二引数はlabel。任意。 user@nodeB:$ tapyrus-cli -conf=/etc/tapyrus/tapyrus.conf getnewaddress "" c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22 vypPXVBfqAuVqVt6unNWvoMXdUpb6BsWqK1aL62GkAjtGxP3AY5QRGaXr5b7ZkNy2Z2zvFS9qcCRth # アドレスを確認 # tokenが指定したCOLOR識別子となっていることがわかる。 user@nodeA:$ tapyrus-cli -conf=/etc/tapyrus/tapyrus.conf getaddressinfo vypPXVBfqAuVqVt6unNWvoMXdUpb6BsWqK1aL62GkAjtGxP3AY5QRGaXr5b7ZkNy2Z2zvFS9qcCRth { "address": "vypPXVBfqAuVqVt6unNWvoMXdUpb6BsWqK1aL62GkAjtGxP3AY5QRGaXr5b7ZkNy2Z2zvFS9qcCRth", "token": "c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22", "amount": 0, "scriptPubKey": "21c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22bc76a914156279703d67559ecf434c10443c6b2551a94a4588ac", "ismine": false, "iswatchonly": false, "isscript": false, "istoken": true, "color": "c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22", "labels": [ ] } # 転送 user@nodeA:$ tapyrus-cli -conf=/etc/tapyrus/tapyrus.conf transfertoken vypPXVBfqAuVqVt6unNWvoMXdUpb6BsWqK1aL62GkAjtGxP3AY5QRGaXr5b7ZkNy2Z2zvFS9qcCRth 1 3b49b5afb9027dd910007424d59c6cd1ce457ab08edb3b521c75163e6eaef500 # txの内容 { "txid": "3b49b5afb9027dd910007424d59c6cd1ce457ab08edb3b521c75163e6eaef500", "hash": "2d6159b377ff26a9b7e711be17ead9ef87228eeb6da0ce870c0b69516a49a64c", "features": 1, "size": 327, "locktime": 187795, "vin": [ { "txid": "153dfc29ce70d7c249fc382055a44deefa72a4c48ee20ec1e3fa8e0c3f9f3120", "vout": 1, "scriptSig": { "asm": "304402200dc914aef786e52d69782ae910e7d2100df89d3bd79dd3d306820d64870b53c5022011e9152407d84df08170521c87cd3d14140ff975e4d161e63b6276ffffba720e[ALL] 02ccdaebb6da9df094d158b279e419fa1c485021ef2cf17fbc3959455c645ad03c", "hex": "47304402200dc914aef786e52d69782ae910e7d2100df89d3bd79dd3d306820d64870b53c5022011e9152407d84df08170521c87cd3d14140ff975e4d161e63b6276ffffba720e012102ccdaebb6da9df094d158b279e419fa1c485021ef2cf17fbc3959455c645ad03c" }, "sequence": 4294967294 }, { "txid": "153dfc29ce70d7c249fc382055a44deefa72a4c48ee20ec1e3fa8e0c3f9f3120", "vout": 0, "scriptSig": { "asm": "76a914c560ac838ad1434d6178dd5da43ddf1afe698f6588ac", "hex": "1976a914c560ac838ad1434d6178dd5da43ddf1afe698f6588ac" }, "sequence": 4294967294 } ], "vout": [ { "token": "c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22", "value": 1, "n": 0, "scriptPubKey": { "asm": "c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22 OP_COLOR OP_DUP OP_HASH160 156279703d67559ecf434c10443c6b2551a94a45 OP_EQUALVERIFY OP_CHECKSIG", "hex": "21c397cad1a9664d9b99696f4c83badf8b3e0cdf54803a17066519aa859cdedd2a22bc76a914156279703d67559ecf434c10443c6b2551a94a4588ac", "reqSigs": 1, "type": "coloredpubkeyhash", "addresses": [ "vypPXVBfqAuVqVt6unNWvoMXdUpb6BsWqK1aL62GkAjtGxP3AY5QRGaXr5b7ZkNy2Z2zvFS9qcCRth" ] } }, { "token": "TPC", "value": 0.99999415, "n": 1, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 0b7b790f099e87ea17828b64fc433134ffaa253d OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a9140b7b790f099e87ea17828b64fc433134ffaa253d88ac", "reqSigs": 1, "type": "pubkeyhash", "addresses": [ "123iMA5vDJgo89NkTosfKqhQXArL3p1Mcm" ] } } ] }

トークンの焼却
インプット焼却対象のトークンを持つUTXO
手数料用のTPCを持つUTXO
アウトプットお釣りUTXO

トークン焼却のトランザクションは、トークンを持つ UTXO、および手数料用の UTXO をインプットにセットし、お釣り UTXO がアウトプットとして返却される。手数料は TPC で支払う必要がある。

# 手持ち $ tapyrus-cli listunspent [ { "txid": "c5d3c6f8d29322834bcba84f71dc3624100d43be62ba906287cd306785241a82", "vout": 0, "address": "vy1vD2goKSGxz6RrAETJ2GfPC25SdNhtde1KMspx2oBRYDPsYWf815mjxLmzFAidPJvks3fLzDTET5", "token": "c37a34d9f3602badf8110d65ee06cc7647539e885c29a981d02b6ee36daf84e4ec", "amount": 1, "label": "", "scriptPubKey": "21c37a34d9f3602badf8110d65ee06cc7647539e885c29a981d02b6ee36daf84e4ecbc76a9141e09d72d4620a62aa27081afb0b1a590cc4f85ee88ac", "confirmations": 1, "spendable": true, "solvable": true, "safe": true }, { "txid": "f91ad0bc723e62b8ec69928faec77706b70ebfef265a19c8ff17ee8713bbc0a5", "vout": 1, "address": "12dFZkyEo3XbPQmnNhGBn6ZWXpUgmKpvTy", "token": "TPC", "amount": 0.07932965, "scriptPubKey": "76a91411d3422c2d6164d16167c04b2195e135bc00302988ac", "confirmations": 2, "spendable": true, "solvable": true, "safe": true }, ... # burn $ tapyrus-cli c37a34d9f3602badf8110d65ee06cc7647539e885c29a981d02b6ee36daf84e4ec 1 6eb2dd62fb164590b3377d34111785e9ecfe4342b8417b41c0eeb94235e29170 # txの内容 { "txid": "6eb2dd62fb164590b3377d34111785e9ecfe4342b8417b41c0eeb94235e29170", "hash": "471018aa8ed5402d1a6ba70a2cc5d8b0d3b46e0bfd3fe353819c4ecbb870457d", "features": 1, "size": 338, "locktime": 188132, "vin": [ { "txid": "f91ad0bc723e62b8ec69928faec77706b70ebfef265a19c8ff17ee8713bbc0a5", "vout": 1, "scriptSig": { "asm": "3044022056ddf6cd953602d9bac639902770c8803c86f6e4258d64afd090ff7a3ed5b2d802200d77b96e93c65d2b83e67eb53721d838a5f18634869fd14a22786dc1539c5649[ALL] 02c85ca219273c2e122519f6b7f97bd08e392bceae338e9d76ed59718d54038ea3", "hex": "473044022056ddf6cd953602d9bac639902770c8803c86f6e4258d64afd090ff7a3ed5b2d802200d77b96e93c65d2b83e67eb53721d838a5f18634869fd14a22786dc1539c5649012102c85ca219273c2e122519f6b7f97bd08e392bceae338e9d76ed59718d54038ea3" }, "sequence": 4294967294 }, { "txid": "c5d3c6f8d29322834bcba84f71dc3624100d43be62ba906287cd306785241a82", "vout": 0, "scriptSig": { "asm": "304402205872ebe121b23831721220d81556d9e6e43611710f6ec7e98edd9ef8aae17c720220345b7defb538fbff85a3f53c96938c024c3164590e4768def8f65e25c275f642[ALL] 03b6f816de05e8748387ef07d6398c6ede9b2198c924af50f74194b9b7fc6287da", "hex": "47304402205872ebe121b23831721220d81556d9e6e43611710f6ec7e98edd9ef8aae17c720220345b7defb538fbff85a3f53c96938c024c3164590e4768def8f65e25c275f642012103b6f816de05e8748387ef07d6398c6ede9b2198c924af50f74194b9b7fc6287da" }, "sequence": 4294967294 } ], "vout": [ { "token": "TPC", "value": 0.07926205, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 da51263c611741c7085ea56a648e21e924d6268d OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a914da51263c611741c7085ea56a648e21e924d6268d88ac", "reqSigs": 1, "type": "pubkeyhash", "addresses": [ "1LuMXBAon9ry3cUwJFcPNX8JADBBu8GPK8" ] } } ] }

これら3つの処理について、一つのトランザクションにまとめることが可能である。有効な組み合わせについては以下の資料を参照。

https://docs.google.com/spreadsheets/d/1hYEe5YVz5NiMzBD2cTYLWdOEPVUkTmVIRp8ytypdr2g/edit#gid=0

関連プロジェクト

Tapyrus Core

GitHub: https://github.com/chaintope/tapyrus-core

Tapyrusのフルノード実装。

Docker image: tapyrus/tapyrusd

Docker Hub: https://hub.docker.com/r/tapyrus/tapyrusd

Tapyrus CoreのDockerイメージ。

Tapyrus SPV

GitHub: https://github.com/chaintope/tapyrus-spv

Tapyrusの軽量ノード。

Tapyrus Signer

GitHub: https://github.com/chaintope/tapyrus-signer

Signer Network を構成する Signerノード実装。

Tapyrus Faucet

GitHub: https://github.com/chaintope/tapyrus-faucet

chaintope が提供する testnet 用の公式 Faucet。Rails で実装されている。

tapyrusrb

GitHub: https://github.com/chaintope/tapyrusrb

Tapyrus の Ruby実装。JS, Rust ライブラリも存在するが、Ruby が一番開発が活発。

Glueby

GitHub: https://github.com/chaintope/glueby

GitHub: https://github.com/chaintope/glueby

「専門知識の必要なしに」をテーマに作られた Ruby ライブラリ。Gem で配布。Rails をサポート。

最近(2022年04月07日)v1.0.0がリリースされた。

Tapyrus API

利用方法: https://github.com/chaintope/tapyrus-api-client-java#tapyrus-api-の利用法

「Gluebyを言語依存なく幅広く利用可能に」をテーマに作られたREST API。利用にはOpenIDによる認証が必要。

クライアントのサンプル

GitHub: https://github.com/chaintope/tapyrus-api-client-examples

Tapyrus Guid

いつの間にか公式ガイドができてました。

workshop

GitHub: https://github.com/chaintope/workshop202107

ブロックチェーン勉強会で使われたサンプルコード。Gluebyの使い方はここから体系的に学ぶことができる。

参考

ブロックチェーン技術概論 理論と実践 - 著:山崎 重一郎, 安土 茂亨, 金子 雄介, 長田 繁幸 - 講談社