mirror of https://codeberg.org/pzp/pzp-db.git
more strict validation (#1)
in an attempt to preempt problems with non-deterministic (de-)serialization.
This commit is contained in:
parent
dc636c01c0
commit
d1247afb06
|
@ -36,7 +36,12 @@ function validateShape(msg) {
|
||||||
|
|
||||||
function validateWho(msg) {
|
function validateWho(msg) {
|
||||||
try {
|
try {
|
||||||
base58.decode(msg.metadata.who)
|
const whoBuf = base58.decode(msg.metadata.who)
|
||||||
|
if (whoBuf.length !== 32) {
|
||||||
|
return new Error(
|
||||||
|
`invalid message: decoded "who" should be 32 bytes but was ${whoBuf.length}`
|
||||||
|
)
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return new Error('invalid message: must have "who" as base58 string')
|
return new Error('invalid message: must have "who" as base58 string')
|
||||||
}
|
}
|
||||||
|
@ -44,7 +49,12 @@ function validateWho(msg) {
|
||||||
|
|
||||||
function validateMsgHash(str) {
|
function validateMsgHash(str) {
|
||||||
try {
|
try {
|
||||||
base58.decode(str)
|
const hashBuf = Buffer.from(base58.decode(str))
|
||||||
|
if (hashBuf.length !== 16) {
|
||||||
|
return new Error(
|
||||||
|
`invalid message: decoded hash should be 16 bytes but was ${hashBuf.length}`
|
||||||
|
)
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return new Error(
|
return new Error(
|
||||||
`invalid message: msgHash ${str} should have been a base58 string`
|
`invalid message: msgHash ${str} should have been a base58 string`
|
||||||
|
@ -52,21 +62,30 @@ function validateMsgHash(str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateSize(msg) {
|
||||||
|
const {
|
||||||
|
metadata: { size },
|
||||||
|
} = msg
|
||||||
|
if (!Number.isSafeInteger(size) || size < 0) {
|
||||||
|
return new Error(`invalid message: "size" should be an unsigned integer`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function validateSignature(msg) {
|
function validateSignature(msg) {
|
||||||
const { sig } = msg
|
const { sig } = msg
|
||||||
if (typeof sig !== 'string') {
|
if (typeof sig !== 'string') {
|
||||||
return new Error('invalid message: must have sig as a string')
|
return new Error('invalid message: must have sig as a string')
|
||||||
}
|
}
|
||||||
|
let sigBuf
|
||||||
try {
|
try {
|
||||||
base58.decode(sig)
|
sigBuf = Buffer.from(base58.decode(sig))
|
||||||
|
if (sigBuf.length !== 64) {
|
||||||
|
// prettier-ignore
|
||||||
|
return new Error('invalid message: sig should be 64 bytes but was ' + sigBuf.length + ', on feed: ' + msg.metadata.who);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return new Error('invalid message: sig must be a base58 string')
|
return new Error('invalid message: sig must be a base58 string')
|
||||||
}
|
}
|
||||||
const sigBuf = Buffer.from(base58.decode(sig))
|
|
||||||
if (sigBuf.length !== 64) {
|
|
||||||
// prettier-ignore
|
|
||||||
return new Error('invalid message: sig should be 64 bytes but was ' + sigBuf.length + ', on feed: ' + msg.metadata.who);
|
|
||||||
}
|
|
||||||
|
|
||||||
const publicKeyBuf = Buffer.from(base58.decode(msg.metadata.who))
|
const publicKeyBuf = Buffer.from(base58.decode(msg.metadata.who))
|
||||||
const signableBuf = Buffer.from(stringify(msg.metadata), 'utf8')
|
const signableBuf = Buffer.from(stringify(msg.metadata), 'utf8')
|
||||||
|
@ -93,9 +112,9 @@ 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') {
|
if (!Number.isSafeInteger(depth) || depth <= 0) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return new Error('invalid message: depth must be a number, on feed: ' + msg.metadata.who);
|
return new Error('invalid message: depth must be a positive integer, on feed: ' + msg.metadata.who);
|
||||||
}
|
}
|
||||||
if (tangle.isFeed()) {
|
if (tangle.isFeed()) {
|
||||||
const { type, who } = tangle.getFeed()
|
const { type, who } = tangle.getFeed()
|
||||||
|
@ -202,6 +221,7 @@ 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 ((err = validateSize(msg))) return err
|
||||||
if (tangle.size() === 0) {
|
if (tangle.size() === 0) {
|
||||||
if ((err = validateTangleRoot(msg, msgHash, rootHash))) return err
|
if ((err = validateTangleRoot(msg, msgHash, rootHash))) return err
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,11 +7,11 @@ interface Msg {
|
||||||
content: any | null, // any object, or null
|
content: any | null, // any object, or null
|
||||||
metadata: {
|
metadata: {
|
||||||
hash: ContentHash, // blake3 hash of the `content` object serialized
|
hash: ContentHash, // blake3 hash of the `content` object serialized
|
||||||
size: number, // byte size of the `content` object serialized
|
size: number, // byte size (unsigned integer) of the `content` object serialized
|
||||||
tangles: {
|
tangles: {
|
||||||
// for each tangle this msg belongs to, identified by the tangle's root
|
// for each tangle this msg belongs to, identified by the tangle's root
|
||||||
[rootMsgHash: string]: {
|
[rootMsgHash: string]: {
|
||||||
depth: number, // maximum distance from this msg to the root
|
depth: number, // maximum distance (positive integer) from this msg to the root
|
||||||
prev: Array<MsgHash>, // list of msg hashes of existing msgs
|
prev: Array<MsgHash>, // list of msg hashes of existing msgs
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue