すべてのトランザクションには実行コンテキストが存在します。コンテキストとは、実行中のプログラムで利用できる一連の事前定義された変数のことです。例えば、すべてのトランザクションには送信者アドレスが存在し、トランザクション・コンテキストにはその送信者アドレスを保持する変数が含まれます。
トランザクション・コンテキストはTxContext
構造体を通じてプログラムに提供されます。この構造体はsui::tx_context
モジュールで定義されており、以下のフィールドを含んでいます。
// File: sui-framework/sources/tx_context.move
/// 現在実行中のトランザクションに関する情報
/// これはトランザクションによって構築されることはない。
/// これは仮想的に作成され、トランザクションのエントリーポイントに
/// `&mut TxContext`として渡される特権オブジェクトである。
struct TxContext has drop {
/// 現在のトランザクションに署名したユーザーのアドレス
sender: address,
/// 現在のトランザクションのハッシュ
tx_hash: vector<u8>,
/// 現在のエポック番号
epoch: u64,
/// エポック開始のタイムスタンプ
epoch_timestamp_ms: u64,
/// このトランザクションの実行中に作成された新規IDの数を記録するカウンタ
/// トランザクション開始時は常に0
ids_created: u64
}
このトランザクション・コンテキストは手動で生成したり、直接変更することはできません。システムによって生成され、トランザクション内の関数に参照として渡されます。トランザクション内で呼び出される関数は、このコンテキストにアクセスでき、さらにその関数内から別の関数に引き継ぐことも可能です。
TxContext
は、関数の引数リストの最後に置かなければなりません。
TxContext
のフィールドのうち、ids_created
以外はすべてgetter関数が用意されています。これらのgetter関数はsui::tx_context
モジュールで定義されており、プログラムで使用できます。これらのgetterはコンテキストを変更しないため、&mut
の参照を必要としません。
public fun some_action(ctx: &TxContext) {
let me = ctx.sender();
let epoch = ctx.epoch();
let digest = ctx.digest();
// ...
}
TxContext
は、システム内で新しいオブジェクト(またはUID)を生成するために必要です。新しいUIDはトランザクションのダイジェスト(ハッシュ値)から生成されますが、このハッシュが一意であるためには、何らかの可変パラメータが必要です。Suiでは、ids_created
フィールドを利用してこれを実現しています。新しいUIDが生成されるたびに、このids_created
の値が1増加するため、常に一意のハッシュが生成されます。
内部的には、以下のderive_id
関数を用いてこのプロセスが実行されます。
// ファイル: sui-framework/sources/tx_context.move
native fun derive_id(tx_hash: vector<u8>, ids_created: u64): address;