func (dht *IpfsDHT) getPublicKeyFromNode(ctx context.Context, p peer.ID) (ci.PubKey, error) { // check locally, just in case... pk := dht.peerstore.PubKey(p) if pk != nil { return pk, nil } pkkey := routing.KeyForPublicKey(p) pmes, err := dht.getValueSingle(ctx, p, pkkey) if err != nil { return nil, err } // node doesn't have key :( record := pmes.GetRecord() if record == nil { return nil, fmt.Errorf("Node not responding with its public key: %s", p) } // Success! We were given the value. we don't need to check // validity because a) we can't. b) we know the hash of the // key we're looking for. val := record.GetValue() log.Debug("DHT got a value from other peer.") pk, err = ci.UnmarshalPublicKey(val) if err != nil { return nil, err } id, err := peer.IDFromPublicKey(pk) if err != nil { return nil, err } if id != p { return nil, fmt.Errorf("public key does not match id: %s", p) } // ok! it's valid. we got it! log.Debugf("DHT got public key from node itself.") return pk, nil }
func (dht *IpfsDHT) GetPublicKey(ctx context.Context, p peer.ID) (ci.PubKey, error) { log.Debugf("getPublicKey for: %s", p) // check locally. pk := dht.peerstore.PubKey(p) if pk != nil { return pk, nil } // ok, try the node itself. if they're overwhelmed or slow we can move on. ctxT, cancelFunc := ctxfrac.WithDeadlineFraction(ctx, 0.3) defer cancelFunc() if pk, err := dht.getPublicKeyFromNode(ctx, p); err == nil { err := dht.peerstore.AddPubKey(p, pk) if err != nil { return pk, err } return pk, nil } // last ditch effort: let's try the dht. log.Debugf("pk for %s not in peerstore, and peer failed. Trying DHT.", p) pkkey := routing.KeyForPublicKey(p) val, err := dht.GetValue(ctxT, pkkey) if err != nil { log.Warning("Failed to find requested public key.") return nil, err } pk, err = ci.UnmarshalPublicKey(val) if err != nil { log.Debugf("Failed to unmarshal public key: %s", err) return nil, err } return pk, dht.peerstore.AddPubKey(p, pk) }