diff --git a/lib/algorithm.js b/lib/algorithm.js index 093e136..60de317 100644 --- a/lib/algorithm.js +++ b/lib/algorithm.js @@ -1,5 +1,5 @@ const { BloomFilter } = require('bloom-filters') -const MsgV2 = require('ppppp-db/msg-v2') +const MsgV3 = require('ppppp-db/msg-v3') const p = require('util').promisify const { isEmptyRange, estimateMsgCount } = require('./range') const { parseGoal } = require('./goal') @@ -105,7 +105,7 @@ class Algorithm { const filter = BloomFilter.create(2 * filterSize, 0.00001) if (!isEmptyRange(range)) { for (const msg of this.yieldMsgsIn(rootMsgHash, range)) { - filter.add('' + round + MsgV2.getMsgHash(msg)) + filter.add('' + round + MsgV3.getMsgHash(msg)) } } for (const msgId of extraIds) { @@ -119,7 +119,7 @@ class Algorithm { const remoteFilter = BloomFilter.fromJSON(remoteBloomJSON) const missing = [] for (const msg of this.yieldMsgsIn(rootMsgHash, range)) { - const msgHash = MsgV2.getMsgHash(msg) + const msgHash = MsgV3.getMsgHash(msg) if (!remoteFilter.has('' + round + msgHash)) { missing.push(msgHash) } @@ -166,7 +166,7 @@ class Algorithm { const validNewMsgs = newMsgs .filter((msg) => { const depth = msg.metadata.tangles[rootMsgHash]?.depth ?? 0 - if (depth === 0 && MsgV2.getMsgHash(msg) !== rootMsgHash) { + if (depth === 0 && MsgV3.getMsgHash(msg) !== rootMsgHash) { return false // the rootMsg is the only acceptable depth-zero msg } if (!msg.data) { diff --git a/lib/index.js b/lib/index.js index 43853b0..998ceb6 100644 --- a/lib/index.js +++ b/lib/index.js @@ -36,13 +36,14 @@ module.exports = { function createStream(remoteId, iamClient) { // prettier-ignore debug('Opening a stream with remote %s %s', iamClient ? 'server' : 'client', remoteId) - const stream = new SyncStream(peer.id, debug, goals, algo) + const stream = new SyncStream(peer.pubkey, debug, goals, algo) streams.push(stream) return stream } peer.on('rpc:connect', function onSyncRPCConnect(rpc, iamClient) { - if (rpc.id === peer.id) return // local client connecting to local server + // TODO: eliminate SSB base64 `.id`, use SHSE `.pubkey` instead + if (rpc.id === peer.pubkey) return // local client connecting to local server if (!iamClient) return const local = toPull.duplex(createStream(rpc.id, true)) diff --git a/package.json b/package.json index 584351f..915af86 100644 --- a/package.json +++ b/package.json @@ -36,15 +36,14 @@ "bs58": "^5.0.0", "c8": "7", "ppppp-db": "github:staltz/ppppp-db", + "ppppp-caps": "github:staltz/ppppp-caps", + "ppppp-keypair": "github:staltz/ppppp-keypair", "prettier": "^2.6.2", "pretty-quick": "^3.1.3", "rimraf": "^4.4.0", "secret-stack": "^6.4.1", + "secret-handshake-ext": "^0.0.7", "ssb-box": "^1.0.1", - "ssb-caps": "^1.1.0", - "ssb-classic": "^1.1.0", - "ssb-keys": "^8.5.0", - "ssb-uri2": "^2.4.1", "tap-arc": "^0.3.5", "tape": "^5.6.3" }, diff --git a/test/feed-sync.test.js b/test/feed-sync.test.js index 5247fe2..b5a9ba5 100644 --- a/test/feed-sync.test.js +++ b/test/feed-sync.test.js @@ -1,70 +1,41 @@ const test = require('tape') -const path = require('path') -const os = require('os') -const rimraf = require('rimraf') -const SecretStack = require('secret-stack') -const caps = require('ssb-caps') -const p = require('util').promisify +const p = require('node:util').promisify +const Keypair = require('ppppp-keypair') const Algorithm = require('../lib/algorithm') -const { generateKeypair } = require('./util') +const { createPeer } = require('./util') -const createPeer = SecretStack({ appKey: caps.shs }) - .use(require('ppppp-db')) - .use(require('ssb-box')) - .use(require('../lib')) - -const ALICE_DIR = path.join(os.tmpdir(), 'dagsync-alice') -const BOB_DIR = path.join(os.tmpdir(), 'dagsync-bob') -const aliceKeys = generateKeypair('alice') -const bobKeys = generateKeypair('bob') +const carolKeypair = Keypair.generate('ed25519', 'carol') test('sync a feed with goal=all', async (t) => { - rimraf.sync(ALICE_DIR) - rimraf.sync(BOB_DIR) - - const alice = createPeer({ - keys: aliceKeys, - path: ALICE_DIR, - }) - - const bob = createPeer({ - keys: bobKeys, - path: BOB_DIR, - }) + const alice = createPeer({ name: 'alice' }) + const bob = createPeer({ name: 'bob' }) await alice.db.loaded() - const aliceGroupRec0 = await p(alice.db.group.create)({ _nonce: 'alice' }) - const aliceId = aliceGroupRec0.hash - await p(alice.db.add)(aliceGroupRec0.msg, aliceId) - await bob.db.loaded() - const bobGroupRec0 = await p(bob.db.group.create)({ _nonce: 'bob' }) - const bobId = bobGroupRec0.hash - await p(bob.db.add)(bobGroupRec0.msg, bobId) - const carolKeys = generateKeypair('carol') - const carolGroupRec0 = await p(alice.db.group.create)({ - keys: carolKeys, + const carolID = await p(alice.db.identity.create)({ + keypair: carolKeypair, + domain: 'account', _nonce: 'carol', }) - const carolId = carolGroupRec0.hash + const carolIDMsg = alice.db.get(carolID) - // Bob knows Alice - await p(bob.db.add)(carolGroupRec0.msg, carolId) + // Bob knows Carol + await p(bob.db.add)(carolIDMsg, carolID) const carolMsgs = [] for (let i = 1; i <= 10; i++) { const rec = await p(alice.db.feed.publish)({ - group: carolId, - type: 'post', + identity: carolID, + domain: 'post', data: { text: 'm' + i }, - keys: carolKeys, + keypair: carolKeypair, }) carolMsgs.push(rec.msg) } t.pass('alice has msgs 1..10 from carol') - const carolPostsRootHash = alice.db.feed.getId(carolId, 'post') + const carolPostsRootHash = alice.db.feed.getId(carolID, 'post') const carolPostsRootMsg = alice.db.get(carolPostsRootHash) await p(bob.db.add)(carolPostsRootMsg, carolPostsRootHash) @@ -74,7 +45,7 @@ test('sync a feed with goal=all', async (t) => { { const arr = [...bob.db.msgs()] - .filter((msg) => msg.metadata.group === carolId && msg.data) + .filter((msg) => msg.metadata.identity === carolID && msg.data) .map((msg) => msg.data.text) t.deepEquals( arr, @@ -95,7 +66,7 @@ test('sync a feed with goal=all', async (t) => { { const arr = [...bob.db.msgs()] - .filter((msg) => msg.metadata.group === carolId && msg.data) + .filter((msg) => msg.metadata.identity === carolID && msg.data) .map((msg) => msg.data.text) t.deepEquals( arr, @@ -110,52 +81,35 @@ test('sync a feed with goal=all', async (t) => { }) test('sync a feed with goal=newest', async (t) => { - rimraf.sync(ALICE_DIR) - rimraf.sync(BOB_DIR) - - const alice = createPeer({ - keys: aliceKeys, - path: ALICE_DIR, - }) - - const bob = createPeer({ - keys: bobKeys, - path: BOB_DIR, - }) + const alice = createPeer({ name: 'alice' }) + const bob = createPeer({ name: 'bob' }) await alice.db.loaded() - const aliceGroupRec0 = await p(alice.db.group.create)({ _nonce: 'alice' }) - const aliceId = aliceGroupRec0.hash - await p(alice.db.add)(aliceGroupRec0.msg, aliceId) - await bob.db.loaded() - const bobGroupRec0 = await p(bob.db.group.create)({ _nonce: 'bob' }) - const bobId = bobGroupRec0.hash - await p(bob.db.add)(bobGroupRec0.msg, bobId) - const carolKeys = generateKeypair('carol') - const carolGroupRec0 = await p(alice.db.group.create)({ - keys: carolKeys, + const carolID = await p(alice.db.identity.create)({ + keypair: carolKeypair, + domain: 'account', _nonce: 'carol', }) - const carolId = carolGroupRec0.hash + const carolIDMsg = alice.db.get(carolID) - // Bob knows Alice - await p(bob.db.add)(carolGroupRec0.msg, carolId) + // Bob knows Carol + await p(bob.db.add)(carolIDMsg, carolID) const carolMsgs = [] for (let i = 1; i <= 10; i++) { const rec = await p(alice.db.feed.publish)({ - group: carolId, - type: 'post', + identity: carolID, + domain: 'post', data: { text: 'm' + i }, - keys: carolKeys, + keypair: carolKeypair, }) carolMsgs.push(rec.msg) } t.pass('alice has msgs 1..10 from carol') - const carolPostsRootHash = alice.db.feed.getId(carolId, 'post') + const carolPostsRootHash = alice.db.feed.getId(carolID, 'post') const carolPostsRootMsg = alice.db.get(carolPostsRootHash) await p(bob.db.add)(carolPostsRootMsg, carolPostsRootHash) @@ -165,7 +119,7 @@ test('sync a feed with goal=newest', async (t) => { { const arr = [...bob.db.msgs()] - .filter((msg) => msg.metadata.group === carolId && msg.data) + .filter((msg) => msg.metadata.identity === carolID && msg.data) .map((msg) => msg.data.text) t.deepEquals( arr, @@ -186,7 +140,7 @@ test('sync a feed with goal=newest', async (t) => { { const arr = [...bob.db.msgs()] - .filter((msg) => msg.metadata.group === carolId && msg.data) + .filter((msg) => msg.metadata.identity === carolID && msg.data) .map((msg) => msg.data.text) t.deepEquals( arr, @@ -201,58 +155,41 @@ test('sync a feed with goal=newest', async (t) => { }) test('sync a feed with goal=newest but too far behind', async (t) => { - rimraf.sync(ALICE_DIR) - rimraf.sync(BOB_DIR) - - const alice = createPeer({ - keys: aliceKeys, - path: ALICE_DIR, - }) - - const bob = createPeer({ - keys: bobKeys, - path: BOB_DIR, - }) + const alice = createPeer({ name: 'alice' }) + const bob = createPeer({ name: 'bob' }) await alice.db.loaded() - const aliceGroupRec0 = await p(alice.db.group.create)({ _nonce: 'alice' }) - const aliceId = aliceGroupRec0.hash - await p(alice.db.add)(aliceGroupRec0.msg, aliceId) - await bob.db.loaded() - const bobGroupRec0 = await p(bob.db.group.create)({ _nonce: 'bob' }) - const bobId = bobGroupRec0.hash - await p(bob.db.add)(bobGroupRec0.msg, bobId) - const carolKeys = generateKeypair('carol') - const carolGroupRec0 = await p(alice.db.group.create)({ - keys: carolKeys, + const carolID = await p(alice.db.identity.create)({ + keypair: carolKeypair, + domain: 'account', _nonce: 'carol', }) - const carolId = carolGroupRec0.hash + const carolIDMsg = alice.db.get(carolID) - // Bob knows Alice - await p(bob.db.add)(carolGroupRec0.msg, carolId) + // Bob knows Carol + await p(bob.db.add)(carolIDMsg, carolID) const carolMsgs = [] for (let i = 1; i <= 10; i++) { const rec = await p(alice.db.feed.publish)({ - group: carolId, - type: 'post', + identity: carolID, + domain: 'post', data: { text: 'm' + i }, - keys: carolKeys, + keypair: carolKeypair, }) carolMsgs.push(rec.msg) } - const carolPostsRootHash = alice.db.feed.getId(carolId, 'post') + const carolPostsRootHash = alice.db.feed.getId(carolID, 'post') const carolPostsRootMsg = alice.db.get(carolPostsRootHash) const algo = new Algorithm(alice) await algo.pruneNewest(carolPostsRootHash, 5) { const arr = [...alice.db.msgs()] - .filter((msg) => msg.metadata.group === carolId && msg.data) + .filter((msg) => msg.metadata.identity === carolID && msg.data) .map((msg) => msg.data.text) t.deepEquals( arr, @@ -268,7 +205,7 @@ test('sync a feed with goal=newest but too far behind', async (t) => { { const arr = [...bob.db.msgs()] - .filter((msg) => msg.metadata.group === carolId && msg.data) + .filter((msg) => msg.metadata.identity === carolID && msg.data) .map((msg) => msg.data.text) t.deepEquals(arr, ['m1', 'm2'], 'bob has msgs 1..2 from carol') } @@ -285,7 +222,7 @@ test('sync a feed with goal=newest but too far behind', async (t) => { { const arr = [...bob.db.msgs()] - .filter((msg) => msg.metadata.group === carolId && msg.data) + .filter((msg) => msg.metadata.identity === carolID && msg.data) .map((msg) => msg.data.text) t.deepEquals( arr, diff --git a/test/identity-sync.test.js b/test/identity-sync.test.js index ac30649..30f2235 100644 --- a/test/identity-sync.test.js +++ b/test/identity-sync.test.js @@ -1,61 +1,47 @@ const test = require('tape') -const path = require('path') -const os = require('os') -const rimraf = require('rimraf') -const SecretStack = require('secret-stack') -const caps = require('ssb-caps') const p = require('util').promisify -const { generateKeypair } = require('./util') +const Keypair = require('ppppp-keypair') +const { createPeer } = require('./util') -const createSSB = SecretStack({ appKey: caps.shs }) - .use(require('ppppp-db')) - .use(require('ssb-box')) - .use(require('../lib')) - -const ALICE_DIR = path.join(os.tmpdir(), 'dagsync-alice') -const BOB_DIR = path.join(os.tmpdir(), 'dagsync-bob') -const aliceKeys = generateKeypair('alice') -const bobKeys = generateKeypair('bob') +const aliceKeypair = Keypair.generate('ed25519', 'alice') +const bobKeys = Keypair.generate('ed25519', 'bob') function getIdentity(iter) { return [...iter] - .filter((msg) => msg.metadata.group === null && msg.data) + .filter((msg) => msg.metadata.identity === 'self' && msg.data) .map((msg) => msg.data.add) } test('sync an identity tangle', async (t) => { - rimraf.sync(ALICE_DIR) - rimraf.sync(BOB_DIR) - - const alice = createSSB({ - keys: aliceKeys, - path: ALICE_DIR, - }) - - const bob = createSSB({ - keys: bobKeys, - path: BOB_DIR, - }) + const alice = createPeer({ name: 'alice', keypair: aliceKeypair }) + const bob = createPeer({ name: 'bob', keypair: bobKeys }) await alice.db.loaded() await bob.db.loaded() // Alice's identity tangle await alice.db.loaded() - const aliceGroupRec0 = await p(alice.db.group.create)({ _nonce: 'alice' }) - const aliceId = aliceGroupRec0.hash - await p(alice.db.add)(aliceGroupRec0.msg, aliceId) + const aliceID = await p(alice.db.identity.create)({ + domain: 'account', + _nonce: 'alice', + }) - const aliceKeys1 = generateKeypair('alice1') - await p(alice.db.group.add)({ group: aliceId, keys: aliceKeys1 }) + const aliceKeypair1 = Keypair.generate('ed25519', 'alice1') + await p(alice.db.identity.add)({ + identity: aliceID, + keypair: aliceKeypair1, + }) - const aliceKeys2 = generateKeypair('alice2') - await p(alice.db.group.add)({ group: aliceId, keys: aliceKeys2 }) + const aliceKeypair2 = Keypair.generate('ed25519', 'alice2') + await p(alice.db.identity.add)({ + identity: aliceID, + keypair: aliceKeypair2, + }) t.deepEquals( getIdentity(alice.db.msgs()), - [aliceKeys.id, aliceKeys1.id, aliceKeys2.id], - "alice has her identity tangle" + [aliceKeypair.public, aliceKeypair1.public, aliceKeypair2.public], + 'alice has her identity tangle' ) t.deepEquals( @@ -64,8 +50,8 @@ test('sync an identity tangle', async (t) => { "bob doesn't have alice's identity tangle" ) - bob.tangleSync.setGoal(aliceId, 'all') - alice.tangleSync.setGoal(aliceId, 'all') + bob.tangleSync.setGoal(aliceID, 'all') + alice.tangleSync.setGoal(aliceID, 'all') const remoteAlice = await p(bob.connect)(alice.getAddress()) t.pass('bob connected to alice') @@ -76,7 +62,7 @@ test('sync an identity tangle', async (t) => { t.deepEquals( getIdentity(bob.db.msgs()), - [aliceKeys.id, aliceKeys1.id, aliceKeys2.id], + [aliceKeypair.public, aliceKeypair1.public, aliceKeypair2.public], "bob has alice's identity tangle" ) diff --git a/test/thread-sync.test.js b/test/thread-sync.test.js index 503b8b8..70b7967 100644 --- a/test/thread-sync.test.js +++ b/test/thread-sync.test.js @@ -1,26 +1,13 @@ const test = require('tape') -const path = require('path') -const os = require('os') -const rimraf = require('rimraf') -const SecretStack = require('secret-stack') -const caps = require('ssb-caps') const p = require('util').promisify -const { generateKeypair } = require('./util') +const Keypair = require('ppppp-keypair') +const { createPeer } = require('./util') -const createSSB = SecretStack({ appKey: caps.shs }) - .use(require('ppppp-db')) - .use(require('ssb-box')) - .use(require('../lib')) - -const ALICE_DIR = path.join(os.tmpdir(), 'dagsync-alice') -const BOB_DIR = path.join(os.tmpdir(), 'dagsync-bob') -const aliceKeys = generateKeypair('alice') -const bobKeys = generateKeypair('bob') +const carolKeypair = Keypair.generate('ed25519', 'carol') +const daveKeypair = Keypair.generate('ed25519', 'dave') function getTexts(iter) { - return [...iter] - .filter((msg) => msg.metadata.group && msg.data) - .map((msg) => msg.data.text) + return [...iter].filter((msg) => msg.data?.text).map((msg) => msg.data.text) } /* @@ -61,81 +48,72 @@ graph TB; ``` */ test('sync a thread where both peers have portions', async (t) => { - rimraf.sync(ALICE_DIR) - rimraf.sync(BOB_DIR) - - const alice = createSSB({ - keys: aliceKeys, - path: ALICE_DIR, - }) - - const bob = createSSB({ - keys: bobKeys, - path: BOB_DIR, - }) + const alice = createPeer({ name: 'alice' }) + const bob = createPeer({ name: 'bob' }) await alice.db.loaded() - const aliceGroupRec0 = await p(alice.db.group.create)({ _nonce: 'alice' }) - const aliceId = aliceGroupRec0.hash - await p(alice.db.add)(aliceGroupRec0.msg, aliceId) + const aliceID = await p(alice.db.identity.create)({ + domain: 'account', + _nonce: 'alice', + }) + const aliceIDMsg = alice.db.get(aliceID) await bob.db.loaded() - const bobGroupRec0 = await p(bob.db.group.create)({ _nonce: 'bob' }) - const bobId = bobGroupRec0.hash - await p(bob.db.add)(bobGroupRec0.msg, bobId) + const bobID = await p(bob.db.identity.create)({ + domain: 'account', + _nonce: 'bob', + }) + const bobIDMsg = bob.db.get(bobID) // Alice created Carol - const carolKeys = generateKeypair('carol') - const carolGroupRec0 = await p(alice.db.group.create)({ - keys: carolKeys, + const carolID = await p(alice.db.identity.create)({ + domain: 'account', + keypair: carolKeypair, _nonce: 'carol', }) - const carolId = carolGroupRec0.hash + const carolIDMsg = alice.db.get(carolID) // Alice created Dave - const daveKeys = generateKeypair('dave') - const daveGroupRec0 = await p(alice.db.group.create)({ - keys: daveKeys, + const daveID = await p(alice.db.identity.create)({ + domain: 'account', + keypair: daveKeypair, _nonce: 'dave', }) - const daveId = daveGroupRec0.hash + const daveIDMsg = alice.db.get(daveID) // Alice knows Bob - await p(alice.db.add)(bobGroupRec0.msg, bobId) + await p(alice.db.add)(bobIDMsg, bobID) // Bob knows Alice, Carol, and Dave - await p(bob.db.add)(aliceGroupRec0.msg, aliceId) - await p(bob.db.add)(carolGroupRec0.msg, carolId) - await p(bob.db.add)(daveGroupRec0.msg, daveId) + await p(bob.db.add)(aliceIDMsg, aliceID) + await p(bob.db.add)(carolIDMsg, carolID) + await p(bob.db.add)(daveIDMsg, daveID) const startA = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A' }, - keys: aliceKeys, }) - const rootHashA = alice.db.feed.getId(aliceId, 'post') + const rootHashA = alice.db.feed.getId(aliceID, 'post') const rootMsgA = alice.db.get(rootHashA) await p(bob.db.add)(rootMsgA, rootHashA) await p(bob.db.add)(startA.msg, rootHashA) const replyB1 = await p(bob.db.feed.publish)({ - group: bobId, - type: 'post', + identity: bobID, + domain: 'post', data: { text: 'B1' }, tangles: [startA.hash], - keys: bobKeys, }) const replyB2 = await p(bob.db.feed.publish)({ - group: bobId, - type: 'post', + identity: bobID, + domain: 'post', data: { text: 'B2' }, tangles: [startA.hash], - keys: bobKeys, }) - const rootHashB = bob.db.feed.getId(bobId, 'post') + const rootHashB = bob.db.feed.getId(bobID, 'post') const rootMsgB = bob.db.get(rootHashB) await p(alice.db.add)(rootMsgB, rootHashB) @@ -143,19 +121,19 @@ test('sync a thread where both peers have portions', async (t) => { await p(alice.db.add)(replyB2.msg, rootHashB) const replyC1 = await p(alice.db.feed.publish)({ - group: carolId, - type: 'post', + identity: carolID, + domain: 'post', data: { text: 'C1' }, tangles: [startA.hash], - keys: carolKeys, + keypair: carolKeypair, }) const replyD1 = await p(bob.db.feed.publish)({ - group: daveId, - type: 'post', + identity: daveID, + domain: 'post', data: { text: 'D1' }, tangles: [startA.hash], - keys: daveKeys, + keypair: daveKeypair, }) t.deepEquals( @@ -198,56 +176,47 @@ test('sync a thread where both peers have portions', async (t) => { }) test('sync a thread where initiator does not have the root', async (t) => { - rimraf.sync(ALICE_DIR) - rimraf.sync(BOB_DIR) - - const alice = createSSB({ - keys: aliceKeys, - path: ALICE_DIR, - }) - - const bob = createSSB({ - keys: bobKeys, - path: BOB_DIR, - }) + const alice = createPeer({ name: 'alice' }) + const bob = createPeer({ name: 'bob' }) await alice.db.loaded() - const aliceGroupRec0 = await p(alice.db.group.create)({ _nonce: 'alice' }) - const aliceId = aliceGroupRec0.hash - await p(alice.db.add)(aliceGroupRec0.msg, aliceId) + const aliceID = await p(alice.db.identity.create)({ + domain: 'account', + _nonce: 'alice', + }) + const aliceIDMsg = alice.db.get(aliceID) await bob.db.loaded() - const bobGroupRec0 = await p(bob.db.group.create)({ _nonce: 'bob' }) - const bobId = bobGroupRec0.hash - await p(bob.db.add)(bobGroupRec0.msg, bobId) + const bobID = await p(bob.db.identity.create)({ + domain: 'account', + _nonce: 'bob', + }) + const bobIDMsg = bob.db.get(bobID) // Alice knows Bob - await p(alice.db.add)(bobGroupRec0.msg, bobId) + await p(alice.db.add)(bobIDMsg, bobID) // Bob knows Alice - await p(bob.db.add)(aliceGroupRec0.msg, aliceId) + await p(bob.db.add)(aliceIDMsg, aliceID) const rootA = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A' }, - keys: aliceKeys, }) const replyA1 = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A1' }, tangles: [rootA.hash], - keys: aliceKeys, }) const replyA2 = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A2' }, tangles: [rootA.hash], - keys: aliceKeys, }) t.deepEquals( @@ -281,56 +250,47 @@ test('sync a thread where initiator does not have the root', async (t) => { }) test('sync a thread where receiver does not have the root', async (t) => { - rimraf.sync(ALICE_DIR) - rimraf.sync(BOB_DIR) - - const alice = createSSB({ - keys: aliceKeys, - path: ALICE_DIR, - }) - - const bob = createSSB({ - keys: bobKeys, - path: BOB_DIR, - }) + const alice = createPeer({ name: 'alice' }) + const bob = createPeer({ name: 'bob' }) await alice.db.loaded() - const aliceGroupRec0 = await p(alice.db.group.create)({ _nonce: 'alice' }) - const aliceId = aliceGroupRec0.hash - await p(alice.db.add)(aliceGroupRec0.msg, aliceId) + const aliceID = await p(alice.db.identity.create)({ + domain: 'account', + _nonce: 'alice', + }) + const aliceIDMsg = alice.db.get(aliceID) await bob.db.loaded() - const bobGroupRec0 = await p(bob.db.group.create)({ _nonce: 'bob' }) - const bobId = bobGroupRec0.hash - await p(bob.db.add)(bobGroupRec0.msg, bobId) + const bobID = await p(bob.db.identity.create)({ + domain: 'account', + _nonce: 'bob', + }) + const bobIDMsg = bob.db.get(bobID) // Alice knows Bob - await p(alice.db.add)(bobGroupRec0.msg, bobId) + await p(alice.db.add)(bobIDMsg, bobID) // Bob knows Alice - await p(bob.db.add)(aliceGroupRec0.msg, aliceId) + await p(bob.db.add)(aliceIDMsg, aliceID) const rootA = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A' }, - keys: aliceKeys, }) const replyA1 = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A1' }, tangles: [rootA.hash], - keys: aliceKeys, }) const replyA2 = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A2' }, tangles: [rootA.hash], - keys: aliceKeys, }) t.deepEquals( @@ -363,64 +323,54 @@ test('sync a thread where receiver does not have the root', async (t) => { }) test('sync a thread with reactions too', async (t) => { - rimraf.sync(ALICE_DIR) - rimraf.sync(BOB_DIR) - - const alice = createSSB({ - keys: aliceKeys, - path: ALICE_DIR, - }) - - const bob = createSSB({ - keys: bobKeys, - path: BOB_DIR, - }) + const alice = createPeer({ name: 'alice' }) + const bob = createPeer({ name: 'bob' }) await alice.db.loaded() - const aliceGroupRec0 = await p(alice.db.group.create)({ _nonce: 'alice' }) - const aliceId = aliceGroupRec0.hash - await p(alice.db.add)(aliceGroupRec0.msg, aliceId) + const aliceID = await p(alice.db.identity.create)({ + domain: 'account', + _nonce: 'alice', + }) + const aliceIDMsg = alice.db.get(aliceID) await bob.db.loaded() - const bobGroupRec0 = await p(bob.db.group.create)({ _nonce: 'bob' }) - const bobId = bobGroupRec0.hash - await p(bob.db.add)(bobGroupRec0.msg, bobId) + const bobID = await p(bob.db.identity.create)({ + domain: 'account', + _nonce: 'bob', + }) + const bobIDMsg = bob.db.get(bobID) // Alice knows Bob - await p(alice.db.add)(bobGroupRec0.msg, bobId) + await p(alice.db.add)(bobIDMsg, bobID) // Bob knows Alice - await p(bob.db.add)(aliceGroupRec0.msg, aliceId) + await p(bob.db.add)(aliceIDMsg, aliceID) const rootA = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A' }, - keys: aliceKeys, }) const replyA1 = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A1' }, tangles: [rootA.hash], - keys: aliceKeys, }) const replyA2 = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'post', + identity: aliceID, + domain: 'post', data: { text: 'A2' }, tangles: [rootA.hash], - keys: aliceKeys, }) const reactionA3 = await p(alice.db.feed.publish)({ - group: aliceId, - type: 'reaction', + identity: aliceID, + domain: 'reaction', data: { text: 'yes', link: replyA1.hash }, tangles: [rootA.hash, replyA1.hash], - keys: aliceKeys, }) t.deepEquals( diff --git a/test/util.js b/test/util.js index 5d30062..27fb975 100644 --- a/test/util.js +++ b/test/util.js @@ -1,14 +1,38 @@ -const ssbKeys = require('ssb-keys') -const SSBURI = require('ssb-uri2') -const base58 = require('bs58') +const os = require('node:os') +const path = require('node:path') +const rimraf = require('rimraf') +const caps = require('ppppp-caps') +const Keypair = require('ppppp-keypair') -function generateKeypair(seed) { - const keys = ssbKeys.generate('ed25519', seed, 'buttwoo-v1') - const { data } = SSBURI.decompose(keys.id) - keys.id = base58.encode(Buffer.from(data, 'base64')) - return keys +function createPeer(opts) { + if (opts.name) { + opts.path ??= path.join(os.tmpdir(), 'tanglesync-' + opts.name) + opts.keypair ??= Keypair.generate('ed25519', opts.name) + opts.name = undefined + } + if (!opts.path) throw new Error('need opts.path in createPeer()') + if (!opts.keypair) throw new Error('need opts.keypair in createPeer()') + + rimraf.sync(opts.path) + return require('secret-stack/lib/api')([], {}) + .use(require('secret-stack/lib/core')) + .use(require('secret-stack/lib/plugins/net')) + .use(require('secret-handshake-ext/secret-stack')) + .use(require('ppppp-db')) + .use(require('ssb-box')) + .use(require('../lib')) + .call(null, { + caps, + connections: { + incoming: { + net: [{ scope: 'device', transform: 'shse', port: null }], + }, + outgoing: { + net: [{ transform: 'shse' }], + }, + }, + ...opts, + }) } -module.exports = { - generateKeypair, -} +module.exports = { createPeer }