-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable tanglePrune #8
Changes from all commits
936a7ad
921d0d8
5aad75d
ff6905b
b618a94
8077af0
dc4e7bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// SPDX-FileCopyrightText: 2022 Mix Irving | ||
// | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
|
||
const bipf = require('bipf') | ||
|
||
/* eslint-disable camelcase */ | ||
// these variables are calculated in | ||
// test/tangle-prune.test.js | ||
// if these variables are out of date and | ||
// * smaller than supposed to: we'll prune a bit much, tangles will converge a bit slower | ||
// * bigger than supposed to: we'll prune less than we can. users might run into 'the message you want to publish is too big' more often | ||
// but either way no catastrophe | ||
const MAX_SIZE_16_recps = 5546 | ||
const MAX_SIZE_1_recps = 6041 | ||
|
||
module.exports = function tanglePrune(content) { | ||
const tangle = 'group' | ||
const maxSize = | ||
content.recps.length > 1 ? MAX_SIZE_16_recps : MAX_SIZE_1_recps | ||
if (getLength(content) <= maxSize) return content | ||
|
||
content.tangles[tangle].previous = content.tangles[tangle].previous.sort(() => | ||
Math.random() < 0.5 ? -1 : +1 | ||
) | ||
// we shuffle so that if multiple peers are also trying to converge, | ||
// we hopefully tangle differently and converge faster | ||
|
||
while ( | ||
content.tangles[tangle].previous.length && | ||
getLength(content) > maxSize | ||
) { | ||
content.tangles[tangle].previous.pop() | ||
} | ||
|
||
return content | ||
} | ||
|
||
function getLength(obj) { | ||
return bipf.encodingLength(obj) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// SPDX-FileCopyrightText: 2022 Mix Irving | ||
// | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
|
||
const test = require('tape') | ||
const bipf = require('bipf') | ||
const Testbot = require('./helpers/testbot') | ||
const tanglePrune = require('../lib/tangle-prune') | ||
|
||
const chars = 'abcABC123=+? '.split('') | ||
const encodedLength = (obj) => bipf.encodingLength(obj) | ||
const randomChar = () => chars.sort(() => (Math.random() < 0.5 ? -1 : +1))[0] | ||
const randomText = (length) => { | ||
let output = '' | ||
while (output.length < length) output += randomChar() | ||
return output | ||
} | ||
|
||
test('tangle prune', async (t) => { | ||
const ssb = Testbot() | ||
const ssbId = ssb.id | ||
|
||
const group = await ssb.tribes2.create() | ||
|
||
const publishSize = async (size, recpCount = 1) => { | ||
const content = { | ||
type: 'post', | ||
text: randomText(size), | ||
recps: [group.id, ...new Array(recpCount - 1).fill(ssbId)], | ||
} | ||
|
||
return new Promise((resolve, reject) => { | ||
ssb.tribes2.publish(content, (err, msg) => { | ||
if (err) return resolve(false) | ||
|
||
ssb.db.get(msg.key, (err, msgVal) => { | ||
if (err) return reject(err) | ||
const plainLength = encodedLength(msgVal.content) | ||
resolve(plainLength) | ||
}) | ||
}) | ||
}) | ||
} | ||
|
||
async function findMaxSize(numberRecps = 1) { | ||
// Apply bisection method to find max size of a message which can be published | ||
|
||
let lower = 4000 | ||
let mid | ||
let upper = 8000 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔥 set upper to 17000 https://github.com/ssbc/ssb-buttwoo-spec#validation
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we change this to 17000 now then later when I do #10 this test won't start failing. I sort of want it to fail so I know that I actually managed to swap the format. But maybe there are more solid ways to test which format we're using? |
||
|
||
const results = new Map([]) | ||
|
||
//let i = 0 | ||
while (upper - lower > 1) { | ||
mid = Math.ceil((lower + upper) / 2) | ||
|
||
if (!results.has(lower)) { | ||
const res = | ||
results.get(lower) || (await publishSize(lower, numberRecps)) | ||
results.set(lower, res) | ||
} | ||
|
||
if (!results.has(mid)) { | ||
const res = results.get(mid) || (await publishSize(mid, numberRecps)) | ||
results.set(mid, res) | ||
} | ||
if (!results.has(upper)) { | ||
const res = | ||
results.get(upper) || (await publishSize(upper, numberRecps)) | ||
results.set(upper, res) | ||
} | ||
|
||
//console.log(i++, { | ||
// [lower]: results.get(lower), | ||
// [mid]: results.get(mid), | ||
// [upper]: results.get(upper), | ||
//}) | ||
|
||
if (Boolean(results.get(lower)) !== Boolean(results.get(mid))) upper = mid | ||
else if (Boolean(results.get(mid)) !== Boolean(results.get(upper))) | ||
lower = mid | ||
else throw new Error('bisection fail') | ||
} | ||
|
||
const result = results.get(upper) || results.get(mid) || results.get(lower) | ||
t.pass(`max stringied content size for ${numberRecps} recps: ${result}`) | ||
return result | ||
} | ||
const max16recps = await findMaxSize(16).catch(t.error) // 5546 | ||
const max1recp = await findMaxSize(1).catch(t.error) // 6041 | ||
ssb.close() | ||
|
||
const msgId = '%RDORgMCjmL6vs51nR4bn0LWNe6wkBfbRJulSdOJsmwg=.sha256' | ||
const content = (prevCount, numRecps) => ({ | ||
type: 'post', | ||
text: 'hello!', | ||
recps: new Array(numRecps).fill(ssbId), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. technically, this need to follow the format recps: [GroupId, FeedId, ... ] // you need to consider the length of a FeedId here |
||
tangles: { | ||
group: { | ||
root: msgId, | ||
previous: new Array(prevCount).fill(msgId), | ||
}, | ||
}, | ||
}) | ||
|
||
//console.time('prune') | ||
const result16 = tanglePrune(content(4000, 16)) | ||
//console.timeEnd('prune') | ||
t.true( | ||
encodedLength(result16) <= max16recps, | ||
`pruned ${4000 - result16.tangles.group.previous.length}` | ||
) | ||
|
||
const result1 = tanglePrune(content(4000, 1)) | ||
t.true( | ||
encodedLength(result1) <= max1recp, | ||
`pruned ${4000 - result1.tangles.group.previous.length}` | ||
) | ||
Comment on lines
+107
to
+119
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a feeling it's a good idea to check we're in the right ballpark and not just under a certain number. So changing this to something like this instead const e = encodedLength(result16)
t.true(e > max16recps - 200 && e <= max16recps) |
||
|
||
t.end() | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🌶️
(emoji for potential spicy problem)
With different feedFormats, the "id" of an feedId is of different lengths, this means that if
recps
is a GroupId + 15 feedIds.... they could be "sigil" style or "ssb-uri" style.We need to clarify in a spec "when you are DM'ing a person to add them to a group, which feedId do you use?"
Is it their rootFeedId (which is bendy butt ssb-uri?)
cc @arj03
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EASY solution @Powersource - assume all ssb-uri of the longest length, which would currently be:
https://github.com/ssbc/ssb-uri2/blob/main/test/fixtures.js#L17-L26
this long:
or wait... what is this
Yeah we need a spec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can they be URI style though? Have we allowed that anywhere actually?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we also know that this is the longest possible string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also worth considering this
ssb-tribes2/lib/tangle-prune.js
Lines 8 to 15 in dc4e7bf