はじめに
そろそろ避けていたものに手を付けなければ
今回は、subCacheMerkleRootsとstateHashの関係に注目します。
State Hash
catapult-service-bootstrapなどを動かした際、標準出力にこのようなものが出力されると思います。
Height: 1
Generation Hash: 5ABBD9F7894EE7E5D4C3CDA934245396AEFCD1CB0426F265AC81F4F3450AB6DD
Transactions Hash: 111461D150B90EBF58A87AB2FA2493DCB716F83E7EE584369820D6CA10DE5E52
Receipts Hash: A207227B111F4242DE80FC87E722B86077931B483883EA65E06A24340176A047
State Hash: BDCAF08330E29EBC7F18A1A9E6C7C60E4CFF99B100FC583FCDBAFA6F875F5DCF
--- Components (7) ---
+ 779F9E5BCEFB8267C084B14F8C2CB981683E6715BAFF4DC3B39BC133AFBEDD1B
+ 7BA3B37CDF34608C3B98BE572C7A743FEAC8B6909654AF21B8E0F4381EFD9164
+ 5D8EEAD5907130D297C322698F3D201A78D629CAC87487A0F4F890C1277B250C
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
これらは、ブロックチェーンの状態(ステート)を表す値で、Components (7)
の値はそれぞれ次のようなステートを表しています。
Finally COW state roots in order:
- account state cache (balances)
- namespace cache
- mosaic cache
- multisig cache
- hash lock cache
- secret lock cache
- property cache
それで、これらの値を代表するものがState Hash
です。
計算してみる
代表しているってなんやねんということですが、とりあえず計算してみましょう。
とあるチェーンのブロック番号600000のステートを見てみます。
stateHashは
5A4AB7830E7CE281252ED3CBADC5A7919A5DF82BA0766788186EC32308934B37
subCacheMerkleRootsは
0 "4401DAC79E1CDBB6903BED8F6CE5D6BB29DF9220D65D1093644968C61DCE5490"
1 "99DCAAB775F4D905A43446A54336A7C52C011D0B036D92E3DEA77A6B4806130D"
2 "30A245258080BA6825F4263AEF2146C2B899FE8891B5E528EFE4C861397FFB8C"
3 "3BD4B1669FAC87AF68A1DB54AE737A0227A3D0B85AECB3A0FF7240E228731715"
4 "0000000000000000000000000000000000000000000000000000000000000000"
5 "0000000000000000000000000000000000000000000000000000000000000000"
6 "A13E3FB1B22964DC32FE77DAB978617F3CB15B3930371D6D4477BE47C961AE47"
さて、subCacheMerkleRoots
をすべて文字列結合してsha3してみます。
sha3(4401DAC79E1CDBB6903BED8F6CE5D6BB29DF9220D65D1093644968C61DCE549099DCAAB775F4D905A43446A54336A7C52C011D0B036D92E3DEA77A6B4806130D30A245258080BA6825F4263AEF2146C2B899FE8891B5E528EFE4C861397FFB8C3BD4B1669FAC87AF68A1DB54AE737A0227A3D0B85AECB3A0FF7240E22873171500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A13E3FB1B22964DC32FE77DAB978617F3CB15B3930371D6D4477BE47C961AE47)
結果は、
5A4AB7830E7CE281252ED3CBADC5A7919A5DF82BA0766788186EC32308934B37
stateHash
と一致します。
コードはこんな感じになるかと思います。
const jssha3 = require('js-sha3');
const payload = '4401DAC79E1CDBB6903BED8F6CE5D6BB29DF9220D65D1093644968C61DCE549099DCAAB775F4D905A43446A54336A7C52C011D0B036D92E3DEA77A6B4806130D30A245258080BA6825F4263AEF2146C2B899FE8891B5E528EFE4C861397FFB8C3BD4B1669FAC87AF68A1DB54AE737A0227A3D0B85AECB3A0FF7240E22873171500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A13E3FB1B22964DC32FE77DAB978617F3CB15B3930371D6D4477BE47C961AE47';
const hasher = jssha3.sha3_256.create();
const hash = hasher.update(Buffer.from(payload, 'hex')).hex().toUpperCase();
console.log(hash);
おわりに
subCacheMerkleRoots
のsha3をとったらstateHash
になりました。stateHash
からsubCacheMerkleRoots
は導出できませんが、subCacheMerkleRoots
が1バイトでも変更されると、stateHash
の値が変わります。これにより、例えば、stateHash
にだけ署名をつけたり、ブロックのデータとして取り込んだりすることにより、subCacheMerkleRoots
が何か別の値に変えられていたりするのを防ぐことができます。
シリーズ
State Hash その1 subCacheMerkleRootsからstateHashの計算