github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/engine/dispatcher.go (about) 1 package engine 2 3 import ( 4 "github.com/hyperledger/burrow/acm" 5 ) 6 7 type Dispatcher interface { 8 // If this Dispatcher is capable of dispatching this account (e.g. if it has the correct bytecode) then return a 9 // Callable that wraps the function, otherwise return nil 10 Dispatch(acc *acm.Account) Callable 11 } 12 13 type DispatcherFunc func(acc *acm.Account) Callable 14 15 func (d DispatcherFunc) Dispatch(acc *acm.Account) Callable { 16 return d(acc) 17 } 18 19 // An ExternalDispatcher is able to Dispatch accounts to external engines as well as Dispatch to itself 20 type ExternalDispatcher interface { 21 Dispatcher 22 SetExternals(externals Dispatcher) 23 } 24 25 // An ExternalDispatcher is able to Dispatch accounts to external engines as well as Dispatch to itself 26 type Externals struct { 27 // Provide any foreign dispatchers to allow calls between VMs 28 externals Dispatcher 29 } 30 31 var _ ExternalDispatcher = (*Externals)(nil) 32 33 func (ed *Externals) Dispatch(acc *acm.Account) Callable { 34 // Try external calls then fallback to EVM 35 if ed.externals == nil { 36 return nil 37 } 38 return ed.externals.Dispatch(acc) 39 } 40 41 func (ed *Externals) SetExternals(externals Dispatcher) { 42 ed.externals = externals 43 } 44 45 type Dispatchers []Dispatcher 46 47 func NewDispatchers(dispatchers ...Dispatcher) Dispatchers { 48 out := dispatchers[:0] 49 // Flatten dispatchers and omit nil dispatchers (allows optional dispatchers in chain) 50 for i, d := range dispatchers { 51 ds, ok := d.(Dispatchers) 52 if ok { 53 // Add tail to nested dispatchers if one exists 54 if len(dispatchers) > i { 55 ds = append(ds, dispatchers[i+1:]...) 56 } 57 return append(out, NewDispatchers(ds...)...) 58 } else if d != nil { 59 out = append(out, d) 60 } 61 } 62 return out 63 } 64 65 // Connect ExternalDispatchers eds to each other so that the underlying engines can mutually call contracts hosted by 66 // other dispatchers 67 func Connect(eds ...ExternalDispatcher) { 68 for i, ed := range eds { 69 // Collect external dispatchers excluding this one (to avoid infinite dispatcher loops!) 70 others := make([]Dispatcher, 0, len(eds)-1) 71 for offset := 1; offset < len(eds); offset++ { 72 idx := (i + offset) % len(eds) 73 others = append(others, eds[idx]) 74 } 75 ed.SetExternals(NewDispatchers(others...)) 76 } 77 } 78 79 func (ds Dispatchers) Dispatch(acc *acm.Account) Callable { 80 for _, d := range ds { 81 callable := d.Dispatch(acc) 82 if callable != nil { 83 return callable 84 } 85 } 86 return nil 87 } 88 89 type ExternalsStorage struct { 90 }