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

     1  package holochain
     2  
     3  import (
     4  	"errors"
     5  	. "github.com/holochain/holochain-proto/hash"
     6  	peer "github.com/libp2p/go-libp2p-peer"
     7  	"reflect"
     8  )
     9  
    10  //------------------------------------------------------------
    11  // ModAgent
    12  
    13  type APIFnModAgent struct {
    14  	Identity   AgentIdentity
    15  	Revocation string
    16  }
    17  
    18  func (fn *APIFnModAgent) Args() []Arg {
    19  	return []Arg{{Name: "options", Type: MapArg, MapType: reflect.TypeOf(ModAgentOptions{})}}
    20  }
    21  
    22  func (fn *APIFnModAgent) Name() string {
    23  	return "updateAgent"
    24  }
    25  func (fn *APIFnModAgent) Call(h *Holochain) (response interface{}, err error) {
    26  	var ok bool
    27  	var newAgent LibP2PAgent = *h.agent.(*LibP2PAgent)
    28  	if fn.Identity != "" {
    29  		newAgent.identity = fn.Identity
    30  		ok = true
    31  	}
    32  
    33  	var revocation *SelfRevocation
    34  	if fn.Revocation != "" {
    35  		err = newAgent.GenKeys(nil)
    36  		if err != nil {
    37  			return
    38  		}
    39  		revocation, err = NewSelfRevocation(h.agent.PrivKey(), newAgent.PrivKey(), []byte(fn.Revocation))
    40  		if err != nil {
    41  			return
    42  		}
    43  		ok = true
    44  	}
    45  	if !ok {
    46  		err = errors.New("expecting identity and/or revocation option")
    47  	} else {
    48  
    49  		//TODO: synchronize this, what happens if two new agent request come in back to back?
    50  		h.agent = &newAgent
    51  		// add a new agent entry and update
    52  		var agentHash Hash
    53  		_, agentHash, err = h.AddAgentEntry(revocation)
    54  		if err != nil {
    55  			return
    56  		}
    57  		h.agentTopHash = agentHash
    58  
    59  		// if there was a revocation put the new key to the DHT and then reset the node ID data
    60  		// TODO make sure this doesn't introduce race conditions in the DHT between new and old identity #284
    61  		if revocation != nil {
    62  			err = h.dht.putKey(&newAgent)
    63  			if err != nil {
    64  				return
    65  			}
    66  
    67  			// send the modification request for the old key
    68  			var oldKey, newKey Hash
    69  			oldPeer := h.nodeID
    70  			oldKey, err = NewHash(h.nodeIDStr)
    71  			if err != nil {
    72  				panic(err)
    73  			}
    74  
    75  			h.nodeID, h.nodeIDStr, err = h.agent.NodeID()
    76  			if err != nil {
    77  				return
    78  			}
    79  
    80  			newKey, err = NewHash(h.nodeIDStr)
    81  			if err != nil {
    82  				panic(err)
    83  			}
    84  
    85  			// close the old node and add the new node
    86  			// TODO currently ignoring the error from node.Close() is this OK?
    87  			h.node.Close()
    88  			h.createNode()
    89  
    90  			h.dht.Change(oldKey, MOD_REQUEST, HoldReq{RelatedHash: oldKey, EntryHash: newKey})
    91  
    92  			warrant, _ := NewSelfRevocationWarrant(revocation)
    93  			var data []byte
    94  			data, err = warrant.Encode()
    95  			if err != nil {
    96  				return
    97  			}
    98  
    99  			// TODO, this isn't really a DHT send, but a management send, so the key is bogus.  have to work this out...
   100  			h.dht.Change(oldKey, LISTADD_REQUEST,
   101  				ListAddReq{
   102  					ListType:    BlockedList,
   103  					Peers:       []string{peer.IDB58Encode(oldPeer)},
   104  					WarrantType: SelfRevocationType,
   105  					Warrant:     data,
   106  				})
   107  
   108  		}
   109  
   110  		response = agentHash
   111  	}
   112  	return
   113  }