github.com/koko1123/flow-go-1@v0.29.6/fvm/utils/view.go (about)

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"github.com/koko1123/flow-go-1/fvm/state"
     8  	"github.com/koko1123/flow-go-1/ledger"
     9  	"github.com/koko1123/flow-go-1/model/flow"
    10  )
    11  
    12  // SimpleView provides a simple view for testing and migration purposes.
    13  type SimpleView struct {
    14  	Parent *SimpleView
    15  	Ledger *MapLedger
    16  }
    17  
    18  func NewSimpleView() *SimpleView {
    19  	return &SimpleView{
    20  		Ledger: NewMapLedger(),
    21  	}
    22  }
    23  
    24  func NewSimpleViewFromPayloads(payloads []ledger.Payload) *SimpleView {
    25  	return &SimpleView{
    26  		Ledger: NewMapLedgerFromPayloads(payloads),
    27  	}
    28  }
    29  
    30  func (v *SimpleView) NewChild() state.View {
    31  	ch := NewSimpleView()
    32  	ch.Parent = v
    33  	return ch
    34  }
    35  
    36  func (v *SimpleView) MergeView(o state.View) error {
    37  	var other *SimpleView
    38  	var ok bool
    39  	if other, ok = o.(*SimpleView); !ok {
    40  		return fmt.Errorf("can not merge: view type mismatch (given: %T, expected:SimpleView)", o)
    41  	}
    42  
    43  	for key, value := range other.Ledger.Registers {
    44  		err := v.Ledger.Set(key.Owner, key.Key, value)
    45  		if err != nil {
    46  			return fmt.Errorf("can not merge: %w", err)
    47  		}
    48  	}
    49  
    50  	for k := range other.Ledger.RegisterTouches {
    51  		v.Ledger.RegisterTouches[k] = struct{}{}
    52  	}
    53  	return nil
    54  }
    55  
    56  func (v *SimpleView) DropDelta() {
    57  	v.Ledger.Registers = make(map[flow.RegisterID]flow.RegisterValue)
    58  }
    59  
    60  func (v *SimpleView) Set(owner, key string, value flow.RegisterValue) error {
    61  	return v.Ledger.Set(owner, key, value)
    62  }
    63  
    64  func (v *SimpleView) Get(owner, key string) (flow.RegisterValue, error) {
    65  	value, err := v.Ledger.Get(owner, key)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	if len(value) > 0 {
    70  		return value, nil
    71  	}
    72  
    73  	if v.Parent != nil {
    74  		return v.Parent.Get(owner, key)
    75  	}
    76  
    77  	return nil, nil
    78  }
    79  
    80  // returns all the registers that has been touched
    81  func (v *SimpleView) AllRegisters() []flow.RegisterID {
    82  	res := make([]flow.RegisterID, 0, len(v.Ledger.RegisterTouches))
    83  	for k := range v.Ledger.RegisterTouches {
    84  		res = append(res, k)
    85  	}
    86  	return res
    87  }
    88  
    89  func (v *SimpleView) RegisterUpdates() ([]flow.RegisterID, []flow.RegisterValue) {
    90  	ids := make([]flow.RegisterID, 0, len(v.Ledger.RegisterUpdated))
    91  	values := make([]flow.RegisterValue, 0, len(v.Ledger.RegisterUpdated))
    92  	for key := range v.Ledger.RegisterUpdated {
    93  		ids = append(ids, key)
    94  		values = append(values, v.Ledger.Registers[key])
    95  	}
    96  	return ids, values
    97  }
    98  
    99  func (v *SimpleView) Touch(owner, key string) error {
   100  	return v.Ledger.Touch(owner, key)
   101  }
   102  
   103  func (v *SimpleView) Delete(owner, key string) error {
   104  	return v.Ledger.Delete(owner, key)
   105  }
   106  
   107  func (v *SimpleView) Payloads() []ledger.Payload {
   108  	return v.Ledger.Payloads()
   109  }
   110  
   111  // A MapLedger is a naive ledger storage implementation backed by a simple map.
   112  //
   113  // This implementation is designed for testing and migration purposes.
   114  type MapLedger struct {
   115  	sync.RWMutex
   116  	Registers       map[flow.RegisterID]flow.RegisterValue
   117  	RegisterTouches map[flow.RegisterID]struct{}
   118  	RegisterUpdated map[flow.RegisterID]struct{}
   119  }
   120  
   121  // NewMapLedger returns an instance of map ledger (should only be used for
   122  // testing and migration)
   123  func NewMapLedger() *MapLedger {
   124  	return &MapLedger{
   125  		Registers:       make(map[flow.RegisterID]flow.RegisterValue),
   126  		RegisterTouches: make(map[flow.RegisterID]struct{}),
   127  		RegisterUpdated: make(map[flow.RegisterID]struct{}),
   128  	}
   129  }
   130  
   131  // NewMapLedger returns an instance of map ledger with entries loaded from
   132  // payloads (should only be used for testing and migration)
   133  func NewMapLedgerFromPayloads(payloads []ledger.Payload) *MapLedger {
   134  	ledger := NewMapLedger()
   135  	for _, entry := range payloads {
   136  		key, err := entry.Key()
   137  		if err != nil {
   138  			panic(err)
   139  		}
   140  
   141  		id := flow.RegisterID{
   142  			Owner: string(key.KeyParts[0].Value),
   143  			Key:   string(key.KeyParts[1].Value),
   144  		}
   145  
   146  		ledger.Registers[id] = entry.Value()
   147  	}
   148  
   149  	return ledger
   150  }
   151  
   152  func (m *MapLedger) Set(owner, key string, value flow.RegisterValue) error {
   153  	m.Lock()
   154  	defer m.Unlock()
   155  
   156  	k := flow.RegisterID{Owner: owner, Key: key}
   157  	m.RegisterTouches[k] = struct{}{}
   158  	m.RegisterUpdated[k] = struct{}{}
   159  	m.Registers[k] = value
   160  	return nil
   161  }
   162  
   163  func (m *MapLedger) Get(owner, key string) (flow.RegisterValue, error) {
   164  	m.Lock()
   165  	defer m.Unlock()
   166  
   167  	k := flow.RegisterID{Owner: owner, Key: key}
   168  	m.RegisterTouches[k] = struct{}{}
   169  	return m.Registers[k], nil
   170  }
   171  
   172  func (m *MapLedger) Touch(owner, key string) error {
   173  	m.Lock()
   174  	defer m.Unlock()
   175  
   176  	m.RegisterTouches[flow.RegisterID{Owner: owner, Key: key}] = struct{}{}
   177  	return nil
   178  }
   179  
   180  func (m *MapLedger) Delete(owner, key string) error {
   181  	m.Lock()
   182  	defer m.Unlock()
   183  
   184  	delete(m.RegisterTouches, flow.RegisterID{Owner: owner, Key: key})
   185  	return nil
   186  }
   187  
   188  func registerIdToLedgerKey(id flow.RegisterID) ledger.Key {
   189  	keyParts := []ledger.KeyPart{
   190  		ledger.NewKeyPart(0, []byte(id.Owner)),
   191  		ledger.NewKeyPart(2, []byte(id.Key)),
   192  	}
   193  
   194  	return ledger.NewKey(keyParts)
   195  }
   196  
   197  func (m *MapLedger) Payloads() []ledger.Payload {
   198  	m.RLock()
   199  	defer m.RUnlock()
   200  
   201  	ret := make([]ledger.Payload, 0, len(m.Registers))
   202  	for id, val := range m.Registers {
   203  		key := registerIdToLedgerKey(id)
   204  		ret = append(ret, *ledger.NewPayload(key, ledger.Value(val)))
   205  	}
   206  
   207  	return ret
   208  }