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

     1  package wasm
     2  
     3  import (
     4  	"github.com/hyperledger/burrow/acm"
     5  	"github.com/hyperledger/burrow/acm/acmstate"
     6  	"github.com/hyperledger/burrow/execution/defaults"
     7  	"github.com/hyperledger/burrow/execution/engine"
     8  	"github.com/hyperledger/burrow/execution/errors"
     9  	"github.com/hyperledger/burrow/execution/exec"
    10  	"github.com/hyperledger/burrow/execution/native"
    11  	lifeExec "github.com/perlin-network/life/exec"
    12  )
    13  
    14  // Implements ewasm, see https://github.com/ewasm/design
    15  // WASM
    16  var DefaultVMConfig = lifeExec.VMConfig{
    17  	DisableFloatingPoint: true,
    18  	MaxMemoryPages:       16,
    19  	DefaultMemoryPages:   16,
    20  }
    21  
    22  type WVM struct {
    23  	engine.Externals
    24  	options            engine.Options
    25  	vmConfig           lifeExec.VMConfig
    26  	externalDispatcher engine.Dispatcher
    27  }
    28  
    29  func New(options engine.Options) *WVM {
    30  	vm := &WVM{
    31  		options:  defaults.CompleteOptions(options),
    32  		vmConfig: DefaultVMConfig,
    33  	}
    34  	vm.externalDispatcher = engine.Dispatchers{&vm.Externals, options.Natives, vm}
    35  	return vm
    36  }
    37  
    38  func Default() *WVM {
    39  	return New(engine.Options{})
    40  }
    41  
    42  // RunWASM creates a WASM VM, and executes the given WASM contract code
    43  func (vm *WVM) Execute(st acmstate.ReaderWriter, blockchain engine.Blockchain, eventSink exec.EventSink,
    44  	params engine.CallParams, code []byte) (output []byte, cerr error) {
    45  	defer func() {
    46  		if r := recover(); r != nil {
    47  			cerr = errors.Codes.ExecutionAborted
    48  		}
    49  	}()
    50  
    51  	st = native.NewState(vm.options.Natives, st)
    52  
    53  	state := engine.State{
    54  		CallFrame:  engine.NewCallFrame(st).WithMaxCallStackDepth(vm.options.CallStackMaxDepth),
    55  		Blockchain: blockchain,
    56  		EventSink:  eventSink,
    57  	}
    58  
    59  	output, err := vm.Contract(code).Call(state, params)
    60  
    61  	if err == nil {
    62  		// Only sync back when there was no exception
    63  		err = state.CallFrame.Sync()
    64  	}
    65  	// Always return output - we may have a reverted exception for which the return is meaningful
    66  	return output, err
    67  }
    68  
    69  func (vm *WVM) Dispatch(acc *acm.Account) engine.Callable {
    70  	if len(acc.WASMCode) == 0 {
    71  		return nil
    72  	}
    73  	return vm.Contract(acc.WASMCode)
    74  }
    75  
    76  func (vm *WVM) Contract(code []byte) *Contract {
    77  	return &Contract{
    78  		vm:   vm,
    79  		code: code,
    80  	}
    81  }