github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/engine/call_frame.go (about)

     1  package engine
     2  
     3  import (
     4  	"github.com/hyperledger/burrow/acm/acmstate"
     5  	"github.com/hyperledger/burrow/crypto"
     6  	"github.com/hyperledger/burrow/execution/errors"
     7  	"github.com/hyperledger/burrow/permission"
     8  )
     9  
    10  type CallFrame struct {
    11  	// Cache this State wraps
    12  	*acmstate.Cache
    13  	// Where we sync
    14  	backend acmstate.ReaderWriter
    15  	// In order for nested cache to inherit any options
    16  	cacheOptions []acmstate.CacheOption
    17  	// Depth of the call stack
    18  	callStackDepth uint64
    19  	// Max call stack depth
    20  	maxCallStackDepth uint64
    21  }
    22  
    23  // Create a new CallFrame to hold state updates at a particular level in the call stack
    24  func NewCallFrame(st acmstate.ReaderWriter, cacheOptions ...acmstate.CacheOption) *CallFrame {
    25  	return newCallFrame(st, 0, 0, cacheOptions...)
    26  }
    27  
    28  func newCallFrame(st acmstate.ReaderWriter, stackDepth uint64, maxCallStackDepth uint64, cacheOptions ...acmstate.CacheOption) *CallFrame {
    29  	return &CallFrame{
    30  		Cache:             acmstate.NewCache(st, cacheOptions...),
    31  		backend:           st,
    32  		cacheOptions:      cacheOptions,
    33  		callStackDepth:    stackDepth,
    34  		maxCallStackDepth: maxCallStackDepth,
    35  	}
    36  }
    37  
    38  // Put this CallFrame in permanent read-only mode
    39  func (st *CallFrame) ReadOnly() *CallFrame {
    40  	acmstate.ReadOnly(st.Cache)
    41  	return st
    42  }
    43  
    44  func (st *CallFrame) WithMaxCallStackDepth(max uint64) *CallFrame {
    45  	st.maxCallStackDepth = max
    46  	return st
    47  }
    48  
    49  func (st *CallFrame) NewFrame(cacheOptions ...acmstate.CacheOption) (*CallFrame, error) {
    50  	if st.maxCallStackDepth > 0 && st.maxCallStackDepth == st.callStackDepth {
    51  		return nil, errors.Codes.CallStackOverflow
    52  	}
    53  	return newCallFrame(st.Cache, st.callStackDepth+1, st.maxCallStackDepth,
    54  		append(st.cacheOptions, cacheOptions...)...), nil
    55  }
    56  
    57  func (st *CallFrame) Sync() error {
    58  	err := st.Cache.Sync(st.backend)
    59  	if err != nil {
    60  		return errors.AsException(err)
    61  	}
    62  	return nil
    63  }
    64  
    65  func (st *CallFrame) CallStackDepth() uint64 {
    66  	return st.callStackDepth
    67  }
    68  
    69  func (st *CallFrame) CreateAccount(creator, address crypto.Address) error {
    70  	err := EnsurePermission(st, creator, permission.CreateAccount)
    71  	if err != nil {
    72  		return err
    73  	}
    74  	return CreateAccount(st, address)
    75  }