github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/execution/storehouse/executing_block_snapshot.go (about)

     1  package storehouse
     2  
     3  import (
     4  	"github.com/onflow/flow-go/engine/execution"
     5  	"github.com/onflow/flow-go/fvm/storage/snapshot"
     6  	"github.com/onflow/flow-go/model/flow"
     7  )
     8  
     9  var _ execution.ExtendableStorageSnapshot = (*ExecutingBlockSnapshot)(nil)
    10  
    11  // ExecutingBlockSnapshot is a snapshot of the storage at an executed collection.
    12  // It starts with a storage snapshot at the end of previous block,
    13  // The register updates at the executed collection at baseHeight + 1 are cached in
    14  // a map, such that retrieving register values at the snapshot will first check
    15  // the cache, and then the storage.
    16  type ExecutingBlockSnapshot struct {
    17  	// the snapshot at the end of previous block
    18  	previous snapshot.StorageSnapshot
    19  
    20  	commitment      flow.StateCommitment
    21  	registerUpdates map[flow.RegisterID]flow.RegisterValue
    22  }
    23  
    24  // create a new storage snapshot for an executed collection
    25  // at the base block at height h - 1
    26  func NewExecutingBlockSnapshot(
    27  	previous snapshot.StorageSnapshot,
    28  	// the statecommitment of a block at height h
    29  	commitment flow.StateCommitment,
    30  ) *ExecutingBlockSnapshot {
    31  	return &ExecutingBlockSnapshot{
    32  		previous:        previous,
    33  		commitment:      commitment,
    34  		registerUpdates: make(map[flow.RegisterID]flow.RegisterValue),
    35  	}
    36  }
    37  
    38  // Get returns the register value at the snapshot.
    39  func (s *ExecutingBlockSnapshot) Get(id flow.RegisterID) (flow.RegisterValue, error) {
    40  	// get from latest updates first
    41  	value, ok := s.getFromUpdates(id)
    42  	if ok {
    43  		return value, nil
    44  	}
    45  
    46  	// get from BlockEndStateSnapshot at previous block
    47  	value, err := s.previous.Get(id)
    48  	return value, err
    49  }
    50  
    51  func (s *ExecutingBlockSnapshot) getFromUpdates(id flow.RegisterID) (flow.RegisterValue, bool) {
    52  	value, ok := s.registerUpdates[id]
    53  	return value, ok
    54  }
    55  
    56  // Extend returns a new storage snapshot at the same block but but for a different state commitment,
    57  // which contains the given registerUpdates
    58  // Usually it's used to create a new storage snapshot at the next executed collection.
    59  // The registerUpdates contains the register updates at the executed collection.
    60  func (s *ExecutingBlockSnapshot) Extend(newCommit flow.StateCommitment, updates map[flow.RegisterID]flow.RegisterValue) execution.ExtendableStorageSnapshot {
    61  	// if there is no update, we can return the original snapshot directly
    62  	// instead of wrapping it with a new ExecutingBlockSnapshot that has no update
    63  	if len(updates) == 0 {
    64  		return s
    65  	}
    66  
    67  	return &ExecutingBlockSnapshot{
    68  		previous:        s,
    69  		commitment:      newCommit,
    70  		registerUpdates: updates,
    71  	}
    72  }
    73  
    74  func (s *ExecutingBlockSnapshot) Commitment() flow.StateCommitment {
    75  	return s.commitment
    76  }