github.com/metacurrency/holochain@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/validate.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 5 // Chain validation protocol. This protocol allows DHT nodes to request data so they can 6 // run validation on the puts and linkings they are asked to perform 7 8 package holochain 9 10 import ( 11 "bytes" 12 "fmt" 13 . "github.com/holochain/holochain-proto/hash" 14 ) 15 16 // Package holds app specified data needed for validation (wire package) 17 type Package struct { 18 Chain []byte 19 } 20 21 // ValidationPackage holds app specified data needed for validation. This version 22 // holds the package with any chain data un-marshaled after validation for passing 23 // into the app for app level validation 24 type ValidationPackage struct { 25 Chain *Chain 26 } 27 28 const ( 29 30 // Constants for the key values of the validation request object returned 31 // by validateXPkg functions 32 33 // PkgReqChain is the key who value is one of the PkgReqChainOptX masks 34 PkgReqChain = "chain" 35 36 // PkgReqEntryTypes is the key who value is an array of entry types to limit 37 // the chain to 38 PkgReqEntryTypes = "types" 39 40 // Constant mask values for PkgReqChain key of the validation request object 41 42 PkgReqChainOptNone = 0x00 43 PkgReqChainOptHeaders = 0x01 44 PkgReqChainOptEntries = 0x02 45 PkgReqChainOptFull = 0x03 46 PkgReqChainOptNoneStr = "0" 47 PkgReqChainOptHeadersStr = "1" 48 PkgReqChainOptEntriesStr = "2" 49 PkgReqChainOptFullStr = "3" 50 ) 51 52 // PackagingReq holds a request from an app for data to be included in the validation response 53 type PackagingReq map[string]interface{} 54 55 // ValidateQuery holds the data from a validation query on the Source protocol 56 type ValidateQuery struct { 57 H Hash 58 } 59 60 // ValidateResponse holds the response to committing validates (PUT/MOD/DEL) 61 type ValidateResponse struct { 62 Type string 63 Header Header 64 Entry GobEntry 65 Package Package 66 } 67 68 // MakePackage converts a package request into a package, loading chain data as necessary 69 // this is the package that gets sent over the wire. Chain DNA is omitted in this package 70 // because it can be added at the destination and the chain will still validate. 71 func MakePackage(h *Holochain, req PackagingReq) (pkg Package, err error) { 72 if f, ok := req[PkgReqChain]; ok { 73 var b bytes.Buffer 74 flags := f.(int64) 75 var mflags int64 76 if (flags & PkgReqChainOptHeaders) == 0 { 77 mflags += ChainMarshalFlagsNoHeaders 78 } 79 if (flags & PkgReqChainOptEntries) == 0 { 80 mflags += ChainMarshalFlagsNoEntries 81 } 82 83 var types []string 84 if t, ok := req[PkgReqEntryTypes]; ok { 85 types = t.([]string) 86 } 87 88 privateEntries := h.GetPrivateEntryDefs() 89 privateTypeNames := make([]string, len(privateEntries)) 90 for i, def := range privateEntries { 91 privateTypeNames[i] = def.Name 92 } 93 94 h.chain.MarshalChain(&b, mflags+ChainMarshalFlagsOmitDNA, types, privateTypeNames) 95 pkg.Chain = b.Bytes() 96 } 97 return 98 } 99 100 // MakeValidationPackage converts a received Package into a ValidationPackage and validates 101 // any chain data that was included 102 func MakeValidationPackage(h *Holochain, pkg *Package) (vpkg *ValidationPackage, err error) { 103 vp := ValidationPackage{} 104 if (pkg != nil) && (pkg.Chain != nil) { 105 buf := bytes.NewBuffer(pkg.Chain) 106 var flags int64 107 flags, vp.Chain, err = UnmarshalChain(h.hashSpec, buf) 108 if err != nil { 109 return 110 } 111 if flags&ChainMarshalFlagsNoEntries == 0 { 112 // restore the chain's DNA data 113 vp.Chain.Entries[0].(*GobEntry).C = h.chain.Entries[0].(*GobEntry).C 114 } 115 if flags&ChainMarshalFlagsNoHeaders == 0 { 116 err = vp.Chain.Validate(flags&ChainMarshalFlagsNoEntries != 0) 117 if err != nil { 118 return 119 } 120 } 121 } 122 vpkg = &vp 123 return 124 } 125 126 // ValidateReceiver handles messages on the Validate protocol 127 func ValidateReceiver(h *Holochain, msg *Message) (response interface{}, err error) { 128 var a ValidatingAction 129 switch msg.Type { 130 case VALIDATE_PUT_REQUEST: 131 a = &ActionPut{} 132 case VALIDATE_MOD_REQUEST: 133 a = &ActionMod{} 134 case VALIDATE_DEL_REQUEST: 135 a = &ActionDel{} 136 case VALIDATE_LINK_REQUEST: 137 a = &ActionLink{} 138 default: 139 err = fmt.Errorf("message type %d not in holochain-validate protocol", int(msg.Type)) 140 } 141 if err == nil { 142 h.dht.dlog.Logf("got validate %s request: %v", a.Name(), msg) 143 switch t := msg.Body.(type) { 144 case ValidateQuery: 145 response, err = h.GetValidationResponse(a, t.H) 146 default: 147 err = fmt.Errorf("expected ValidateQuery got %T", t) 148 } 149 } 150 h.dht.dlog.Logf("validate responding with: %T %v (err=%v)", response, response, err) 151 return 152 }