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  }