TransferTransactionのスキーマを読み解こうその３

# トランザクションのスキーマ

![スクリーンショット 2022-06-24 1.55.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253981/fb46afdd-2511-4297-f418-84b3d178d10c.png)

該当ソースコードはこちら

https://github.com/symbol/symbol/blob/dev/catbuffer/schemas/symbol/transaction.cats#L1-L22

これがトランザクションのスキーマの全体像。

```
import "entity.cats"
import "transaction_type.cats"

# binary layout for a transaction
@size(size)
@initializes(version, TRANSACTION_VERSION)
@initializes(type, TRANSACTION_TYPE)
@discriminator(type)
@is_aligned
abstract struct Transaction
	inline SizePrefixedEntity
	inline VerifiableEntity
	inline EntityBody

	# transaction type
	type = TransactionType

	# transaction fee
	fee = Amount

	# transaction deadline
	deadline = Timestamp
```


## トランザクションの属性について

```
@size(size)
@initializes(version, TRANSACTION_VERSION)
@initializes(type, TRANSACTION_TYPE)
@discriminator(type)
@is_aligned
```

ここの@で始まるところは「属性」（アトリビュート）と言いまして、
トランザクションのスキーマに対して属性を付与することができます。

たとえば魔法使いの属性に水属性を付与すると水の魔法使いとなってリムル・テンペストが
種族が龍の個体に風属性を付与するとヴェルドラ・テンペスト
となるように属性を付与することができる認識でいます。

まず、ここでは「トランザクション」に対するバイナリのレイアウトを設定してますので、
トランザクションの属性を示唆しているわけです。
その属性をそれぞれ見ていきましょう。

```
@size(size)
```

:::note
size(x): x フィールドが（可変長の）構造体のフルサイズを含むことを示す。
:::

これはトランザクションの構造体の長さ（バイト数）と思っていいと思います

![スクリーンショット 2022-06-24 1.58.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253981/7d09c25b-39b1-e13e-3772-80500a32e4f5.png)


```
@initializes(version, TRANSACTION_VERSION)
@initializes(type, TRANSACTION_TYPE)
```

:::note
initializes(x, Y): xフィールドがY定数で初期化されるべきであることを示す。
:::

ここではトランザクションのバージョンとトランザクションのタイプが初期化されます。
symbolではトランザクションのバージョンは1しかなく、ここは固定値になります。

またトランザクションのタイプはいろいろありますが、
転送トランザクションの場合は0x4154が入ります

こっちでトランザクションのタイプを確認できます。

https://docs.symbol.dev/ja/concepts/transaction.html

![スクリーンショット 2022-06-24 2.00.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253981/7e1d8d2b-b213-f2d7-1492-2b1d4452dc3b.png)


```
@discriminator(type)
```

:::note
discriminator(x [, y ]+): (x, ...y)プロパティがファクトリー生成時に識別器として使用されるべきであることを示す
（抽象構造に対してのみ意味を持つ）。
:::

ここではトランザクションのタイプの16進数からどう言ったタイプなのか識別子ます。
なので流れはトランザクションのタイプを１６進数で定義してから
識別器を使ってトランザクションの種類を判別する

```
@initializes(type, 0x4154) # この状態ではまだ転送トランザクションと認識されない
@discriminator(type)　# この引数のtypeは上で初期化したtypeです。@discriminatorで初めて転送トランザクションということがわかります。
```

![スクリーンショット 2022-06-24 2.00.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253981/023d0e6c-25d8-bc7c-f45a-5be3271aa6e5.png)


```
@is_aligned
```

:::note
is_aligned: すべての構造体フィールドがアライメントされた境界上に配置されることを示す。
:::

これはパフォーマンスの最適化（計算効率の向上）のために属性が指定されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253981/ceec40b9-9232-0d84-2259-cf925acd1b22.png)


たとえばこれが
Heightが7バイト
Timestampが3バイト
Difficultyが4バイト
とそれぞれバラバラだったとすると
Heightのポインター（Heightの最初のアドレス）
Timestampのポインター（Timestampの最初のアドレス）
Difficultyのポインター（Difficultyの最初のアドレス）
を探すのが難しくなります。

そこでHeightを7バイトの後ろに意味のない1バイトを入れることによって8バイトとすることで
コンピュータはポインタを探すのが早くなります。
そのようなデータ構造を持たせることでどこになにがあるかを調べる必要がなくできるので
計算効率が上がるということです。

この@is_alignedの属性にはそのような意味があります（スキーマによってサイズ数は異なることもありますが８バイト単位に揃えることでデータを扱いやすくなります。）

ある時

![スクリーンショット 2022-06-11 1.20.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253981/6932e552-f15e-1bd4-f685-5b02beee5879.png)


ない時

![スクリーンショット 2022-06-11 1.21.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253981/38b87656-bab2-c32d-6cda-05112ad6b12a.png)

とりあえずこれでトランザクションの属性はわかりました。