Near Blockchainの仕組みや特徴についてまとめている記事です。
初めまして。
普段ブロックチェーン関連の開発や発信をしているかるでねと申します。
今回はNear Blockchainについてまとめていきます。
アカウントはユニークなアドレスによって識別され、メールアドレスを使用したりTelegramを通じてウォレットを取得するなどで作成可能です。また、オプション機能として、アクセスキーによって制御されるスマートコントラクトを保持することも可能です。
ユーザーは自身のアカウントでトランザクションに署名することで以下のことが可能になります。
デジタル資産の送受信。
スマートコントラクトの作成や実行。
Ethereumをはじめとする他チェーンのアカウントの管理。
取引コスト(ガス代)を負担して、新規ユーザーのオンボーディング支援。
アカウントには64文字のアドレス (Implicit Address)と名前付きアドレス(alice.near
など)の2つが存在します。
Implicit Addressは、ユニークな公開/秘密鍵のペアが生成され、秘密鍵を管理する人がそのアカウントを管理できます。
秘密鍵
ed25519:4x1xiJ6u3sZF3NgrwPUCnHqup2o...
公開鍵
ed25519:CQLP1o1F3Jbdttek3GoRJYhzfT...
アカウント
a96ad3cb539b653e4b869bd7cf26590690e8971...
名前付きアカウントは人が読みやすく、ドメインのようにサブアカウントを作成することができます。また、アカウントは他のアカウントのサブアカウントの作成はできず、サブアカウントの制御もできません。
最上位アカウント
cardene
サブアカウント
near.cardene
サブアカウントのサブアカウント
mirror.near.cardene
NEARでは、以下の2つの特徴を持つ複数のアクセスキーを保有できます。
Full-Access Keys
Function-Call Keys
アカウントを完全に制御できるキーで、あらゆるトランザクションに署名ができて以下の処理が実行できます。
NEARの送付。
アカウントの削除とサブアカウントの作成。
アクセスキーの追加と削除。
アカウントにスマートコントラクトをデプロイ。
コントラクトのメソッド実行。
特定のコントラクトを呼び出すトランザクションにのみ署名でき、NEARトークンの送付などはできません。以下の3つの属性によって定義されます。
receiver_id
method_names
allowance
第3者がキーの保有者のアカウントでコントラクトを呼び出すことができるため、以下のようなことが実現できます。
例えばゲームにおいて、ゲームを中断することなくトランザクションに署名が可能。
アカウントを作成するコントラクトを用意し、簡単にユーザーのアカウントを作成する。
キーが漏れた場合、新しいキーに切り替えることが可能。
アカウントから全てのキーが削除されると、そのアカウント名でトランザクションが実行できなくなります。一方、コントラクトのみがアカウントを制御できるようになるため、コントラクトのデプロイに向いています。
NEARアカウントに存在する実行可能コードで、JavascriptかRustで作成できます。ストレージへのデータ保存やアカウント名でのトランザクション実行、他アカウントが操作できるメソッドの公開などができます。
アカウントを完全に制御でき、以下のことが実行できます。
$NEARトークンの送付。
他のコントラクトのメソッド実行。
新しいアカウントの作成と、コントラクトのデプロイ。
独自コードの更新。
また、コントラクトは以下のようなDappsの作成に役立ちます。
DAO
NFTマーケットプレイス
DEX
コントラクトは、アカウントのステート(コントラクトが管理するデータを保存する領域)に以下のようなkey-valueペアの構造でデータを保存します。
データを保存するためには料金を支払う必要があり、以下のような仕組みになっています。
コントラクトのストレージにデータが追加されるとアカウントの残高が減少(ロック)する。
データが削除されるとアカウントの残高は増加する。
現在だと、100kbのデータを保存するのに約1 NEARかかります。
ユーザーは自身の秘密鍵を使用してトランザクションに署名し、ネットワークにブロードキャスト後検証されてNEARとやり取りできます。
トランザクションは以下のフィールドから構成されます。
Signer
Actions
実行されるアクションのセット。
各アクションには一定量のガスユニット(NEARトークン)がかかる。
Receiver
PublicKey
Nonce
Signer
ごとにこれまで送信されたトランザクションの数。BlockHash
最新のブロックのハッシュ。
トランザクションの有効期間を制限する。
各トランザクションでは、以下の9つのアクションを実行できます。
FunctionCall
Transfer
DeployContract
CreateAccount
near.cardene
)。DeleteAccount
AddKey
DeleteKey
DelegateActions
Stake
1つのトランザクションに、上記のアクションを複数まとめることも可能で、指定された順序で実行されて1つでもアクションが失敗するとトランザクションは破棄されます。
トランザクション実行するために、ガス代($NEAR)と呼ばれる手数料が必要になります。
全てのアクションに固定量のガスがかかり、ガスユニットという単位で計算されます。ガスユニットは、コンピュータの処理時間やネットワークの帯域幅、ストレージの読み書きなどのリソース使用量を表しています。
ガスユニットの基本単位は「Tgas
(テラガス)」で、1 Tgas
(0.0001 Ⓝ
)は約1ミリ秒(0.001秒)のコンピュータ処理時間に相当します。NEARでは、1つのトランザクションが使用できるガスユニットの上限が300 Tgas(約0.3秒)に設定されていて、0.3秒以内に処理が完了しない場合トランザクション処理が失敗とみなされ処理が中断します。
また、NEARでは1秒ごとにブロックが生成され、仮にトランザクションの平均処理時間が150ミリ秒(0.15秒)とした場合、約6つのトランザクションを処理してブロックに含めることができます。
$NEARのガス代はトランザクション内の全てのアクションコストにガス価格をかけます。ガス価格はブロック毎に計算され、前のブロックに含まれるトランザクションの総ガス量50%以上埋まっていれば需要が高いことを示しているため、ガス価格が1%上昇します。逆に前のブロックが50%未満の場合は1%減少します。
アクションには以下のように固定のコストが設定されています。
アカウントの作成
0.42 Tgas = 0.000042 Ⓝ
NEARの送付
0.45 Tgas = 0.000045 Ⓝ
FullAccessキーの追加
0.42 Tgas = 0.000042 Ⓝ
キーの削除
0.41 Tgas = 0.000041 Ⓝ
コントラクトの関数呼び出し
≤ 300 Tgas = ≤ 0.03 Ⓝ
16kbのコントラクトデプロイ
2.65 Tgas = 0.000265 Ⓝ
Xkbのコントラクトデプロイ
0.58 + 0.13X Tgas = (0.58 + 0.13X) * 0.0001 Ⓝ
コントラクトの実行で発生するガス料金の30%が、コントラクトのアカウントに支払われます。これにより、開発者はコントラクトを作成し運用するインセンティブになります。
ガスコストを見積もるには、SDKのメソッドであるused_gas
を使用して以下のように指定することで実行できます。
トランザクションがネットワークに送信されると、ノード間でレシートと呼ばれるメッセージが交換されます。このライフサイクルについて見ていきます。
トランザクションがネットワークに届くと、ネットワークでは1ブロックが生成されるまでにトランザクションを検証し、実行される全てのアクセションを含むレシート(Receipt
)に変換します。レシートの作成中に、署名者(singer
)の残高からガス代と送付するNEARが差し引かれます。署名者(singer
)と受信者(receiver
)が一致する場合(例:署名者がキーを追加する場合)、レシートは最初のブロックですぐに処理され、トランザクションは確定します。
署名者(singer
)と受信者(receiver
)が異なる場合(例:署名者が受信者にNEARを送金する場合)、レシートは2番目のブロックで処理されます。この処理中に、FunctionCall
がクロスコントラクトコールを生成し、1つ以上の新しいレシートを作成します。
関数呼び出しから作成された各レシートは、処理されるために追加のブロックを必要とします。これらのレシートがFunctionCall
である場合、新しいレシートを生成できます。これが繰り返されることもあります。
最終レシートは新しいブロックで処理され、ユーザーが支払った余分なガスが払い戻されます。
トランザクションは、すべてのレシートが処理されると確定したとみなされます。ほとんどのトランザクションは、アクションを処理するためのレシートと、ガスを払い戻すためのレシートの2つを生成し、1〜3ブロック(約1〜3秒)で確定します。
署名者(singer
)と受信者(receiver
)が一致する場合は1ブロック。
署名者(singer
)と受信者(receiver
)が異なる場合は3ブロック(最初のブロックでレシートを作成し、最後のブロックでガスを払い戻すため)。
関数呼び出しは複数のレシートを生成する可能性があるため、より時間がかかる場合があります。ネットワークの混雑もレシートの処理時間を増加させる可能性があります。
レシートが処理されると、トランザクションに以下のステータスが付与されます。
Success
Failed
Unknown
以下の注意点も知っておきましょう。
最初のレシートのアクションが失敗すると、トランザクションは失敗とマークされるため、トランザクションのステータスは、すべてのアクションを含む最初のレシートによって決定されます。
レシートのアクションが失敗すると、そのレシート内のすべてのアクションがロールバックされます。これはレシートのステータスであり、トランザクションのステータスではないことに注意してください。
FunctionCall
が正常に新しいレシートを生成したが、その後の関数呼び出しが失敗した場合、トランザクションは成功とマークされることがあります。これは、元の関数呼び出しが成功したためです。
NEAR Protocolのブロックチェーンのデータフローについて説明していきます。
まず、ブロックチェーンのデータフローは、始まりはあるが終わりのない無限のタイムラインで、このタイムライン上に一定の間隔でブロックが生成されます。各ブロックは前のブロックの情報を持っていて、これにより「ブロックの連鎖」が作られます。
NEAR Protocolはシャード化されたブロックチェーンで、複数の並列ネットワーク(シャードと呼ばれる)が同時に稼働しています。各シャードは一定の間隔でブロックのチャンク(ブロックの一部分)を生成します。NEARブロックチェーンにおけるブロックは、全シャードのブロックチャンクの集合体です。
以下の図ではわかりやすくデータフローを表しています。
各シャードには独自のトラックセットがあります。一番上のトラックはチャンク用で、一定の間隔で生成され(NEARブロックチェーンでは約1秒間隔)、トランザクションが送信されなくてもチャンクは生成されます。
最初にトランザクションがあり、ブロックチェーン上で実行したい指示が含まれています。トランザクションはNEARブロックチェーンに送信されてすぐに実行され、トランザクション実行の即時の結果である「レシート」を取得します。レシートは、シャード間で情報を渡すために存在する内部トランザクションと考えることができます。
異なるシャードに属する2つのアカウント(alice.near
とbob.near
)があるとしますalice.near
(Shard #0)はbob.near
(Shard #1)にトークンを送るトランザクションを作成します。トランザクションはすぐに実行され、トランザクションのExecutionOutcomeは常にレシートになります。
しかし、このレシートはShard #0で実行できません。なぜならbob.near
はalice.near
と同じシャードにいないからです。そのため、レシートは受信者のシャードで実行される必要があるため、レシートはbob.near
が属するシャードに移動します。移動先のシャードでレシートが実行され、プロセスは完了したとみなされます。
NEARブロックチェーンにおいて、レシートはシャード間を移動できる重要な内部トランザクションです。クロスコントラクトコールを含むより複雑なトランザクションでは、より多くのレシートとExecutionOutcomeが発生します。
以下の動画を見るとより理解が深まります。
この動画やドキュメントを見る限りだと、各トランザクションだけでなく、各アカウントもランダムにシャードに割り当てられていそうです。並行してトランザクションを処理できるが、別シャード内のトランザクションに依存していたり、別シャード内のアカウントに送付などがある場合はシャードを跨ぐ必要性が出てくるイメージです。
ランダムに割り当てない場合、特定のシャードに負荷が集中されてしまうため、負荷分散のために行っているのかなという予想です。特にその部分について書かれているドキュメントなど見つからないためあくまで予想です。より詳しく知りたい方はシャードについての以下のPDFを読むことをお勧めします。
以下の2パターンのNEARプロトコルにおけるトークン送付についてフローを確認していきます。
異なるシャードにあるアカウント間のトークン送付。
同じシャードにあるアカウント間のトークン送付。
また、必要以上のガスを渡した時、そのガスに関しては払い戻し(リファンド)がされます。
alice.near
とbob.near
という2つのアカウントが異なるシャードに属していて、alice.near
がbob.near
にトークンを送信するとします。
alice.near
が署名したトランザクションがネットワークに送信され、すぐに実行されます。ExecutionOutcome(実行結果)はトランザクションをレシートに変換した結果です。
生成されたレシートは、次のブロック以降に実行され、受信者のシャードで実行される必要があります。そのため、レシートはbob.near
のシャードに移動し、実行キューに入ります。
レシートは次のブロックで実行されます。ExecutionOutcomeは、送信者にガスを払い戻すための新しいレシートになります。
このリファンド用のレシートは、受信者であるalice.near
のシャードに移動し、そこで実行されます。
両方のアカウントが同じシャードにある場合、レシートがシャード間を移動するプロセス以外は同じです。
トランザクションが実行され、レシートが生成されます。
レシートは既に受信者のシャードにあるので、次のブロックの実行キューに入ります。
レシートが実行され、ExecutionOutcomeは送信者にガスを払い戻すための新しいレシートになります。
リファンド用のレシートも同じシャードで実行キューに入り、次のブロックで実行されます。
NEARプロトコルで使用されるネイティブトークンです。
NEARプロトコルはPoS(プルーフ・オブ・ステーク)というコンセンサスアルゴリズムを持つブロックチェーンです。NEARをステーキングすることでネットワークを維持します。
PoS(Proof of Stake)は、ブロックチェーンにおけるコンセンサスアルゴリズムの一種です。コンセンサスアルゴリズムとは、分散ネットワーク内の多数の参加者が、取引の有効性について合意に達するためのメカニズムです。
PoSでは、新しいブロックを作成し、ネットワークを保護する役割を担うバリデーター(検証者)が、保有するコインの量(ステーク)に基づいて選ばれます。より多くのコインをステーキング(預け入れ)しているバリデーターほど、新しいブロックを生成する機会が与えられる確率が高くなります。
PoSのメリットは以下の通りです。
エネルギー効率が高い:PoWのように複雑な計算を必要としないため、消費電力が少なくて済む。
より高い拡張性:PoWと比べて、より多くの取引を高速に処理できる可能性がある。
51%攻撃に対する耐性:攻撃者は大量のコインを保有する必要があるため、攻撃のコストが高くなる。
ステーカーへのインセンティブ:バリデーターはブロックの作成に成功するとリワードを得られるので、ネットワークを守るインセンティブが働く。
一方で、PoSにはいくつかの課題もあります。
より多くのコインを持つ者がより多くのリワードを得られるため、富の集中化が起こりやすくなる。
バリデーターがあまりペナルティを受けずに不正行為ができてしまう可能性がある。
PoWと比べると、長期的なセキュリティを保証するのが難しいという意見もある。
また、NEARはトランザクションの処理やストレージへのデータ保存時の手数料として使用できます。
以下のようなシナリオでトークンを失う可能性があるため十分に注意が必要です。
不適切なキー管理
削除されたアカウントへの払い戻し
バッチ処理での関数呼び出しの失敗
FullAccess
キーを紛失した場合、他のキーがなければ資金を回復できず、永久にロックされてしまいます。
唯一のFunctionCall
アクセスキーを削除した場合も同様の結果になります。
バックアップキーを発行しておくことで、キーを紛失・削除した際のアカウント復旧が可能になります。
存在しないアカウントを受取人として指定してアカウントを削除した場合、払い戻しは元のアカウントに対して発行されますが、元のアカウントは既に削除されているため、資金はバリデーター間で分配されます。
残高ゼロのアカウントは、払い戻しを受け取る直前にガベージコレクションによって削除される可能性があり、その場合も資金はバリデーター間で分配されます。
スマートコントラクト設計時は、NEARプロトコルの非同期性を考慮する必要があります。
ある関数f1
が他の2つ(以上)の関数f2
とf3
を呼び出し、そのうち少なくとも1つが失敗した場合、失敗した関数からトークンは払い戻されますが、成功した関数からは払い戻しがされずトークンが渡されます。
バッチ処理の1つでも失敗した場合にバッチ全体が失敗したと見なすケースでは、成功した呼び出しのトークンは失われたと考えられます。
NEARブロックチェーンに保存される全てのデータはkey-value構造で保存されます。
以下のドキュメントではSDKを使用してNEARブロックチェーンのストレージにデータを保存するコードがまとめられています(この記事では技術の詳細は省くため別記事で取り上げます)。
NEARでデータを保存する時は、以下の制約事項を考慮する必要があります。
ストレージステーキングのコストが加算される可能性がある。
一度にアップロードできるデータは4MBに制限されている。
例えば、NFTをIPFSなどの分散ストレージではなく、ブロックチェーン上に置くとほぼ無制限のストレージを利用できますが、使用したストレージ100KBあたり1 $NEAR
を支払う必要があります。
また、MAX_GAS
の制約により、ユーザーが一度のコントラクト呼び出しでアップロードできるデータは4MBに制限されています。1つの関数呼び出しに付与できるガスの最大量は前述した通り300 TGas
です
NEARでは、スマートコントラクトをデプロイする時、そのコントラクトが必要とするストレージの料金を「ストレージステーキング」と呼ばれるメカニズムを通じて支払います。
ストレージステーキング(ステートステーキング)では、スマートコントラクトを所有するアカウントは、そのスマートコントラクトに保存されているデータ量に応じてトークンをステーク(ロック)する必要があります。
NEARの設計では、ストレージにステークされたトークンは、バリデーションステークなど他の用途に使用できなくなります。これにより、バリデーターが受け取る利回りが増加します。
トークンがステークされるのは、データを追加する各トランザクションが来たときです。例えば、SNSアプリをデプロイし、ユーザーがメッセージを送信すると、ユーザーは少額のガス料金を支払ってメッセージをコントラクトに送信します。NEARはexample.near
というアカウントの残高が、保存したいストレージをカバーするのに十分な量をステークできるかどうかをチェックします。できない場合、トランザクションは失敗します。
ユーザーにとってデータ送信のコストがほとんどかからないのに対し、コントラクトオーナーにとってはかなりのコストがかかる場合、攻撃の対象になる可能性があります。そのため、攻撃者にとって割に合わないようにスマートコントラクトを設計する必要があります。
データを削除することでトークンの一部をアンステークすることができます。インデックスノードはすべてのデータを永久に保持しますが、バリデーションノード(ネットワークのほとんどのバリデーターが運営するノード)はそうではありません。スマートコントラクトはデータを削除する方法を提供でき、このデータはネットワークのほとんどのノードから数エポック以内に削除されます。
ただし、データを削除するためのスマートコントラクトへの呼び出しにはガス料金がかかるため、NEARのガスリミットを考えると、1つのトランザクションで削除できるデータ量には上限があることになります。
ストレージステーキングのコストは、ネットワークによって設定された金額で、1バイトあたり1E19 yoctoNEAR、つまり100kbあたり1 NEARトークン(Ⓝ)です。
yoctoNEAR (yN)
は、NEAR の最小単位です。1 NEAR = 1e24 y
N (1 後ろに 24 個のゼロがつく数)。したがって、1E19 yoctoNEAR
は0.00001 NEAR
に相当します。
例として、100万個のトークンを管理する非代替性トークン(NFT)を考えてみます。トークンIDから所有者のアカウントIDへのマッピングを保存するために、どれだけのストレージが必要で、そのストレージのためにどれくらいのトークンをステークする必要があるでしょうか?
データをUTF-8
文字列として保存するPersistentMap
を使用する場合のストレージ要件を計算してみます。
NEARブロックチェーンに保存されるすべてのデータはキーバリューデータベースに保存されます。PersistentMap
に渡される't2o'
変数は、すべての値を追跡するのに役立ちます。
100万個のトークンについて、以下のものを合計して100万倍する必要があります。
プレフィックスt2o
は、UTF-8
で3
バイトとしてシリアル化され、2つのコロンがさらに2
バイト追加されます。合計5
バイトです。
TokenId
が自動インクリメントする実装では、値は0
から999999
の間になり、平均の長さは5
バイトになります。
適切に形成されたNEAR AccountId
を想定し、平均約10文字に加えて.near
のようなトップレベルの名前が付くため、悲観的に見積もって25
とします。NEAR account IDはASCII文字セットの文字を使用する必要があるため、これは25
バイトに相当します。
上記の計算式になり、結果は3500万バイト(350×100Kib = Ⓝ 350
)となります。1バイトあたり1e19 yoctoNEAR
を掛けると、3500万バイトのtokenToOwner
マッピングには3.5e26 yoctoNEAR
、つまりⓃ 350
のステーキングが必要になります。
プレフィックスをt2o
から1文字に変更するだけで、Ⓝ 330
に減らすことができるためコストを見積もることで削減ポイントを見つけることができます。
ストレージコストを抑える他の方法として、以下の2つのアプローチがあります。
JSONではなく、バイナリシリアライゼーションフォーマットを使用する。
データをオフチェーンに保存する。
NEARのコアチームは「borsh」というライブラリを使用しています。
例えば、[0, 1, 2, 3]
のような配列を保存する場合、JSON形式で保存すると9
バイトが必要ですが、borshを使用すると8
バイトで済みます。このように、JSONでは新しい要素ごとに2
バイト(コンマと数字)が必要ですが、borshでは1
バイトしか増えません。
例えば、SNSアプリで、ユーザーがメッセージを残せるとします。この時、データをオンチェーンに保存するとコントラクトオーナーの負担が大きくなるため、IPFSなどのオフチェーンにデータを保存するのが望ましいです。
NEARネットワークは分散化されており、バリデーターが協力してネットワークの安全性を維持しています。
NEARプロトコルでは、Proof-of-Stake(PoS)の一種である「Thresholded Proof of Stake」を使用して、トランザクションが有効か検証しています。PoSでは、ユーザーはNEARトークンを特定のバリデーターに委任(ステーキング)することでそのバリデーターへの支持を示します。
バリデーターには以下の役割があります。
トランザクションを検証・実行し、それらをブロックチェーンを形成するブロックに集約する。
他のバリデーターを監視し、無効なブロックを生成したり代替チェーンを作成しない。
バリデーターが不正行為を行っていることが発覚した場合、「スラッシング」と呼ばれるペナルティが課され、ステークの一部または全部が没収(burn)されます。
バリデーターは、ネットワークへのサービス提供の見返りとして、毎エポックに目標とする数のNEARを報酬として受け取ります(年間のインフレ率4.5%)。
各エポックで収集されたすべてのトランザクション手数料はシステムによってburnされます。インフレ報酬(バリデーターがネットワークへの貢献に対して得ることができる経済的インセンティブ)は、収集またはburnされた手数料の額に関係なく、バリデーターに同じ割合で支払われます。
バリデータになるためにはハードウェア(CPUで十分)が必要になり、月の運用コストは$330が見込まれます。バリデーターになるための最低シート価格(バリデーターになるために必要なトークンの最低量)は、バリデーターのプロポーザルに基づいて決定されます。提出されたプロポーザルが300個以上ある場合、300番目に多いステーク(トークンの量)がシート価格(25,500 NEAR以上であるかも確認)として設定されます。
Chunk-Only Producersは、NEARネットワークの一部である特定のシャード(ネットワークの分割区画)で「チャンク」の生成を担当し、初期投資額を抑えてネットワークに参加できます。チャンクとは、ブロックの一部分であり、特定のシャードからのデータを含んでいます。Chunk-Only Producersは、年間で最低4.5%の報酬を受け取ります。ネットワーク上でステークされているトークンが100%未満の場合、さらに多くの報酬を得ることができます。
NEARプロトコルは以下のネットワークが存在します。
メインネット (mainnet)
テストネット (testnet)
ローカルネット (localnet)
エポック(Epoch)とは、ネットワークのバリデーターが一定の期間ブロックの生成とトランザクションの検証を行う時間単位で、ブロック数で測定されます。
テストネットとメインネットのエポック期間は、どちらも43,200ブロックです。ブロックは毎秒作成されるので、大体エポックは約12時間続きます。
NEARは、ブロックチェーンをユーザーエクスペリエンスから抽象化するための一連のサービスを提供することで、ユーザーがブロックチェーンを意識せずにアプリを楽しめるようにしています。
この抽象化を実現するために、NEARは以下の技術を組み合わせています。
リレーヤー
FastAuth
マルチチェーン署名
アカウントを持っていれば、アプリはユーザーにメタトランザクションの作成を求め、それを任意のリレーヤーに送信できます。リレーヤーはトランザクションをネットワークに渡し、実行料金を支払うためのNEARを送ります。リレーヤーはNEARを送付するだけなので、トランザクションはユーザーが送信したかのように実行されます。
このように、NEARのチェーン抽象化サービスは、ブロックチェーンの複雑さをユーザーから隠し、よりシームレスでアクセスしやすいユーザーエクスペリエンスを提供することを目的としています。
メタトランザクションは、ユーザーがガスやトークンを所有せずにNEAR上でトランザクションを実行できる仕組みです。これを可能にするために、ユーザーはオフチェーンでトランザクションを構築して署名します。トランザクションの送信と実行の手数料は、サードパーティ(リレーヤー)が負担します。
メタトランザクションについては、Ethereumについてですが以下の記事を参考にしてください。
メタトランザクションの流れ。
アリスは、ファンジブルトークン$FTを一定量所有しています。アリスはft_transfer("john", 10)
を呼び出して、10トークンをジョンに送金したいと考えています。
アリスは他の誰かが資金を提供したNEARアカウントと、そのアカウントの秘密鍵しか保有しておらず、NEARトークンを保有していません。アリスはft_transfer("john", 10)
を行う署名済みトランザクションを作成できますが、ガスを購入するのに必要なNEARトークンの残高がないため、バリデーターノードはそれを受け入れません。
メタトランザクションを使えば、アリスはトランザクションに非常によく似たDelegateAction
を作成できます。これにはアクションのリストとそれらのアクションの単一の受信者が含まれます。アリスはDelegateAction
に署名し、それをオフチェーンでリレーヤーに転送します。リレーヤーはそれをトランザクションにラップし、リレーヤー自身がそのトランザクションの署名者となり、ガス代を支払います。
オンチェーンでは、トランザクション内のSignedDelegateAction
は、リレーヤーのシャードに同じSignedDelegateAction
を持つアクションレシートに変換されます。このレシートはアリスのアカウントに転送され、そこでSignedDelegateAction
が展開され、アリスによって有効なNonceなどを使って署名されていることが検証されます。すべてのチェックが成功すると、アクションのレシートがFTに送信され、ft_transfer
の呼び出しが実行されます。
メタトランザクションはリレーヤーがいないと機能しません。リレーヤーは、SignedDelegateAction
を受け取り、それに対していくつかのチェックを行い、最終的にそれをトランザクションの中に入れてブロックチェーンネットワークに転送するサーバーのようなものです。
リレーヤーは、NEARユーザーから署名済みのトランザクションを受け取り、そのガス代を負担するためのトークンを添付してネットワークに中継するシンプルなWebサービスです。]ユーザーがNEARを購入しなくてもトランザクションを実行できるアプリケーションを作成するのに役立ちます
リレーヤーは、メタトランザクションという仕組みから生まれ、インテントにも関連する部分です。
ユーザーは「チェーン上で特定のアクションを実行したい」というインテントを表明し、オフチェーンで署名してリレーヤーに送信します。リレーヤーはこのメッセージを実際のトランザクションにラップし、必要な資金を添付して、ネットワークに送信します。
リレーヤーを使用する理由には以下があります。
トランザクションをカバーするためのガスを持っていない。
アカウントを持っているが、FTしか残高がないためFTを使ってガス代を支払いたい。
企業や大規模なスタートアップとして、既存のユーザーをシームレスにNEARにオンボーディングしたいが、ガス代やシードフレーズを気にさせたくない。
大量のトランザクションを一気に流したくないため、リレーヤーを緊急性の低いトランザクションのキューとして機能させる。
ガス料金をカバーする代わりに、リレーヤー運営者はユーザーの資産の使用場所を制限しつつ、ユーザーに資産の管理と所有権を与える。
リレーヤーは、ユーザーにとってはガス代を気にせずにNEARエコシステムを利用できる手段であり、企業にとってはユーザーのオンボーディングを容易にし、ガス代の管理を効率化する手段だと言えます。
チェーン署名は、スマートコントラクトを含むNEARアカウントが、多くのブロックチェーンプロトコルにまたがってトランザクションに署名し、実行できるようにする技術です。
他のブロックチェーンプラットフォーム上のアカウントとその資産を制御することは、以下の3つの要素の相互作用によって可能になります。
導出パス(Derivation Paths)
マルチチェーンスマートコントラクト
マルチパーティ計算(MPC)サービス
導出パスにより、1つのNEARアカウント(例:near.cardene
)から複数のイーサリアムアドレスを導出することができます。
マルチチェーンスマートコントラクトは、他のブロックチェーン上のトランザクションの署名をリクエストするために使用されます。このコントラクトには、ターゲットブロックチェーン用に署名されるペイロード(トランザクション)と、トランザクションの署名に使用するアカウントを識別するパスの2つのパラメータを取るsign
メソッドがあります。
MPCサービスは、秘密鍵を公開することなく、ユーザーに代わってトランザクションに安全に署名できます。NEARのMPCサービスは、複数の独立したノードで構成されており、どのノードも単独では署名できませんが、代わりに複数のラウンドを通じて集約される署名シェアを作成し、共同でトランザクションに署名します。
チェーンシグネチャーを使うと、マルチチェーンおよびクロスチェーンのワークフローをシンプルに実装することができます。
チェーンシグネチャーを使えば、異なるブロックチェーン上の資金を管理するNEARアカウントの所有権を交換するだけで、チェーン間で資産を取引できます。例えば、X BTC
を持つビットコインアカウントを管理するNEARアカウントを、Y ETH
を持つイーサリアムアカウントを管理する別のNEARアカウントと交換できます。
このようにして、ネイティブトークンをそのネイティブブロックチェーン(例えば、ビットコイン上のBTC
、イーサリアム上のETH
、アービトラム上のARB
)に保持したまま、ブリッジなしで取引することができます。さらに、取引はチェーンをまたいでアトミックに行われ、決済はわずか2秒で完了し、どのチェーン上のどのトークンでもサポートされるというメリットもあります。
注意点としては、異なるブロックチェーン上でトランザクションが発生しているということです。違いは、マルチパーティ計算(MPC)サービスがユーザーの代わりにトランザクションに署名し、そのトランザクションが別のブロックチェーンのRPCノードやAPIにブロードキャストされるということです。
基本的なトランザクションの流れは以下のようになります。
ユーザーはNEARチェーンシグネチャーで制御されるアカウントを作成する。
ユーザーはこれらのアカウントにネイティブブロックチェーン上で資金を提供する(預け入れ)。
必要な資金を新しいアカウントに入れて注文を出す。
別のユーザーがその注文を受け入れる。
注文を履行するために、ユーザーがキーの制御を交換する。
具体的なステップとしては、例えば以下のようになります。
ユーザーBは、NEARを使って、ビットコイン上に1 BTC
を持つ新しいアカウントを作成し、資金を提供します。
ユーザーBは、スポットマーケットプレイススマートコントラクトを使用して、指値注文を作成するトランザクションに署名します。これにより、ビットコインアカウントの管理がスマートコントラクトに移ります。
ユーザーAは、2つのステップを持つバッチトランザクションを作成します。
10 ETH
を持つ新しいイーサリアムアカウントを作成して資金を入れる。
注文を受け入れ、アカウントの制御をアトミックにスワップ(交換)する。
ユーザーAは1 BTC
を持つビットコインアカウントの所有権を取得し、ユーザーBは10 ETH
を持つイーサリアムアカウントの所有権を取得します。
ユーザーAとBは、資産をそれぞれの「メイン」アカウントに送金することで、注文から資産を「引き出す」ことができます。
このように、チェーンシグネチャーを活用することで、異なるブロックチェーン間での資産取引をシームレスに行うことができるようになります。
ユーザーのJWTトークンの所有者がブロックチェーントランザクション(Ethereum、Polygon、Avalancheなど)に署名できるようにするNEARコントラクトをデプロイすることで、既存のWeb2アカウントを使ってユーザーをオンボーディングさせることができます。ユーザーは第三者とのIDを検証してJWTトークンを受け取り、そのトークンを保持しているユーザーは、トークンの有効期間中、NEARコントラクトを介してEthereum/Polygon/その他のブロックチェーンアプリとやりとりできます。
KEYPOMを使用して、期限付きのアカウントを発行することができ、NFTドロップ、FTドロップ、チケットなどに使用できます。
開発者が制限付きのNEARアカウントを作成し、NEARチェーンの資産を入れます。ユーザーはアカウントを制限付きで管理できるキーを受け取り、資産が入っているアカウントを使ってNEAR上の管理されたエンドポイントを呼び出します。最後に、ユーザーは残りの資金を開発者に返却し、アカウントのロックが解除されます。
チェーンシグネチャを使用すると、NEAR上のスマートコントラクトが、ビットコイン、ドージコイン、XRPレジャー、ビットテンサー、コスモスハブなどのスマートコントラクトではないチェーン上の外部所有アカウントを制御できます。これにより、開発者はNEARをネイティブにこの機能をサポートしないチェーンのスマートコントラクト「レイヤー」として使用できます。
例えば、開発者はNEAR上のスマートコントラクトを使ってビットコインオーディナルの分散型取引所を構築し、コントラクトが制御するビットコインアドレスへの入金を管理し、2人のユーザーがBTCとオーディナルまたはBRC20トークンの取引に合意したときにスワップを検証・実行できます。
ブロックチェーンから情報を取得する時、通常はRPCノードというものを使用します。この時、複数の単一のブロックからデータを取得する必要があるため、取得に時間がかかります。
RPC(Remote Procedure Call)は、1つのコンピュータ(クライアント)が別のコンピュータ(サーバー)にあるプログラムを実行するための技術です。これにより、クライアントは自分のシステム上でプログラムを実行しているかのように、サーバー上のプログラムを遠隔操作できます。
RPCの基本概念
クライアントとサーバー間の通信
クライアントはサーバーに対して特定の手続き(関数やメソッド)の実行を要求します。
サーバーはその手続きを実行し、結果をクライアントに返します。
透過性
- RPCは、遠隔地にある手続きを呼び出しているという事実を抽象化し、開発者がローカルで手続きを呼び出すかのように感じられるようにします。
データ交換形式
- RPCの実装には多くの形式がありますが、JSON-RPCはデータ交換にJSON形式を使用することが特徴です。
JSON-RPCとは
JSON-RPCはRPCの一種で、データフォーマットとしてJSON(JavaScript Object Notation)を使用します。これにより、データがテキストベースで人間にも読みやすい形式でやり取りされ、Web開発で広く利用されています。
NEARプロトコル
NEARプロトコルでは、ブロックチェーンとのインタラクションを容易にするためにJSON-RPCエンドポイントを提供しています。ユーザーや開発者は、このAPIを通じてブロックチェーン上で以下のような操作を行うことができます:
スマートコントラクトの実行
ブロックやトランザクションの情報取得
アカウントの状態やトークンの残高確認
ただし、すべてのデータがJSON-RPCを通じて利用可能なわけではありません。例えば、ローカルレシートなど、ノードの内部データベースに保存されていない情報は、このAPIを使ってアクセスできない場合があります。
大量のデータや複雑なデータをブロックチェーン上から取得することを解決する方法として、「ブロックチェーン インデクサー」を使用することがあげられます。
ブロックチェーンインデクサーは、データを取得するプッシュモデルです。
プルモデル(インデクサーを使わない方法):
プッシュモデル(インデクサーを使う方法)
ブロックチェーン上にデータが追加されるたびにその変更を読み取り、別の場所(データベース)にその情報を整理して保存。
ユーザーが情報を探すときは、そのDBなどを見るだけで済む。
インデクサーの役割は、ブロックチェーンに追加される新しいデータを常に監視し、そのデータを即座にフィルタリングして処理し、データベースに保存することです。これにより、ブロックチェーンから直接データを引き出す(プルする)のではなく、整理されたデータにアクセスできるようになります。
また、インデクサーを使うと、複数のブロックにまたがる複雑なクエリの実行も簡単になります。
インデックスサービスとしては以下のようなものがあります。
インデクサーを作成した場合は以下の記事が参考になります。
今回はNEAR Blockchainについてまとめてきました。
実装については別の記事でまとめていきます。
今後も技術的な部分を中心にわかりやすくまとめていこうと思います。
他の媒体でも情報発信しているのでよければ見ていってください!