mirror of https://codeberg.org/pzp/pzp-db.git
alphabetize tangles (#5)
Co-authored-by: André Staltz <andre@staltz.com>
This commit is contained in:
parent
f8bc73d52b
commit
e66483391b
|
@ -118,7 +118,7 @@ function create(opts) {
|
|||
const depth = tangle.getMaxDepth() + 1
|
||||
const tips = tangle.getTips()
|
||||
const lipmaaSet = tangle.getLipmaaSet(depth)
|
||||
const prev = [...union(lipmaaSet, tips)]
|
||||
const prev = ([...union(lipmaaSet, tips)]).sort()
|
||||
tangles[rootId] = { depth, prev }
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -127,6 +127,7 @@ function validateTangle(msg, tangle, tangleId) {
|
|||
return new Error(`invalid message: who "${msg.metadata.who}" does not match feed who "${who}"`)
|
||||
}
|
||||
}
|
||||
let lastPrev = null
|
||||
let minDiff = Infinity
|
||||
let countPrevUnknown = 0
|
||||
for (const p of prev) {
|
||||
|
@ -138,6 +139,15 @@ function validateTangle(msg, tangle, tangleId) {
|
|||
// prettier-ignore
|
||||
return new Error('invalid message: prev must not contain URIs, on feed: ' + msg.metadata.who);
|
||||
}
|
||||
if (lastPrev !== null) {
|
||||
if (p === lastPrev) {
|
||||
return new Error(`invalid message: prev must be unique set, on feed ${msg.metadata.who}`)
|
||||
}
|
||||
if (p < lastPrev) {
|
||||
return new Error(`invalid message: prev must be sorted in alphabetical order, on feed ${msg.metadata.who}`)
|
||||
}
|
||||
}
|
||||
lastPrev = p
|
||||
|
||||
if (!tangle.has(p)) {
|
||||
countPrevUnknown += 1
|
||||
|
|
|
@ -12,7 +12,7 @@ interface Msg {
|
|||
// for each tangle this msg belongs to, identified by the tangle's root
|
||||
[rootMsgHash: string]: {
|
||||
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, unique set and ordered alphabetically
|
||||
},
|
||||
},
|
||||
type: string, // alphanumeric string, at least 3 chars, max 100 chars
|
||||
|
|
|
@ -171,8 +171,8 @@ tape('create() handles DAG tips correctly', (t) => {
|
|||
const msgHash3 = FeedV1.getMsgHash(msg3)
|
||||
t.deepEquals(
|
||||
msg3.metadata.tangles[rootHash].prev,
|
||||
[rootHash, msgHash2B],
|
||||
'msg3.prev is root(lipmaa),msg2B(previous)'
|
||||
[rootHash, msgHash2B].sort(),
|
||||
'msg3.prev is [root(lipmaa),msg2B(previous)], sorted'
|
||||
)
|
||||
tangle.add(msgHash3, msg3)
|
||||
|
||||
|
@ -190,8 +190,8 @@ tape('create() handles DAG tips correctly', (t) => {
|
|||
})
|
||||
t.deepEquals(
|
||||
msg4.metadata.tangles[rootHash].prev,
|
||||
[msgHash3, msgHash2A],
|
||||
'msg4.prev is [msg3(previous),msg2A(old fork as tip)]'
|
||||
[msgHash3, msgHash2A].sort(),
|
||||
'msg4.prev is [msg3(previous),msg2A(old fork as tip)], sorted'
|
||||
)
|
||||
|
||||
t.end()
|
||||
|
|
|
@ -220,3 +220,95 @@ tape('invalid feed msg with a different type', (t) => {
|
|||
)
|
||||
t.end()
|
||||
})
|
||||
|
||||
tape('invalid feed msg with non-alphabetical prev', (t) => {
|
||||
const keys = generateKeypair('alice')
|
||||
|
||||
const rootMsg = FeedV1.createRoot(keys, 'post')
|
||||
const rootHash = FeedV1.getMsgHash(rootMsg)
|
||||
|
||||
const tangle = new FeedV1.Tangle(rootHash)
|
||||
tangle.add(rootHash, rootMsg)
|
||||
|
||||
const msg1 = FeedV1.create({
|
||||
keys,
|
||||
content: { text: '1' },
|
||||
type: 'post',
|
||||
tangles: {
|
||||
[rootHash]: tangle,
|
||||
},
|
||||
})
|
||||
const msgHash1 = FeedV1.getMsgHash(msg1)
|
||||
|
||||
const msg2 = FeedV1.create({
|
||||
keys,
|
||||
content: { text: '2' },
|
||||
type: 'post',
|
||||
tangles: {
|
||||
[rootHash]: tangle,
|
||||
},
|
||||
})
|
||||
const msgHash2 = FeedV1.getMsgHash(msg2)
|
||||
|
||||
tangle.add(msgHash1, msg1)
|
||||
tangle.add(msgHash2, msg2)
|
||||
|
||||
const msg3 = FeedV1.create({
|
||||
keys,
|
||||
content: { text: '3' },
|
||||
type: 'post',
|
||||
tangles: {
|
||||
[rootHash]: tangle,
|
||||
},
|
||||
})
|
||||
const msgHash3 = FeedV1.getMsgHash(msg3)
|
||||
|
||||
let prevHashes = msg3.metadata.tangles[rootHash].prev
|
||||
if (prevHashes[0] < prevHashes[1]) {
|
||||
prevHashes = [prevHashes[1], prevHashes[0]]
|
||||
} else {
|
||||
prevHashes = [prevHashes[0], prevHashes[1]]
|
||||
}
|
||||
msg3.metadata.tangles[rootHash].prev = prevHashes
|
||||
|
||||
const err = FeedV1.validate(msg3, tangle, msgHash3, rootHash)
|
||||
t.ok(err, 'invalid 3rd msg throws')
|
||||
t.match(
|
||||
err.message,
|
||||
/prev must be sorted in alphabetical order/,
|
||||
'invalid error message'
|
||||
)
|
||||
t.end()
|
||||
})
|
||||
|
||||
tape('invalid feed msg with duplicate prev', (t) => {
|
||||
const keys = generateKeypair('alice')
|
||||
|
||||
const rootMsg = FeedV1.createRoot(keys, 'post')
|
||||
const rootHash = FeedV1.getMsgHash(rootMsg)
|
||||
|
||||
const tangle = new FeedV1.Tangle(rootHash)
|
||||
tangle.add(rootHash, rootMsg)
|
||||
|
||||
const msg1 = FeedV1.create({
|
||||
keys,
|
||||
content: { text: '1' },
|
||||
type: 'post',
|
||||
tangles: {
|
||||
[rootHash]: tangle,
|
||||
},
|
||||
})
|
||||
const msgHash1 = FeedV1.getMsgHash(msg1)
|
||||
|
||||
const [prevHash] = msg1.metadata.tangles[rootHash].prev
|
||||
msg1.metadata.tangles[rootHash].prev = [prevHash, prevHash]
|
||||
|
||||
const err = FeedV1.validate(msg1, tangle, msgHash1, rootHash)
|
||||
t.ok(err, 'invalid 1st msg throws')
|
||||
t.match(
|
||||
err.message,
|
||||
/prev must be unique set/,
|
||||
'invalid error message'
|
||||
)
|
||||
t.end()
|
||||
})
|
||||
|
|
|
@ -50,7 +50,7 @@ tape('lipmaa prevs', (t) => {
|
|||
t.equals(msg3.metadata.tangles[rootHash].depth, 3, 'msg3 depth')
|
||||
t.deepEquals(
|
||||
msg3.metadata.tangles[rootHash].prev,
|
||||
[rootHash, msgHash2],
|
||||
[rootHash, msgHash2].sort(),
|
||||
'msg3 prev (has lipmaa!)'
|
||||
)
|
||||
|
||||
|
@ -106,7 +106,7 @@ tape('lipmaa prevs', (t) => {
|
|||
t.equals(msg7.metadata.tangles[rootHash].depth, 7, 'msg7 depth')
|
||||
t.deepEquals(
|
||||
msg7.metadata.tangles[rootHash].prev,
|
||||
[msgHash3, msgHash6],
|
||||
[msgHash3, msgHash6].sort(),
|
||||
'msg7 prev (has lipmaa!)'
|
||||
)
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ tape('simple multi-author tangle', (t) => {
|
|||
|
||||
t.deepEquals(
|
||||
Object.keys(msg2.metadata.tangles),
|
||||
[rootHashB, msgHash1],
|
||||
[rootHashB, msgHash1].sort(),
|
||||
'msg2 has feed tangle and misc tangle'
|
||||
)
|
||||
t.equal(msg2.metadata.tangles[rootHashB].depth, 1, 'msg2 feed tangle depth')
|
||||
|
@ -154,7 +154,7 @@ tape('lipmaa in multi-author tangle', (t) => {
|
|||
|
||||
t.deepEquals(
|
||||
msg4.metadata.tangles[msgHash1].prev,
|
||||
[msgHash1, msgHash3],
|
||||
[msgHash1, msgHash3].sort(),
|
||||
'A:msg4 points to A:msg1,B:msg3'
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue