validate is synchronous

This commit is contained in:
Andre Staltz 2023-04-18 18:40:52 +03:00
parent 8288432785
commit 3ab7d98550
5 changed files with 93 additions and 93 deletions

View File

@ -222,6 +222,10 @@ class Tangle {
return path return path
} }
size() {
return this.#depth.size
}
getMaxDepth() { getMaxDepth() {
return this.#maxDepth return this.#maxDepth
} }

View File

@ -110,6 +110,7 @@ function validateTangle(msg, tangle, tangleId) {
} }
} }
let minDiff = Infinity let minDiff = Infinity
let countPrevUnknown = 0
for (const p of prev) { for (const p of prev) {
if (typeof p !== 'string') { if (typeof p !== 'string') {
// prettier-ignore // prettier-ignore
@ -121,8 +122,8 @@ function validateTangle(msg, tangle, tangleId) {
} }
if (!tangle.has(p)) { if (!tangle.has(p)) {
// prettier-ignore countPrevUnknown += 1
return new Error('invalid message: prev ' + p + ' is not locally known, on feed: ' + msg.metadata.who); continue
} }
const prevDepth = tangle.getDepth(p) const prevDepth = tangle.getDepth(p)
@ -133,13 +134,23 @@ function validateTangle(msg, tangle, tangleId) {
} }
if (diff < minDiff) minDiff = diff if (diff < minDiff) minDiff = diff
} }
if (minDiff !== 1) {
if (countPrevUnknown === prev.length) {
// prettier-ignore
return new Error('invalid message: all prev are locally unknown, on feed: ' + msg.metadata.who)
}
if (countPrevUnknown === 0 && minDiff !== 1) {
// prettier-ignore // prettier-ignore
return new Error('invalid message: depth must be the largest prev depth plus one'); return new Error('invalid message: depth must be the largest prev depth plus one');
} }
} }
function validateTangleRoot(msg, tangleId) { function validateTangleRoot(msg, msgHash, tangleId) {
if (msgHash !== tangleId) {
// prettier-ignore
return new Error('invalid message: tangle root hash must match tangleId, on feed: ' + msg.metadata.who);
}
if (msg.metadata.tangles[tangleId]) { if (msg.metadata.tangles[tangleId]) {
// prettier-ignore // prettier-ignore
return new Error('invalid message: tangle root must not have self tangle data, on feed: ' + msg.metadata.who); return new Error('invalid message: tangle root must not have self tangle data, on feed: ' + msg.metadata.who);
@ -190,12 +201,12 @@ function validateContent(msg) {
// FIXME: validateDepth should be +1 of the max of prev depth // FIXME: validateDepth should be +1 of the max of prev depth
function validateSync(msg, tangle, msgHash, rootHash) { function validate(msg, tangle, msgHash, rootHash) {
let err let err
if ((err = validateShape(msg))) return err if ((err = validateShape(msg))) return err
if ((err = validateWho(msg))) return err if ((err = validateWho(msg))) return err
if (msgHash === rootHash) { if (tangle.size() === 0) {
if ((err = validateTangleRoot(msg))) return err if ((err = validateTangleRoot(msg, msgHash, rootHash))) return err
} else { } else {
if ((err = validateTangle(msg, tangle, rootHash))) return err if ((err = validateTangle(msg, tangle, rootHash))) return err
} }
@ -203,14 +214,6 @@ function validateSync(msg, tangle, msgHash, rootHash) {
if ((err = validateSignature(msg))) return err if ((err = validateSignature(msg))) return err
} }
function validate(msg, tangle, msgHash, rootHash, cb) {
let err
if ((err = validateSync(msg, tangle, msgHash, rootHash))) {
return cb(err)
}
cb()
}
// function validateBatch(nativeMsgs, prevNativeMsg, hmacKey, cb) { // function validateBatch(nativeMsgs, prevNativeMsg, hmacKey, cb) {
// let err // let err
// let prev = prevNativeMsg // let prev = prevNativeMsg

View File

@ -189,19 +189,22 @@ exports.init = function initDB(peer, config) {
const tangle = new DBTangle(tangleRootHash, records()) const tangle = new DBTangle(tangleRootHash, records())
const msgHash = FeedV1.getMsgHash(msg) const msgHash = FeedV1.getMsgHash(msg)
FeedV1.validate(msg, tangle, msgHash, tangleRootHash, validationCB)
function validationCB(err) { // TODO: optimize this. Perhaps have a Map() of msgHash -> record
let rec
if ((rec = getRecord(msgHash))) return cb(null, rec)
let err
if ((err = FeedV1.validate(msg, tangle, msgHash, tangleRootHash))) {
// prettier-ignore // prettier-ignore
if (err) return cb(new Error('add() failed validation for feed format v1', {cause: err})) return cb(new Error('add() failed validation for feed format v1', {cause: err}))
logAppend(msgHash, msg, logAppendCB)
} }
function logAppendCB(err, rec) { logAppend(msgHash, msg, (err, rec) => {
if (err) return cb(new Error('add() failed in the log', { cause: err })) if (err) return cb(new Error('add() failed in the log', { cause: err }))
onRecordAdded.set(rec) onRecordAdded.set(rec)
cb(null, rec) cb(null, rec)
} })
} }
function create(opts, cb) { function create(opts, cb) {

View File

@ -23,12 +23,11 @@ tape('invalid msg with non-array prev', (t) => {
msg.metadata.tangles[rootHash].prev = null msg.metadata.tangles[rootHash].prev = null
const msgHash = FeedV1.getMsgHash(msg) const msgHash = FeedV1.getMsgHash(msg)
FeedV1.validate(msg, tangle, msgHash, rootHash, (err) => { const err = FeedV1.validate(msg, tangle, msgHash, rootHash)
t.ok(err, 'invalid 2nd msg throws') t.ok(err, 'invalid 2nd msg throws')
t.match(err.message, /prev must be an array/, 'invalid 2nd msg description') t.match(err.message, /prev must be an array/, 'invalid 2nd msg description')
t.end() t.end()
}) })
})
tape('invalid msg with bad prev', (t) => { tape('invalid msg with bad prev', (t) => {
const keys = generateKeypair('alice') const keys = generateKeypair('alice')
@ -62,7 +61,7 @@ tape('invalid msg with bad prev', (t) => {
msg2.metadata.tangles[rootHash].prev = [1234] msg2.metadata.tangles[rootHash].prev = [1234]
const msgHash2 = FeedV1.getMsgHash(msg2) const msgHash2 = FeedV1.getMsgHash(msg2)
FeedV1.validate(msg2, tangle, msgHash2, rootHash, (err) => { const err = FeedV1.validate(msg2, tangle, msgHash2, rootHash)
t.ok(err, 'invalid 2nd msg throws') t.ok(err, 'invalid 2nd msg throws')
t.match( t.match(
err.message, err.message,
@ -71,7 +70,6 @@ tape('invalid msg with bad prev', (t) => {
) )
t.end() t.end()
}) })
})
tape('invalid msg with URI in prev', (t) => { tape('invalid msg with URI in prev', (t) => {
const keys = generateKeypair('alice') const keys = generateKeypair('alice')
@ -107,7 +105,7 @@ tape('invalid msg with URI in prev', (t) => {
msg2.metadata.tangles[rootHash].depth = 1 msg2.metadata.tangles[rootHash].depth = 1
msg2.metadata.tangles[rootHash].prev = [fakeMsgKey1] msg2.metadata.tangles[rootHash].prev = [fakeMsgKey1]
FeedV1.validate(msg2, tangle, msgHash2, rootHash, (err) => { const err = FeedV1.validate(msg2, tangle, msgHash2, rootHash)
t.ok(err, 'invalid 2nd msg throws') t.ok(err, 'invalid 2nd msg throws')
t.match( t.match(
err.message, err.message,
@ -116,7 +114,6 @@ tape('invalid msg with URI in prev', (t) => {
) )
t.end() t.end()
}) })
})
tape('invalid msg with unknown prev', (t) => { tape('invalid msg with unknown prev', (t) => {
const keys = generateKeypair('alice') const keys = generateKeypair('alice')
@ -148,8 +145,9 @@ tape('invalid msg with unknown prev', (t) => {
}) })
const unknownMsgHash = FeedV1.getMsgHash(unknownMsg) const unknownMsgHash = FeedV1.getMsgHash(unknownMsg)
const tangle2 = new FeedV1.Tangle(rootHash) const fakeRootHash = 'ABCDEabcde' + rootHash.substring(10)
tangle2.add(rootHash, rootMsg) const tangle2 = new FeedV1.Tangle(fakeRootHash)
tangle2.add(fakeRootHash, rootMsg)
tangle2.add(unknownMsgHash, unknownMsg) tangle2.add(unknownMsgHash, unknownMsg)
const msg2 = FeedV1.create({ const msg2 = FeedV1.create({
@ -157,21 +155,20 @@ tape('invalid msg with unknown prev', (t) => {
content: { text: 'Hello world!' }, content: { text: 'Hello world!' },
type: 'post', type: 'post',
tangles: { tangles: {
[rootHash]: tangle2 [rootHash]: tangle2,
}, },
}) })
const msgHash2 = FeedV1.getMsgHash(msg2) const msgHash2 = FeedV1.getMsgHash(msg2)
FeedV1.validate(msg2, tangle, msgHash2, rootHash, (err) => { const err = FeedV1.validate(msg2, tangle, msgHash2, rootHash)
t.ok(err, 'invalid 2nd msg throws') t.ok(err, 'invalid 2nd msg throws')
t.match( t.match(
err.message, err.message,
/prev .+ is not locally known/, /all prev are locally unknown/,
'invalid 2nd msg description' 'invalid 2nd msg description'
) )
t.end() t.end()
}) })
})
tape('invalid feed msg with a different who', (t) => { tape('invalid feed msg with a different who', (t) => {
const keysA = generateKeypair('alice') const keysA = generateKeypair('alice')
@ -192,11 +189,10 @@ tape('invalid feed msg with a different who', (t) => {
}) })
const msgHash = FeedV1.getMsgHash(msg) const msgHash = FeedV1.getMsgHash(msg)
FeedV1.validate(msg, feedTangle, msgHash, rootHash, (err) => { const err = FeedV1.validate(msg, feedTangle, msgHash, rootHash)
t.match(err.message, /who ".*" does not match feed who/, 'invalid feed msg') t.match(err.message, /who ".*" does not match feed who/, 'invalid feed msg')
t.end() t.end()
}) })
})
tape('invalid feed msg with a different type', (t) => { tape('invalid feed msg with a different type', (t) => {
const keysA = generateKeypair('alice') const keysA = generateKeypair('alice')
@ -216,7 +212,7 @@ tape('invalid feed msg with a different type', (t) => {
}) })
const msgHash = FeedV1.getMsgHash(msg) const msgHash = FeedV1.getMsgHash(msg)
FeedV1.validate(msg, feedTangle, msgHash, rootHash, (err) => { const err = FeedV1.validate(msg, feedTangle, msgHash, rootHash)
t.match( t.match(
err.message, err.message,
/type "comment" does not match feed type "post"/, /type "comment" does not match feed type "post"/,
@ -224,4 +220,3 @@ tape('invalid feed msg with a different type', (t) => {
) )
t.end() t.end()
}) })
})

View File

@ -9,14 +9,12 @@ tape('validate root msg', (t) => {
const rootMsg = FeedV1.createRoot(keys, 'post') const rootMsg = FeedV1.createRoot(keys, 'post')
const rootHash = FeedV1.getMsgHash(rootMsg) const rootHash = FeedV1.getMsgHash(rootMsg)
const tangle = new FeedV1.Tangle(rootHash) const tangle = new FeedV1.Tangle(rootHash)
tangle.add(rootHash, rootMsg)
FeedV1.validate(rootMsg, tangle, rootHash, rootHash, (err) => { const err = FeedV1.validate(rootMsg, tangle, rootHash, rootHash)
if (err) console.log(err) if (err) console.log(err)
t.error(err, 'valid root msg') t.error(err, 'valid root msg')
t.end() t.end()
}) })
})
tape('validate 2nd msg with existing root', (t) => { tape('validate 2nd msg with existing root', (t) => {
const keys = generateKeypair('alice') const keys = generateKeypair('alice')
@ -37,12 +35,11 @@ tape('validate 2nd msg with existing root', (t) => {
const msgHash1 = FeedV1.getMsgHash(msg1) const msgHash1 = FeedV1.getMsgHash(msg1)
tangle.add(msgHash1, msg1) tangle.add(msgHash1, msg1)
FeedV1.validate(msg1, tangle, msgHash1, rootHash, (err) => { const err = FeedV1.validate(msg1, tangle, msgHash1, rootHash)
if (err) console.log(err) if (err) console.log(err)
t.error(err, 'valid 2nd msg') t.error(err, 'valid 2nd msg')
t.end() t.end()
}) })
})
tape('validate 2nd forked msg', (t) => { tape('validate 2nd forked msg', (t) => {
const keys = generateKeypair('alice') const keys = generateKeypair('alice')
@ -75,12 +72,11 @@ tape('validate 2nd forked msg', (t) => {
tangle.add(msgHash1A, msg1A) tangle.add(msgHash1A, msg1A)
tangle.add(msgHash1B, msg1B) tangle.add(msgHash1B, msg1B)
FeedV1.validate(msg1B, tangle, msgHash1B, rootHash, (err) => { const err = FeedV1.validate(msg1B, tangle, msgHash1B, rootHash)
if (err) console.log(err) if (err) console.log(err)
t.error(err, 'valid 2nd forked msg') t.error(err, 'valid 2nd forked msg')
t.end() t.end()
}) })
})
tape('invalid msg with unknown previous', (t) => { tape('invalid msg with unknown previous', (t) => {
const keys = generateKeypair('alice') const keys = generateKeypair('alice')
@ -104,13 +100,12 @@ tape('invalid msg with unknown previous', (t) => {
msg1.metadata.tangles[rootHash].prev = [fakeMsgHash] msg1.metadata.tangles[rootHash].prev = [fakeMsgHash]
FeedV1.validate(msg1, tangle, msgHash1, rootHash, (err) => { const err = FeedV1.validate(msg1, tangle, msgHash1, rootHash)
t.ok(err, 'invalid 2nd msg throws') t.ok(err, 'invalid 2nd msg throws')
t.match( t.match(
err.message, err.message,
/prev .+ is not locally known/, /all prev are locally unknown/,
'invalid 2nd msg description' 'invalid 2nd msg description'
) )
t.end() t.end()
}) })
})