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