github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/ledger/complete/mtrie/flattener/encoding_v3.go (about)

     1  package flattener
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/onflow/flow-go/ledger"
     9  	"github.com/onflow/flow-go/ledger/common/hash"
    10  	"github.com/onflow/flow-go/ledger/common/utils"
    11  	"github.com/onflow/flow-go/ledger/complete/mtrie/node"
    12  	"github.com/onflow/flow-go/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  }