Don't force-insert a node with unknown relationships just because they are the marked recipient of a DM. Closes #44.

This commit is contained in:
Jack Kingsman
2026-03-12 14:30:26 -07:00
parent 3ee4f9d7a2
commit 07934093e6
3 changed files with 89 additions and 17 deletions
@@ -593,20 +593,8 @@ export function buildCanonicalPathForPacket(
if (parsed.payloadType === PayloadType.TextMessage && parsed.dstHash) {
if (context.myPrefix && parsed.dstHash.toLowerCase() === context.myPrefix) {
path.push('self');
} else {
const nodeId = resolveNode(
state,
context,
{ type: 'prefix', value: parsed.dstHash },
false,
true,
activityAtMs
);
if (nodeId) {
path.push(nodeId);
} else if (!isOutgoingDm) {
path.push('self');
}
} else if (!isOutgoingDm && path.length > 0) {
path.push('self');
}
} else if (path.length > 0) {
path.push('self');
@@ -181,6 +181,53 @@ describe('packetNetworkGraph', () => {
expect(projection.links.get('565656565656->self')?.hasDirectObservation).toBe(true);
});
it('does not add a DM recipient node from destination metadata alone', () => {
const selfKey = 'ffffffffffff0000000000000000000000000000000000000000000000000000';
const aliceKey = 'aaaaaaaaaaaa0000000000000000000000000000000000000000000000000000';
const bobKey = 'bbbbbbbbbbbb0000000000000000000000000000000000000000000000000000';
const repeaterKey = '5656565656560000000000000000000000000000000000000000000000000000';
packetFixtures.set('dm-third-party-no-dst-node', {
payloadType: PayloadType.TextMessage,
messageHash: 'dm-third-party-no-dst-node',
pathBytes: ['565656565656'],
srcHash: 'aaaaaaaaaaaa',
dstHash: 'bbbbbbbbbbbb',
advertPubkey: null,
groupTextSender: null,
anonRequestPubkey: null,
});
const state = createPacketNetworkState('Me');
const context = buildPacketNetworkContext({
contacts: [
createContact(aliceKey, 'Alice'),
createContact(bobKey, 'Bob'),
createContact(repeaterKey, 'Relay', CONTACT_TYPE_REPEATER),
],
config: createConfig(selfKey),
repeaterAdvertPaths: [],
splitAmbiguousByTraffic: false,
useAdvertPathHints: false,
});
const ingested = ingestPacketIntoPacketNetwork(
state,
context,
createPacket('dm-third-party-no-dst-node')
);
expect(ingested?.canonicalPath).toEqual(['aaaaaaaaaaaa', '565656565656', 'self']);
expect(state.nodes.has('bbbbbbbbbbbb')).toBe(false);
expect(snapshotNeighborIds(state)).toEqual(
new Map([
['565656565656', ['aaaaaaaaaaaa', 'self']],
['aaaaaaaaaaaa', ['565656565656']],
['self', ['565656565656']],
])
);
});
it('replays real advert packets through the semantic layer', () => {
const state = createPacketNetworkState('Me');
const context = buildPacketNetworkContext({
+40 -3
View File
@@ -200,7 +200,7 @@ describe('useVisualizerData3D', () => {
expect(result.current.renderedNodeIds.has('?32')).toBe(false);
});
it('does not append self after a resolved outgoing DM destination', async () => {
it('does not place a resolved outgoing DM destination into topology', async () => {
const selfKey = 'ffffffffffff0000000000000000000000000000000000000000000000000000';
const bobKey = 'bbbbbbbbbbbb0000000000000000000000000000000000000000000000000000';
const repeaterKey = '3232323232320000000000000000000000000000000000000000000000000000';
@@ -226,11 +226,48 @@ describe('useVisualizerData3D', () => {
showAmbiguousPaths: true,
});
await waitFor(() => expect(result.current.links.size).toBe(2));
await waitFor(() => expect(result.current.links.size).toBe(1));
expect(result.current.links.has(buildLinkKey('self', '323232323232'))).toBe(true);
expect(result.current.links.has(buildLinkKey('323232323232', 'bbbbbbbbbbbb'))).toBe(true);
expect(result.current.links.has(buildLinkKey('323232323232', 'bbbbbbbbbbbb'))).toBe(false);
expect(result.current.links.has(buildLinkKey('self', 'bbbbbbbbbbbb'))).toBe(false);
expect(result.current.renderedNodeIds.has('bbbbbbbbbbbb')).toBe(false);
});
it('does not place a third-party DM destination into topology', async () => {
const selfKey = 'ffffffffffff0000000000000000000000000000000000000000000000000000';
const aliceKey = 'aaaaaaaaaaaa0000000000000000000000000000000000000000000000000000';
const bobKey = 'bbbbbbbbbbbb0000000000000000000000000000000000000000000000000000';
const repeaterKey = '3232323232320000000000000000000000000000000000000000000000000000';
packetFixtures.set('dm-third-party-known-dst', {
payloadType: PayloadType.TextMessage,
messageHash: 'dm-third-party-known-dst',
pathBytes: ['323232323232'],
srcHash: 'aaaaaaaaaaaa',
dstHash: 'bbbbbbbbbbbb',
advertPubkey: null,
groupTextSender: null,
anonRequestPubkey: null,
});
const { result } = renderVisualizerData({
packets: [createPacket('dm-third-party-known-dst')],
contacts: [
createContact(aliceKey, 'Alice'),
createContact(bobKey, 'Bob'),
createContact(repeaterKey, 'Relay', CONTACT_TYPE_REPEATER),
],
config: createConfig(selfKey),
showAmbiguousPaths: true,
});
await waitFor(() => expect(result.current.links.size).toBe(2));
expect(result.current.links.has(buildLinkKey('aaaaaaaaaaaa', '323232323232'))).toBe(true);
expect(result.current.links.has(buildLinkKey('323232323232', 'self'))).toBe(true);
expect(result.current.links.has(buildLinkKey('323232323232', 'bbbbbbbbbbbb'))).toBe(false);
expect(result.current.renderedNodeIds.has('bbbbbbbbbbbb')).toBe(false);
});
it('collapses a high-confidence ambiguous repeater into its known sibling when both share the same next hop', async () => {