github.com/koko1123/flow-go-1@v0.29.6/engine/execution/state/delta/view.go (about) 1 package delta 2 3 import ( 4 "fmt" 5 "sync" 6 7 "github.com/onflow/flow-go/crypto/hash" 8 "github.com/koko1123/flow-go-1/fvm/state" 9 "github.com/koko1123/flow-go-1/model/flow" 10 ) 11 12 // GetRegisterFunc is a function that returns the value for a register. 13 type GetRegisterFunc func(owner, key string) (flow.RegisterValue, error) 14 15 // A View is a read-only view into a ledger stored in an underlying data source. 16 // 17 // A ledger view records writes to a delta that can be used to update the 18 // underlying data source. 19 type View struct { 20 delta Delta 21 regTouchSet map[flow.RegisterID]struct{} // contains all the registers that have been touched (either read or written to) 22 readsCount uint64 // contains the total number of reads 23 // spockSecret keeps the secret used for SPoCKs 24 // TODO we can add a flag to disable capturing spockSecret 25 // for views other than collection views to improve performance 26 spockSecret []byte 27 spockSecretLock *sync.Mutex // using pointer instead, because using value would cause mock.Called to trigger race detector 28 spockSecretHasher hash.Hasher 29 readFunc GetRegisterFunc 30 } 31 32 type Snapshot struct { 33 Delta Delta 34 SnapshotStats 35 Reads map[flow.RegisterID]struct{} 36 } 37 38 type SnapshotStats struct { 39 NumberOfBytesWrittenToRegisters int 40 NumberOfRegistersTouched int 41 } 42 43 // Snapshot is state of interactions with the register 44 type SpockSnapshot struct { 45 Snapshot 46 SpockSecret []byte 47 } 48 49 func AlwaysEmptyGetRegisterFunc(owner, key string) (flow.RegisterValue, error) { 50 return nil, nil 51 } 52 53 // NewView instantiates a new ledger view with the provided read function. 54 func NewView(readFunc GetRegisterFunc) *View { 55 return &View{ 56 delta: NewDelta(), 57 spockSecretLock: &sync.Mutex{}, 58 regTouchSet: make(map[flow.RegisterID]struct{}), 59 readFunc: readFunc, 60 spockSecretHasher: hash.NewSHA3_256(), 61 } 62 } 63 64 // Snapshot returns copy of current state of interactions with a View 65 func (v *View) Interactions() *SpockSnapshot { 66 67 var delta = Delta{ 68 Data: make(map[flow.RegisterID]flow.RegisterValue, len(v.delta.Data)), 69 } 70 var reads = make(map[flow.RegisterID]struct{}, len(v.regTouchSet)) 71 72 bytesWrittenToRegisters := 0 73 // copy data 74 for s, value := range v.delta.Data { 75 delta.Data[s] = value 76 bytesWrittenToRegisters += len(value) 77 } 78 79 for k := range v.regTouchSet { 80 reads[k] = struct{}{} 81 } 82 83 return &SpockSnapshot{ 84 Snapshot: Snapshot{ 85 Delta: delta, 86 Reads: reads, 87 SnapshotStats: SnapshotStats{ 88 NumberOfBytesWrittenToRegisters: bytesWrittenToRegisters, 89 NumberOfRegistersTouched: len(reads), 90 }, 91 }, 92 SpockSecret: v.SpockSecret(), 93 } 94 } 95 96 // AllRegisters returns all the register IDs either in read or delta 97 func (r *Snapshot) AllRegisters() []flow.RegisterID { 98 set := make(map[flow.RegisterID]struct{}, len(r.Reads)+len(r.Delta.Data)) 99 for reg := range r.Reads { 100 set[reg] = struct{}{} 101 } 102 for _, reg := range r.Delta.RegisterIDs() { 103 set[reg] = struct{}{} 104 } 105 ret := make([]flow.RegisterID, 0, len(set)) 106 for r := range set { 107 ret = append(ret, r) 108 } 109 return ret 110 } 111 112 // NewChild generates a new child view, with the current view as the base, sharing the Get function 113 func (v *View) NewChild() state.View { 114 return NewView(v.Peek) 115 } 116 117 func (v *View) DropDelta() { 118 v.delta = NewDelta() 119 } 120 121 func (v *View) AllRegisters() []flow.RegisterID { 122 return v.Interactions().AllRegisters() 123 } 124 125 // RegisterUpdates returns a list of register updates 126 func (v *View) RegisterUpdates() ([]flow.RegisterID, []flow.RegisterValue) { 127 return v.Delta().RegisterUpdates() 128 } 129 130 // Get gets a register value from this view. 131 // 132 // This function will return an error if it fails to read from the underlying 133 // data source for this view. 134 func (v *View) Get(owner, key string) (flow.RegisterValue, error) { 135 var err error 136 registerID := flow.NewRegisterID(owner, key) 137 138 value, exists := v.delta.Get(owner, key) 139 if !exists { 140 value, err = v.readFunc(owner, key) 141 if err != nil { 142 return nil, fmt.Errorf("get register failed: %w", err) 143 } 144 // capture register touch 145 v.regTouchSet[registerID] = struct{}{} 146 // increase reads 147 v.readsCount++ 148 } 149 // every time we read a value (order preserving) we update the secret 150 // with the registerID only (value is not required) 151 _, err = v.spockSecretHasher.Write(registerID.Bytes()) 152 if err != nil { 153 return nil, fmt.Errorf("get register failed: %w", err) 154 } 155 return value, nil 156 } 157 158 // Peek reads the value without registering the read, as when used as parent read function 159 func (v *View) Peek(owner, key string) (flow.RegisterValue, error) { 160 value, exists := v.delta.Get(owner, key) 161 if exists { 162 return value, nil 163 } 164 165 return v.readFunc(owner, key) 166 } 167 168 // Set sets a register value in this view. 169 func (v *View) Set(owner, key string, value flow.RegisterValue) error { 170 registerID := flow.NewRegisterID(owner, key) 171 // every time we write something to delta (order preserving) we update 172 // the spock secret with both the register ID and value. 173 174 _, err := v.spockSecretHasher.Write(registerID.Bytes()) 175 if err != nil { 176 return fmt.Errorf("set register failed: %w", err) 177 } 178 179 _, err = v.spockSecretHasher.Write(value) 180 if err != nil { 181 return fmt.Errorf("set register failed: %w", err) 182 } 183 184 // capture register touch 185 v.regTouchSet[registerID] = struct{}{} 186 // add key value to delta 187 v.delta.Set(owner, key, value) 188 return nil 189 } 190 191 // Touch explicitly adds a register to the touched registers set. 192 func (v *View) Touch(owner, key string) error { 193 194 k := flow.NewRegisterID(owner, key) 195 196 // capture register touch 197 v.regTouchSet[k] = struct{}{} 198 // increase reads 199 v.readsCount++ 200 201 return nil 202 } 203 204 // Delete removes a register in this view. 205 func (v *View) Delete(owner, key string) error { 206 return v.Set(owner, key, nil) 207 } 208 209 // Delta returns a record of the registers that were mutated in this view. 210 func (v *View) Delta() Delta { 211 return v.delta 212 } 213 214 // MergeView applies the changes from a the given view to this view. 215 // TODO rename this, this is not actually a merge as we can't merge 216 // readFunc s. 217 218 func (v *View) MergeView(ch state.View) error { 219 220 child, ok := ch.(*View) 221 if !ok { 222 return fmt.Errorf("can not merge view: view type mismatch (given: %T, expected:delta.View)", ch) 223 } 224 225 for id := range child.Interactions().RegisterTouches() { 226 v.regTouchSet[id] = struct{}{} 227 } 228 229 // SpockSecret is order aware 230 // TODO return the error and handle it properly on other places 231 232 spockSecret := child.SpockSecret() 233 234 _, err := v.spockSecretHasher.Write(spockSecret) 235 if err != nil { 236 return fmt.Errorf("merging SPoCK secrets failed: %w", err) 237 } 238 v.delta.MergeWith(child.delta) 239 240 v.readsCount += child.readsCount 241 242 return nil 243 } 244 245 // RegisterTouches returns the register IDs touched by this view (either read or write) 246 func (r *Snapshot) RegisterTouches() map[flow.RegisterID]struct{} { 247 ret := make(map[flow.RegisterID]struct{}, len(r.Reads)) 248 for k := range r.Reads { 249 ret[k] = struct{}{} 250 } 251 return ret 252 } 253 254 // ReadsCount returns the total number of reads performed on this view including all child views 255 func (v *View) ReadsCount() uint64 { 256 return v.readsCount 257 } 258 259 // SpockSecret returns the secret value for SPoCK 260 // 261 // This function modifies the internal state of the SPoCK secret hasher. 262 // Once called, it doesn't allow writing more data into the SPoCK secret. 263 func (v *View) SpockSecret() []byte { 264 // check if spockSecret has been already computed 265 v.spockSecretLock.Lock() 266 if v.spockSecret == nil { 267 v.spockSecret = v.spockSecretHasher.SumHash() 268 } 269 v.spockSecretLock.Unlock() 270 return v.spockSecret 271 } 272 273 // Detach detaches view from parent, by setting readFunc to 274 // default, empty one 275 func (v *View) Detach() { 276 v.readFunc = AlwaysEmptyGetRegisterFunc 277 }