mirror of https://codeberg.org/pzp/pzp-sync.git
update to msg-v3 format
This commit is contained in:
parent
17b720cb60
commit
07f83677d4
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
46
test/util.js
46
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 }
|
||||
|
|
Loading…
Reference in New Issue