validate who+type in feed tangles

This commit is contained in:
Andre Staltz 2023-04-17 15:57:11 +03:00
parent 5883e1df21
commit 0917361305
3 changed files with 98 additions and 1 deletions

View File

@ -90,6 +90,22 @@ function validateTangle(msg, tangle, tangleId) {
// prettier-ignore // prettier-ignore
return new Error('invalid message: prev must be an array, on feed: ' + msg.metadata.who); return new Error('invalid message: prev must be an array, on feed: ' + msg.metadata.who);
} }
if (typeof depth !== 'number') {
// prettier-ignore
return new Error('invalid message: depth must be a number, on feed: ' + msg.metadata.who);
}
if (tangle.isFeed()) {
const { type, who } = tangle.getFeed()
if (type !== msg.metadata.type) {
// prettier-ignore
return new Error(`invalid message: type "${msg.metadata.type}" does not match feed type "${type}"`)
}
if (who !== msg.metadata.who) {
// prettier-ignore
return new Error(`invalid message: who "${msg.metadata.who}" does not match feed who "${who}"`)
}
}
let minDiff = Infinity
for (const p of prev) { for (const p of prev) {
if (typeof p !== 'string') { if (typeof p !== 'string') {
// prettier-ignore // prettier-ignore
@ -106,10 +122,16 @@ function validateTangle(msg, tangle, tangleId) {
} }
const prevDepth = tangle.getDepth(p) const prevDepth = tangle.getDepth(p)
if (prevDepth >= depth) { const diff = depth - prevDepth
if (diff <= 0) {
// prettier-ignore // prettier-ignore
return new Error('invalid message: depth of prev ' + p + ' is not lower, on feed: ' + msg.metadata.who); return new Error('invalid message: depth of prev ' + p + ' is not lower, on feed: ' + msg.metadata.who);
} }
if (diff < minDiff) minDiff = diff
}
if (minDiff !== 1) {
// prettier-ignore
return new Error('invalid message: depth must be the largest prev depth plus one');
} }
} }

View File

@ -2,6 +2,10 @@
* @typedef {import("./plugin").Rec} Rec * @typedef {import("./plugin").Rec} Rec
*/ */
/**
* @typedef {import("./feed-v1").Msg} Msg
*/
function lipmaa(n) { function lipmaa(n) {
let m = 1 let m = 1
let po3 = 3 let po3 = 3
@ -45,6 +49,11 @@ class Tangle {
*/ */
#rootHash #rootHash
/**
* @type {Msg}
*/
#rootMsg
/** /**
* @type {Set<string>} * @type {Set<string>}
*/ */
@ -89,6 +98,7 @@ class Tangle {
this.#tips.add(msgHash) this.#tips.add(msgHash)
this.#perDepth.set(0, [msgHash]) this.#perDepth.set(0, [msgHash])
this.#depth.set(msgHash, 0) this.#depth.set(msgHash, 0)
this.#rootMsg = msg
} else if (tangles[this.#rootHash]) { } else if (tangles[this.#rootHash]) {
this.#tips.add(msgHash) this.#tips.add(msgHash)
const prev = tangles[this.#rootHash].prev const prev = tangles[this.#rootHash].prev
@ -162,6 +172,18 @@ class Tangle {
return this.#depth.get(msgHash) ?? -1 return this.#depth.get(msgHash) ?? -1
} }
isFeed() {
if (this.#rootMsg.content) return false
const metadata = this.#rootMsg.metadata
return metadata.size === 0 && metadata.proof === ''
}
getFeed() {
if (!this.isFeed()) return null
const { type, who } = this.#rootMsg.metadata
return { type, who }
}
#shortestPathToRoot(msgHash) { #shortestPathToRoot(msgHash) {
const path = [] const path = []
let current = msgHash let current = msgHash

View File

@ -176,3 +176,56 @@ tape('invalid msg with unknown prev', (t) => {
t.end() t.end()
}) })
}) })
tape('invalid feed msg with a different who', (t) => {
const keysA = generateKeypair('alice')
const keysB = generateKeypair('bob')
const rootMsg = FeedV1.createRoot(keysA, 'post')
const rootHash = FeedV1.getMsgHash(rootMsg)
const feedTangle = new Tangle(rootHash, [{ hash: rootHash, msg: rootMsg }])
const msg = FeedV1.create({
keys: keysB,
content: { text: 'Hello world!' },
type: 'post',
tangles: {
[rootHash]: feedTangle,
},
when: 1652030002000,
})
const msgHash = FeedV1.getMsgHash(msg)
FeedV1.validate(msg, feedTangle, msgHash, rootHash, (err) => {
t.match(err.message, /who ".*" does not match feed who/, 'invalid feed msg')
t.end()
})
})
tape('invalid feed msg with a different type', (t) => {
const keysA = generateKeypair('alice')
const rootMsg = FeedV1.createRoot(keysA, 'post')
const rootHash = FeedV1.getMsgHash(rootMsg)
const feedTangle = new Tangle(rootHash, [{ hash: rootHash, msg: rootMsg }])
const msg = FeedV1.create({
keys: keysA,
content: { text: 'Hello world!' },
type: 'comment',
tangles: {
[rootHash]: feedTangle,
},
when: 1652030002000,
})
const msgHash = FeedV1.getMsgHash(msg)
FeedV1.validate(msg, feedTangle, msgHash, rootHash, (err) => {
t.match(
err.message,
/type "comment" does not match feed type "post"/,
'invalid feed msg'
)
t.end()
})
})