トランザクション

一般的にトランザクションとはデータベースシステム内での作業単位を表します。ブロックチェーンにおいて、 アカウント によって署名されたアクションが、それ自身の状態を変えるときを指します。

トランザクションタイプ

Symbol にはたくさんの異なるトランザクションタイプがあります。例えば、 モザイク をアカウント間で転送したり、メッセージング、アカウントの所有権を転送または構築する ( マルチシグ ルールも含めて) などがあります。

デフォルトでは、次のトランザクションタイプが Symbol ベースのネットワークに含まれます:

TransactionType

Size: 2 bytes = 0x2
schema

Enumeration of Transaction types

0x414c
ACCOUNT_KEY_LINK
0x424c
NODE_KEY_LINK
0x4141
AGGREGATE_COMPLETE
0x4241
AGGREGATE_BONDED
0x4143
VOTING_KEY_LINK
0x4243
VRF_KEY_LINK
0x4148
HASH_LOCK
0x4152
SECRET_LOCK
0x4252
SECRET_PROOF
0x4144
ACCOUNT_METADATA
0x4244
MOSAIC_METADATA
0x4344
NAMESPACE_METADATA
0x414d
MOSAIC_DEFINITION
0x424d
MOSAIC_SUPPLY_CHANGE
0x434d
MOSAIC_SUPPLY_REVOCATION
0x4155
MULTISIG_ACCOUNT_MODIFICATION
0x424e
ADDRESS_ALIAS
0x434e
MOSAIC_ALIAS
0x414e
NAMESPACE_REGISTRATION
0x4150
ACCOUNT_ADDRESS_RESTRICTION
0x4250
ACCOUNT_MOSAIC_RESTRICTION
0x4350
ACCOUNT_OPERATION_RESTRICTION
0x4251
MOSAIC_ADDRESS_RESTRICTION
0x4151
MOSAIC_GLOBAL_RESTRICTION
0x4154
TRANSFER

Symbol で利用可能なすべての基本トランザクションタイプは個別の プラグイン として定義されています。このプラグインアプローチにより、開発者はコアエンジンを変更したり、他の機能を分断することなく、新しいトランザクションタイプを導入できます。

トランザクションの定義

トランザクションはシリアル化された形式で定義されます。すべてのトランザクションは基本 Transaction スキーマを拡張し、特定の型プロパティが追加されています。

すべてのトランザクションは deadline と max_fee を定義する必要があります:

  • deadline: トランザクションは期限に到達する前に受け入れられるタイムウィンドウを持ちます。期限に到達してトランザクションが期限切れになると、すべてのノードはトランザクションを拒否します。デフォルトで SDK は期限を 2 時間に設定しますが、最大 6 時間 ( アグリゲートボンド トランザクションの場合は 48 時間) まで延長できます。

  • max_fee: トランザクション送信者がトランザクションを承認されるために支払う意思のあるネットワーク通貨の最大額。 次のドキュメント は最適な max_fee 値を設定する方法を示しています。

注釈

catbuffer スキーマ リポジトリは各トランザクションタイプがどのようにシリアライズされるべきかを定義しています。 catbuffer-generators プロジェクトと組み合わせると、開発者は特定のプログラミング言語用のビルダークラスを生成できます。

新しいトランザクションを定義するには SDK を使用することを推奨します。

  // replace with recipient address
  const rawAddress = 'TB6Q5E-YACWBP-CXKGIL-I6XWCH-DRFLTB-KUK34I-YJQ';
  const recipientAddress = Address.createFromRawAddress(rawAddress);

  const transferTransaction = TransferTransaction.create(
    Deadline.create(epochAdjustment),
    recipientAddress,
    [currency.createRelative(10)],
    PlainMessage.create('This is a test message'),
    networkType,
    UInt64.fromUint(2000000),
  );

トランザクションへの署名

アカウントはトランザクションをネットワークにアナウンスする前に、トランザクションに署名する必要があります。トランザクションへの署名は、定義通りにネットワークの状態を変更することにアカウントが同意することを表明します。

例えば、TransferTransaction には受信者が誰であるかと、転送するモザイクの量が記述されます。この場合、トランザクションに署名することは、それらのモザイクをあるアカウントの残高から他方のアカウントに移動することに同意することを意味します。

アカウントは トランザクションへ署名 をするために次のステップに従う必要があります:

  1. サイズ、署名、および署名者以外のトランザクションのすべてのバイトである 署名バイト を取得します。

  2. ネメシスブロックの generation hash を取得してください。 NODE_URL /node/info' にアクセスして meta.networkGenerationHash の値をコピーします。

  3. 署名バイトにネメシスブロックのジェネレーションハッシュを接頭します。

  4. 署名者の秘密鍵で結果文字列に署名します。これはトランザクションに 署名 を与えます。

  5. 署名者の署名と公開鍵をトランザクションに追加して ペイロード を取得します。

  6. 署名の最初の 32 バイト、署名者公開鍵、ネメシスブロックジェネレーションハッシュ、残りのトランザクションペイロードに SHA3-512 ハッシュアルゴリズムを適用して トランザクションハッシュ を計算します。

  // replace with sender private key
  const privateKey =
    '1111111111111111111111111111111111111111111111111111111111111111';
  const account = Account.createFromPrivateKey(privateKey, networkType);
  const signedTransaction = account.sign(
    transferTransaction,
    networkGenerationHash,
  );
  console.log('Payload:', signedTransaction.payload);
  console.log('Transaction Hash:', signedTransaction.hash);

トランザクションのアナウンス

Signed transactions are ready to be announced to the network. You can either use the SDK TransactionHttp service or append the payload to the request of the transaction endpoint.

  const transactionRepository = repositoryFactory.createTransactionRepository();
  const response = await transactionRepository
    .announce(signedTransaction)
    .toPromise();
  console.log(response);
curl -X PUT -H "Content-type: application/json" -d '{"payload":"B3000000F77A8DCFCB57B81F9BE5B46738F7132998F55123BFF4D89DC8E5CAE1F071A040E5571F4D8DA125B243C785DA5261F878E3DE898815F6E8F12A2C0A5F0A9C3504FA6249E8334E3F83E972461125504AFFD3E7750AFBB3371E7B2D22A599A3D0E3039054410000000000000000265DEE3F1700000090FA39EC47E05600AFA74308A7EA607D145E371B5F4F1447BC0F00010057656C636F6D6520546F204E454D44B262C46CEABB858096980000000000"}' http://localhost:3000/transaction

トランザクションのアナウンスをすると、REST API は常にOKをすぐに返します。この時点ではトランザクションが正当かどうかは不明です。

../_images/transaction-cycle.png

トランザクションサイクル

バリデーション

バリデーションの初回ステージは API ノードで行われます。トランザクションにエラーがある場合、WebSocket はステータスチャンネルへ通知を投げます。そうでなければ、トランザクションは P2P ネットワークへ 未承認 ステータスとして到達します。この状態の場合、トランザクションがブロックに含まれるかどうかはまだ明確ではありません。そのため、未承認状態のトランザクションを信頼してはいけません。

トランザクションが ハーベストされたブロック に追加される前に、2つ目のバリデーションが実施されます。成功した場合、ハーベスターはブロックにトランザクションを保存し、そのトランザクションは 承認済み のステータスとなります。この状態において、トランザクションはブロックチェーン台帳に承認の上に記録されていますが、まだ ファイナリティ は得ていません。

ネットワーク障害やパーティションなど、特定の状況下では最後に承認されたブロックが rolled back される可能性があります。そのため、ファイナライズされていない承認済みのトランザクションはネットワークによって認識されますが、巻き戻される可能性があるため、不変ではありません。

ブロックが不変となるためには finalization プロセスを完了する必要があります。ブロックがファイナライズされると、ブロックと含まれるトランザクションがブロックチェーン台帳に恒久的に記録されます。

スパムスロットル

ノードのキャッシュはブロックに取り込まれるまで、未承認トランザクションを保持します。キャッシュは貴重なリソースのため、 Symbol は攻撃者が未承認トランザクションでキャッシュを満たすことを防ぎながら、正当な利用者が新しい未承認トランザクションを正常に送信できるようにするためのスパムスロットルを実装しています。

スパムスロットルはアカウントのインポータンススコアを比較して、アカウントごとのキャッシュの配分を公平に計算することにより、アカウントが送信できる未承認トランザクションの量を制御します。アカウントがキャッシュの公平な配分を超過しており、ノードキャッシュに未承認トランザクションが1つのブロックに含めることができる量よりも多い場合、トランザクションは拒否されます。これにより、悪意のある利用者がノードにスパムトランザクションの送信を効果的にブロックし、他のユーザーがノードを通常通り使用できるようにします。