Browse Source

Regularize use of fingerprint concept across code.

Adam Ierymenko 5 years ago
parent
commit
416068f68e

+ 33 - 41
include/ZeroTierCore.h

@@ -278,6 +278,32 @@ extern "C" {
 
 /* ----------------------------------------------------------------------------------------------------------------- */
 
+
+/**
+ * Identity type codes
+ */
+enum ZT_Identity_Type
+{
+	/* These values must be the same as in Identity.hpp in the core. */
+	ZT_IDENTITY_TYPE_C25519 = 0,
+	ZT_IDENTITY_TYPE_P384 = 1
+};
+
+/**
+ * A ZeroTier identity (opaque)
+ */
+typedef void ZT_Identity;
+
+/**
+ * Full identity fingerprint with address and 384-bit hash of public key(s)
+ */
+ZT_PACKED_STRUCT(struct _ZT_Fingerprint
+{
+	uint64_t address;
+	uint8_t hash[48];
+});
+typedef struct _ZT_Fingerprint ZT_Fingerprint;
+
 /**
  * Credential type IDs
  */
@@ -460,8 +486,7 @@ _ZT_TRACE_EVENT_STRUCT_END()
  * move around on the network.
  */
 _ZT_TRACE_EVENT_STRUCT_START(VL1_RESETTING_PATHS_IN_SCOPE)
-	uint64_t reporter;                               /* ZeroTier address that triggered the reset */
-	uint8_t reporterIdentityHash[48];                /* full identity hash of triggering node's identity */
+	ZT_Fingerprint reporter;                         /* node that triggered the reset */
 	struct ZT_TraceEventPathAddress from;            /* physical origin of triggering packet */
 	struct ZT_TraceEventPathAddress oldExternal;     /* previous detected external address */
 	struct ZT_TraceEventPathAddress newExternal;     /* new detected external address */
@@ -475,14 +500,12 @@ _ZT_TRACE_EVENT_STRUCT_END()
  * we might hear of them. A node tries a path by sending a trial message to it.
  */
 _ZT_TRACE_EVENT_STRUCT_START(VL1_TRYING_NEW_PATH)
-	uint64_t address;                                /* short address of node we're trying to reach */
-	uint8_t identityHash[48];                        /* identity hash of node we're trying to reach */
+	ZT_Fingerprint peer;                             /* node we're trying to reach */
 	struct ZT_TraceEventPathAddress physicalAddress; /* physical address being tried */
 	struct ZT_TraceEventPathAddress triggerAddress;  /* physical origin of triggering packet */
 	uint64_t triggeringPacketId;                     /* packet ID of triggering packet */
 	uint8_t triggeringPacketVerb;                    /* packet verb of triggering packet */
-	uint64_t triggeredByAddress;                     /* short address of node triggering attempt */
-	uint8_t triggeredByIdentityHash[48];             /* full identity hash of node triggering attempt */
+	ZT_Fingerprint triggeringPeer;                   /* peer that triggered attempt */
 	uint8_t reason;                                  /* ZT_TraceTryingNewPathReason */
 _ZT_TRACE_EVENT_STRUCT_END()
 
@@ -491,8 +514,7 @@ _ZT_TRACE_EVENT_STRUCT_END()
  */
 _ZT_TRACE_EVENT_STRUCT_START(VL1_LEARNED_NEW_PATH)
 	uint64_t packetId;                               /* packet ID of confirming packet */
-	uint64_t address;                                /* short address of learned peer */
-	uint8_t identityHash[48];                        /* full identity hash of learned peer */
+	ZT_Fingerprint peer;                             /* peer on other side of new path */
 	struct ZT_TraceEventPathAddress physicalAddress; /* physical address learned */
 	struct ZT_TraceEventPathAddress replaced;        /* if non-empty, an older address that was replaced */
 _ZT_TRACE_EVENT_STRUCT_END()
@@ -506,8 +528,7 @@ _ZT_TRACE_EVENT_STRUCT_END()
 _ZT_TRACE_EVENT_STRUCT_START(VL1_INCOMING_PACKET_DROPPED)
 	uint64_t packetId;                               /* packet ID of failed packet */
 	uint64_t networkId;                              /* VL2 network ID or 0 if unrelated to a network or unknown */
-	uint64_t address;                                /* short address that sent packet */
-	uint8_t identityHash[48];                        /* full identity hash of sending node */
+	ZT_Fingerprint peer;                             /* peer that sent packet */
 	struct ZT_TraceEventPathAddress physicalAddress; /* physical origin address of packet */
 	uint8_t hops;                                    /* hop count of packet */
 	uint8_t verb;                                    /* packet verb */
@@ -535,7 +556,7 @@ _ZT_TRACE_EVENT_STRUCT_START(VL2_INCOMING_FRAME_DROPPED)
 	uint64_t networkId;                              /* VL2 network ID */
 	uint64_t sourceMac;                              /* 48-bit source MAC */
 	uint64_t destMac;                                /* 48-bit destination MAC */
-	uint64_t address;                                /* short address of sending peer */
+	ZT_Fingerprint sender;                           /* sending peer */
 	struct ZT_TraceEventPathAddress physicalAddress; /* physical source address of packet */
 	uint8_t hops;                                    /* hop count of packet */
 	uint16_t frameLength;                            /* length of frame in bytes */
@@ -582,7 +603,7 @@ _ZT_TRACE_EVENT_STRUCT_END()
  */
 _ZT_TRACE_EVENT_STRUCT_START(VL2_CREDENTIAL_REJECTED)
 	uint64_t networkId;                              /* VL2 network ID */
-	uint64_t address;                                /* short address of sender */
+	ZT_Fingerprint peer;                             /* sending peer */
 	uint32_t credentialId;                           /* credential ID */
 	int64_t credentialTimestamp;                     /* credential timestamp */
 	uint8_t credentialType;                          /* credential type */
@@ -728,21 +749,6 @@ enum ZT_Event
 	ZT_EVENT_USER_MESSAGE = 6
 };
 
-/**
- * Identity type codes
- */
-enum ZT_Identity_Type
-{
-	/* These values must be the same as in Identity.hpp in the core. */
-	ZT_IDENTITY_TYPE_C25519 = 0,
-	ZT_IDENTITY_TYPE_P384 = 1
-};
-
-/**
- * A ZeroTier identity (opaque)
- */
-typedef void ZT_Identity;
-
 /**
  * User message used with ZT_EVENT_USER_MESSAGE
  *
@@ -1343,11 +1349,6 @@ typedef struct
 	 */
 	const ZT_Identity *identity;
 
-	/**
-	 * SHA384 hash of identity public key(s)
-	 */
-	uint8_t identityHash[48];
-
 	/**
 	 * Remote major version or -1 if not known
 	 */
@@ -2141,15 +2142,6 @@ ZT_SDK_API int ZT_Identity_hasPrivate(const ZT_Identity *id);
  */
 ZT_SDK_API uint64_t ZT_Identity_address(const ZT_Identity *id);
 
-/**
- * Compute a hash of this identity's public keys (or both public and private if includePrivate is true)
- *
- * @param id Identity to query
- * @param h Buffer for 384-bit hash
- * @param includePrivate If true include private keys if any
- */
-ZT_SDK_API void ZT_Identity_hash(const ZT_Identity *id,uint8_t h[48],int includePrivate);
-
 /**
  * Delete an identity and free associated memory
  *

+ 18 - 22
node/Fingerprint.hpp

@@ -16,11 +16,14 @@
 
 #include "Constants.hpp"
 #include "TriviallyCopyable.hpp"
+#include "Address.hpp"
 
 #include <algorithm>
 
 namespace ZeroTier {
 
+class Identity;
+
 /**
  * Container for 384-bit identity hashes
  *
@@ -33,39 +36,32 @@ namespace ZeroTier {
  */
 class Fingerprint : public TriviallyCopyable
 {
-public:
-	ZT_ALWAYS_INLINE Fingerprint() noexcept {}
-
-	ZT_ALWAYS_INLINE void zero() noexcept { memoryZero(this); }
+	friend class Identity;
 
-	ZT_ALWAYS_INLINE uint8_t *data() noexcept { return reinterpret_cast<uint8_t *>(_h); }
-	ZT_ALWAYS_INLINE const uint8_t *data() const noexcept { return reinterpret_cast<const uint8_t *>(_h); }
-
-	ZT_ALWAYS_INLINE uint8_t operator[](const unsigned int i) const noexcept { return reinterpret_cast<const uint8_t *>(_h)[i]; }
-	ZT_ALWAYS_INLINE uint8_t &operator[](const unsigned int i) noexcept { return reinterpret_cast<uint8_t *>(_h)[i]; }
+public:
+	/**
+	 * Create an empty/nil fingerprint
+	 */
+	ZT_ALWAYS_INLINE Fingerprint() noexcept { memoryZero(this); }
 
-	static constexpr unsigned int size() noexcept { return 48; }
+	ZT_ALWAYS_INLINE Address address() const noexcept { return Address(_fp.address); }
+	ZT_ALWAYS_INLINE const uint8_t *hash() const noexcept { return _fp.hash; }
+	ZT_ALWAYS_INLINE void setZTFingerprint(ZT_Fingerprint *fp) const noexcept { memcpy(fp,&_fp,sizeof(ZT_Fingerprint)); }
 
-	ZT_ALWAYS_INLINE unsigned long hashCode() const noexcept { return _h[0]; }
+	ZT_ALWAYS_INLINE void zero() noexcept { memoryZero(this); }
+	ZT_ALWAYS_INLINE unsigned long hashCode() const noexcept { return _fp.address; }
 
-	ZT_ALWAYS_INLINE operator bool() const noexcept
-	{
-		for(unsigned int i=0;i<(384 / (sizeof(unsigned long) * 8));++i) {
-			if (_h[i] != 0)
-				return true;
-		}
-		return false;
-	}
+	ZT_ALWAYS_INLINE operator bool() const noexcept { return (_fp.address != 0); }
 
-	ZT_ALWAYS_INLINE bool operator==(const Fingerprint &h) const noexcept { return std::equal(_h,_h + (384 / (sizeof(unsigned long) * 8)),h._h); }
+	ZT_ALWAYS_INLINE bool operator==(const Fingerprint &h) const noexcept { return ((_fp.address == h._fp.address)&&(memcmp(_fp.hash,h._fp.hash,ZT_IDENTITY_HASH_SIZE) == 0)); }
 	ZT_ALWAYS_INLINE bool operator!=(const Fingerprint &h) const noexcept { return !(*this == h); }
-	ZT_ALWAYS_INLINE bool operator<(const Fingerprint &h) const noexcept { return std::lexicographical_compare(_h,_h + (384 / (sizeof(unsigned long) * 8)),h._h,h._h + (384 / (sizeof(unsigned long) * 8))); }
+	ZT_ALWAYS_INLINE bool operator<(const Fingerprint &h) const noexcept { return ((_fp.address < h._fp.address) || ((_fp.address == h._fp.address)&&(memcmp(_fp.hash,h._fp.hash,ZT_IDENTITY_HASH_SIZE) < 0))); }
 	ZT_ALWAYS_INLINE bool operator>(const Fingerprint &h) const noexcept { return (h < *this); }
 	ZT_ALWAYS_INLINE bool operator<=(const Fingerprint &h) const noexcept { return !(h < *this); }
 	ZT_ALWAYS_INLINE bool operator>=(const Fingerprint &h) const noexcept { return !(*this < h); }
 
 private:
-	unsigned long _h[384 / (sizeof(unsigned long) * 8)];
+	ZT_Fingerprint _fp;
 };
 
 } // namespace ZeroTier

+ 11 - 17
node/Identity.cpp

@@ -111,8 +111,7 @@ bool Identity::generate(const Type t)
 				Utils::storeBigEndian(_pub.t1mimc52,mimc52Delay(&_pub,sizeof(_pub) - sizeof(_pub.t1mimc52),ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE));
 
 				// Compute SHA384 fingerprint hash of keys and MIMC output and generate address directly from it.
-				_computeHash();
-				_address.setTo(_fp.data());
+				_computeHash(); // this sets the address for P384
 				if (!_address.isReserved())
 					break;
 			}
@@ -140,7 +139,7 @@ bool Identity::locallyValidate() const noexcept
 				}
 
 				case P384:
-					if (_address == Address(_fp.data())) {
+					if (_address == Address(_fp.hash())) {
 						// The most significant 8 bits of the MIMC proof included with v1 identities can be used to store a multiplier
 						// that can indicate that more work than the required minimum has been performed. Right now this is never done
 						// but it could have some use in the future. There is no harm in doing it, and we'll accept any round count
@@ -445,10 +444,8 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
 	_fp.zero();
 	_hasPrivate = false;
 
-	if (len < (ZT_ADDRESS_LENGTH + 1))
+	if (len < (1 + ZT_ADDRESS_LENGTH))
 		return -1;
-	_address.setTo(data);
-
 	unsigned int privlen;
 	switch((_type = (Type)data[ZT_ADDRESS_LENGTH])) {
 
@@ -457,6 +454,7 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
 				return -1;
 
 			memcpy(_pub.c25519,data + ZT_ADDRESS_LENGTH + 1,ZT_C25519_PUBLIC_KEY_LEN);
+			_address.setTo(data);
 			_computeHash();
 
 			privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN];
@@ -477,8 +475,8 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
 				return -1;
 
 			memcpy(&_pub,data + ZT_ADDRESS_LENGTH + 1,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
-			_computeHash();
-			if (_address != Address(_fp.data())) // for v1 we can sanity check this here, but this isn't a full validate
+			_computeHash(); // this sets the address for P384
+			if (_address != Address(data)) // sanity check address in data stream
 				return -1;
 
 			privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE];
@@ -507,11 +505,14 @@ void Identity::_computeHash()
 			break;
 
 		case C25519:
-			SHA384(_fp.data(),_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
+			_fp._fp.address = _address.toInt();
+			SHA384(_fp._fp.hash,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
 			break;
 
 		case P384:
-			SHA384(_fp.data(),&_pub,sizeof(_pub));
+			SHA384(_fp._fp.hash,&_pub,sizeof(_pub));
+			_address.setTo(reinterpret_cast<const uint8_t *>(_fp._fp.hash));
+			_fp._fp.address = _address.toInt();
 			break;
 	}
 }
@@ -601,13 +602,6 @@ uint64_t ZT_Identity_address(const ZT_Identity *id)
 	return reinterpret_cast<const ZeroTier::Identity *>(id)->address().toInt();
 }
 
-void ZT_Identity_hash(const ZT_Identity *id,uint8_t h[48],int includePrivate)
-{
-	if (includePrivate)
-		reinterpret_cast<const ZeroTier::Identity *>(id)->hashWithPrivate(h);
-	else memcpy(h,reinterpret_cast<const ZeroTier::Identity *>(id)->fingerprint().data(),ZT_IDENTITY_HASH_SIZE);
-}
-
 ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id)
 {
 	if (id)

+ 9 - 9
node/Membership.cpp

@@ -130,13 +130,13 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
 {
 	const int64_t newts = com.timestamp();
 	if (newts <= _comRevocationThreshold) {
-		RR->t->credentialRejected(tPtr,0xd9992121,com.networkId(),sourcePeerIdentity.address(),com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
+		RR->t->credentialRejected(tPtr,0xd9992121,com.networkId(),sourcePeerIdentity.address(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
 		return ADD_REJECTED;
 	}
 
 	const int64_t oldts = _com.timestamp();
 	if (newts < oldts) {
-		RR->t->credentialRejected(tPtr,0xd9928192,com.networkId(),sourcePeerIdentity.address(),com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
+		RR->t->credentialRejected(tPtr,0xd9928192,com.networkId(),sourcePeerIdentity.address(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
 		return ADD_REJECTED;
 	}
 	if ((newts == oldts)&&(_com == com))
@@ -144,13 +144,13 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
 
 	switch(com.verify(RR,tPtr)) {
 		default:
-			RR->t->credentialRejected(tPtr,0x0f198241,com.networkId(),sourcePeerIdentity.address(),com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
+			RR->t->credentialRejected(tPtr,0x0f198241,com.networkId(),sourcePeerIdentity.address(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
 			return Membership::ADD_REJECTED;
 		case Credential::VERIFY_OK:
 			_com = com;
 			return ADD_ACCEPTED_NEW;
 		case Credential::VERIFY_BAD_SIGNATURE:
-			RR->t->credentialRejected(tPtr,0xbaf0aaaa,com.networkId(),sourcePeerIdentity.address(),com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
+			RR->t->credentialRejected(tPtr,0xbaf0aaaa,com.networkId(),sourcePeerIdentity.address(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
 			return ADD_REJECTED;
 		case Credential::VERIFY_NEED_IDENTITY:
 			return ADD_DEFERRED_FOR_WHOIS;
@@ -171,7 +171,7 @@ static ZT_ALWAYS_INLINE Membership::AddCredentialResult _addCredImpl(
 	C *rc = remoteCreds.get(cred.id());
 	if (rc) {
 		if (rc->timestamp() > cred.timestamp()) {
-			RR->t->credentialRejected(tPtr,0x40000001,nconf.networkId,sourcePeerIdentity.address(),cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
+			RR->t->credentialRejected(tPtr,0x40000001,nconf.networkId,sourcePeerIdentity.address(),sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
 			return Membership::ADD_REJECTED;
 		}
 		if (*rc == cred)
@@ -180,13 +180,13 @@ static ZT_ALWAYS_INLINE Membership::AddCredentialResult _addCredImpl(
 
 	const int64_t *const rt = revocations.get(Membership::credentialKey(C::credentialType(),cred.id()));
 	if ((rt)&&(*rt >= cred.timestamp())) {
-		RR->t->credentialRejected(tPtr,0x24248124,nconf.networkId,sourcePeerIdentity.address(),cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
+		RR->t->credentialRejected(tPtr,0x24248124,nconf.networkId,sourcePeerIdentity.address(),sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
 		return Membership::ADD_REJECTED;
 	}
 
 	switch(cred.verify(RR,tPtr)) {
 		default:
-			RR->t->credentialRejected(tPtr,0x01feba012,nconf.networkId,sourcePeerIdentity.address(),cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
+			RR->t->credentialRejected(tPtr,0x01feba012,nconf.networkId,sourcePeerIdentity.address(),sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
 			return Membership::ADD_REJECTED;
 		case 0:
 			if (!rc)
@@ -206,7 +206,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
 	int64_t *rt;
 	switch(rev.verify(RR,tPtr)) {
 		default:
-			RR->t->credentialRejected(tPtr,0x938fffff,nconf.networkId,sourcePeerIdentity.address(),rev.id(),0,ZT_CREDENTIAL_TYPE_REVOCATION,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
+			RR->t->credentialRejected(tPtr,0x938fffff,nconf.networkId,sourcePeerIdentity.address(),sourcePeerIdentity,rev.id(),0,ZT_CREDENTIAL_TYPE_REVOCATION,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
 			return ADD_REJECTED;
 		case 0: {
 			const ZT_CredentialType ct = rev.typeBeingRevoked();
@@ -228,7 +228,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
 					}
 					return ADD_ACCEPTED_REDUNDANT;
 				default:
-					RR->t->credentialRejected(tPtr,0x0bbbb1a4,nconf.networkId,sourcePeerIdentity.address(),rev.id(),0,ZT_CREDENTIAL_TYPE_REVOCATION,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
+					RR->t->credentialRejected(tPtr,0x0bbbb1a4,nconf.networkId,sourcePeerIdentity.address(),sourcePeerIdentity,rev.id(),0,ZT_CREDENTIAL_TYPE_REVOCATION,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
 					return ADD_REJECTED;
 			}
 		}

+ 1 - 1
node/Network.cpp

@@ -1010,7 +1010,7 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD
 	try {
 		if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id))
 			return 0; // invalid config that is not for us or not for this network
-		if ((!Utils::allZero(nconf.issuedToIdentityHash,ZT_IDENTITY_HASH_SIZE))&&(memcmp(nconf.issuedToIdentityHash,RR->identity.fingerprint().data(),ZT_IDENTITY_HASH_SIZE) != 0))
+		if ((!Utils::allZero(nconf.issuedToFingerprintHash,ZT_IDENTITY_HASH_SIZE))&&(memcmp(nconf.issuedToFingerprintHash,RR->identity.fingerprint().hash(),ZT_IDENTITY_HASH_SIZE) != 0))
 			return 0; // full identity hash is present and does not match
 
 		if (_config == nconf)

+ 3 - 3
node/NetworkConfig.cpp

@@ -32,7 +32,7 @@ bool NetworkConfig::toDictionary(Dictionary &d,bool includeLegacy) const
 		d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,this->credentialTimeMaxDelta);
 		d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision);
 		d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo.toString((char *)tmp));
-		d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH,this->issuedToIdentityHash,ZT_IDENTITY_HASH_SIZE);
+		d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH,this->issuedToFingerprintHash,ZT_IDENTITY_HASH_SIZE);
 		d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags);
 		d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit);
 		d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint16_t)this->type);
@@ -122,9 +122,9 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
 		this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,0);
 		const std::vector<uint8_t> *blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH]);
 		if (blob->size() == ZT_IDENTITY_HASH_SIZE) {
-			memcpy(this->issuedToIdentityHash,blob->data(),ZT_IDENTITY_HASH_SIZE);
+			memcpy(this->issuedToFingerprintHash,blob->data(),ZT_IDENTITY_HASH_SIZE);
 		} else {
-			memset(this->issuedToIdentityHash,0,ZT_IDENTITY_HASH_SIZE);
+			memset(this->issuedToFingerprintHash,0,ZT_IDENTITY_HASH_SIZE);
 		}
 		if (!this->issuedTo)
 			return false;

+ 1 - 1
node/NetworkConfig.hpp

@@ -280,7 +280,7 @@ struct NetworkConfig : TriviallyCopyable
 	 * If this field is all zero it is treated as undefined since old controllers
 	 * do not set it.
 	 */
-	uint8_t issuedToIdentityHash[ZT_IDENTITY_HASH_SIZE];
+	uint8_t issuedToFingerprintHash[ZT_IDENTITY_HASH_SIZE];
 
 	/**
 	 * Flags (64-bit)

+ 4 - 2
node/Node.cpp

@@ -111,7 +111,10 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
 			stateObjectPut(tPtr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
 	}
 
-	RR->identity.hashWithPrivate(RR->localCacheSymmetricKey);
+	uint8_t tmph[ZT_IDENTITY_HASH_SIZE];
+	RR->identity.hashWithPrivate(tmph);
+	RR->localCacheSymmetric.init(tmph);
+	Utils::burn(tmph,sizeof(tmph));
 
 	// This constructs all the components of the ZeroTier core within a single contiguous memory container,
 	// which reduces memory fragmentation and may improve cache locality.
@@ -483,7 +486,6 @@ ZT_PeerList *Node::peers() const
 		p->address = (*pi)->address().toInt();
 		identities[pl->peerCount] = (*pi)->identity(); // need to make a copy in case peer gets deleted
 		p->identity = &identities[pl->peerCount];
-		memcpy(p->identityHash,(*pi)->identity().fingerprint().data(),ZT_IDENTITY_HASH_SIZE);
 		if ((*pi)->remoteVersionKnown()) {
 			p->versionMajor = (int)(*pi)->remoteVersionMajor();
 			p->versionMinor = (int)(*pi)->remoteVersionMinor();

+ 35 - 12
node/Peer.cpp

@@ -123,7 +123,7 @@ void Peer::received(
 			RR->t->learnedNewPath(tPtr,0x582fabdd,packetId,_id,path->address(),old);
 		} else {
 			if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,path->localSocket(),path->address())) {
-				RR->t->tryingNewPath(tPtr,0xb7747ddd,_id,path->address(),path->address(),packetId,(uint8_t)verb,_id.address(),_id.fingerprint().data(),ZT_TRACE_TRYING_NEW_PATH_REASON_PACKET_RECEIVED_FROM_UNKNOWN_PATH);
+				RR->t->tryingNewPath(tPtr,0xb7747ddd,_id,path->address(),path->address(),packetId,(uint8_t)verb,_id,ZT_TRACE_TRYING_NEW_PATH_REASON_PACKET_RECEIVED_FROM_UNKNOWN_PATH);
 				path->sent(now,sendHELLO(tPtr,path->localSocket(),path->address(),now));
 			}
 		}
@@ -135,11 +135,11 @@ path_check_done:
 
 		InetAddress addr;
 		if ((_bootstrap.type() == Endpoint::TYPE_INETADDR_V4)||(_bootstrap.type() == Endpoint::TYPE_INETADDR_V6)) {
-			RR->t->tryingNewPath(tPtr,0x0a009444,_id,_bootstrap.inetAddr(),InetAddress::NIL,0,0,0,nullptr,ZT_TRACE_TRYING_NEW_PATH_REASON_BOOTSTRAP_ADDRESS);
+			RR->t->tryingNewPath(tPtr,0x0a009444,_id,_bootstrap.inetAddr(),InetAddress::NIL,0,0,Identity::NIL,ZT_TRACE_TRYING_NEW_PATH_REASON_BOOTSTRAP_ADDRESS);
 			sendHELLO(tPtr,-1,_bootstrap.inetAddr(),now);
 		} if (RR->node->externalPathLookup(tPtr,_id,-1,addr)) {
 			if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,-1,addr)) {
-				RR->t->tryingNewPath(tPtr,0x84a10000,_id,_bootstrap.inetAddr(),InetAddress::NIL,0,0,0,nullptr,ZT_TRACE_TRYING_NEW_PATH_REASON_EXPLICITLY_SUGGESTED_ADDRESS);
+				RR->t->tryingNewPath(tPtr,0x84a10000,_id,_bootstrap.inetAddr(),InetAddress::NIL,0,0,Identity::NIL,ZT_TRACE_TRYING_NEW_PATH_REASON_EXPLICITLY_SUGGESTED_ADDRESS);
 				sendHELLO(tPtr,-1,addr,now);
 			}
 		}
@@ -485,14 +485,23 @@ void Peer::alarm(void *tPtr,const int64_t now)
 
 int Peer::marshal(uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept
 {
-	RWMutex::RLock l(_lock);
-
 	data[0] = 0; // serialized peer version
 
-	int s = _id.marshal(data + 1,false);
+	// For faster unmarshaling on large nodes the long-term secret key is cached. It's
+	// encrypted with a symmetric key derived from a hash of the local node's identity
+	// secrets, so the local node's address is also included. That way the unmarshal
+	// code can check this address and not use this cached key if the local identity has
+	// changed. In that case agreement must be executed again.
+	RR->identity.address().copyTo(data + 1);
+	RR->localCacheSymmetric.encrypt(_key,data + 6);
+	RR->localCacheSymmetric.encrypt(_key + 16,data + 22);
+
+	RWMutex::RLock l(_lock);
+
+	int s = _id.marshal(data + 38,false);
 	if (s <= 0)
 		return s;
-	int p = 1 + s;
+	int p = s + 38;
 	s = _locator.marshal(data + p);
 	if (s <= 0)
 		return s;
@@ -520,17 +529,26 @@ int Peer::marshal(uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept
 int Peer::unmarshal(const uint8_t *restrict data,const int len) noexcept
 {
 	int p;
+	bool mustRecomputeSecret;
 
 	{
 		RWMutex::Lock l(_lock);
 
-		if ((len <= 1) || (data[0] != 0))
+		if ((len <= 38) || (data[0] != 0))
 			return -1;
 
-		int s = _id.unmarshal(data + 1,len - 1);
+		if (Address(data + 1) == RR->identity.address()) {
+			RR->localCacheSymmetric.decrypt(data + 6,_key);
+			RR->localCacheSymmetric.decrypt(data + 22,_key + 16);
+			mustRecomputeSecret = false;
+		} else {
+			mustRecomputeSecret = true; // can't use cached key if local identity has changed
+		}
+
+		int s = _id.unmarshal(data + 38,len - 38);
 		if (s <= 0)
 			return s;
-		p = 1 + s;
+		p = s + 38;
 		s = _locator.unmarshal(data + p,len - p);
 		if (s <= 0)
 			return s;
@@ -542,6 +560,7 @@ int Peer::unmarshal(const uint8_t *restrict data,const int len) noexcept
 
 		if ((p + 10) > len)
 			return -1;
+
 		_vProto = Utils::loadBigEndian<uint16_t>(data + p);
 		p += 2;
 		_vMajor = Utils::loadBigEndian<uint16_t>(data + p);
@@ -551,12 +570,16 @@ int Peer::unmarshal(const uint8_t *restrict data,const int len) noexcept
 		_vRevision = Utils::loadBigEndian<uint16_t>(data + p);
 		p += 2;
 		p += 2 + (int)Utils::loadBigEndian<uint16_t>(data + p);
+
 		if (p > len)
 			return -1;
 	}
 
-	if (!RR->identity.agree(_id,_key))
-		return -1;
+	if (mustRecomputeSecret) {
+		if (!RR->identity.agree(_id,_key))
+			return -1;
+	}
+
 	_incomingProbe = Protocol::createProbe(_id,RR->identity,_key);
 
 	return p;

+ 1 - 1
node/Peer.hpp

@@ -33,7 +33,7 @@
 #include <list>
 
 // version, identity, locator, bootstrap, version info, length of any additional fields
-#define ZT_PEER_MARSHAL_SIZE_MAX (1 + ZT_IDENTITY_MARSHAL_SIZE_MAX + ZT_LOCATOR_MARSHAL_SIZE_MAX + ZT_INETADDRESS_MARSHAL_SIZE_MAX + (2*4) + 2)
+#define ZT_PEER_MARSHAL_SIZE_MAX (1 + ZT_ADDRESS_LENGTH + ZT_PEER_SECRET_KEY_LENGTH + ZT_IDENTITY_MARSHAL_SIZE_MAX + ZT_LOCATOR_MARSHAL_SIZE_MAX + ZT_INETADDRESS_MARSHAL_SIZE_MAX + (2*4) + 2)
 
 namespace ZeroTier {
 

+ 2 - 2
node/Protocol.cpp

@@ -33,8 +33,8 @@ std::atomic<uint64_t> _s_packetIdCtr((uint64_t)time(nullptr) << 32U);
 uint64_t createProbe(const Identity &sender,const Identity &recipient,const uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]) noexcept
 {
 	uint8_t tmp[ZT_IDENTITY_HASH_SIZE + ZT_IDENTITY_HASH_SIZE];
-	memcpy(tmp,sender.fingerprint().data(),ZT_IDENTITY_HASH_SIZE);
-	memcpy(tmp + ZT_IDENTITY_HASH_SIZE,recipient.fingerprint().data(),ZT_IDENTITY_HASH_SIZE);
+	memcpy(tmp,sender.fingerprint().hash(),ZT_IDENTITY_HASH_SIZE);
+	memcpy(tmp + ZT_IDENTITY_HASH_SIZE,recipient.fingerprint().hash(),ZT_IDENTITY_HASH_SIZE);
 	uint64_t hash[6];
 	SHA384(hash,tmp,sizeof(tmp),key,ZT_PEER_SECRET_KEY_LENGTH);
 	return hash[0];

+ 3 - 4
node/RuntimeEnvironment.hpp

@@ -17,6 +17,7 @@
 #include "Constants.hpp"
 #include "Utils.hpp"
 #include "Identity.hpp"
+#include "AES.hpp"
 
 namespace ZeroTier {
 
@@ -57,7 +58,6 @@ public:
 	ZT_ALWAYS_INLINE ~RuntimeEnvironment()
 	{
 		Utils::burn(secretIdentityStr,sizeof(secretIdentityStr));
-		Utils::burn(localCacheSymmetricKey,sizeof(localCacheSymmetricKey));
 	}
 
 	// Node instance that owns this RuntimeEnvironment
@@ -81,9 +81,8 @@ public:
 	char publicIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
 	char secretIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
 
-	// A hash of this node identity's public and private keys that is used as
-	// a secret key to encrypt locally cached sensitive information.
-	uint8_t localCacheSymmetricKey[ZT_IDENTITY_HASH_SIZE];
+	// AES keyed with a hash of this node's identity secret keys for local cache encryption at rest (where needed).
+	AES localCacheSymmetric;
 };
 
 } // namespace ZeroTier

+ 1 - 1
node/Tests.cpp

@@ -285,7 +285,7 @@ extern "C" const char *ZTT_general()
 			ZT_T_ASSERT(sizeof(sockaddr_in) <= sizeof(InetAddress));
 			ZT_T_ASSERT(sizeof(sockaddr_in6) <= sizeof(InetAddress));
 			ZT_T_ASSERT(sizeof(sockaddr) <= sizeof(InetAddress));
-			ZT_T_ASSERT(sizeof(Fingerprint) == 48);
+			ZT_T_ASSERT(sizeof(Fingerprint) == sizeof(ZT_Fingerprint));
 			ZT_T_PRINTF("OK" ZT_EOL_S);
 		}
 

+ 1 - 1
node/Topology.hpp

@@ -351,7 +351,7 @@ private:
 #endif
 			return h + (uint64_t)Utils::ntoh(reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port) + (uint64_t)l;
 		} else {
-			return Utils::hashString(reinterpret_cast<const void *>(&r),sizeof(InetAddress)) + (uint64_t)l;
+			return Utils::fnv1a32(reinterpret_cast<const void *>(&r),sizeof(InetAddress)) + (uint64_t)l;
 		}
 	}
 

+ 13 - 19
node/Trace.cpp

@@ -109,24 +109,19 @@ void Trace::_tryingNewPath(
 	const InetAddress &triggerAddress,
 	const uint64_t triggeringPacketId,
 	const uint8_t triggeringPacketVerb,
-	const uint64_t triggeredByAddress,
-	const uint8_t *triggeredByIdentityHash,
+	const Identity &triggeringPeer,
 	const ZT_TraceTryingNewPathReason reason)
 {
 	ZT_TraceEvent_VL1_TRYING_NEW_PATH ev;
 	ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
 	ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL1_TRYING_NEW_PATH);
 	ev.codeLocation = Utils::hton(codeLocation);
-	ev.address = Utils::hton(trying.address().toInt());
-	memcpy(ev.identityHash,trying.fingerprint().data(),48);
+	trying.fingerprint().setZTFingerprint(&ev.peer);
 	physicalAddress.forTrace(ev.physicalAddress);
 	triggerAddress.forTrace(ev.triggerAddress);
 	ev.triggeringPacketId = triggeringPacketId;
 	ev.triggeringPacketVerb = triggeringPacketVerb;
-	ev.triggeredByAddress = Utils::hton(triggeredByAddress);
-	if (triggeredByIdentityHash)
-		memcpy(ev.triggeredByIdentityHash,triggeredByIdentityHash,ZT_IDENTITY_HASH_SIZE);
-	else memset(ev.triggeredByIdentityHash,0,ZT_IDENTITY_HASH_SIZE);
+	triggeringPeer.fingerprint().setZTFingerprint(&ev.triggeringPeer);
 	ev.reason = (uint8_t)reason;
 	RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
 }
@@ -144,8 +139,7 @@ void Trace::_learnedNewPath(
 	ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL1_LEARNED_NEW_PATH);
 	ev.codeLocation = Utils::hton(codeLocation);
 	ev.packetId = packetId; // packet IDs are kept in big-endian
-	ev.address = Utils::hton(peerIdentity.address().toInt());
-	memcpy(ev.identityHash,peerIdentity.fingerprint().data(),ZT_IDENTITY_HASH_SIZE);
+	peerIdentity.fingerprint().setZTFingerprint(&ev.peer);
 	physicalAddress.forTrace(ev.physicalAddress);
 	replaced.forTrace(ev.replaced);
 
@@ -169,13 +163,7 @@ void Trace::_incomingPacketDropped(
 	ev.codeLocation = Utils::hton(codeLocation);
 	ev.packetId = packetId; // packet IDs are kept in big-endian
 	ev.networkId = Utils::hton(networkId);
-	if (peerIdentity) {
-		ev.address = Utils::hton(peerIdentity.address().toInt());
-		memcpy(ev.identityHash,peerIdentity.fingerprint().data(),ZT_IDENTITY_HASH_SIZE);
-	} else {
-		ev.address = 0;
-		memset(ev.identityHash,0,ZT_IDENTITY_HASH_SIZE);
-	}
+	peerIdentity.fingerprint().setZTFingerprint(&ev.peer);
 	physicalAddress.forTrace(ev.physicalAddress);
 	ev.hops = hops;
 	ev.verb = verb;
@@ -238,7 +226,7 @@ void Trace::_incomingNetworkFrameDropped(
 	ev.networkId = Utils::hton(networkId);
 	ev.sourceMac = Utils::hton(sourceMac.toInt());
 	ev.destMac = Utils::hton(destMac.toInt());
-	ev.address = Utils::hton(peerIdentity.address().toInt());
+	peerIdentity.fingerprint().setZTFingerprint(&ev.sender);
 	physicalAddress.forTrace(ev.physicalAddress);
 	ev.hops = hops;
 	ev.frameLength = Utils::hton(frameLength);
@@ -325,6 +313,7 @@ void Trace::_credentialRejected(
 	const uint32_t codeLocation,
 	const uint64_t networkId,
 	const Address &address,
+	const Identity &identity,
 	const uint32_t credentialId,
 	const int64_t credentialTimestamp,
 	const uint8_t credentialType,
@@ -335,7 +324,12 @@ void Trace::_credentialRejected(
 	ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_FILTER);
 	ev.codeLocation = Utils::hton(codeLocation);
 	ev.networkId = Utils::hton(networkId);
-	ev.address = Utils::hton(address.toInt());
+	if (identity) {
+		identity.fingerprint().setZTFingerprint(&ev.peer);
+	} else {
+		ev.peer.address = address.toInt();
+		memset(ev.peer.hash,0,sizeof(ev.peer.hash));
+	}
 	ev.credentialId = Utils::hton(credentialId);
 	ev.credentialTimestamp = Utils::hton(credentialTimestamp);
 	ev.credentialType = credentialType;

+ 6 - 6
node/Trace.hpp

@@ -119,11 +119,10 @@ public:
 		const InetAddress &triggerAddress,
 		uint64_t triggeringPacketId,
 		uint8_t triggeringPacketVerb,
-		uint64_t triggeredByAddress,
-		const uint8_t *triggeredByIdentityHash,
+		const Identity &triggeringPeer,
 		ZT_TraceTryingNewPathReason reason)
 	{
-		if (_vl1) _tryingNewPath(tPtr,codeLocation,trying,physicalAddress,triggerAddress,triggeringPacketId,triggeringPacketVerb,triggeredByAddress,triggeredByIdentityHash,reason);
+		if (_vl1) _tryingNewPath(tPtr,codeLocation,trying,physicalAddress,triggerAddress,triggeringPacketId,triggeringPacketVerb,triggeringPeer,reason);
 	}
 
 	ZT_ALWAYS_INLINE void learnedNewPath(
@@ -239,12 +238,13 @@ public:
 		const uint32_t codeLocation,
 		uint64_t networkId,
 		const Address &address,
+		const Identity &identity,
 		uint32_t credentialId,
 		int64_t credentialTimestamp,
 		uint8_t credentialType,
 		ZT_TraceCredentialRejectionReason reason)
 	{
-		if (_vl2) _credentialRejected(tPtr,codeLocation,networkId,address,credentialId,credentialTimestamp,credentialType,reason);
+		if (_vl2) _credentialRejected(tPtr,codeLocation,networkId,address,identity,credentialId,credentialTimestamp,credentialType,reason);
 	}
 
 private:
@@ -264,8 +264,7 @@ private:
 		const InetAddress &triggerAddress,
 		uint64_t triggeringPacketId,
 		uint8_t triggeringPacketVerb,
-		uint64_t triggeredByAddress,
-		const uint8_t *triggeredByIdentityHash,
+		const Identity &triggeringPeer,
 		ZT_TraceTryingNewPathReason reason);
 	void _learnedNewPath(
 		void *tPtr,
@@ -336,6 +335,7 @@ private:
 		uint32_t codeLocation,
 		uint64_t networkId,
 		const Address &address,
+		const Identity &identity,
 		uint32_t credentialId,
 		int64_t credentialTimestamp,
 		uint8_t credentialType,

+ 11 - 15
node/Utils.hpp

@@ -258,24 +258,20 @@ static ZT_ALWAYS_INLINE unsigned long long hexStrToU64(const char *s) noexcept
 }
 
 /**
- * Calculate a non-cryptographic hash of a byte string
+ * Compute 32-bit FNV-1a checksum
  *
- * @param key Key to hash
- * @param len Length in bytes
- * @return Non-cryptographic hash suitable for use in a hash table
+ * See: http://www.isthe.com/chongo/tech/comp/fnv/
+ *
+ * @param data Data to checksum
+ * @param len Length of data
+ * @return FNV1a checksum
  */
-static ZT_ALWAYS_INLINE unsigned long hashString(const void *restrict key,const unsigned int len) noexcept
+static ZT_ALWAYS_INLINE uint32_t fnv1a32(const void *const data,const unsigned int len) noexcept
 {
-	const uint8_t *p = reinterpret_cast<const uint8_t *>(key);
-	unsigned long h = 0;
-	for (unsigned int i=0;i<len;++i) {
-		h += p[i];
-		h += (h << 10U);
-		h ^= (h >> 6U);
-	}
-	h += (h << 3U);
-	h ^= (h >> 11U);
-	h += (h << 15U);
+	uint32_t h = 0x811c9dc5;
+	const uint32_t p = 0x01000193;
+	for(unsigned int i=0;i<len;++i)
+		h = (h ^ (uint32_t)reinterpret_cast<const uint8_t *>(data)[i]) * p;
 	return h;
 }
 

+ 3 - 3
node/VL1.cpp

@@ -823,7 +823,7 @@ bool VL1::_RENDEZVOUS(void *tPtr,const SharedPtr<Path> &path,const SharedPtr<Pee
 						if ((sizeof(Protocol::RENDEZVOUS) + rdv.addressLength) <= packetSize) {
 							const InetAddress atAddr(pkt.unsafeData + sizeof(Protocol::RENDEZVOUS),rdv.addressLength,port);
 							peer->contact(tPtr,Endpoint(atAddr),now,false);
-							RR->t->tryingNewPath(tPtr,0x55a19aaa,with->identity(),atAddr,path->address(),Protocol::packetId(pkt,packetSize),Protocol::VERB_RENDEZVOUS,peer->address(),peer->identity().fingerprint().data(),ZT_TRACE_TRYING_NEW_PATH_REASON_RENDEZVOUS);
+							RR->t->tryingNewPath(tPtr,0x55a19aaa,with->identity(),atAddr,path->address(),Protocol::packetId(pkt,packetSize),Protocol::VERB_RENDEZVOUS,peer->identity(),ZT_TRACE_TRYING_NEW_PATH_REASON_RENDEZVOUS);
 						}
 						break;
 					case 255: {
@@ -835,7 +835,7 @@ bool VL1::_RENDEZVOUS(void *tPtr,const SharedPtr<Path> &path,const SharedPtr<Pee
 								case Endpoint::TYPE_INETADDR_V4:
 								case Endpoint::TYPE_INETADDR_V6:
 									peer->contact(tPtr,ep,now,false);
-									RR->t->tryingNewPath(tPtr,0x55a19aab,with->identity(),ep.inetAddr(),path->address(),Protocol::packetId(pkt,packetSize),Protocol::VERB_RENDEZVOUS,peer->address(),peer->identity().fingerprint().data(),ZT_TRACE_TRYING_NEW_PATH_REASON_RENDEZVOUS);
+									RR->t->tryingNewPath(tPtr,0x55a19aab,with->identity(),ep.inetAddr(),path->address(),Protocol::packetId(pkt,packetSize),Protocol::VERB_RENDEZVOUS,peer->identity(),ZT_TRACE_TRYING_NEW_PATH_REASON_RENDEZVOUS);
 									break;
 								default:
 									break;
@@ -969,7 +969,7 @@ bool VL1::_PUSH_DIRECT_PATHS(void *tPtr,const SharedPtr<Path> &path,const Shared
 		}
 
 		if (a) {
-			RR->t->tryingNewPath(tPtr,0xa5ab1a43,peer->identity(),a,path->address(),Protocol::packetId(pkt,packetSize),Protocol::VERB_RENDEZVOUS,peer->address(),peer->identity().fingerprint().data(),ZT_TRACE_TRYING_NEW_PATH_REASON_RECEIVED_PUSH_DIRECT_PATHS);
+			RR->t->tryingNewPath(tPtr,0xa5ab1a43,peer->identity(),a,path->address(),Protocol::packetId(pkt,packetSize),Protocol::VERB_RENDEZVOUS,peer->identity(),ZT_TRACE_TRYING_NEW_PATH_REASON_RECEIVED_PUSH_DIRECT_PATHS);
 		}
 
 		ptr += (int)addrRecordLen;