github.com/koko1123/flow-go-1@v0.29.6/ledger/complete/mtrie/flattener/encoding_v3.go (about) 1 package flattener 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 8 "github.com/koko1123/flow-go-1/ledger" 9 "github.com/koko1123/flow-go-1/ledger/common/hash" 10 "github.com/koko1123/flow-go-1/ledger/common/utils" 11 "github.com/koko1123/flow-go-1/ledger/complete/mtrie/node" 12 "github.com/koko1123/flow-go-1/ledger/complete/mtrie/trie" 13 ) 14 15 // This file contains decoding functions for checkpoint v3 and earlier versions. 16 // These functions are for backwards compatibility, not optimized. 17 18 const encodingDecodingVersion = uint16(0) 19 20 // getNodeFunc returns node by nodeIndex along with node's regCount and regSize. 21 type getNodeFunc func(nodeIndex uint64) (n *node.Node, regCount uint64, regSize uint64, err error) 22 23 // ReadNodeFromCheckpointV3AndEarlier returns a node recontructed from data in 24 // checkpoint v3 and earlier versions. It also returns node's regCount and regSize. 25 // Encoded node in checkpoint v3 and earlier is in the following format: 26 // - version (2 bytes) 27 // - height (2 bytes) 28 // - lindex (8 bytes) 29 // - rindex (8 bytes) 30 // - max depth (2 bytes) 31 // - reg count (8 bytes) 32 // - path (2 bytes + 32 bytes) 33 // - payload (4 bytes + n bytes) 34 // - hash (2 bytes + 32 bytes) 35 func ReadNodeFromCheckpointV3AndEarlier(reader io.Reader, getNode getNodeFunc) (*node.Node, uint64, uint64, error) { 36 37 // Read version (2 bytes) 38 buf := make([]byte, 2) 39 _, err := io.ReadFull(reader, buf) 40 if err != nil { 41 return nil, 0, 0, fmt.Errorf("failed to read version of serialized node in v3: %w", err) 42 } 43 44 // Decode version 45 version, _, err := utils.ReadUint16(buf) 46 if err != nil { 47 return nil, 0, 0, fmt.Errorf("failed to decode version of serialized node in v3: %w", err) 48 } 49 50 if version > encodingDecodingVersion { 51 return nil, 0, 0, fmt.Errorf("found unsuported version %d (> %d) of serialized node in v3", version, encodingDecodingVersion) 52 } 53 54 // fixed-length data: 55 // height (2 bytes) + 56 // left child node index (8 bytes) + 57 // right child node index (8 bytes) + 58 // max depth (2 bytes) + 59 // reg count (8 bytes) 60 buf = make([]byte, 2+8+8+2+8) 61 62 // Read fixed-length part 63 _, err = io.ReadFull(reader, buf) 64 if err != nil { 65 return nil, 0, 0, fmt.Errorf("failed to read fixed-length part of serialized node in v3: %w", err) 66 } 67 68 var height, maxDepth uint16 69 var lchildIndex, rchildIndex, regCount uint64 70 var path, hashValue, encPayload []byte 71 72 // Decode height (2 bytes) 73 height, buf, err = utils.ReadUint16(buf) 74 if err != nil { 75 return nil, 0, 0, fmt.Errorf("failed to decode height of serialized node in v3: %w", err) 76 } 77 78 // Decode left child index (8 bytes) 79 lchildIndex, buf, err = utils.ReadUint64(buf) 80 if err != nil { 81 return nil, 0, 0, fmt.Errorf("failed to decode left child index of serialized node in v3: %w", err) 82 } 83 84 // Decode right child index (8 bytes) 85 rchildIndex, buf, err = utils.ReadUint64(buf) 86 if err != nil { 87 return nil, 0, 0, fmt.Errorf("failed to decode right child index of serialized node in v3: %w", err) 88 } 89 90 // Decode max depth (2 bytes) 91 maxDepth, buf, err = utils.ReadUint16(buf) 92 if err != nil { 93 return nil, 0, 0, fmt.Errorf("failed to decode max depth of serialized node in v3: %w", err) 94 } 95 96 // Decode reg count (8 bytes) 97 regCount, _, err = utils.ReadUint64(buf) 98 if err != nil { 99 return nil, 0, 0, fmt.Errorf("failed to decode reg count of serialized node in v3: %w", err) 100 } 101 102 // Read path (2 bytes + 32 bytes) 103 path, err = utils.ReadShortDataFromReader(reader) 104 if err != nil { 105 return nil, 0, 0, fmt.Errorf("failed to read path of serialized node in v3: %w", err) 106 } 107 108 // Read payload (4 bytes + n bytes) 109 encPayload, err = utils.ReadLongDataFromReader(reader) 110 if err != nil { 111 return nil, 0, 0, fmt.Errorf("failed to read payload of serialized node in v3: %w", err) 112 } 113 114 // Read hash (2 bytes + 32 bytes) 115 hashValue, err = utils.ReadShortDataFromReader(reader) 116 if err != nil { 117 return nil, 0, 0, fmt.Errorf("failed to read hash of serialized node in v3: %w", err) 118 } 119 120 // Create (and copy) hash from raw data. 121 nodeHash, err := hash.ToHash(hashValue) 122 if err != nil { 123 return nil, 0, 0, fmt.Errorf("failed to decode hash of serialized node in v3: %w", err) 124 } 125 126 // maxDepth and regCount are removed from Node. 127 _ = maxDepth 128 _ = regCount 129 130 if len(path) > 0 { 131 // Create (and copy) path from raw data. 132 path, err := ledger.ToPath(path) 133 if err != nil { 134 return nil, 0, 0, fmt.Errorf("failed to decode path of serialized node in v3: %w", err) 135 } 136 137 // Decode payload (payload data isn't copied). 138 payload, err := ledger.DecodePayload(encPayload) 139 if err != nil { 140 return nil, 0, 0, fmt.Errorf("failed to decode payload of serialized node in v3: %w", err) 141 } 142 143 // Make a copy of payload 144 var pl *ledger.Payload 145 if payload != nil { 146 pl = payload.DeepCopy() 147 } 148 149 n := node.NewNode(int(height), nil, nil, path, pl, nodeHash) 150 151 // Leaf node has 1 register and register size is payload size. 152 return n, 1, uint64(pl.Size()), nil 153 } 154 155 // Get left child node by node index 156 lchild, lchildRegCount, lchildRegSize, err := getNode(lchildIndex) 157 if err != nil { 158 return nil, 0, 0, fmt.Errorf("failed to find left child node of serialized node in v3: %w", err) 159 } 160 161 // Get right child node by node index 162 rchild, rchildRegCount, rchildRegSize, err := getNode(rchildIndex) 163 if err != nil { 164 return nil, 0, 0, fmt.Errorf("failed to find right child node of serialized node in v3: %w", err) 165 } 166 167 n := node.NewNode(int(height), lchild, rchild, ledger.DummyPath, nil, nodeHash) 168 return n, lchildRegCount + rchildRegCount, lchildRegSize + rchildRegSize, nil 169 } 170 171 // ReadTrieFromCheckpointV3AndEarlier reconstructs a trie from data in checkpoint v3 and earlier versions. 172 // Encoded trie in checkpoint v3 and earlier is in the following format: 173 // - version (2 bytes) 174 // - root node index (8 bytes) 175 // - root node hash (2 bytes + 32 bytes) 176 func ReadTrieFromCheckpointV3AndEarlier(reader io.Reader, getNode getNodeFunc) (*trie.MTrie, error) { 177 178 // Read version (2 bytes) 179 buf := make([]byte, 2) 180 _, err := io.ReadFull(reader, buf) 181 if err != nil { 182 return nil, fmt.Errorf("failed to read version of serialized trie in v3: %w", err) 183 } 184 185 // Decode version 186 version, _, err := utils.ReadUint16(buf) 187 if err != nil { 188 return nil, fmt.Errorf("failed to decode version of serialized trie in v3: %w", err) 189 } 190 191 if version > encodingDecodingVersion { 192 return nil, fmt.Errorf("found unsuported version %d (> %d) of serialized trie in v3", version, encodingDecodingVersion) 193 } 194 195 // Read root index (8 bytes) 196 buf = make([]byte, 8) 197 _, err = io.ReadFull(reader, buf) 198 if err != nil { 199 return nil, fmt.Errorf("failed to read root index of serialized trie in v3: %w", err) 200 } 201 202 // Decode root index 203 rootIndex, _, err := utils.ReadUint64(buf) 204 if err != nil { 205 return nil, fmt.Errorf("failed to decode root index of serialized trie in v3: %w", err) 206 } 207 208 // Read root hash (2 bytes + 32 bytes) 209 readRootHash, err := utils.ReadShortDataFromReader(reader) 210 if err != nil { 211 return nil, fmt.Errorf("failed to read root hash of serialized trie in v3: %w", err) 212 } 213 214 // Get node by index 215 rootNode, regCount, regSize, err := getNode(rootIndex) 216 if err != nil { 217 return nil, fmt.Errorf("failed to find root node of serialized trie in v3: %w", err) 218 } 219 220 mtrie, err := trie.NewMTrie(rootNode, regCount, regSize) 221 if err != nil { 222 return nil, fmt.Errorf("failed to restore serialized trie in v3: %w", err) 223 } 224 225 rootHash := mtrie.RootHash() 226 if !bytes.Equal(readRootHash, rootHash[:]) { 227 return nil, fmt.Errorf("failed to restore serialized trie in v3: roothash doesn't match") 228 } 229 230 return mtrie, nil 231 }