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

     1  package holochain
     2  
     3  import (
     4  	. "github.com/holochain/holochain-proto/hash"
     5  	peer "github.com/libp2p/go-libp2p-peer"
     6  )
     7  
     8  //------------------------------------------------------------
     9  // Mod
    10  
    11  type APIFnMod struct {
    12  	action ActionMod
    13  }
    14  
    15  func (fn *APIFnMod) Name() string {
    16  	return fn.action.Name()
    17  }
    18  
    19  func (fn *APIFnMod) Args() []Arg {
    20  	return []Arg{{Name: "entryType", Type: StringArg}, {Name: "entry", Type: EntryArg}, {Name: "replaces", Type: HashArg}}
    21  }
    22  
    23  func (fn *APIFnMod) Call(h *Holochain) (response interface{}, err error) {
    24  	a := &fn.action
    25  	response, err = h.commitAndShare(a, a.replaces)
    26  	return
    27  }
    28  
    29  type ActionMod struct {
    30  	entryType string
    31  	entry     Entry
    32  	header    *Header
    33  	replaces  Hash
    34  }
    35  
    36  func NewModAction(entryType string, entry Entry, replaces Hash) *ActionMod {
    37  	a := ActionMod{entryType: entryType, entry: entry, replaces: replaces}
    38  	return &a
    39  }
    40  
    41  func (a *ActionMod) Entry() Entry {
    42  	return a.entry
    43  }
    44  
    45  func (a *ActionMod) EntryType() string {
    46  	return a.entryType
    47  }
    48  
    49  func (a *ActionMod) Name() string {
    50  	return "mod"
    51  }
    52  
    53  func (a *ActionMod) SetHeader(header *Header) {
    54  	a.header = header
    55  }
    56  
    57  func (a *ActionMod) GetHeader() (header *Header) {
    58  	return a.header
    59  }
    60  
    61  func (a *ActionMod) Share(h *Holochain, def *EntryDef) (err error) {
    62  	if def.isSharingPublic() {
    63  		// if it's a public entry send the DHT MOD & PUT messages
    64  		// TODO handle errors better!!
    65  		h.dht.Change(a.header.EntryLink, PUT_REQUEST, HoldReq{EntryHash: a.header.EntryLink})
    66  		h.dht.Change(a.replaces, MOD_REQUEST, HoldReq{RelatedHash: a.replaces, EntryHash: a.header.EntryLink})
    67  	}
    68  	return
    69  }
    70  
    71  func (a *ActionMod) SysValidation(h *Holochain, def *EntryDef, pkg *Package, sources []peer.ID) (err error) {
    72  	switch def.Name {
    73  	case DNAEntryType:
    74  		err = ErrNotValidForDNAType
    75  		return
    76  	case HeadersEntryType:
    77  		err = ErrNotValidForHeadersType
    78  		return
    79  	case DelEntryType:
    80  		err = ErrNotValidForDelType
    81  		return
    82  	case KeyEntryType:
    83  	case AgentEntryType:
    84  	}
    85  
    86  	if def.DataFormat == DataFormatLinks {
    87  		err = ErrModInvalidForLinks
    88  		return
    89  	}
    90  
    91  	if a.entry == nil {
    92  		err = ErrNilEntryInvalid
    93  		return
    94  	}
    95  	if a.header == nil {
    96  		err = ErrModMissingHeader
    97  		return
    98  	}
    99  	if a.replaces.String() == a.header.EntryLink.String() {
   100  		err = ErrModReplacesHashNotDifferent
   101  		return
   102  	}
   103  	// no need to check for virtual entries on the chain because they aren't there
   104  	// currently the only virtual entry is the node id
   105  	/*
   106  		if !def.IsVirtualEntry() {
   107  			var header *Header
   108  			header, err = h.chain.GetEntryHeader(a.replaces)
   109  			if err != nil {
   110  				return
   111  			}
   112  			if header.Type != a.entryType {
   113  				err = ErrEntryTypeMismatch
   114  				return
   115  			}
   116  		}*/
   117  	err = sysValidateEntry(h, def, a.entry, pkg)
   118  	return
   119  }
   120  
   121  func (a *ActionMod) Receive(dht *DHT, msg *Message) (response interface{}, err error) {
   122  	//var hashStatus int
   123  	t := msg.Body.(HoldReq)
   124  	var holdResp *HoldResp
   125  
   126  	err = RunValidationPhase(dht.h, msg.From, VALIDATE_MOD_REQUEST, t.EntryHash, func(resp ValidateResponse) error {
   127  		a := NewModAction(resp.Type, &resp.Entry, t.RelatedHash)
   128  		a.header = &resp.Header
   129  
   130  		//@TODO what comes back from Validate Mod
   131  		_, err = dht.h.ValidateAction(a, resp.Type, &resp.Package, []peer.ID{msg.From})
   132  		if err != nil {
   133  			// how do we record an invalid Mod?
   134  			//@TODO store as REJECTED?
   135  		} else {
   136  			err = dht.Mod(msg, t.RelatedHash, t.EntryHash)
   137  			if err == nil {
   138  				holdResp, err = dht.MakeHoldResp(msg, StatusLive)
   139  			}
   140  		}
   141  		return err
   142  	})
   143  	if holdResp != nil {
   144  		response = *holdResp
   145  	}
   146  	return
   147  }
   148  
   149  func (a *ActionMod) CheckValidationRequest(def *EntryDef) (err error) {
   150  	return
   151  }