2019年12月3日時点でCatapultのエンドポイントにアクセスしてみます。
(まもなく公開テストネットのアナウンスがあると思いますが、本記事はFushicho1です)
Catapultをコアエンジンに持つNEMの最大の特徴は、手を伸ばせば誰でもブロックチェーンにアクセスできることです。
そこには、サーバーを構築する煩雑さも、キャッシュされた古い情報でもありません。今回の記事でも直接ノードにアクセスできるようリンクを張っています。より近くにブロックチェーンを感じていただければ幸いです。
最新ブロック高を取得
/chain/height
まずはここから。最新のブロック高を取得しましょう。
https://jp5.nemesis.land:3001/chain/height
解説:Get the current height of the chain
{"height":"310968"}
取れました。このチェーンが生まれて31万回ブロックが生成されているようです。
ブロック履歴を取得
/blocks/{height}/limit/{limit}
次に、指定ブロックを基準に25件のブロック情報を取得します。先ほど取れた 310968
から過去に25件さかのぼって取得してみましょう。
https://jp5.nemesis.land:3001/blocks/310968/limit/25
解説:Get blocks information
{
"meta":{
"hash":"7BF0B784BCC45C6E9B9D22E64C57CA4A18BB62B26F52DB41663FA026B7DEE6EA",
"generationHash":"E6236A8051582B173A2BEF8E7D130293B777E00A58ED1A32B89328C85B92B14C",
"totalFee":"0",
"stateHashSubCacheMerkleRoots":[
"499EA894476DF2A1C2F3DD4F53E6525A98944C2AC1D5DDB427FA1B13C6D3A7A7",
"0B6E6282D4C6DA3D84FF456062952E442BD8BCD8A54891E2541207EDF84C2070",
"D2A968FF0E0E7605CB5C88EEF6A1936565F17B99992A782CCA8F87490AD23FDC",
"2FBB075624F21EE96D05204CDFFFF76A3DFBA40C9919F75CAFAAF7315AE66F24",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000"
],
"numTransactions":0,
"numStatements":1
},
"block":{
"signature":"D15CEF6E8EDFFA2F208B1C3DDEC9D8DA85DDC78660A32A3B0888398E7059AB82C4DCEC1E630E9AF90B815D1189C78EF3C0E1132F3103AF190661B92E43DE4805",
"signerPublicKey":"F7ACF6940B01271C42E7BAF68E32F1855F619759ED901FF2FA0F729A0BE4DEFD",
"version":36867,
"type":33091,
"height":"310925",
"timestamp":"115864009337",
"difficulty":"38251451324382",
"feeMultiplier":0,
"previousBlockHash":"72B8B13BCEB323FA7D2277E2708A3B6CF36E2BFC08CB08C21B2FFA3A39D799A7",
"transactionsHash":"0000000000000000000000000000000000000000000000000000000000000000",
"receiptsHash":"C53ABF9D8F5D1BDAEB9C68F567E08AAC9E3529E2F7C3AED4F5271CE1FFFF4AE8",
"stateHash":"117C21897713A3026C77A4175F0C0042D44AD3D4616013EF0B142868D4B440F1",
"beneficiaryPublicKey":"F7ACF6940B01271C42E7BAF68E32F1855F619759ED901FF2FA0F729A0BE4DEFD"
}
}
取れました。
NEM1との大きな違いはstateHashの存在感でしょうか。前ブロックからの追加された情報がすべてこの文字列に集約されています。外部VMを動かしている人であれば、作業指示が間違いなくこのチェーンから発せられたかどうか、マークル証明という手法を使って検証できます。
トランザクション一覧を取得
/block/{height}/transactions
では上記ブロック一覧の中から、meta.numTransactions
が0でないブロックを探して、トランザクションの中身を調べてみます。とはいえ、今のテストネットではなかなか見つかりませんので、block高=1 のものを調べてみます。
https://jp5.nemesis.land:3001/block/1/transactions
解説:Get transactions from a block
"meta":{
"height":"1","hash":"C9DD6B279FD2F65E4B94EA1B21DCAFF33809B954AF96C034C478FBFCB34D8F52",
"merkleComponentHash":"C9DD6B279FD2F65E4B94EA1B21DCAFF33809B954AF96C034C478FBFCB34D8F52",
"index":0,
"id":"5DA07F28546DE27F4D0CA5E4"
},
"transaction":{
"signature":"1CA084C8A5D19E70B3B415E6CF24A7316ECAB7ECE1EF8E92FBC6D397405B457E00D4BBEFB4F2BB635865B17A3BC1D4E9D727A47875263F1BBA512CAFD5929F0E",
"signerPublicKey":"30CA0A8179477777AB3407611405EAAE6C4BA12156035E4DF8A73BD7651D6D9C",
"version":36865,
"type":16718,
"maxFee":"0",
"deadline":"1",
"registrationType":0,
"duration":"0",
"id":"84B3552D375FFA4B",
"name":"nem"
}
まず注目するのは transaction.type
です。これでトランザクションの種類が分かります。ドキュメントには16進数のみで10進数の表記がなかったのでここで対応表を上げておきます。
0x414C (16716) - AccountLinkTransaction.
0x4141 (16705) - AggregateCompleteTransaction.
0x4241 (16961) - AggregateBondedTransaction.
0x414D (16717) - MosaicDefinitionTransaction.
0x424D (16973) - MosaicSupplyChangeTransaction.
0x414E (16718) - NamespaceRegistrationTransaction.
0x424E (16974) - AddressAliasTransaction.
0x434E (17230) - MosaicAliasTransaction.
0x4144 (16708) - AccountMetadataTransaction.
0x4244 (16964) - MosaicMetadataTransaction.
0x4344 (17220) - NamespaceMetadataTransaction.
0x4155 (16725) - MultisigAccountModificationTransaction.
0x4148 (16712) - HashLockTransaction.
0x4152 (16722) - SecretLockTransaction.
0x4252 (16978) - SecretProofTransaction.
0x4150 (16720) - AccountAddressRestrictionTransaction.
0x4250 (16976) - AccountMosaicRestrictionTransaction.
0x4350 (17232) - AccountOperationRestrictionTransaction.
0x4151 (16721) - MosaicGlobalRestrictionTransaction.
0x4251 (16977) - MosaicAddressRestrictionTransaction.
0x4154 (16724) - TransferTransaction.
(16718) - NamespaceRegistrationTransaction.
とあるので、最初のトランザクションでnem
が定義されているのが分かります。
もう一つトランザクションを調べてみましょう
"meta":{
"height":"1","hash":"22EA568265676D21AD73C66C9F9411458C679246988D4A6CC5E4C6D7EB1B91FC",
"merkleComponentHash":"22EA568265676D21AD73C66C9F9411458C679246988D4A6CC5E4C6D7EB1B91FC",
"index":12,
"id":"5DA07F28546DE27F4D0CA5E5"
},
"transaction":{
"signature":"4F84F1BBF1E85E8BEBB8FD2D8EE3861DAD42291CB9BFF67EBD7D70D3B0A3CE149B5627C9B9BE806E541E5282FB3081C9E580771E5480FDDCC0029FBD6FE3B100",
"signerPublicKey":"30CA0A8179477777AB3407611405EAAE6C4BA12156035E4DF8A73BD7651D6D9C",
"version":36865,
"type":16724,
"maxFee":"0",
"deadline":"1",
"recipientAddress":"906574C6E23A0B0403915686A762EBE6D177C2D2174A496EE1",
"mosaics":[{"id":"D525AD41D95FCF29","amount":"449949999900000"}]
}
transaction.type
が16724なので、これが送金トランザクションです。
amountが49949999900000
とあります。これは小数点を除いた整数値で記述されているので
実際には 49,949,999.900000 という量になります。
送金元が
"signerPublicKey":"30CA0A8179477777AB3407611405EAAE6C4BA12156035E4DF8A73BD7651D6D9C"
送金先が
"recipientAddress":"906574C6E23A0B0403915686A762EBE6D177C2D2174A496EE1"
とあります。これを見慣れたSから始まるアドレスに変換してみます。MIJIN_TESTというネットワークはSで始まると決められています。今後たくさんのMIIJN_TESTが生まれた場合、他のネットワークで生成された署名を使いまわすとう攻撃が可能なため、トランザクションの発行にはBlock高=1のgenerationHashを添えて署名することになります。
脱線しました。アドレスの変換でしたね。ここはノードのお仕事ではないのでnem2-sdkの力を借ります。
chromeのデバッグ画面を開いて(F12)以下のスクリプトをコンソールに張り付けてください。
(script = document.createElement('script')).src = 'https://s3-ap-northeast-1.amazonaws.com/xembook.net/nem2-sdk/nem2-sdk-0.14.0.js'
document.getElementsByTagName('head')[0].appendChild(script);
//ここで一度改行
const nem = require("/node_modules/nem2-sdk");
これでconsole上でnem2-sdkが使えるようになりました。では送金元と送金先のアドレスを確認してみます。
公開鍵→アドレス変換
> nem.Address.createFromPublicKey("30CA0A8179477777AB3407611405EAAE6C4BA12156035E4DF8A73BD7651D6D9C", nem.NetworkType.MIJIN_TEST).address
< SDDMHGWEJRYXBPEYKVJ25FZDTVGQDVBAEZZXZ2PT
アドレスのデコード
> nem.Address.createFromEncoded("906574C6E23A0B0403915686A762EBE6D177C2D2174A496EE1").address
< SBSXJRXCHIFQIA4RK2DKOYXL43IXPQWSC5FES3XB
よく見る形のアドレスが取得できました。
残りは transaction.mosaicsのidが気になりますね。D525AD41D95FCF29
とは何を送っているのでしょうか?
ネームスペースを調べる手法はPOSTメソッドしか提供されていないので、consoleで以下のように入力します。
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://jp5.nemesis.land:3001/namespace/names');
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
xhr.send(JSON.stringify({
namespaceIds: ["D525AD41D95FCF29"]
}));
Networkタブを表示すると以下のようなレスポンスが得られました。XEMを送金したようですね。
[
{
"id":"D525AD41D95FCF29",
"name":"xem",
"parentId":"84B3552D375FFA4B"
},
{
"id":"84B3552D375FFA4B",
"name":"nem"
}
]
ところでCatapultになってからトランザクションにタイムスタンプの表記がなくなりました。以前からトランザクション内のタイムスタンプは署名前のクライアントの端末の時計しか刻むことができないため、タイムスタンプ証明という点ではあまり意味を成していませんでした。しかしながら、トランザクションIDにはmongoDBのタイムスタンプが入っているため、おおよその時間を推測することができます。
> new Date(parseInt("5DA07F28546DE27F4D0CA5E5".substring(0, 8), 16) * 1000);
< Fri Oct 11 2019 22:10:00 GMT+0900 (日本標準時)
そういえばブロック内に含まれるタイムスタンプの変換方法をお伝えしていませんでしたね。ここでもnem2-sdkの力を借ります。
RESTで出力される文字列からUint64型に変換し、チェーンの生まれた時間を足し合わせます。
> Date(nem.UInt64.fromNumericString("115864009337") + Date.UTC(2016, 3, 1, 0, 0, 0, 0))
< Tue Dec 03 2019 15:30:59 GMT+0900 (日本標準時)
これでツアーは終了です。
最新のブロックを取得しそこからブロック一覧、トランザクション一覧を取得、必要な情報を変換する方法を通じて簡単なCatapultノードとの対話の仕方を説明してみました。近いうちにFushicho2バージョンも公開したいと思います。
ぜひ、気になるトランザクションを調べてみてください。