github.com/klaytn/klaytn@v1.12.1/storage/statedb/node_test.go (about)

     1  // Copyright 2023 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package statedb
    18  
    19  import (
    20  	"testing"
    21  
    22  	"github.com/klaytn/klaytn/common"
    23  	"github.com/stretchr/testify/assert"
    24  )
    25  
    26  // testNodeEncodingTC represents a trie node in various forms.
    27  type testNodeEncodingTC struct {
    28  	hash     []byte // Keccak(encoded)
    29  	encoded  []byte // RLP(inserted)
    30  	expanded node   // node{..., flags: {Hash}}
    31  	inserted node   // rawNode{...}
    32  }
    33  
    34  var nodeEncodingTCs map[string]testNodeEncodingTC
    35  
    36  func hexToHashNode(s string) hashNode {
    37  	return hashNode(common.HexToHash(s).Bytes())
    38  }
    39  
    40  func hexToExtHashNode(s string) hashNode {
    41  	return hashNode(common.BytesToExtHash(common.FromHex(s)).Bytes())
    42  }
    43  
    44  func init() {
    45  	var (
    46  		// subpaths in HEX and COMPACT encodings
    47  		hex_abc = common.FromHex("0a0b0c")
    48  		com_abc = common.FromHex("1abc")
    49  		hex_de  = common.FromHex("0d0e10")
    50  		com_de  = common.FromHex("20de")
    51  		hex_f   = common.FromHex("0f10")
    52  		com_f   = common.FromHex("3f")
    53  
    54  		// plain byte values
    55  		val2  = valueNode("hi")
    56  		val4  = valueNode("tiny")
    57  		val24 = valueNode("data_little_less_than_32")
    58  		val31 = valueNode("data_little_less_than_32_bytes")
    59  		val36 = valueNode("data_definitely_longer_than_32_bytes")
    60  
    61  		// dummy ref values
    62  		hash32  = hexToHashNode("00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff")
    63  		extzero = hexToExtHashNode("00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00000000000000")
    64  		exthash = hexToExtHashNode("00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344")
    65  
    66  		// computed ref from hasher
    67  		hZero = "00000000000000"
    68  		hExt  = "ccccddddeeee01"
    69  		hExt2 = "ccccddddeeee02"
    70  	)
    71  
    72  	// To create testcases,
    73  	// - Install https://github.com/ethereumjs/rlp
    74  	//     npm install -g rlp
    75  	// - In bash, run
    76  	//     maketc(){ rlp encode "$1"; rlp encode "$1" | xxd -r -p | keccak-256sum; }
    77  	//     maketc '["0x20de", "hello"]'
    78  
    79  	// TC names:
    80  	// - collapsed/*: single-depth node as stored in databased. decodeNode() can handle it.
    81  	// - resolved/*: multi-depth node exists in memory. decodeNode() cannot handle it.
    82  	// - */unext: only contains hash32
    83  	// - */extroot: contains exthash, and the node is state root
    84  	// - */exthash: contains exthash, and the node is not state root
    85  
    86  	nodeEncodingTCs = map[string]testNodeEncodingTC{
    87  		// Leaf nodes
    88  		"collapsed/leaf_short/unext": {
    89  			// leaf node with len(data) < 32 but lenEncoded > 32. ["0x20de", "data_little_less_than_32_bytes"]
    90  			hash:     common.FromHex("b39ab6f7fe5f3fffa2f24c1ef22a70965186732c72bc7417ac24e7ed0e3afa38" + hZero),
    91  			encoded:  common.FromHex("0xe28220de9e646174615f6c6974746c655f6c6573735f7468616e5f33325f6279746573"),
    92  			expanded: &shortNode{Key: hex_de, Val: val31},
    93  			inserted: &rawShortNode{Key: com_de, Val: val31},
    94  		},
    95  		"collapsed/leaf_long/unext": {
    96  			// leaf node with len(data) >= 32. ["0x20de", "data_definitely_longer_than_32_bytes"]
    97  			hash:     common.FromHex("916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80eb" + hZero),
    98  			encoded:  common.FromHex("0xe88220dea4646174615f646566696e6974656c795f6c6f6e6765725f7468616e5f33325f6279746573"),
    99  			expanded: &shortNode{Key: hex_de, Val: val36},
   100  			inserted: &rawShortNode{Key: com_de, Val: val36},
   101  		},
   102  
   103  		// Extension nodes without ref
   104  		"collapsed/extension_embedded_leaf/unext": {
   105  			// extension node with an embedded leaf. ["0x1abc", ["0x20de", "data_little_less_than_32"]]
   106  			hash:     common.FromHex("7604c7ac8fc0e0ac99c455cd2f05e5b4ac6929f40b937e6fc164b1d032d65173" + hZero),
   107  			encoded:  common.FromHex("0xe0821abcdc8220de98646174615f6c6974746c655f6c6573735f7468616e5f3332"),
   108  			expanded: &shortNode{Key: hex_abc, Val: &shortNode{Key: hex_de, Val: val24}},
   109  			inserted: &rawShortNode{Key: com_abc, Val: &rawShortNode{Key: com_de, Val: val24}},
   110  		},
   111  		"collapsed/extension_embedded_branch/unext": {
   112  			// extension node with an embedded branch. ["0x1abc", [["0x20de", "tiny"], ["0x3f", "hi"], "","","","","","","","","","","","","","",""]]
   113  			hash:    common.FromHex("e5eb732b1c680825db277638d7c055020de26823a6d1cc16fe7b12c6cbc83620" + hZero),
   114  			encoded: common.FromHex("0xe1821abcddc88220de8474696e79c43f826869808080808080808080808080808080"),
   115  			expanded: &shortNode{
   116  				Key: hex_abc,
   117  				Val: &fullNode{Children: [17]node{
   118  					0: &shortNode{Key: hex_de, Val: val4},
   119  					1: &shortNode{Key: hex_f, Val: val2},
   120  				}},
   121  			},
   122  			inserted: &rawShortNode{
   123  				Key: com_abc,
   124  				Val: rawFullNode([17]node{
   125  					0: &rawShortNode{Key: com_de, Val: val4},
   126  					1: &rawShortNode{Key: com_f, Val: val2},
   127  				}),
   128  			},
   129  		},
   130  
   131  		// Branch nodes without ref
   132  		"collapsed/branch_embedded_leaf/unext": {
   133  			// full node with an embedded leaf. [["0x20de","tiny"],"","","","","","","","","","","","","","","","data_little_less_than_32"]
   134  			hash:    common.FromHex("9b112f76f00fd35094375d08864e936fd9a00bb92509006fb020aeb0f2e10714" + hZero),
   135  			encoded: common.FromHex("0xf1c88220de8474696e7980808080808080808080808080808098646174615f6c6974746c655f6c6573735f7468616e5f3332"),
   136  			expanded: &fullNode{Children: [17]node{
   137  				0:  &shortNode{Key: hex_de, Val: val4},
   138  				16: val24,
   139  			}},
   140  			inserted: rawFullNode([17]node{
   141  				0:  &rawShortNode{Key: com_de, Val: val4},
   142  				16: val24,
   143  			}),
   144  		},
   145  
   146  		// Extension nodes with ref
   147  		"collapsed/extension_ref/unext": {
   148  			// extension node with a hash. ["0x1abc", "0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"]
   149  			hash:     common.FromHex("07eb19f1985a7e529b62bd44decd98a18b26faa10370a8b5f08bdf88cfce573e" + hZero),
   150  			encoded:  common.FromHex("0xe4821abca000112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"),
   151  			expanded: &shortNode{Key: hex_abc, Val: extzero},   // decodeNode will hash32.ExtendZero()
   152  			inserted: &rawShortNode{Key: com_abc, Val: hash32}, // hasher will canonicalRef() to hash32
   153  		},
   154  		"collapsed/extension_ref/extroot": {
   155  			// extension node with a hash.
   156  			// hashing ["0x1abc", "0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"]
   157  			// storing ["0x1abc", "0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344"]
   158  			hash:     common.FromHex("07eb19f1985a7e529b62bd44decd98a18b26faa10370a8b5f08bdf88cfce573e" + hZero),
   159  			encoded:  common.FromHex("0xeb821abca700112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344"),
   160  			expanded: &shortNode{Key: hex_abc, Val: exthash},    // decodeNode will leave exthash as-is
   161  			inserted: &rawShortNode{Key: com_abc, Val: exthash}, // hasher will leave exthash as-is
   162  		},
   163  		"collapsed/extension_ref/exthash": {
   164  			// extension node with a hash.
   165  			// hashing ["0x1abc", "0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"]
   166  			// storing ["0x1abc", "0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344"]
   167  			hash:     common.FromHex("07eb19f1985a7e529b62bd44decd98a18b26faa10370a8b5f08bdf88cfce573e" + hExt),
   168  			encoded:  common.FromHex("0xeb821abca700112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344"),
   169  			expanded: &shortNode{Key: hex_abc, Val: exthash},    // decodeNode will leave exthash as-is
   170  			inserted: &rawShortNode{Key: com_abc, Val: exthash}, // hasher will leave exthash as-is
   171  		},
   172  
   173  		// Branch nodes with ref
   174  		"collapsed/branch_ref/unext": {
   175  			// branch node with a hash and a value. ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff","","","","","","","","","","","","","","","","data_little_less_than_32_bytes"]
   176  			hash:     common.FromHex("16cf3239c032f06e83a71ee519f4c58a41e5e3e609f641841d65bb49c09d59d2" + hZero),
   177  			encoded:  common.FromHex("0xf84fa000112233445566778899aabbccddeeff00112233445566778899aabbccddeeff8080808080808080808080808080809e646174615f6c6974746c655f6c6573735f7468616e5f33325f6279746573"),
   178  			expanded: &fullNode{Children: [17]node{0: extzero, 16: val31}}, // decodeNode will hash32.ExtendZero()
   179  			inserted: rawFullNode([17]node{0: hash32, 16: val31}),          // hasher will canonicalRef() to hash32
   180  		},
   181  		"collapsed/branch_ref/extroot": {
   182  			// hashing ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff","","","","","","","","","","","","","","","","data_little_less_than_32_bytes"]
   183  			// storing ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344","","","","","","","","","","","","","","","","data_little_less_than_32_bytes"]
   184  			hash:     common.FromHex("16cf3239c032f06e83a71ee519f4c58a41e5e3e609f641841d65bb49c09d59d2" + hZero),
   185  			encoded:  common.FromHex("0xf856a700112233445566778899aabbccddeeff00112233445566778899aabbccddeeff111122223333448080808080808080808080808080809e646174615f6c6974746c655f6c6573735f7468616e5f33325f6279746573"),
   186  			expanded: &fullNode{Children: [17]node{0: exthash, 16: val31}}, // decodeNode will leave exthash as-is
   187  			inserted: rawFullNode([17]node{0: exthash, 16: val31}),         // hasher will leave exthash as-is
   188  		},
   189  		"collapsed/branch_ref/exthash": {
   190  			// hashing ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff","","","","","","","","","","","","","","","","data_little_less_than_32_bytes"]
   191  			// storing ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344","","","","","","","","","","","","","","","","data_little_less_than_32_bytes"]
   192  			hash:     common.FromHex("16cf3239c032f06e83a71ee519f4c58a41e5e3e609f641841d65bb49c09d59d2" + hExt),
   193  			encoded:  common.FromHex("0xf856a700112233445566778899aabbccddeeff00112233445566778899aabbccddeeff111122223333448080808080808080808080808080809e646174615f6c6974746c655f6c6573735f7468616e5f33325f6279746573"),
   194  			expanded: &fullNode{Children: [17]node{0: exthash, 16: val31}}, // decodeNode will leave exthash as-is
   195  			inserted: rawFullNode([17]node{0: exthash, 16: val31}),         // hasher will leave exthash as-is
   196  		},
   197  
   198  		// Branch and extension nodes with a resovled child node
   199  		"resolved/branch_leaf/unext": {
   200  			// parent = ["0x916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80eb","","","","","","","","","","","","","","","",""]
   201  			// child  = ["0x20de", "data_definitely_longer_than_32_bytes"]
   202  			hash:    common.FromHex("f240b93556d06a01f7220537a11bcf4c02c690e7ff5a97fa6c98157e7298b0f1" + hZero),
   203  			encoded: common.FromHex("0xf1a0916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80eb80808080808080808080808080808080"),
   204  			expanded: &fullNode{Children: [17]node{
   205  				0: &shortNode{Key: hex_de, Val: val36},
   206  			}},
   207  			inserted: rawFullNode([17]node{
   208  				0: hashNode(common.FromHex("0x916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80eb")),
   209  			}),
   210  		},
   211  		"resolved/branch_leaf/extroot": {
   212  			// parent hashing = ["0x916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80eb","","","","","","","","","","","","","","","",""]
   213  			// parent storing = ["0x916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80ebccccddddeeee01","","","","","","","","","","","","","","","",""]
   214  			// child          = ["0x20de", "data_definitely_longer_than_32_bytes"]
   215  			hash:    common.FromHex("f240b93556d06a01f7220537a11bcf4c02c690e7ff5a97fa6c98157e7298b0f1" + hZero),
   216  			encoded: common.FromHex("0xf838a7916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80ebccccddddeeee0180808080808080808080808080808080"),
   217  			expanded: &fullNode{Children: [17]node{
   218  				0: &shortNode{Key: hex_de, Val: val36},
   219  			}},
   220  			inserted: rawFullNode([17]node{
   221  				0: hashNode(common.FromHex("0x916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80eb" + hExt)),
   222  			}),
   223  		},
   224  		"resolved/branch_leaf/exthash": {
   225  			// parent hashing = ["0x916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80eb","","","","","","","","","","","","","","","",""]
   226  			// parent storing = ["0x916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80ebccccddddeeee01","","","","","","","","","","","","","","","",""]
   227  			// child          = ["0x20de", "data_definitely_longer_than_32_bytes"]
   228  			hash:    common.FromHex("f240b93556d06a01f7220537a11bcf4c02c690e7ff5a97fa6c98157e7298b0f1" + hExt2), // parent node hashed after child
   229  			encoded: common.FromHex("0xf838a7916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80ebccccddddeeee0180808080808080808080808080808080"),
   230  			expanded: &fullNode{Children: [17]node{
   231  				0: &shortNode{Key: hex_de, Val: val36},
   232  			}},
   233  			inserted: rawFullNode([17]node{
   234  				0: hashNode(common.FromHex("0x916d1af8295fc9ad621dc43ecfa4c9f25286a619715b270929d0425cd37c80eb" + hExt)), // child node first hashed
   235  			}),
   236  		},
   237  
   238  		"resolved/extension_branch/unext": {
   239  			// parent = ["0x1abc", "0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7"]
   240  			// child  = ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff","","","","","","","","","","","","","","","",""]
   241  			hash:    common.FromHex("3cd041acf721fcf611e8a06c39e347cb7daed5e6e9e9e9951473f8f920082659" + hZero),
   242  			encoded: common.FromHex("0xe4821abca0df5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7"),
   243  			expanded: &shortNode{
   244  				Key: hex_abc,
   245  				Val: &fullNode{Children: [17]node{0: hash32}},
   246  			},
   247  			inserted: &rawShortNode{
   248  				Key: com_abc,
   249  				Val: hashNode(common.FromHex("0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7")),
   250  			},
   251  		},
   252  		"resolved/extension_branch/extroot": {
   253  			// parent hashing = ["0x1abc", "0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7"]
   254  			// parent storing = ["0x1abc", "0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7ccccddddeeee01"]
   255  			// child          = ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344","","","","","","","","","","","","","","","",""]
   256  			hash:    common.FromHex("3cd041acf721fcf611e8a06c39e347cb7daed5e6e9e9e9951473f8f920082659" + hZero),
   257  			encoded: common.FromHex("0xeb821abca7df5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7ccccddddeeee01"),
   258  			expanded: &shortNode{
   259  				Key: hex_abc,
   260  				Val: &fullNode{Children: [17]node{0: exthash}},
   261  			},
   262  			inserted: &rawShortNode{
   263  				Key: com_abc,
   264  				Val: hashNode(common.FromHex("0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7" + hExt)),
   265  			},
   266  		},
   267  		"resolved/extension_branch/exthash": {
   268  			// parent hashing = ["0x1abc", "0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7"]
   269  			// parent storing = ["0x1abc", "0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7ccccddddeeee01"]
   270  			// child          = ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344","","","","","","","","","","","","","","","",""]
   271  			hash:    common.FromHex("3cd041acf721fcf611e8a06c39e347cb7daed5e6e9e9e9951473f8f920082659" + hExt2), // parent node hashed after child
   272  			encoded: common.FromHex("0xeb821abca7df5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7ccccddddeeee01"),
   273  			expanded: &shortNode{
   274  				Key: hex_abc,
   275  				Val: &fullNode{Children: [17]node{0: exthash}},
   276  			},
   277  			inserted: &rawShortNode{
   278  				Key: com_abc,
   279  				Val: hashNode(common.FromHex("0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7" + hExt)), // child node first hashed
   280  			},
   281  		},
   282  
   283  		"resolved/branch_branch/unext": {
   284  			// parent = ["","0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7","","","","","","","","","","","","","","",""]
   285  			// child  = ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff","","","","","","","","","","","","","","","",""]
   286  			hash:    common.FromHex("e03dce39399489a1bf77c4d766668fddb2fff56f52090c71e16689e75ac97a25" + hZero),
   287  			encoded: common.FromHex("0xf180a0df5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7808080808080808080808080808080"),
   288  			expanded: &fullNode{Children: [17]node{
   289  				1: &fullNode{Children: [17]node{0: hash32}},
   290  			}},
   291  			inserted: rawFullNode([17]node{
   292  				1: hashNode(common.FromHex("0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7")),
   293  			}),
   294  		},
   295  		"resolved/branch_branch/extroot": {
   296  			// parent hashing = ["","0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7","","","","","","","","","","","","","","",""]
   297  			// parent storing = ["","0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7ccccddddeeee01","","","","","","","","","","","","","","",""]
   298  			// child          = ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344","","","","","","","","","","","","","","","",""]
   299  			hash:    common.FromHex("e03dce39399489a1bf77c4d766668fddb2fff56f52090c71e16689e75ac97a25" + hZero),
   300  			encoded: common.FromHex("0xf83880a7df5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7ccccddddeeee01808080808080808080808080808080"),
   301  			expanded: &fullNode{Children: [17]node{
   302  				1: &fullNode{Children: [17]node{0: exthash}},
   303  			}},
   304  			inserted: rawFullNode([17]node{
   305  				1: hashNode(common.FromHex("0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7" + hExt)),
   306  			}),
   307  		},
   308  		"resolved/branch_branch/exthash": {
   309  			// parent hashing = ["","0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7","","","","","","","","","","","","","","",""]
   310  			// parent storing = ["","0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7ccccddddeeee01","","","","","","","","","","","","","","",""]
   311  			// child          = ["0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff11112222333344","","","","","","","","","","","","","","","",""]
   312  			hash:    common.FromHex("e03dce39399489a1bf77c4d766668fddb2fff56f52090c71e16689e75ac97a25" + hExt2), // parent node hashed after child
   313  			encoded: common.FromHex("0xf83880a7df5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7ccccddddeeee01808080808080808080808080808080"),
   314  			expanded: &fullNode{Children: [17]node{
   315  				1: &fullNode{Children: [17]node{0: hash32}},
   316  			}},
   317  			inserted: rawFullNode([17]node{
   318  				1: hashNode(common.FromHex("0xdf5551a5661b69abe1ad76df12ceb6471f01b2639a24dbd2f8fe72d26e0dffb7" + hExt)), // child node first hashed
   319  			}),
   320  		},
   321  	}
   322  }
   323  
   324  func selectNodeEncodingTCs(names []string) map[string]testNodeEncodingTC {
   325  	testcases := map[string]testNodeEncodingTC{}
   326  	for _, name := range names {
   327  		testcases[name] = nodeEncodingTCs[name]
   328  	}
   329  	return testcases
   330  }
   331  
   332  func collapsedNodeTCs_unext() map[string]testNodeEncodingTC {
   333  	return selectNodeEncodingTCs([]string{
   334  		"collapsed/leaf_short/unext",
   335  		"collapsed/leaf_long/unext",
   336  		"collapsed/extension_embedded_leaf/unext",
   337  		"collapsed/extension_embedded_branch/unext",
   338  		"collapsed/branch_embedded_leaf/unext",
   339  		"collapsed/extension_ref/unext",
   340  		"collapsed/branch_ref/unext",
   341  	})
   342  }
   343  
   344  func collapsedNodeTCs_extroot() map[string]testNodeEncodingTC {
   345  	return selectNodeEncodingTCs([]string{
   346  		"collapsed/extension_ref/extroot",
   347  		"collapsed/branch_ref/extroot",
   348  	})
   349  }
   350  
   351  func collapsedNodeTCs_exthash() map[string]testNodeEncodingTC {
   352  	return selectNodeEncodingTCs([]string{
   353  		"collapsed/extension_ref/exthash",
   354  		"collapsed/branch_ref/exthash",
   355  	})
   356  }
   357  
   358  func resolvedNodeTCs_unext() map[string]testNodeEncodingTC {
   359  	return selectNodeEncodingTCs([]string{
   360  		"resolved/branch_leaf/unext",
   361  		"resolved/extension_branch/unext",
   362  		"resolved/branch_branch/unext",
   363  	})
   364  }
   365  
   366  func resolvedNodeTCs_extroot() map[string]testNodeEncodingTC {
   367  	return selectNodeEncodingTCs([]string{
   368  		"resolved/branch_leaf/extroot",
   369  		"resolved/extension_branch/extroot",
   370  		"resolved/branch_branch/extroot",
   371  	})
   372  }
   373  
   374  func resolvedNodeTCs_exthash() map[string]testNodeEncodingTC {
   375  	return selectNodeEncodingTCs([]string{
   376  		"resolved/branch_leaf/exthash",
   377  		"resolved/extension_branch/exthash",
   378  		"resolved/branch_branch/exthash",
   379  	})
   380  }
   381  
   382  func checkDecodeNode(t *testing.T, name string, tc testNodeEncodingTC) {
   383  	n, err := decodeNode(tc.hash, tc.encoded)
   384  	t.Logf("tc[%s]\n %s", name, n)
   385  	assert.Nil(t, err, name)
   386  
   387  	// Result from decodeNode must contain .flags.hash
   388  	// But tc.expanded may not contain .flags.hash. Fill it here.
   389  	switch exp := tc.expanded.(type) {
   390  	case *fullNode:
   391  		exp.flags = nodeFlag{hash: tc.hash}
   392  	case *shortNode:
   393  		exp.flags = nodeFlag{hash: tc.hash}
   394  	}
   395  
   396  	assert.Equal(t, tc.expanded, n, name)
   397  }
   398  
   399  func TestDecodeNodeTC(t *testing.T) {
   400  	for name, tc := range collapsedNodeTCs_unext() {
   401  		checkDecodeNode(t, name, tc)
   402  	}
   403  	for name, tc := range collapsedNodeTCs_exthash() {
   404  		checkDecodeNode(t, name, tc)
   405  	}
   406  	for name, tc := range collapsedNodeTCs_extroot() {
   407  		checkDecodeNode(t, name, tc)
   408  	}
   409  }