github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/nucleus.go (about) 1 // Copyright (C) 2013-2017, 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 5 package holochain 6 7 import ( 8 "fmt" 9 "github.com/google/uuid" 10 . "github.com/holochain/holochain-proto/hash" 11 ) 12 13 type DNA struct { 14 Version int 15 UUID uuid.UUID 16 Name string 17 Properties map[string]string 18 PropertiesSchema string 19 PropertiesSchemaFile string 20 AgentIdentitySchema string // defines what must go in the Indentity field of a key/agent entry 21 BasedOn Hash // references hash of another holochain that these schemas and code are derived from 22 RequiresVersion int 23 DHTConfig DHTConfig 24 Progenitor Progenitor 25 Zomes []Zome 26 propertiesSchemaValidator SchemaValidator 27 } 28 29 func (dna *DNA) check() (err error) { 30 if dna.RequiresVersion > Version { 31 err = fmt.Errorf("Chain requires Holochain version %d", dna.RequiresVersion) 32 } 33 return 34 } 35 36 // Nucleus encapsulates Application parts: Ribosomes to run code in Zomes, plus application 37 // validation and direct message passing protocols 38 type Nucleus struct { 39 dna *DNA 40 h *Holochain 41 alog *Logger // the app logger 42 } 43 44 func (n *Nucleus) DNA() (dna *DNA) { 45 return n.dna 46 } 47 48 // NewNucleus creates a new Nucleus structure 49 func NewNucleus(h *Holochain, dna *DNA) *Nucleus { 50 nucleus := Nucleus{ 51 dna: dna, 52 h: h, 53 alog: &h.Config.Loggers.App, 54 } 55 return &nucleus 56 } 57 58 func (n *Nucleus) RunGenesis() (err error) { 59 var ribosome Ribosome 60 // run the init functions of each zome 61 for _, zome := range n.dna.Zomes { 62 ribosome, err = zome.MakeRibosome(n.h) 63 if err == nil { 64 err = ribosome.ChainGenesis() 65 if err != nil { 66 err = fmt.Errorf("In '%s' zome: %s", zome.Name, err.Error()) 67 return 68 } 69 } 70 } 71 return 72 } 73 74 func (n *Nucleus) Start() (err error) { 75 h := n.h 76 if err = h.node.StartProtocol(h, ValidateProtocol); err != nil { 77 return 78 } 79 if err = h.node.StartProtocol(h, ActionProtocol); err != nil { 80 return 81 } 82 return 83 } 84 85 type AppMsg struct { 86 ZomeType string 87 Body string 88 } 89 90 // ActionReceiver handles messages on the action protocol 91 func ActionReceiver(h *Holochain, msg *Message) (response interface{}, err error) { 92 return actionReceiver(h, msg, MaxRetries) 93 } 94 95 func isRelatedHoldMessage(msg *Message) bool { 96 return msg.Type == MOD_REQUEST || msg.Type == DEL_REQUEST || msg.Type == LINK_REQUEST 97 } 98 99 func actionReceiver(h *Holochain, msg *Message, retries int) (response interface{}, err error) { 100 dht := h.dht 101 // to protect against crashes from background routines after close 102 if dht == nil { 103 return 104 } 105 var a Action 106 a, err = MakeActionFromMessage(msg) 107 if err == nil { 108 dht.dlog.Logf("ActionReceiver got %s: %v", a.Name(), msg) 109 110 // If this is a Del/Mod/Link message then we need to check to see if we 111 // have the Related Hash and if not, queue for retry 112 if isRelatedHoldMessage(msg) { 113 t := msg.Body.(HoldReq) 114 err = dht.Exists(t.RelatedHash, StatusDefault) 115 if err != nil { 116 if err == ErrHashNotFound { 117 dht.dlog.Logf("don't yet have %s, trying again later", t.RelatedHash) 118 retry := &retry{msg: *msg, retries: retries} 119 dht.retryQueue <- retry 120 response = DHTChangeUnknownHashQueuedForRetry 121 err = nil 122 } 123 } 124 125 if response != nil || err != nil { 126 return 127 } 128 } 129 130 // N.B. a.Receive calls made to an Action whose values are NOT populated. 131 // The Receive functions understand this and use the values from the message body 132 // TODO, this indicates an architectural error, so fix! 133 response, err = a.Receive(dht, msg) 134 } 135 return 136 } 137 138 // NewUUID generates a new UUID for the DNA 139 func (dna *DNA) NewUUID() (err error) { 140 dna.UUID, err = uuid.NewUUID() 141 if err != nil { 142 return 143 } 144 return 145 }