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 }