github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/ribosome.go (about)

     1  // Copyright (C) 2013-2018, The MetaCurrency Project (Eric Harris-Braun, Arthur Brock, et. al.)
     2  // Use of this source code is governed by GPLv3 found in the LICENSE file
     3  //----------------------------------------------------------------------------------------
     4  // Ribosome provides an interface for an execution environment interface for chains and their entries
     5  // and factory code for creating ribosome instances
     6  
     7  package holochain
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	. "github.com/holochain/holochain-proto/hash"
    13  	"sort"
    14  	"strings"
    15  )
    16  
    17  type RibosomeFactory func(h *Holochain, zome *Zome) (Ribosome, error)
    18  
    19  const (
    20  
    21  	// calling types
    22  
    23  	STRING_CALLING = "string"
    24  	JSON_CALLING   = "json"
    25  
    26  	// exposure types for functions
    27  
    28  	// ZOME_EXPOSURE is the default and means the function is only exposed for use by other zomes in the app
    29  	ZOME_EXPOSURE = ""
    30  	// AUTHENTICATED_EXPOSURE means that the function is only available after authentication (TODO)
    31  	AUTHENTICATED_EXPOSURE = "auth"
    32  	// PUBLIC_EXPOSURE means that the function is callable by anyone
    33  	PUBLIC_EXPOSURE = "public"
    34  
    35  	// these constants are for a removed feature, see ChangeAppProperty
    36  	// @TODO figure out how to remove code over time that becomes obsolete, i.e. for long-dead changes
    37  
    38  	ID_PROPERTY         = "_id"
    39  	AGENT_ID_PROPERTY   = "_agent_id"
    40  	AGENT_NAME_PROPERTY = "_agent_name"
    41  
    42  	BridgeCaller    = 0
    43  	BridgeCallee    = 1
    44  	BridgeCallerStr = "0"
    45  	BridgeCalleeStr = "1"
    46  
    47  	BundleCancelReasonUserCancel = "userCancel"
    48  	BundleCancelReasonTimeout    = "timeout"
    49  
    50  	BundleCancelResponseOK     = ""
    51  	BundleCancelResponseCommit = "commit"
    52  
    53  	ValidationFailedErrMsg = "Validation Failed"
    54  )
    55  
    56  var ValidationFailedErr = errors.New(ValidationFailedErrMsg)
    57  
    58  // ValidationFailed creates a validation failed error message
    59  func ValidationFailed(msgs ...string) error {
    60  	if len(msgs) == 0 {
    61  		return ValidationFailedErr
    62  	}
    63  	return errors.New(ValidationFailedErrMsg + ": " + strings.Join(msgs, `, `))
    64  }
    65  
    66  func IsValidationFailedErr(err error) bool {
    67  	return strings.HasPrefix(err.Error(), ValidationFailedErrMsg)
    68  }
    69  
    70  // FunctionDef holds the name and calling type of an DNA exposed function
    71  type FunctionDef struct {
    72  	Name        string
    73  	CallingType string
    74  	Exposure    string
    75  }
    76  
    77  // ValidExposure verifies that the function can be called in the given context
    78  func (f *FunctionDef) ValidExposure(context string) bool {
    79  	if f.Exposure == PUBLIC_EXPOSURE {
    80  		return true
    81  	}
    82  	return f.Exposure == context
    83  }
    84  
    85  // Ribosome type abstracts the functions of code execution environments
    86  type Ribosome interface {
    87  	Type() string
    88  	ValidateAction(action Action, def *EntryDef, pkg *ValidationPackage, sources []string) (err error)
    89  	ValidatePackagingRequest(action ValidatingAction, def *EntryDef) (req PackagingReq, err error)
    90  	ChainGenesis() error
    91  	BridgeGenesis(side int, dnaHash Hash, data string) error
    92  	Receive(from string, msg string) (response string, err error)
    93  	Call(fn *FunctionDef, params interface{}) (interface{}, error)
    94  	Run(code string) (result interface{}, err error)
    95  	RunAsyncSendResponse(response AppMsg, callback string, callbackID string) (result interface{}, err error)
    96  	BundleCanceled(reason string) (response string, err error)
    97  }
    98  
    99  var ribosomeFactories = make(map[string]RibosomeFactory)
   100  
   101  // RegisterRibosome sets up a Ribosome to be used by the CreateRibosome function
   102  func RegisterRibosome(name string, factory RibosomeFactory) {
   103  	if factory == nil {
   104  		panic(fmt.Sprintf("Ribosome factory for type %s does not exist.", name))
   105  	}
   106  	_, registered := ribosomeFactories[name]
   107  	if registered {
   108  		panic(fmt.Sprintf("Ribosome factory for type %s already registered. ", name))
   109  	}
   110  	ribosomeFactories[name] = factory
   111  }
   112  
   113  // RegisterBultinRibosomes adds the built in ribosome types to the factory hash
   114  func RegisterBultinRibosomes() {
   115  	RegisterRibosome(ZygoRibosomeType, NewZygoRibosome)
   116  	RegisterRibosome(JSRibosomeType, NewJSRibosome)
   117  }
   118  
   119  // CreateRibosome returns a new Ribosome of the given type
   120  func CreateRibosome(h *Holochain, zome *Zome) (Ribosome, error) {
   121  
   122  	factory, ok := ribosomeFactories[zome.RibosomeType]
   123  	if !ok {
   124  		// Factory has not been registered.
   125  		// Make a list of all available ribosome factories for error.
   126  		var available []string
   127  		for k := range ribosomeFactories {
   128  			available = append(available, k)
   129  		}
   130  		sort.Strings(available)
   131  		return nil, fmt.Errorf("Invalid ribosome name. Must be one of: %s", strings.Join(available, ", "))
   132  	}
   133  
   134  	return factory(h, zome)
   135  }