github.com/onflow/flow-go@v0.33.17/model/flow/chunk.go (about)

     1  package flow
     2  
     3  import (
     4  	"github.com/ipfs/go-cid"
     5  )
     6  
     7  type ChunkBody struct {
     8  	CollectionIndex uint
     9  
    10  	// execution info
    11  	StartState      StateCommitment // start state when starting executing this chunk
    12  	EventCollection Identifier      // Events generated by executing results
    13  	BlockID         Identifier      // Block id of the execution result this chunk belongs to
    14  
    15  	// Computation consumption info
    16  	TotalComputationUsed uint64 // total amount of computation used by running all txs in this chunk
    17  	NumberOfTransactions uint64 // number of transactions inside the collection
    18  }
    19  
    20  type Chunk struct {
    21  	ChunkBody
    22  
    23  	Index uint64 // chunk index inside the ER (starts from zero)
    24  	// EndState inferred from next chunk or from the ER
    25  	EndState StateCommitment
    26  }
    27  
    28  func NewChunk(
    29  	blockID Identifier,
    30  	collectionIndex int,
    31  	startState StateCommitment,
    32  	numberOfTransactions int,
    33  	eventCollection Identifier,
    34  	endState StateCommitment,
    35  	totalComputationUsed uint64,
    36  ) *Chunk {
    37  	return &Chunk{
    38  		ChunkBody: ChunkBody{
    39  			BlockID:              blockID,
    40  			CollectionIndex:      uint(collectionIndex),
    41  			StartState:           startState,
    42  			NumberOfTransactions: uint64(numberOfTransactions),
    43  			EventCollection:      eventCollection,
    44  			TotalComputationUsed: totalComputationUsed,
    45  		},
    46  		Index:    uint64(collectionIndex),
    47  		EndState: endState,
    48  	}
    49  }
    50  
    51  // ID returns a unique id for this entity
    52  func (ch *Chunk) ID() Identifier {
    53  	return MakeID(ch.ChunkBody)
    54  }
    55  
    56  // Checksum provides a cryptographic commitment for a chunk content
    57  func (ch *Chunk) Checksum() Identifier {
    58  	return MakeID(ch)
    59  }
    60  
    61  // ChunkDataPack holds all register touches (any read, or write).
    62  //
    63  // Note that we have to capture a read proof for each write before updating the registers.
    64  // `Proof` includes proofs for all registers read to execute the chunk.
    65  // Register proofs order must not be correlated to the order of register reads during
    66  // the chunk execution in order to enforce the SPoCK secret high entropy.
    67  type ChunkDataPack struct {
    68  	ChunkID    Identifier      // ID of the chunk this data pack is for
    69  	StartState StateCommitment // commitment for starting state
    70  	Proof      StorageProof    // proof for all registers read during the chunk execution
    71  	Collection *Collection     // collection executed in this chunk
    72  
    73  	// ExecutionDataRoot is the root data structure of an execution_data.BlockExecutionData.
    74  	// It contains the necessary information for a verification node to validate that the
    75  	// BlockExecutionData produced is valid.
    76  	ExecutionDataRoot BlockExecutionDataRoot
    77  }
    78  
    79  // NewChunkDataPack returns an initialized chunk data pack.
    80  func NewChunkDataPack(
    81  	chunkID Identifier,
    82  	startState StateCommitment,
    83  	proof StorageProof,
    84  	collection *Collection,
    85  	execDataRoot BlockExecutionDataRoot,
    86  ) *ChunkDataPack {
    87  	return &ChunkDataPack{
    88  		ChunkID:           chunkID,
    89  		StartState:        startState,
    90  		Proof:             proof,
    91  		Collection:        collection,
    92  		ExecutionDataRoot: execDataRoot,
    93  	}
    94  }
    95  
    96  // ID returns the unique identifier for the concrete view, which is the ID of
    97  // the chunk the view is for.
    98  func (c *ChunkDataPack) ID() Identifier {
    99  	return c.ChunkID
   100  }
   101  
   102  // Checksum returns the checksum of the chunk data pack.
   103  func (c *ChunkDataPack) Checksum() Identifier {
   104  	return MakeID(c)
   105  }
   106  
   107  // TODO: This is the basic version of the list, we need to substitute it with something like Merkle tree at some point
   108  type ChunkList []*Chunk
   109  
   110  func (cl ChunkList) Fingerprint() Identifier {
   111  	return MerkleRoot(GetIDs(cl)...)
   112  }
   113  
   114  func (cl *ChunkList) Insert(ch *Chunk) {
   115  	*cl = append(*cl, ch)
   116  }
   117  
   118  func (cl ChunkList) Items() []*Chunk {
   119  	return cl
   120  }
   121  
   122  // Empty returns true if the chunk list is empty. Otherwise it returns false.
   123  func (cl ChunkList) Empty() bool {
   124  	return len(cl) == 0
   125  }
   126  
   127  func (cl ChunkList) Indices() []uint64 {
   128  	indices := make([]uint64, len(cl))
   129  	for i, chunk := range cl {
   130  		indices[i] = chunk.Index
   131  	}
   132  
   133  	return indices
   134  }
   135  
   136  // ByChecksum returns an entity from the list by entity fingerprint
   137  func (cl ChunkList) ByChecksum(cs Identifier) (*Chunk, bool) {
   138  	for _, ch := range cl {
   139  		if ch.Checksum() == cs {
   140  			return ch, true
   141  		}
   142  	}
   143  	return nil, false
   144  }
   145  
   146  // ByIndex returns an entity from the list by index
   147  // if requested chunk is within range of list, it returns chunk and true
   148  // if requested chunk is out of the range, it returns nil and false
   149  // boolean return value indicates whether requested chunk is within range
   150  func (cl ChunkList) ByIndex(i uint64) (*Chunk, bool) {
   151  	if i >= uint64(len(cl)) {
   152  		// index out of range
   153  		return nil, false
   154  	}
   155  	return cl[i], true
   156  }
   157  
   158  // Len returns the number of Chunks in the list. It is also part of the sort
   159  // interface that makes ChunkList sortable
   160  func (cl ChunkList) Len() int {
   161  	return len(cl)
   162  }
   163  
   164  // BlockExecutionDataRoot represents the root of a serialized execution_data.BlockExecutionData.
   165  // The hash of the serialized BlockExecutionDataRoot is the ExecutionDataID used within an
   166  // flow.ExecutionResult.
   167  // Context:
   168  //   - The trie updates in BlockExecutionDataRoot contain the _mutated_ registers only, which is
   169  //     helpful for clients to truslessly replicate the state.
   170  //   - In comparison, the chunk data packs contains all the register values at the chunk's starting
   171  //     state that were _touched_ (written and/or read). This is necessary for Verification Nodes to
   172  //     re-run the chunk the computation.
   173  type BlockExecutionDataRoot struct {
   174  	// BlockID is the ID of the block, whose result this execution data is for.
   175  	BlockID Identifier
   176  
   177  	// ChunkExecutionDataIDs is a list of the root CIDs for each serialized execution_data.ChunkExecutionData
   178  	// associated with this block.
   179  	ChunkExecutionDataIDs []cid.Cid
   180  }