暗号通貨に関する事など

暗号通貨に関する覚書など。メモや日記。

※技術的なことに関して、間違っていたらコメントから指摘していただけると泣いて喜びます

【仮想通貨NEM】TransferTransactionの構造

はじめに

 NEMはビットコイン等と違い、基本的にはネイティブ機能として様々な機能を実装しており、機能毎に送信するトランザクションの構造自体が変化する。今回、我々が普段の利用で最もよく利用するxemやモザイクを送信する時に使うTransferTransactionというトランザクションの構造を調べたので記録として残す。


 間違っていたら指摘してください。


TransferTransactionの構造

 早速ですが構造を図にしたので載せます。下記図参照。


 ちなみに、バイトオーダーはリトルエンディアンになっている。また、当然といえば当然だがこの中で登場するintやlong値はマイナスであってはならない。


 versionとtype以外はそれほど特殊なものは無いと思う。ちなみに、上記表の中には全トランザクション共通の部分がある。上から見ていってversion〜deadlineまでは全てのトランザクションで共通の部分となる。
 一応説明の補足としてクラスの継承の図を載せておく。各クラスで定義されたフィールドを見ればどこが共通した部分か分かると思います。

 
 次に、構造の最上部2つ、versionとtypeの部分について、補足が必要だと思ったのでそのことについて書く。
 

version

 versionは4byteでただのintかと思いきや、実際は3byteと1byteに分かれている。3byteの部分がversionを表現する数値、最後の1byteがネットワークを表現している。下記図参照。

※network info部分は名前が分からなかったので私が勝手にそう呼んでいるだけです


type

 typeは4byteのフィールドだが、単にVerifiableEntityの種類によって1から数えて数値を割り振っているわけではない。先頭2byteを利用して大分類と小分類の分類分けを利用して表現している。 " 0x [小分類] [大分類] 00 00 "といった具合にそのtypeの値を決めている。下記図参照。


write系メソッドとBinarySerializerClass

 トランザクションに署名を行うとき、トランザクションをバイナリデータにする必要がある。バイナリデータを生成する時に利用される言葉が"serialize"という言葉で、実際VerifiableEntityClassやTransferTransactionClassのソースコード内にserializeというメソッドがある。


 serializeメソッドが呼ばれるとその中でwriteIntメソッドやwirteBytesメソッドが呼ばれているのが分かるが、それらがBinarySerializerによってどういった変換がされているかというと...

  • writeInt => 4byte int
  • writeLong => 8byte long
  • wirteDouble => 8byte double
  • writeBytes => 4byte dataLength + var byte dataPayload
  • writeObject => 4byte objectSerializedDataLength + var byte serializedObject
  • writeObjectArray => 4byte objectArraySize + var byte serializedObject(add 4byte length prefix)
 となっている。説明に難があるが要するに、intは4byteのデータでシリアライズされ、longは8byteのデータになる。バイト配列のデータ(utf-8としてバイト配列化されたデータ等)は、まず最初に4byteでデータ長が頭につくと思えば良いし、そういう目で一番上のTransaction構造の図を見ればそうなっていることが分かる。

example

 ここで実際にnem-coreのソースを利用して出力したデータをサンプルとして載せる。バイナリデータを各フィールド毎に切って説明を加えたものが下にある図になる。


 なお、無理やり出力させたせいで手数料など一部おかしな部分が有ります。そこは参考にせず構造だけ参考にしてみてください。


【条件】
・ネットワーク
 テストネット
・署名者(送金者)の公開鍵
 C4E97281C84749E67E06027BBC695EF4034C9885AF369715B2F9A44E10D52BA8
・受取者アドレス
 NBUO7V7YQ5A33IAKWUOEROEORCXNVPAMV5NCUIGR
・メッセージ
 Hello NEM
・mosaic1
 alice:alicecoinを10枚送信
・mosaic2
 test.bob:bobcoinを20枚送信


【連結されたデータ】
0101000002000098E290180020000000157367594486F1C427C9A9D30FE88DBDD73599245702CC0EED50C57F5E11281580841E000000000000000000280000004E42554F37563759513541333349414B57554F45524F454F5243584E5650414D56354E435549475200E1F5050000000011000000010000000900000048656C6C6F204E454D02000000220000001600000005000000616C69636509000000616C696365636F696E0A00000000000000230000001700000008000000746573742E626F6207000000626F62636F696E1400000000000000


【フィールド毎に切ったもの】
01010000 type
02000098 version
D4171600 timestamp
20000000 SignerDataLength(32)
C4E97281C84749E67E06027BBC695EF4034C9885AF369715B2F9A44E10D52BA8 SignerPublicKey
80841E0000000000 amountFee(2,000,000)
00000000 deadLine


28000000 recipientAddressDataLength(40)
4E42554F37563759513541333349414B57554F45524F454F5243584E5650414D56354E4355494752 recipientAddress(UTF-8)
00E1F50500000000 amountSendXem(100,000,000)


11000000 messageObjectDataLength(17)
01000000 messageType(1 => PlainMesage)
09000000 messageLength(9)
48656C6C6F204E454D messagePayload("Hello NEM")


02000000 mosaicCount(2)


22000000                     mosaic1 ObjectDataLength(34)
16000000                     mosaic1 MosaicInfoDataLength(22)
05000000                     mosaic1 NameSpaceDataLength(5)
616C696365                 mosaic1 NameSoaceDataPayload("alice")
09000000                      mosaic1 MosaicDataLength(9)
616C696365636F696E mosaic1 MosaicDataPayload("alicecoin")
0A00000000000000      mosaic1 sendQuantity(10)


23000000                 mosaic2 ObjectDataLength(35)
17000000                 mosaic2 MosaicInfoDataLength(22)
08000000                 mosaic2 NameSpaceDataLength(8)
746573742E626F62 mosaic2 NameSoaceDataPayload("test.bob")
07000000                  mosaic2 MosaicDataLength(7)
626F62636F696E     mosaic2 MosaicDataPayload("bobcoin")
1400000000000000  mosaic2 sendQuantity(20)


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

 署名は上記のバイナリデータに署名を行うことになります。暗号はEd25519です。


注意点(追記)

・mosaic添付時のAmountフィールドに関して



さいごに

 カタパルトで構造が変わるかも知れないのでここまではあまり触れずに来ましたが、確かにこういう記事って無いので、書いてみました。


 nem-coreのソースコードをコンパイルして出力したので構造自体は間違ってないと思いたいですが、間違っていたら教えてください。ちなみに、nem-coreのソースコードのままだと署名用データはprivateで隠蔽されるのでpublicに変更したりモザイク情報が無いので本来エラーが出るところを無理やり無視させて出力させたりしています。


 他人のコード読むことってこういう機会でもないと無いので、色々良い勉強になったなと思います。実際いい勉強になったという感想が一番強いです。カタパルトOSS化したらまた見てみようかなと思ってます。その場合C/C++の勉強をするのが先になりますが...。

×

非ログインユーザーとして返信する