From 9fbb9956dd9aa14d5999bac994e4dbbc60cc9b4b Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Wed, 30 Aug 2023 20:04:41 -0700 Subject: [PATCH 1/3] fix: topic non-determinism --- src/keystore/InMemoryKeystore.ts | 9 +++---- test/keystore/InMemoryKeystore.test.ts | 34 +++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/keystore/InMemoryKeystore.ts b/src/keystore/InMemoryKeystore.ts index 0407930e..4b6a5cc9 100644 --- a/src/keystore/InMemoryKeystore.ts +++ b/src/keystore/InMemoryKeystore.ts @@ -273,17 +273,16 @@ export default class InMemoryKeystore implements Keystore { } const created = nsToDate(req.createdNs) const recipient = toSignedPublicKeyBundle(req.recipient) + const myAddress = await this.getAccountAddress() + const theirAddress = await recipient.walletSignatureAddress() const secret = await this.v2Keys.sharedSecret( recipient, this.v2Keys.getCurrentPreKey().publicKey, - false + myAddress > theirAddress ) - const sortedAddresses = [ - this.accountAddress, - await recipient.walletSignatureAddress(), - ].sort() + const sortedAddresses = [myAddress, theirAddress].sort() const msgString = (req.context?.conversationId || '') + sortedAddresses.join() diff --git a/test/keystore/InMemoryKeystore.test.ts b/test/keystore/InMemoryKeystore.test.ts index 5d296f33..e93a2461 100644 --- a/test/keystore/InMemoryKeystore.test.ts +++ b/test/keystore/InMemoryKeystore.test.ts @@ -616,7 +616,39 @@ describe('InMemoryKeystore', () => { ).toHaveLength(25) }) - it('works with persistence', async () => {}) + it('creates deterministic topics bidirectionally', async () => { + const aliceInvite = await aliceKeystore.createInvite({ + recipient: SignedPublicKeyBundle.fromLegacyBundle( + bobKeys.getPublicKeyBundle() + ), + createdNs: dateToNs(new Date()), + context: undefined, + }) + const bobInvite = await bobKeystore.createInvite({ + recipient: SignedPublicKeyBundle.fromLegacyBundle( + aliceKeys.getPublicKeyBundle() + ), + createdNs: dateToNs(new Date()), + context: undefined, + }) + expect( + await aliceKeys.sharedSecret( + bobKeys.getPublicKeyBundle(), + aliceKeys.getCurrentPreKey().publicKey, + false + ) + ).toEqual( + await bobKeys.sharedSecret( + aliceKeys.getPublicKeyBundle(), + bobKeys.getCurrentPreKey().publicKey, + true + ) + ) + + expect(aliceInvite.conversation!.topic).toEqual( + bobInvite.conversation!.topic + ) + }) }) describe('createAuthToken', () => { From 4785676903f01574b3e6e20cde9835d0eb746db4 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 31 Aug 2023 13:59:55 -0700 Subject: [PATCH 2/3] fix: switch the direction of the comparison --- src/keystore/InMemoryKeystore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keystore/InMemoryKeystore.ts b/src/keystore/InMemoryKeystore.ts index 4b6a5cc9..dc6244a4 100644 --- a/src/keystore/InMemoryKeystore.ts +++ b/src/keystore/InMemoryKeystore.ts @@ -279,7 +279,7 @@ export default class InMemoryKeystore implements Keystore { const secret = await this.v2Keys.sharedSecret( recipient, this.v2Keys.getCurrentPreKey().publicKey, - myAddress > theirAddress + myAddress < theirAddress ) const sortedAddresses = [myAddress, theirAddress].sort() From d0863cf90400c883890abc378809bb613794dd30 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Thu, 31 Aug 2023 16:40:33 -0500 Subject: [PATCH 3/3] test: add test for non-deterministic topic --- test/keystore/InMemoryKeystore.test.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/test/keystore/InMemoryKeystore.test.ts b/test/keystore/InMemoryKeystore.test.ts index e93a2461..a0a2da80 100644 --- a/test/keystore/InMemoryKeystore.test.ts +++ b/test/keystore/InMemoryKeystore.test.ts @@ -554,13 +554,15 @@ describe('InMemoryKeystore', () => { ) ).v1! ) + bobKeystore = await InMemoryKeystore.create(bobKeys) + expect(await aliceKeystore.getAccountAddress()).toEqual( '0xF56d1F3b1290204441Cb3843C2Cac1C2f5AEd690' ) // alice expect(bobKeys.getPublicKeyBundle().walletSignatureAddress()).toEqual( '0x3De402A325323Bb97f00cE3ad5bFAc96A11F9A34' ) // bob - const response = await aliceKeystore.createInvite({ + const aliceInvite = await aliceKeystore.createInvite({ recipient: SignedPublicKeyBundle.fromLegacyBundle( bobKeys.getPublicKeyBundle() ), @@ -570,7 +572,21 @@ describe('InMemoryKeystore', () => { metadata: {}, }, }) - expect(response.conversation!.topic).toEqual( + expect(aliceInvite.conversation!.topic).toEqual( + '/xmtp/0/m-4b52be1e8567d72d0bc407debe2d3c7fca2ae93a47e58c3f9b5c5068aff80ec5/proto' + ) + + const bobInvite = await bobKeystore.createInvite({ + recipient: SignedPublicKeyBundle.fromLegacyBundle( + aliceKeys.getPublicKeyBundle() + ), + createdNs: dateToNs(new Date()), + context: { + conversationId: 'test', + metadata: {}, + }, + }) + expect(bobInvite.conversation!.topic).toEqual( '/xmtp/0/m-4b52be1e8567d72d0bc407debe2d3c7fca2ae93a47e58c3f9b5c5068aff80ec5/proto' ) })