mirror of https://codeberg.org/pzp/pzp-db.git
Prune the accountTangle in getSigkeysInAccount (#23)
This commit is contained in:
parent
d332308104
commit
e40c7cff09
26
lib/index.js
26
lib/index.js
|
@ -376,11 +376,11 @@ function initDB(peer, config) {
|
|||
|
||||
/**
|
||||
* @param {Pick<RecPresent, 'id' | 'msg'>} rec
|
||||
* @returns {Tangle | null}
|
||||
* @returns {DBTangle | null}
|
||||
*/
|
||||
function getAccountTangle(rec) {
|
||||
const accountID = getAccountID(rec)
|
||||
let accountTangle = /** @type {Tangle | null} */ (null)
|
||||
let accountTangle = /** @type {DBTangle | null} */ (null)
|
||||
if (accountID) {
|
||||
accountTangle = new DBTangle(accountID, records(), get)
|
||||
if (rec.id === accountID) {
|
||||
|
@ -397,15 +397,20 @@ function initDB(peer, config) {
|
|||
* Find which sigkeys are authorized to sign this msg given the account.
|
||||
*
|
||||
* @private
|
||||
* @param {Tangle | null} accountTangle
|
||||
* @param {DBTangle | null} accountTangle
|
||||
* @param {Msg['metadata']['accountTips']} accountTipsInMsg
|
||||
* @returns {Set<string>}
|
||||
*/
|
||||
function getSigkeysInAccount(accountTangle) {
|
||||
function getSigkeysInAccount(accountTangle, accountTipsInMsg) {
|
||||
const sigkeys = new Set()
|
||||
if (!accountTangle) return sigkeys
|
||||
// TODO: prune the accountTangle beyond msg.metadata.accountTips
|
||||
for (const msgID of accountTangle.topoSort()) {
|
||||
const msg = get(msgID)
|
||||
|
||||
const prunedTangle = accountTangle.slice(
|
||||
undefined,
|
||||
accountTipsInMsg ?? undefined
|
||||
)
|
||||
|
||||
for (const msg of prunedTangle) {
|
||||
if (!msg?.data) continue
|
||||
/** @type {AccountData} */
|
||||
const data = msg.data
|
||||
|
@ -461,14 +466,17 @@ function initDB(peer, config) {
|
|||
}
|
||||
|
||||
// Identify the account and its sigkeys:
|
||||
/** @type {Tangle | null} */
|
||||
/** @type {DBTangle | null} */
|
||||
let accountTangle
|
||||
try {
|
||||
accountTangle = getAccountTangle(rec)
|
||||
} catch (err) {
|
||||
return new Error('Unknown account tangle owning this msg', { cause: err })
|
||||
}
|
||||
const sigkeys = getSigkeysInAccount(accountTangle)
|
||||
const sigkeys = getSigkeysInAccount(
|
||||
accountTangle,
|
||||
rec.msg.metadata.accountTips
|
||||
)
|
||||
|
||||
// Don't accept ghosts to come back, unless they are trail msgs
|
||||
if (!!rec.msg.data && ghosts.read(tangleID).has(rec.id)) {
|
||||
|
|
|
@ -306,7 +306,7 @@ function isRoot(msg) {
|
|||
* @returns {msg is FeedMsg<T>}
|
||||
*/
|
||||
function isFeedMsg(msg) {
|
||||
const {account, accountTips} = msg.metadata
|
||||
const { account, accountTips } = msg.metadata
|
||||
return Array.isArray(accountTips) && account !== 'self' && account !== 'any'
|
||||
}
|
||||
|
||||
|
|
|
@ -235,6 +235,6 @@ test('MsgV4.Tangle can add msgs in random order', (t) => {
|
|||
tangle.add(msgID2, msg2)
|
||||
tangle.add(msgID1, msg1)
|
||||
|
||||
assert.deepEqual(tangle.topoSort(), [mootAID, msgID1, msgID2]);
|
||||
assert.deepEqual(tangle.topoSort(), [mootAID, msgID1, msgID2])
|
||||
assert.deepEqual([...tangle.tips], [msgID2], 'tangle tips')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
const test = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const path = require('node:path')
|
||||
const p = require('node:util').promisify
|
||||
const os = require('node:os')
|
||||
const rimraf = require('rimraf')
|
||||
const Keypair = require('ppppp-keypair')
|
||||
const { createPeer } = require('./util')
|
||||
const MsgV4 = require('../lib/msg-v4')
|
||||
|
||||
const DIR = path.join(os.tmpdir(), 'ppppp-db-sigkeys')
|
||||
const DIR2 = path.join(os.tmpdir(), 'ppppp-db-sigkeys2')
|
||||
rimraf.sync(DIR)
|
||||
rimraf.sync(DIR2)
|
||||
|
||||
test('sigkeys', async (t) => {
|
||||
await t.test(
|
||||
"Can't add msg that is signed by key newer than what accountTips points to",
|
||||
async () => {
|
||||
const keypair1 = Keypair.generate('ed25519', 'alice')
|
||||
const keypair2 = Keypair.generate('ed25519', 'alice2')
|
||||
const keypairOther = Keypair.generate('ed25519', 'bob')
|
||||
|
||||
const peer = createPeer({ keypair: keypair1, path: DIR })
|
||||
const peerOther = createPeer({ keypair: keypairOther, path: DIR2 })
|
||||
|
||||
await peer.db.loaded()
|
||||
await peerOther.db.loaded()
|
||||
|
||||
const account = await p(peer.db.account.create)({
|
||||
keypair: keypair1,
|
||||
subdomain: 'person',
|
||||
})
|
||||
const accountMsg0 = peer.db.get(account)
|
||||
|
||||
const consent = peer.db.account.consent({ account, keypair: keypair2 })
|
||||
|
||||
const accountRec1 = await p(peer.db.account.add)({
|
||||
account,
|
||||
keypair: keypair2,
|
||||
consent,
|
||||
powers: ['external-encryption'],
|
||||
})
|
||||
|
||||
const goodRec = await p(peer.db.feed.publish)({
|
||||
account,
|
||||
domain: 'post',
|
||||
data: { text: 'potatoGood' },
|
||||
keypair: keypair2,
|
||||
})
|
||||
|
||||
const postMootId = peer.db.feed.getID(account, 'post')
|
||||
const postMootMsg = peer.db.get(postMootId)
|
||||
|
||||
const tangle = new MsgV4.Tangle(postMootId)
|
||||
tangle.add(postMootId, postMootMsg)
|
||||
tangle.add(goodRec.id, goodRec.msg)
|
||||
const badMsg = MsgV4.create({
|
||||
account,
|
||||
accountTips: [account], // intentionally excluding keypair2
|
||||
domain: 'post',
|
||||
keypair: keypair2, // intentionally using newer key than accountTips points to
|
||||
tangles: {
|
||||
[postMootId]: tangle,
|
||||
},
|
||||
data: { text: 'potato' },
|
||||
})
|
||||
await assert.rejects(
|
||||
p(peer.db.add)(badMsg, postMootId),
|
||||
/add\(\) failed to verify msg/,
|
||||
"Shouldn't be able to add() own bad msg"
|
||||
)
|
||||
|
||||
await p(peerOther.db.add)(accountMsg0, account)
|
||||
await p(peerOther.db.add)(accountRec1.msg, account)
|
||||
await p(peerOther.db.add)(postMootMsg, postMootId)
|
||||
await p(peerOther.db.add)(goodRec.msg, postMootId)
|
||||
await assert.rejects(
|
||||
p(peerOther.db.add)(badMsg, postMootId),
|
||||
/add\(\) failed to verify msg/,
|
||||
"Shouldn't be able to add() someone else's bad msg"
|
||||
)
|
||||
|
||||
await p(peer.close)()
|
||||
await p(peerOther.close)()
|
||||
}
|
||||
)
|
||||
})
|
Loading…
Reference in New Issue