some breaking change renaming

msgHash => msgID
Feed root => moot
rec.hash => rec.id
This commit is contained in:
Andre Staltz 2023-08-28 15:14:15 +03:00
parent c06828cd99
commit c76584953b
No known key found for this signature in database
GPG Key ID: 9EDE23EA7E8A4890
24 changed files with 549 additions and 607 deletions

View File

@ -64,7 +64,7 @@ function decrypt(rec, peer, config) {
const msgDecrypted = MsgV3.fromPlaintextBuffer(plaintextBuf, msgEncrypted) const msgDecrypted = MsgV3.fromPlaintextBuffer(plaintextBuf, msgEncrypted)
return { return {
hash: rec.hash, id: rec.id,
msg: msgDecrypted, msg: msgDecrypted,
received: rec.received, received: rec.received,
misc: { misc: {
@ -78,20 +78,18 @@ function decrypt(rec, peer, config) {
/** /**
* @param {RecPresent} rec * @param {RecPresent} rec
* @returns {RecPresent}
*/ */
function reEncrypt(rec) { function reEncrypt(rec) {
return { return {
hash: rec.hash, id: rec.id,
msg: { ...rec.msg, data: rec.misc.originalData }, msg: { ...rec.msg, data: rec.misc.originalData },
received: rec.received, received: rec.received,
...(rec.misc.size misc: {
? { seq: rec.misc.seq,
misc: { offset: rec.misc.offset,
offset: rec.misc.offset, size: rec.misc.size,
size: rec.misc.size, },
},
}
: null),
} }
} }

View File

@ -31,7 +31,7 @@ const { decrypt } = require('./encryption')
/** /**
* @typedef {{ * @typedef {{
* hash?: never; * id?: never;
* msg?: never; * msg?: never;
* received?: never; * received?: never;
* misc: { * misc: {
@ -42,7 +42,7 @@ const { decrypt } = require('./encryption')
* }} RecDeleted * }} RecDeleted
* *
* @typedef {{ * @typedef {{
* hash: string; * id: string;
* msg: Msg; * msg: Msg;
* received: number; * received: number;
* misc: { * misc: {
@ -69,26 +69,26 @@ const { decrypt } = require('./encryption')
class DBTangle extends MsgV3.Tangle { class DBTangle extends MsgV3.Tangle {
/** /**
* @param {string} rootHash * @param {string} rootID
* @param {Iterable<Rec>} recordsIter * @param {Iterable<Rec>} recordsIter
*/ */
constructor(rootHash, recordsIter) { constructor(rootID, recordsIter) {
super(rootHash) super(rootID)
for (const rec of recordsIter) { for (const rec of recordsIter) {
if (!rec.msg) continue if (!rec.msg) continue
this.add(rec.hash, rec.msg) this.add(rec.id, rec.msg)
} }
} }
/** /**
* @param {string} msgHash * @param {string} msgID
*/ */
getDeletablesAndErasables(msgHash) { getDeletablesAndErasables(msgID) {
const erasables = this.shortestPathToRoot(msgHash) const erasables = this.shortestPathToRoot(msgID)
const sorted = this.topoSort() const sorted = this.topoSort()
const index = sorted.indexOf(msgHash) const index = sorted.indexOf(msgID)
const deletables = sorted.filter( const deletables = sorted.filter(
(msgHash, i) => i < index && !erasables.includes(msgHash) (id, i) => i < index && !erasables.includes(id)
) )
return { deletables, erasables } return { deletables, erasables }
} }
@ -180,14 +180,14 @@ function initDB(peer, config) {
}) })
/** /**
* @param {string} hash * @param {string} id
* @param {Msg} msg * @param {Msg} msg
* @param {CB<Rec>} cb * @param {CB<RecPresent>} cb
*/ */
function logAppend(hash, msg, cb) { function logAppend(id, msg, cb) {
/** @type {RecPresent} */ /** @type {RecPresent} */
const rec = { const rec = {
hash, id,
msg, msg,
received: Date.now(), received: Date.now(),
misc: { misc: {
@ -244,13 +244,13 @@ function initDB(peer, config) {
} }
/** /**
* @param {Array<string>} tangleIds * @param {Array<string>} tangleIDs
*/ */
function populateTangles(tangleIds) { function populateTangles(tangleIDs) {
/** @type {Record<string, DBTangle>} */ /** @type {Record<string, DBTangle>} */
const tangles = {} const tangles = {}
for (const tangleId of tangleIds) { for (const tangleID of tangleIDs) {
tangles[tangleId] ??= new DBTangle(tangleId, records()) tangles[tangleID] ??= new DBTangle(tangleID, records())
} }
return tangles return tangles
} }
@ -265,21 +265,21 @@ function initDB(peer, config) {
/** /**
* @param {Msg} msg * @param {Msg} msg
* @param {string} tangleRootHash * @param {string} tangleID
* @param {CB<Rec>} cb * @param {CB<RecPresent>} cb
*/ */
function add(msg, tangleRootHash, cb) { function add(msg, tangleID, cb) {
const msgHash = MsgV3.getMsgHash(msg) const msgID = MsgV3.getMsgID(msg)
// TODO: optimize this. Perhaps have a Map() of msgHash -> record // TODO: optimize this. Perhaps have a Map() of msgID -> record
// Or even better, a bloom filter. If you just want to answer no/perhaps. // Or even better, a bloom filter. If you just want to answer no/perhaps.
let rec let rec
if ((rec = getRecord(msgHash))) return cb(null, rec) if ((rec = getRecord(msgID))) return cb(null, rec)
else rec = { msg, hash: msgHash } else rec = { msg, id: msgID }
// TODO: optimize this. This may be slow if you're adding many msgs in a // TODO: optimize this. This may be slow if you're adding many msgs in a
// row, because it creates a new Map() each time. Perhaps with QuickLRU // row, because it creates a new Map() each time. Perhaps with QuickLRU
const tangle = new DBTangle(tangleRootHash, records()) const tangle = new DBTangle(tangleID, records())
// Find which pubkeys are authorized to sign this msg given the account: // Find which pubkeys are authorized to sign this msg given the account:
const pubkeys = new Set() const pubkeys = new Set()
@ -292,8 +292,8 @@ function initDB(peer, config) {
return cb(new Error('add() failed because the account tangle is unknown')) return cb(new Error('add() failed because the account tangle is unknown'))
} }
// TODO: prune the accountTangle beyond msg.metadata.accountTips // TODO: prune the accountTangle beyond msg.metadata.accountTips
for (const msgHash of accountTangle.topoSort()) { for (const msgID of accountTangle.topoSort()) {
const msg = get(msgHash) const msg = get(msgID)
if (!msg?.data) continue if (!msg?.data) continue
/** @type {AccountData} */ /** @type {AccountData} */
const data = msg.data const data = msg.data
@ -305,7 +305,7 @@ function initDB(peer, config) {
} }
let err let err
if ((err = MsgV3.validate(msg, tangle, pubkeys, msgHash, tangleRootHash))) { if ((err = MsgV3.validate(msg, tangle, pubkeys, msgID, tangleID))) {
return cb(new Error('add() failed msg validation', { cause: err })) return cb(new Error('add() failed msg validation', { cause: err }))
} }
@ -325,7 +325,7 @@ function initDB(peer, config) {
// TODO validate 'del' // TODO validate 'del'
} }
logAppend(msgHash, msg, (err, rec) => { logAppend(msgID, 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)
@ -340,31 +340,30 @@ function initDB(peer, config) {
const keypair = opts.keypair ?? config.keypair const keypair = opts.keypair ?? config.keypair
const { account, domain } = opts const { account, domain } = opts
const feedRootHash = getFeedId(account, domain) const mootID = getFeedID(account, domain)
if (feedRootHash) return cb(null, feedRootHash) if (mootID) return cb(null, mootID)
const feedRoot = MsgV3.createRoot(account, domain, keypair) const moot = MsgV3.createMoot(account, domain, keypair)
add(feedRoot, MsgV3.getMsgHash(feedRoot), (err, rec) => { add(moot, MsgV3.getMsgID(moot), (err, rec) => {
// prettier-ignore // prettier-ignore
if (err) return cb(new Error('initializeFeed() failed to add root', { cause: err })); if (err) return cb(new Error('initializeFeed() failed to add root', { cause: err }));
const recHash = /** @type {string} */ (rec.hash) cb(null, rec.id)
cb(null, recHash)
}) })
} }
/** /**
* Public the account ID from the given record. * Public the account ID from the given record.
* *
* @param {Pick<RecPresent, 'msg' | 'hash'>} rec * @param {Pick<RecPresent, 'msg' | 'id'>} rec
* @returns {string | null} * @returns {string | null}
*/ */
function getAccountID(rec) { function getAccountID(rec) {
if (!rec.msg) return null if (!rec.msg) return null
if (rec.msg.metadata.account === ACCOUNT_SELF) { if (rec.msg.metadata.account === ACCOUNT_SELF) {
for (const tangleId in rec.msg.metadata.tangles) { for (const tangleID in rec.msg.metadata.tangles) {
return tangleId return tangleID
} }
return rec.hash return rec.id
} else if (rec.msg.metadata.account) { } else if (rec.msg.metadata.account) {
return rec.msg.metadata.account return rec.msg.metadata.account
} else { } else {
@ -398,9 +397,9 @@ function initDB(peer, config) {
if (rec.msg.metadata.domain !== domain) continue if (rec.msg.metadata.domain !== domain) continue
const data = /** @type {AccountData} */ (rec.msg.data) const data = /** @type {AccountData} */ (rec.msg.data)
if (data.action === 'add' && data.add.key.bytes === keypair.public) { if (data.action === 'add' && data.add.key.bytes === keypair.public) {
const accountId = getAccountID(rec) const accountID = getAccountID(rec)
if (accountId) { if (accountID) {
cb(null, accountId) cb(null, accountID)
} else { } else {
// prettier-ignore // prettier-ignore
cb(new Error(`account.find() failed to find ID in ${JSON.stringify(rec.msg)}`)) cb(new Error(`account.find() failed to find ID in ${JSON.stringify(rec.msg)}`))
@ -427,8 +426,8 @@ function initDB(peer, config) {
const keypair = opts?.keypair ?? config.keypair const keypair = opts?.keypair ?? config.keypair
const accountTangle = new DBTangle(opts.account, records()) const accountTangle = new DBTangle(opts.account, records())
for (const msgHash of accountTangle.topoSort()) { for (const msgID of accountTangle.topoSort()) {
const msg = get(msgHash) const msg = get(msgID)
if (!msg?.data) continue if (!msg?.data) continue
/** @type {AccountData} */ /** @type {AccountData} */
const data = msg.data const data = msg.data
@ -465,14 +464,13 @@ function initDB(peer, config) {
} catch (err) { } catch (err) {
return cb(new Error('account.create() failed', { cause: err })) return cb(new Error('account.create() failed', { cause: err }))
} }
const msgHash = MsgV3.getMsgHash(msg) const msgID = MsgV3.getMsgID(msg)
logAppend(msgHash, msg, (err, rec) => { logAppend(msgID, msg, (err, rec) => {
// prettier-ignore // prettier-ignore
if (err) return cb(new Error('account.create() failed in the log', { cause: err })) if (err) return cb(new Error('account.create() failed in the log', { cause: err }))
onRecordAdded.set(rec) onRecordAdded.set(rec)
const recHash = /** @type {string} */ (rec.hash) cb(null, rec.id)
cb(null, recHash)
}) })
} }
@ -507,8 +505,8 @@ function initDB(peer, config) {
*/ */
function getAccountPowers(accountTangle, keypair) { function getAccountPowers(accountTangle, keypair) {
const powers = new Set() const powers = new Set()
for (const msgHash of accountTangle.topoSort()) { for (const msgID of accountTangle.topoSort()) {
const msg = get(msgHash) const msg = get(msgID)
if (!msg?.data) continue if (!msg?.data) continue
/** @type {AccountData} */ /** @type {AccountData} */
const data = msg.data const data = msg.data
@ -564,7 +562,7 @@ function initDB(peer, config) {
* keypair: Keypair; * keypair: Keypair;
* consent?: never; * consent?: never;
* })} opts * })} opts
* @param {CB<Rec>} cb * @param {CB<RecPresent>} cb
*/ */
function addToAccount(opts, cb) { function addToAccount(opts, cb) {
if (!opts) return cb(new Error('account.add() requires an `opts`')) if (!opts) return cb(new Error('account.add() requires an `opts`'))
@ -659,9 +657,9 @@ function initDB(peer, config) {
} catch (err) { } catch (err) {
return cb(new Error('account.add() failed', { cause: err })) return cb(new Error('account.add() failed', { cause: err }))
} }
const msgHash = MsgV3.getMsgHash(msg) const msgID = MsgV3.getMsgID(msg)
logAppend(msgHash, msg, (err, rec) => { logAppend(msgID, msg, (err, rec) => {
// prettier-ignore // prettier-ignore
if (err) return cb(new Error('account.add() failed to append the log', { cause: err })) if (err) return cb(new Error('account.add() failed to append the log', { cause: err }))
onRecordAdded.set(rec) onRecordAdded.set(rec)
@ -678,7 +676,7 @@ function initDB(peer, config) {
* account: string; * account: string;
* tangles?: Array<string>; * tangles?: Array<string>;
* }} opts * }} opts
* @param {CB<Rec>} cb * @param {CB<RecPresent>} cb
*/ */
function publishToFeed(opts, cb) { function publishToFeed(opts, cb) {
if (!opts) return cb(new Error('feed.publish() requires an `opts`')) if (!opts) return cb(new Error('feed.publish() requires an `opts`'))
@ -695,13 +693,13 @@ function initDB(peer, config) {
if (!opts.account) if (!opts.account)
return cb(new Error('feed.publish() requires a `account`')) return cb(new Error('feed.publish() requires a `account`'))
initializeFeed(opts, (err, feedRootHash) => { initializeFeed(opts, (err, mootID) => {
// prettier-ignore // prettier-ignore
if (err) return cb(new Error('feed.publish() failed to initialize feed', { cause: err })); if (err) return cb(new Error('feed.publish() failed to initialize feed', { cause: err }));
// Fill-in tangle opts: // Fill-in tangle opts:
const tangleTemplates = opts.tangles ?? [] const tangleTemplates = opts.tangles ?? []
tangleTemplates.push(feedRootHash) tangleTemplates.push(mootID)
const tangles = populateTangles(tangleTemplates) const tangles = populateTangles(tangleTemplates)
const accountTangle = new DBTangle(opts.account, records()) const accountTangle = new DBTangle(opts.account, records())
const accountTips = [...accountTangle.getTips()] const accountTips = [...accountTangle.getTips()]
@ -746,10 +744,10 @@ function initDB(peer, config) {
} catch (err) { } catch (err) {
return cb(new Error('feed.publish() failed', { cause: err })) return cb(new Error('feed.publish() failed', { cause: err }))
} }
const msgHash = MsgV3.getMsgHash(msg) const msgID = MsgV3.getMsgID(msg)
// Encode the native message and append it to the log: // Encode the native message and append it to the log:
logAppend(msgHash, msg, (err, rec) => { logAppend(msgID, msg, (err, rec) => {
// prettier-ignore // prettier-ignore
if (err) return cb(new Error('feed.publish() failed to append the log', { cause: err })) if (err) return cb(new Error('feed.publish() failed to append the log', { cause: err }))
onRecordAdded.set(rec) onRecordAdded.set(rec)
@ -762,45 +760,46 @@ function initDB(peer, config) {
* @param {string} id * @param {string} id
* @param {string} findDomain * @param {string} findDomain
*/ */
function getFeedId(id, findDomain) { function getFeedID(id, findDomain) {
const findAccount = MsgV3.stripAccount(id) const findAccount = MsgV3.stripAccount(id)
for (const rec of records()) { for (const rec of records()) {
if (rec.msg && MsgV3.isFeedRoot(rec.msg, findAccount, findDomain)) { if (rec.msg && MsgV3.isMoot(rec.msg, findAccount, findDomain)) {
return rec.hash return rec.id
} }
} }
return null return null
} }
/** /**
* @param {string} msgId * @param {string} msgID
* @returns {RecPresent | null}
*/ */
function getRecord(msgId) { function getRecord(msgID) {
// TODO: improve performance of this when getting many messages, the arg // TODO: improve performance of this when getting many messages, the arg
// could be an array of hashes, so we can do a single pass over the records. // could be an array of hashes, so we can do a single pass over the records.
const isUri = msgId.startsWith('ppppp:') const isUri = msgID.startsWith('ppppp:')
for (let i = 0; i < recs.length; i++) { for (let i = 0; i < recs.length; i++) {
const rec = recs[i] const rec = recs[i]
if (!rec) continue if (!rec) continue
if (isUri && rec.hash && msgId.endsWith(rec.hash)) return rec if (isUri && rec.id && msgID.endsWith(rec.id)) return rec
else if (!isUri && rec.hash === msgId) return rec else if (!isUri && rec.id === msgID) return rec
} }
return null return null
} }
/** /**
* @param {string} msgId * @param {string} msgID
*/ */
function get(msgId) { function get(msgID) {
return getRecord(msgId)?.msg return getRecord(msgID)?.msg
} }
/** /**
* @param {string} msgId * @param {string} msgID
* @param {CBVoid} cb * @param {CBVoid} cb
*/ */
function del(msgId, cb) { function del(msgID, cb) {
const rec = getRecord(msgId) const rec = getRecord(msgID)
if (!rec) return cb() if (!rec) return cb()
if (!rec.msg) return cb() if (!rec.msg) return cb()
const { offset, size, seq } = rec.misc const { offset, size, seq } = rec.misc
@ -811,11 +810,11 @@ function initDB(peer, config) {
} }
/** /**
* @param {string} msgId * @param {string} msgID
* @param {CBVoid} cb * @param {CBVoid} cb
*/ */
function erase(msgId, cb) { function erase(msgID, cb) {
const rec = getRecord(msgId) const rec = getRecord(msgID)
if (!rec) return cb() if (!rec) return cb()
if (!rec.msg) return cb() if (!rec.msg) return cb()
if (!rec.msg.data) return cb() if (!rec.msg.data) return cb()
@ -825,11 +824,11 @@ function initDB(peer, config) {
} }
/** /**
* @param {string} tangleId * @param {string} tangleID
* @returns {DBTangle} * @returns {DBTangle}
*/ */
function getTangle(tangleId) { function getTangle(tangleID) {
return new DBTangle(tangleId, records()) return new DBTangle(tangleID, records())
} }
function* msgs() { function* msgs() {
@ -861,7 +860,7 @@ function initDB(peer, config) {
}, },
feed: { feed: {
publish: publishToFeed, publish: publishToFeed,
getId: getFeedId, getID: getFeedID,
}, },
getRecord, getRecord,
get, get,

View File

@ -23,7 +23,7 @@ function getMsgHashBuf(msg) {
* @param {Msg | string} x * @param {Msg | string} x
* @returns {string} * @returns {string}
*/ */
function getMsgHash(x) { function getMsgID(x) {
if (typeof x === 'string') { if (typeof x === 'string') {
if (x.startsWith('ppppp:message/v3/')) { if (x.startsWith('ppppp:message/v3/')) {
const msgUri = x const msgUri = x
@ -44,9 +44,9 @@ function getMsgHash(x) {
* @param {Msg} msg * @param {Msg} msg
* @returns {string} * @returns {string}
*/ */
function getMsgId(msg) { function getMsgURI(msg) {
const { account, domain } = msg.metadata const { account, domain } = msg.metadata
const msgHash = getMsgHash(msg) const msgHash = getMsgID(msg)
if (domain) { if (domain) {
return `ppppp:message/v3/${account}/${domain}/${msgHash}` return `ppppp:message/v3/${account}/${domain}/${msgHash}`
} else { } else {
@ -54,4 +54,4 @@ function getMsgId(msg) {
} }
} }
module.exports = { getMsgId, getMsgHash } module.exports = { getMsgURI, getMsgID }

View File

@ -7,14 +7,14 @@ const Keypair = require('ppppp-keypair')
// @ts-ignore // @ts-ignore
const union = require('set.prototype.union') const union = require('set.prototype.union')
const { stripAccount } = require('./strip') const { stripAccount } = require('./strip')
const isFeedRoot = require('./is-feed-root') const isMoot = require('./is-moot')
const { getMsgId, getMsgHash } = require('./get-msg-id') const { getMsgID } = require('./get-msg-id')
const representData = require('./represent-data') const representData = require('./represent-data')
const { const {
validateDomain, validateDomain,
validateData, validateData,
validate, validate,
validateMsgHash, validateMsgID,
} = require('./validation') } = require('./validation')
const Tangle = require('./tangle') const Tangle = require('./tangle')
const { const {
@ -101,7 +101,7 @@ const { isEmptyObject } = require('./util')
* @param {string} domain * @param {string} domain
* @returns {string} * @returns {string}
*/ */
function getFeedRootHash(id, domain) { function getMootID(id, domain) {
/** @type {Msg} */ /** @type {Msg} */
const msg = { const msg = {
data: null, data: null,
@ -118,7 +118,7 @@ function getFeedRootHash(id, domain) {
sig: '', sig: '',
} }
return getMsgHash(msg) return getMsgID(msg)
} }
/** /**
@ -144,18 +144,18 @@ function create(opts) {
const tangles = /** @type {Msg['metadata']['tangles']} */ ({}) const tangles = /** @type {Msg['metadata']['tangles']} */ ({})
if (opts.tangles) { if (opts.tangles) {
for (const rootId in opts.tangles) { for (const rootID in opts.tangles) {
if ((err = validateMsgHash(rootId))) throw err if ((err = validateMsgID(rootID))) throw err
const tangle = opts.tangles[rootId] const tangle = opts.tangles[rootID]
const depth = tangle.getMaxDepth() + 1 const depth = tangle.getMaxDepth() + 1
const tips = tangle.getTips() const tips = tangle.getTips()
const lipmaaSet = tangle.getLipmaaSet(depth) const lipmaaSet = tangle.getLipmaaSet(depth)
const prev = [...union(lipmaaSet, tips)].sort() const prev = [...union(lipmaaSet, tips)].sort()
tangles[rootId] = { depth, prev } tangles[rootID] = { depth, prev }
} }
} else { } else {
// prettier-ignore // prettier-ignore
throw new Error(`cannot create msg without tangles, that's the case for createRoot()`) throw new Error(`cannot create msg without tangles, that's the case for createMoot()`)
} }
/** @type {Msg} */ /** @type {Msg} */
@ -190,7 +190,7 @@ function create(opts) {
* @param {Keypair} keypair * @param {Keypair} keypair
* @returns {Msg} * @returns {Msg}
*/ */
function createRoot(id, domain, keypair) { function createMoot(id, domain, keypair) {
let err let err
if ((err = validateDomain(domain))) throw err if ((err = validateDomain(domain))) throw err
@ -279,18 +279,17 @@ function isRoot(msg) {
} }
module.exports = { module.exports = {
getMsgHash, isMoot,
getMsgId, isRoot,
isFeedRoot, getMsgID,
getFeedRootHash, getMootID,
create, create,
createRoot, createMoot,
createAccount, createAccount,
erase, erase,
stripAccount, stripAccount,
toPlaintextBuffer, toPlaintextBuffer,
fromPlaintextBuffer, fromPlaintextBuffer,
isRoot,
Tangle, Tangle,
validate, validate,
} }

View File

@ -10,7 +10,7 @@ const { isEmptyObject } = require('./util')
* @param {string | 0} id * @param {string | 0} id
* @param {string | 0} findDomain * @param {string | 0} findDomain
*/ */
function isFeedRoot(msg, id = 0, findDomain = 0) { function isMoot(msg, id = 0, findDomain = 0) {
const { dataHash, dataSize, account, accountTips, tangles, domain } = const { dataHash, dataSize, account, accountTips, tangles, domain } =
msg.metadata msg.metadata
if (dataHash !== null) return false if (dataHash !== null) return false
@ -23,4 +23,4 @@ function isFeedRoot(msg, id = 0, findDomain = 0) {
return true return true
} }
module.exports = isFeedRoot module.exports = isMoot

View File

@ -1,25 +1,7 @@
const { getMsgHash } = require('./get-msg-id')
/** /**
* @typedef {import('.').Msg} Msg * @typedef {import('.').Msg} Msg
*/ */
/**
* @param {any} msgKey
*/
function stripMsgKey(msgKey) {
if (typeof msgKey === 'object') {
if (msgKey.key) return stripMsgKey(msgKey.key)
else return getMsgHash(msgKey)
}
if (msgKey.startsWith('ppppp:message/v3/')) {
const parts = msgKey.split('/')
return parts[parts.length - 1]
} else {
return msgKey
}
}
/** /**
* @param {string} id * @param {string} id
* @returns {string} * @returns {string}
@ -31,6 +13,5 @@ function stripAccount(id) {
} }
module.exports = { module.exports = {
stripMsgKey,
stripAccount, stripAccount,
} }

View File

@ -1,3 +1,5 @@
const isMoot = require('./is-moot')
/** /**
* @typedef {import("./index").Msg} Msg * @typedef {import("./index").Msg} Msg
*/ */
@ -38,7 +40,7 @@ function lipmaa(n) {
* @param {string} b * @param {string} b
* @returns number * @returns number
*/ */
function compareMsgHashes(a, b) { function compareMsgIDs(a, b) {
return a.localeCompare(b) return a.localeCompare(b)
} }
@ -46,7 +48,7 @@ class Tangle {
/** /**
* @type {string} * @type {string}
*/ */
#rootHash #rootID
/** /**
* @type {Msg | undefined} * @type {Msg | undefined}
@ -79,41 +81,41 @@ class Tangle {
#maxDepth #maxDepth
/** /**
* @param {string} rootHash * @param {string} rootID
*/ */
constructor(rootHash) { constructor(rootID) {
this.#rootHash = rootHash this.#rootID = rootID
this.#maxDepth = 0 this.#maxDepth = 0
} }
/** /**
* @param {string} msgHash * @param {string} msgID
* @param {Msg} msg * @param {Msg} msg
*/ */
add(msgHash, msg) { add(msgID, msg) {
if (msgHash === this.#rootHash && !this.#rootMsg) { if (msgID === this.#rootID && !this.#rootMsg) {
this.#tips.add(msgHash) this.#tips.add(msgID)
this.#perDepth.set(0, [msgHash]) this.#perDepth.set(0, [msgID])
this.#depth.set(msgHash, 0) this.#depth.set(msgID, 0)
this.#rootMsg = msg this.#rootMsg = msg
return return
} }
const tangles = msg.metadata.tangles const tangles = msg.metadata.tangles
if (msgHash !== this.#rootHash && tangles[this.#rootHash]) { if (msgID !== this.#rootID && tangles[this.#rootID]) {
if (this.#depth.has(msgHash)) return if (this.#depth.has(msgID)) return
this.#tips.add(msgHash) this.#tips.add(msgID)
const prev = tangles[this.#rootHash].prev const prev = tangles[this.#rootID].prev
for (const p of prev) { for (const p of prev) {
this.#tips.delete(p) this.#tips.delete(p)
} }
this.#prev.set(msgHash, prev) this.#prev.set(msgID, prev)
const depth = tangles[this.#rootHash].depth const depth = tangles[this.#rootID].depth
if (depth > this.#maxDepth) this.#maxDepth = depth if (depth > this.#maxDepth) this.#maxDepth = depth
this.#depth.set(msgHash, depth) this.#depth.set(msgID, depth)
const atDepth = this.#perDepth.get(depth) ?? [] const atDepth = this.#perDepth.get(depth) ?? []
atDepth.push(msgHash) atDepth.push(msgID)
atDepth.sort(compareMsgHashes) atDepth.sort(compareMsgIDs)
this.#perDepth.set(depth, atDepth) this.#perDepth.set(depth, atDepth)
return return
} }
@ -139,8 +141,8 @@ class Tangle {
const max = this.#maxDepth const max = this.#maxDepth
for (let i = 0; i <= max; i++) { for (let i = 0; i <= max; i++) {
const atDepth = this.#getAllAtDepth(i) const atDepth = this.#getAllAtDepth(i)
for (const msgHash of atDepth) { for (const msgID of atDepth) {
sorted.push(msgHash) sorted.push(msgID)
} }
} }
return sorted return sorted
@ -171,19 +173,19 @@ class Tangle {
} }
/** /**
* @param {string} msgHash * @param {string} msgID
* @returns {boolean} * @returns {boolean}
*/ */
has(msgHash) { has(msgID) {
return this.#depth.has(msgHash) return this.#depth.has(msgID)
} }
/** /**
* @param {string} msgHash * @param {string} msgID
* @returns {number} * @returns {number}
*/ */
getDepth(msgHash) { getDepth(msgID) {
return this.#depth.get(msgHash) ?? -1 return this.#depth.get(msgID) ?? -1
} }
isFeed() { isFeed() {
@ -191,34 +193,29 @@ class Tangle {
console.trace('Tangle is missing root message') console.trace('Tangle is missing root message')
return false return false
} }
if (this.#rootMsg.data) return false return isMoot(this.#rootMsg)
const metadata = this.#rootMsg.metadata
if (metadata.dataSize > 0) return false
if (metadata.dataHash !== null) return false
if (metadata.accountTips !== null) return false
return true
} }
getFeed() { getMoot() {
if (!this.isFeed()) return null if (!this.isFeed()) return null
if (!this.#rootMsg) { if (!this.#rootMsg) {
console.trace('Tangle is missing root message') console.trace('Tangle is missing root message')
return null return null
} }
const { account, domain } = this.#rootMsg.metadata const { account, domain } = this.#rootMsg.metadata
return { account, domain } return { account, domain, id: this.#rootID }
} }
/** /**
* @param {string} msgHash * @param {string} msgID
*/ */
shortestPathToRoot(msgHash) { shortestPathToRoot(msgID) {
if (!this.#rootMsg) { if (!this.#rootMsg) {
console.trace('Tangle is missing root message') console.trace('Tangle is missing root message')
return [] return []
} }
const path = [] const path = []
let current = msgHash let current = msgID
while (true) { while (true) {
const prev = this.#prev.get(current) const prev = this.#prev.get(current)
if (!prev) break if (!prev) break
@ -229,7 +226,7 @@ class Tangle {
if (d < minDepth) { if (d < minDepth) {
minDepth = d minDepth = d
min = p min = p
} else if (d === minDepth && compareMsgHashes(p, min) < 0) { } else if (d === minDepth && compareMsgIDs(p, min) < 0) {
min = p min = p
} }
} }
@ -240,21 +237,21 @@ class Tangle {
} }
/** /**
* @param {string} msgHashA * @param {string} msgAID
* @param {string} msgHashB * @param {string} msgBID
*/ */
precedes(msgHashA, msgHashB) { precedes(msgAID, msgBID) {
if (!this.#rootMsg) { if (!this.#rootMsg) {
console.trace('Tangle is missing root message') console.trace('Tangle is missing root message')
return false return false
} }
if (msgHashA === msgHashB) return false if (msgAID === msgBID) return false
if (msgHashB === this.#rootHash) return false if (msgBID === this.#rootID) return false
let toCheck = [msgHashB] let toCheck = [msgBID]
while (toCheck.length > 0) { while (toCheck.length > 0) {
const prev = this.#prev.get(/** @type {string} */ (toCheck.shift())) const prev = this.#prev.get(/** @type {string} */ (toCheck.shift()))
if (!prev) continue if (!prev) continue
if (prev.includes(msgHashA)) return true if (prev.includes(msgAID)) return true
toCheck.push(...prev) toCheck.push(...prev)
} }
return false return false

View File

@ -5,7 +5,7 @@ const Keypair = require('ppppp-keypair')
const stringify = require('json-canon') const stringify = require('json-canon')
const Tangle = require('./tangle') const Tangle = require('./tangle')
const representData = require('./represent-data') const representData = require('./represent-data')
const isFeedRoot = require('./is-feed-root') const isMoot = require('./is-moot')
const { SIGNATURE_TAG_MSG_V3, ACCOUNT_SELF } = require('./constants') const { SIGNATURE_TAG_MSG_V3, ACCOUNT_SELF } = require('./constants')
/** /**
@ -87,7 +87,7 @@ function validatePubkey(msg) {
*/ */
function validateAccountPubkey(msg, pubkeys) { function validateAccountPubkey(msg, pubkeys) {
// Unusual case: if the msg is a feed root, ignore the account and pubkey // Unusual case: if the msg is a feed root, ignore the account and pubkey
if (isFeedRoot(msg)) return if (isMoot(msg)) return
if ( if (
msg.metadata.account && msg.metadata.account &&
@ -103,7 +103,7 @@ function validateAccountPubkey(msg, pubkeys) {
* @param {string} str * @param {string} str
* @returns {string | undefined} * @returns {string | undefined}
*/ */
function validateMsgHash(str) { function validateMsgID(str) {
try { try {
const hashBuf = b4a.from(base58.decode(str)) const hashBuf = b4a.from(base58.decode(str))
if (hashBuf.length !== 16) { if (hashBuf.length !== 16) {
@ -111,7 +111,7 @@ function validateMsgHash(str) {
return `invalid message: decoded hash should be 16 bytes but was ${hashBuf.length}` return `invalid message: decoded hash should be 16 bytes but was ${hashBuf.length}`
} }
} catch (err) { } catch (err) {
return `invalid message: msgHash "${str}" should have been a base58 string` return `invalid message: msgID "${str}" should have been a base58 string`
} }
} }
@ -163,21 +163,21 @@ function validateSignature(msg) {
} }
/** /**
* @typedef {NonNullable<ReturnType<Tangle['getFeed']>>} FeedDetails * @typedef {NonNullable<ReturnType<Tangle['getMoot']>>} FeedDetails
*/ */
/** /**
* @param {Msg} msg * @param {Msg} msg
* @param {Tangle} tangle * @param {Tangle} tangle
* @param {string} tangleId * @param {string} tangleID
* @returns * @returns
*/ */
function validateTangle(msg, tangle, tangleId) { function validateTangle(msg, tangle, tangleID) {
if (!msg.metadata.tangles[tangleId]) { if (!msg.metadata.tangles[tangleID]) {
// prettier-ignore // prettier-ignore
return `invalid message: must have metadata.tangles.${tangleId}\n` + JSON.stringify(msg) return `invalid message: must have metadata.tangles.${tangleID}\n` + JSON.stringify(msg)
} }
const { depth, prev } = msg.metadata.tangles[tangleId] const { depth, prev } = msg.metadata.tangles[tangleID]
if (!prev || !Array.isArray(prev)) { if (!prev || !Array.isArray(prev)) {
// prettier-ignore // prettier-ignore
return `invalid message: prev "${prev}" should have been an array\n` + JSON.stringify(msg) return `invalid message: prev "${prev}" should have been an array\n` + JSON.stringify(msg)
@ -187,7 +187,7 @@ function validateTangle(msg, tangle, tangleId) {
return `invalid message: depth "${depth}" should have been a positive integer\n` + JSON.stringify(msg) return `invalid message: depth "${depth}" should have been a positive integer\n` + JSON.stringify(msg)
} }
if (tangle.isFeed()) { if (tangle.isFeed()) {
const { account, domain } = /** @type {FeedDetails} */ (tangle.getFeed()) const { account, domain } = /** @type {FeedDetails} */ (tangle.getMoot())
if (domain !== msg.metadata.domain) { if (domain !== msg.metadata.domain) {
// prettier-ignore // prettier-ignore
return `invalid message: domain "${msg.metadata.domain}" should have been feed domain "${domain}"\n` + JSON.stringify(msg) return `invalid message: domain "${msg.metadata.domain}" should have been feed domain "${domain}"\n` + JSON.stringify(msg)
@ -248,17 +248,17 @@ function validateTangle(msg, tangle, tangleId) {
/** /**
* @param {Msg} msg * @param {Msg} msg
* @param {string} msgHash * @param {string} msgID
* @param {string} tangleId * @param {string} tangleID
*/ */
function validateTangleRoot(msg, msgHash, tangleId) { function validateTangleRoot(msg, msgID, tangleID) {
if (msgHash !== tangleId) { if (msgID !== tangleID) {
// prettier-ignore // prettier-ignore
return `invalid message: tangle root hash "${msgHash}" must match tangleId "${tangleId}"\n` + JSON.stringify(msg) return `invalid message: tangle root "${msgID}" must match tangleID "${tangleID}"\n` + JSON.stringify(msg)
} }
if (msg.metadata.tangles[tangleId]) { if (msg.metadata.tangles[tangleID]) {
// prettier-ignore // prettier-ignore
return `invalid message: tangle root "${tangleId}" must not have self tangle data\n` + JSON.stringify(msg) return `invalid message: tangle root "${tangleID}" must not have self tangle data\n` + JSON.stringify(msg)
} }
} }
@ -319,10 +319,10 @@ function validateData(msg) {
* @param {Msg} msg * @param {Msg} msg
* @param {Tangle} tangle * @param {Tangle} tangle
* @param {Set<string>} pubkeys * @param {Set<string>} pubkeys
* @param {string} msgHash * @param {string} msgID
* @param {string} rootHash * @param {string} rootID
*/ */
function validate(msg, tangle, pubkeys, msgHash, rootHash) { function validate(msg, tangle, pubkeys, msgID, rootID) {
let err let err
if ((err = validateShape(msg))) return err if ((err = validateShape(msg))) return err
if ((err = validatePubkey(msg))) return err if ((err = validatePubkey(msg))) return err
@ -331,9 +331,9 @@ function validate(msg, tangle, pubkeys, msgHash, rootHash) {
if ((err = validateDomain(msg.metadata.domain))) return err if ((err = validateDomain(msg.metadata.domain))) return err
if ((err = validateAccountPubkey(msg, pubkeys))) return err if ((err = validateAccountPubkey(msg, pubkeys))) return err
if (tangle.size() === 0) { if (tangle.size() === 0) {
if ((err = validateTangleRoot(msg, msgHash, rootHash))) return err if ((err = validateTangleRoot(msg, msgID, rootID))) return err
} else { } else {
if ((err = validateTangle(msg, tangle, rootHash))) return err if ((err = validateTangle(msg, tangle, rootID))) return err
} }
if ((err = validateSignature(msg))) return err if ((err = validateSignature(msg))) return err
} }
@ -342,5 +342,5 @@ module.exports = {
validateDomain, validateDomain,
validateData, validateData,
validate, validate,
validateMsgHash, validateMsgID,
} }

View File

@ -55,7 +55,7 @@ interface Msg {
dataSize: number dataSize: number
domain: string // alphanumeric string, at least 3 chars, max 100 chars domain: string // alphanumeric string, at least 3 chars, max 100 chars
tangles: { tangles: {
[accountTangleId: string]: { [accountTangleID: string]: {
depth: number // maximum distance (positive integer) 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, unique set and ordered alphabetically prev: Array<MsgHash> // list of msg hashes of existing msgs, unique set and ordered alphabetically
} }

View File

@ -21,24 +21,24 @@ test('account.add()', async (t) => {
.call(null, { keypair: keypair1, path: DIR }) .call(null, { keypair: keypair1, path: DIR })
await peer.db.loaded() await peer.db.loaded()
const id = await p(peer.db.account.create)({ const account = await p(peer.db.account.create)({
keypair: keypair1, keypair: keypair1,
domain: 'person', domain: 'person',
}) })
assert.equal(peer.db.account.has({ account: id, keypair: keypair2 }), false) assert.equal(peer.db.account.has({ account, keypair: keypair2 }), false)
const consent = peer.db.account.consent({ account: id, keypair: keypair2 }) const consent = peer.db.account.consent({ account, keypair: keypair2 })
const accountRec1 = await p(peer.db.account.add)({ const accountRec1 = await p(peer.db.account.add)({
account: id, account,
keypair: keypair2, keypair: keypair2,
consent, consent,
powers: ['box'], powers: ['box'],
}) })
assert.ok(accountRec1, 'accountRec1 exists') assert.ok(accountRec1, 'accountRec1 exists')
const { hash, msg } = accountRec1 const { id, msg } = accountRec1
assert.ok(hash, 'hash exists') assert.ok(account, 'id exists')
assert.deepEqual( assert.deepEqual(
msg.data, msg.data,
{ {
@ -60,12 +60,12 @@ test('account.add()', async (t) => {
assert.equal(msg.metadata.domain, 'person', 'msg.metadata.domain') assert.equal(msg.metadata.domain, 'person', 'msg.metadata.domain')
assert.deepEqual( assert.deepEqual(
msg.metadata.tangles, msg.metadata.tangles,
{ [id]: { depth: 1, prev: [id] } }, { [account]: { depth: 1, prev: [account] } },
'msg.metadata.tangles' 'msg.metadata.tangles'
) )
assert.equal(msg.pubkey, keypair1.public, 'msg.pubkey OLD KEY') assert.equal(msg.pubkey, keypair1.public, 'msg.pubkey OLD KEY')
assert.equal(peer.db.account.has({ account: id, keypair: keypair2 }), true) assert.equal(peer.db.account.has({ account, keypair: keypair2 }), true)
await p(peer.close)() await p(peer.close)()
}) })
@ -182,8 +182,8 @@ test('publish with a key in the account', async (t) => {
keypair: keypair2, keypair: keypair2,
}) })
assert.equal(postRec.msg.data.text, 'hello', 'post text correct') assert.equal(postRec.msg.data.text, 'hello', 'post text correct')
const postsId = peer.db.feed.getId(account, 'post') const postsID = peer.db.feed.getID(account, 'post')
assert.ok(postsId, 'postsId exists') assert.ok(postsID, 'postsID exists')
const recs = [...peer.db.records()] const recs = [...peer.db.records()]
assert.equal(recs.length, 4, '4 records') assert.equal(recs.length, 4, '4 records')
@ -220,8 +220,8 @@ test('publish with a key in the account', async (t) => {
await p(carol.db.add)(accountMsg0, account) await p(carol.db.add)(accountMsg0, account)
await p(carol.db.add)(accountRec1.msg, account) await p(carol.db.add)(accountRec1.msg, account)
await p(carol.db.add)(postsRoot.msg, postsId) await p(carol.db.add)(postsRoot.msg, postsID)
await p(carol.db.add)(postRec.msg, postsId) await p(carol.db.add)(postRec.msg, postsID)
// t.pass('carol added all messages successfully') // t.pass('carol added all messages successfully')
await p(carol.close)() await p(carol.close)()

View File

@ -22,17 +22,17 @@ test('add()', async (t) => {
await peer.db.loaded() await peer.db.loaded()
const accountMsg0 = MsgV3.createAccount(keypair, 'person') const accountMsg0 = MsgV3.createAccount(keypair, 'person')
const id = MsgV3.getMsgHash(accountMsg0) const id = MsgV3.getMsgID(accountMsg0)
await p(peer.db.add)(accountMsg0, id) await p(peer.db.add)(accountMsg0, id)
const rootMsg = MsgV3.createRoot(id, 'post', keypair) const rootMsg = MsgV3.createMoot(id, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const rootID = MsgV3.getMsgID(rootMsg)
const recRoot = await p(peer.db.add)(rootMsg, rootHash) const recRoot = await p(peer.db.add)(rootMsg, rootID)
assert.equal(recRoot.msg.metadata.dataSize, 0, 'root msg added') assert.equal(recRoot.msg.metadata.dataSize, 0, 'root msg added')
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(rootID)
tangle.add(recRoot.hash, recRoot.msg) tangle.add(recRoot.id, recRoot.msg)
const inputMsg = MsgV3.create({ const inputMsg = MsgV3.create({
keypair, keypair,
@ -41,11 +41,11 @@ test('add()', async (t) => {
account: id, account: id,
accountTips: [id], accountTips: [id],
tangles: { tangles: {
[rootHash]: tangle, [rootID]: tangle,
}, },
}) })
const rec = await p(peer.db.add)(inputMsg, rootHash) const rec = await p(peer.db.add)(inputMsg, rootID)
assert.equal(rec.msg.data.text, 'This is the first post!') assert.equal(rec.msg.data.text, 'This is the first post!')
await p(peer.close)(true) await p(peer.close)(true)

View File

@ -23,14 +23,14 @@ test('del', async (t) => {
const id = await p(peer.db.account.create)({ domain: 'person' }) const id = await p(peer.db.account.create)({ domain: 'person' })
const msgHashes = [] const msgIDs = []
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
const rec = await p(peer.db.feed.publish)({ const rec = await p(peer.db.feed.publish)({
account: id, account: id,
domain: 'post', domain: 'post',
data: { text: 'm' + i }, data: { text: 'm' + i },
}) })
msgHashes.push(rec.hash) msgIDs.push(rec.id)
} }
const before = [] const before = []
@ -46,7 +46,7 @@ test('del', async (t) => {
'msgs before the delete' 'msgs before the delete'
) )
await p(peer.db.del)(msgHashes[2]) await p(peer.db.del)(msgIDs[2])
const after = [] const after = []
for (const msg of peer.db.msgs()) { for (const msg of peer.db.msgs()) {

View File

@ -23,14 +23,14 @@ test('erase', async (t) => {
const id = await p(peer.db.account.create)({ domain: 'person' }) const id = await p(peer.db.account.create)({ domain: 'person' })
const msgHashes = [] const msgIDs = []
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
const rec = await p(peer.db.feed.publish)({ const rec = await p(peer.db.feed.publish)({
account: id, account: id,
domain: 'post', domain: 'post',
data: { text: 'm' + i }, data: { text: 'm' + i },
}) })
msgHashes.push(rec.hash) msgIDs.push(rec.id)
} }
const before = [] const before = []
@ -46,7 +46,7 @@ test('erase', async (t) => {
'5 msgs before the erase' '5 msgs before the erase'
) )
await p(peer.db.erase)(msgHashes[2]) await p(peer.db.erase)(msgIDs[2])
const after = [] const after = []
for (const msg of peer.db.msgs()) { for (const msg of peer.db.msgs()) {
@ -59,8 +59,8 @@ test('erase', async (t) => {
const after2 = [] const after2 = []
for (const msg of peer.db.msgs()) { for (const msg of peer.db.msgs()) {
for (const tangleId in msg.metadata.tangles) { for (const tangleID in msg.metadata.tangles) {
after2.push(msg.metadata.tangles[tangleId].depth) after2.push(msg.metadata.tangles[tangleID].depth)
} }
} }

View File

@ -15,8 +15,8 @@ rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
let peer let peer
let id let id
let rootMsg let moot
let rootHash let mootID
test('setup', async (t) => { test('setup', async (t) => {
peer = SecretStack({ appKey: caps.shse }) peer = SecretStack({ appKey: caps.shse })
.use(require('../lib')) .use(require('../lib'))
@ -26,15 +26,15 @@ test('setup', async (t) => {
await peer.db.loaded() await peer.db.loaded()
id = (await p(peer.db.account.create)({domain: 'person'})) id = (await p(peer.db.account.create)({domain: 'person'}))
rootMsg = MsgV3.createRoot(id, 'post', keypair) moot = MsgV3.createMoot(id, 'post', keypair)
rootHash = MsgV3.getMsgHash(rootMsg) mootID = MsgV3.getMsgID(moot)
await p(peer.db.add)(rootMsg, rootHash) await p(peer.db.add)(moot, mootID)
}) })
test('feed.getId()', async (t) => { test('feed.getID()', async (t) => {
const feedId = peer.db.feed.getId(id, 'post') const feedID = peer.db.feed.getID(id, 'post')
assert.equal(feedId, rootHash, 'feed.getId() returns root hash') assert.equal(feedID, mootID, 'feed.getID() returns moot ID')
}) })
test('teardown', (t) => { test('teardown', (t) => {

View File

@ -16,8 +16,8 @@ const keypair = Keypair.generate('ed25519', 'alice')
const bobKeypair = Keypair.generate('ed25519', 'bob') const bobKeypair = Keypair.generate('ed25519', 'bob')
let peer let peer
let id let id
let rootMsg let moot
let rootHash let mootID
test('setup', async (t) => { test('setup', async (t) => {
peer = SecretStack({ appKey: caps.shse }) peer = SecretStack({ appKey: caps.shse })
.use(require('../lib')) .use(require('../lib'))
@ -27,13 +27,13 @@ test('setup', async (t) => {
await peer.db.loaded() await peer.db.loaded()
id = (await p(peer.db.account.create)({domain: 'person'})) id = (await p(peer.db.account.create)({domain: 'person'}))
rootMsg = MsgV3.createRoot(id, 'post', keypair) moot = MsgV3.createMoot(id, 'post', keypair)
rootHash = MsgV3.getMsgHash(rootMsg) mootID = MsgV3.getMsgID(moot)
}) })
let msgHash1 let msgID1
let rec1 let rec1
let msgHash2 let msgID2
test('feed.publish()', async (t) => { test('feed.publish()', async (t) => {
rec1 = await p(peer.db.feed.publish)({ rec1 = await p(peer.db.feed.publish)({
account: id, account: id,
@ -42,17 +42,17 @@ test('feed.publish()', async (t) => {
}) })
assert.equal(rec1.msg.data.text, 'I am 1st post', 'msg1 text correct') assert.equal(rec1.msg.data.text, 'I am 1st post', 'msg1 text correct')
assert.equal( assert.equal(
rec1.msg.metadata.tangles[rootHash].depth, rec1.msg.metadata.tangles[mootID].depth,
1, 1,
'msg1 tangle depth correct' 'msg1 tangle depth correct'
) )
assert.deepEqual( assert.deepEqual(
rec1.msg.metadata.tangles[rootHash].prev, rec1.msg.metadata.tangles[mootID].prev,
[rootHash], [mootID],
'msg1 tangle prev correct' 'msg1 tangle prev correct'
) )
msgHash1 = MsgV3.getMsgHash(rec1.msg) msgID1 = MsgV3.getMsgID(rec1.msg)
const rec2 = await p(peer.db.feed.publish)({ const rec2 = await p(peer.db.feed.publish)({
account: id, account: id,
@ -61,22 +61,22 @@ test('feed.publish()', async (t) => {
}) })
assert.equal(rec2.msg.data.text, 'I am 2nd post', 'msg2 text correct') assert.equal(rec2.msg.data.text, 'I am 2nd post', 'msg2 text correct')
assert.equal( assert.equal(
rec2.msg.metadata.tangles[rootHash].depth, rec2.msg.metadata.tangles[mootID].depth,
2, 2,
'msg2 tangle depth correct' 'msg2 tangle depth correct'
) )
assert.deepEqual( assert.deepEqual(
rec2.msg.metadata.tangles[rootHash].prev, rec2.msg.metadata.tangles[mootID].prev,
[msgHash1], [msgID1],
'msg2 tangle prev correct' 'msg2 tangle prev correct'
) )
msgHash2 = MsgV3.getMsgHash(rec2.msg) msgID2 = MsgV3.getMsgID(rec2.msg)
}) })
test('add() forked then feed.publish() merged', async (t) => { test('add() forked then feed.publish() merged', async (t) => {
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
tangle.add(rec1.hash, rec1.msg) tangle.add(rec1.id, rec1.msg)
const msg3 = MsgV3.create({ const msg3 = MsgV3.create({
keypair, keypair,
@ -85,12 +85,12 @@ test('add() forked then feed.publish() merged', async (t) => {
domain: 'post', domain: 'post',
data: { text: '3rd post forked from 1st' }, data: { text: '3rd post forked from 1st' },
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const rec3 = await p(peer.db.add)(msg3, rootHash) const rec3 = await p(peer.db.add)(msg3, mootID)
const msgHash3 = MsgV3.getMsgHash(rec3.msg) const msgID3 = MsgV3.getMsgID(rec3.msg)
const rec4 = await p(peer.db.feed.publish)({ const rec4 = await p(peer.db.feed.publish)({
account: id, account: id,
@ -99,20 +99,20 @@ test('add() forked then feed.publish() merged', async (t) => {
}) })
assert.ok(rec4, '4th post published') assert.ok(rec4, '4th post published')
assert.equal( assert.equal(
rec4.msg.metadata.tangles[rootHash].prev.length, rec4.msg.metadata.tangles[mootID].prev.length,
3, 3,
'msg4 prev has 3' // is root, msg2 and msg3' 'msg4 prev has 3' // is root, msg2 and msg3'
) )
assert.ok( assert.ok(
rec4.msg.metadata.tangles[rootHash].prev.includes(rootHash), rec4.msg.metadata.tangles[mootID].prev.includes(mootID),
'msg4 prev has root' 'msg4 prev has root'
) )
assert.ok( assert.ok(
rec4.msg.metadata.tangles[rootHash].prev.includes(msgHash2), rec4.msg.metadata.tangles[mootID].prev.includes(msgID2),
'msg4 prev has msg2' 'msg4 prev has msg2'
) )
assert.ok( assert.ok(
rec4.msg.metadata.tangles[rootHash].prev.includes(msgHash3), rec4.msg.metadata.tangles[mootID].prev.includes(msgID3),
'msg4 prev has msg3' 'msg4 prev has msg3'
) )
}) })
@ -127,7 +127,7 @@ test('feed.publish() encrypted with box', async (t) => {
assert.equal(typeof recEncrypted.msg.data, 'string') assert.equal(typeof recEncrypted.msg.data, 'string')
assert.ok(recEncrypted.msg.data.endsWith('.box'), '.box') assert.ok(recEncrypted.msg.data.endsWith('.box'), '.box')
const msgDecrypted = peer.db.get(recEncrypted.hash) const msgDecrypted = peer.db.get(recEncrypted.id)
assert.equal(msgDecrypted.data.text, 'I am chewing food') assert.equal(msgDecrypted.data.text, 'I am chewing food')
}) })
@ -143,13 +143,13 @@ test('feed.publish() with tangles', async (t) => {
account: id, account: id,
domain: 'comment', domain: 'comment',
data: { text: 'I am comment 1' }, data: { text: 'I am comment 1' },
tangles: [recA.hash], tangles: [recA.id],
keypair: bobKeypair, keypair: bobKeypair,
}) })
assert.equal(recB.msg.metadata.tangles[recA.hash].depth, 1, 'tangle depth 1') assert.equal(recB.msg.metadata.tangles[recA.id].depth, 1, 'tangle depth 1')
assert.deepEqual( assert.deepEqual(
recB.msg.metadata.tangles[recA.hash].prev, recB.msg.metadata.tangles[recA.id].prev,
[recA.hash], [recA.id],
'tangle prev' 'tangle prev'
) )
}) })

View File

@ -15,8 +15,7 @@ rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
let peer let peer
let id let id
let msgHash1 let msgID1
let msgId1
test('setup', async (t) => { test('setup', async (t) => {
peer = SecretStack({ appKey: caps.shse }) peer = SecretStack({ appKey: caps.shse })
.use(require('../lib')) .use(require('../lib'))
@ -32,18 +31,11 @@ test('setup', async (t) => {
domain: 'post', domain: 'post',
data: { text: 'I am 1st post' }, data: { text: 'I am 1st post' },
}) })
msgHash1 = MsgV3.getMsgHash(rec1.msg) msgID1 = MsgV3.getMsgID(rec1.msg)
msgId1 = MsgV3.getMsgId(rec1.msg)
}) })
test('get() supports ppppp URIs', async (t) => { test('get() supports msg IDs', async (t) => {
const msg = peer.db.get(msgId1) const msg = peer.db.get(msgID1)
assert.ok(msg, 'msg exists')
assert.equal(msg.data.text, 'I am 1st post')
})
test('get() supports msg hashes', async (t) => {
const msg = peer.db.get(msgHash1)
assert.ok(msg, 'msg exists') assert.ok(msg, 'msg exists')
assert.equal(msg.data.text, 'I am 1st post') assert.equal(msg.data.text, 'I am 1st post')
}) })

View File

@ -41,9 +41,9 @@ test('setup', async (t) => {
domain: 'comment', domain: 'comment',
data: { text: 'root' }, data: { text: 'root' },
}) })
).hash ).id
const [{ hash: reply1B }, { hash: reply1C }] = await Promise.all([ const [{ id: reply1B }, { id: reply1C }] = await Promise.all([
p(peer.db.feed.publish)({ p(peer.db.feed.publish)({
account: id, account: id,
keypair: keypairB, keypair: keypairB,
@ -70,9 +70,9 @@ test('setup', async (t) => {
data: { text: 'reply 2' }, data: { text: 'reply 2' },
tangles: [rootPost], tangles: [rootPost],
}) })
).hash ).id
const [{ hash: reply3B }, { hash: reply3C }] = await Promise.all([ const [{ id: reply3B }, { id: reply3C }] = await Promise.all([
p(peer.db.feed.publish)({ p(peer.db.feed.publish)({
account: id, account: id,
keypair: keypairB, keypair: keypairB,
@ -217,11 +217,11 @@ test('Tangle.getDeletablesAndErasables with lipmaa', (t) => {
test('Tangle.topoSort after some have been deleted and erased', async (t) => { test('Tangle.topoSort after some have been deleted and erased', async (t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(reply3Lo) const { deletables, erasables } = tangle.getDeletablesAndErasables(reply3Lo)
for (const msgHash of deletables) { for (const msgID of deletables) {
await p(peer.db.del)(msgHash) await p(peer.db.del)(msgID)
} }
for (const msgHash of erasables) { for (const msgID of erasables) {
await p(peer.db.erase)(msgHash) await p(peer.db.erase)(msgID)
} }
const tangle2 = peer.db.getTangle(rootPost) const tangle2 = peer.db.getTangle(rootPost)

View File

@ -35,38 +35,38 @@ test('MsgV3.createAccount()', (t) => {
assert.equal(accountMsg0.metadata.v, 3, 'v') assert.equal(accountMsg0.metadata.v, 3, 'v')
assert.equal(accountMsg0.pubkey, keypair.public, 'pubkey') assert.equal(accountMsg0.pubkey, keypair.public, 'pubkey')
account = MsgV3.getMsgHash(accountMsg0) account = MsgV3.getMsgID(accountMsg0)
assert.equal(account, 'J2SUr6XtJuFuTusNbagEW5', 'account ID') assert.equal(account, 'J2SUr6XtJuFuTusNbagEW5', 'account ID')
}) })
let rootMsg = null let moot = null
let rootHash = null let mootID = null
test('MsgV3.createRoot()', (t) => { test('MsgV3.createMoot()', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
rootMsg = MsgV3.createRoot(account, 'post', keypair) moot = MsgV3.createMoot(account, 'post', keypair)
console.log(JSON.stringify(rootMsg, null, 2)) console.log(JSON.stringify(moot, null, 2))
assert.equal(rootMsg.data, null, 'data') assert.equal(moot.data, null, 'data')
assert.equal(rootMsg.metadata.dataHash, null, 'hash') assert.equal(moot.metadata.dataHash, null, 'hash')
assert.equal(rootMsg.metadata.dataSize, 0, 'size') assert.equal(moot.metadata.dataSize, 0, 'size')
assert.equal(rootMsg.metadata.account, account, 'account') assert.equal(moot.metadata.account, account, 'account')
assert.equal(rootMsg.metadata.accountTips, null, 'accountTips') assert.equal(moot.metadata.accountTips, null, 'accountTips')
assert.deepEqual(rootMsg.metadata.tangles, {}, 'tangles') assert.deepEqual(moot.metadata.tangles, {}, 'tangles')
assert.equal(rootMsg.metadata.domain, 'post', 'domain') assert.equal(moot.metadata.domain, 'post', 'domain')
assert.equal(rootMsg.metadata.v, 3, 'v') assert.equal(moot.metadata.v, 3, 'v')
assert.equal(rootMsg.pubkey, keypair.public, 'pubkey') assert.equal(moot.pubkey, keypair.public, 'pubkey')
rootHash = MsgV3.getMsgHash(rootMsg) mootID = MsgV3.getMsgID(moot)
assert.equal(rootHash, 'VsBFptgidvAspk4xTKZx6c', 'root hash') assert.equal(mootID, 'VsBFptgidvAspk4xTKZx6c', 'moot ID')
}) })
test('MsgV3.create()', (t) => { test('MsgV3.create()', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const data = { text: 'Hello world!' } const data = { text: 'Hello world!' }
const tangle1 = new MsgV3.Tangle(rootHash) const tangle1 = new MsgV3.Tangle(mootID)
tangle1.add(rootHash, rootMsg) tangle1.add(mootID, moot)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
keypair, keypair,
@ -75,7 +75,7 @@ test('MsgV3.create()', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle1, [mootID]: tangle1,
}, },
}) })
console.log(JSON.stringify(msg1, null, 2)) console.log(JSON.stringify(msg1, null, 2))
@ -101,22 +101,14 @@ test('MsgV3.create()', (t) => {
) )
assert.deepEqual(msg1.metadata.dataSize, 23, 'metadata.dataSize') assert.deepEqual(msg1.metadata.dataSize, 23, 'metadata.dataSize')
assert.equal(msg1.metadata.account, account, 'metadata.account') assert.equal(msg1.metadata.account, account, 'metadata.account')
assert.deepEqual( assert.deepEqual(msg1.metadata.accountTips, [account], 'metadata.accountTips')
msg1.metadata.accountTips,
[account],
'metadata.accountTips'
)
assert.deepEqual( assert.deepEqual(
Object.keys(msg1.metadata.tangles), Object.keys(msg1.metadata.tangles),
[rootHash], [mootID],
'metadata.tangles' 'metadata.tangles'
) )
assert.equal(msg1.metadata.tangles[rootHash].depth, 1, 'tangle depth') assert.equal(msg1.metadata.tangles[mootID].depth, 1, 'tangle depth')
assert.deepEqual( assert.deepEqual(msg1.metadata.tangles[mootID].prev, [mootID], 'tangle prev')
msg1.metadata.tangles[rootHash].prev,
[rootHash],
'tangle prev'
)
assert.equal(msg1.metadata.domain, 'post', 'metadata.domain') assert.equal(msg1.metadata.domain, 'post', 'metadata.domain')
assert.deepEqual(msg1.metadata.v, 3, 'metadata.v') assert.deepEqual(msg1.metadata.v, 3, 'metadata.v')
assert.equal( assert.equal(
@ -130,17 +122,13 @@ test('MsgV3.create()', (t) => {
'sig' 'sig'
) )
const msgHash1 = 'R5G9WtDAQrco4FABRdvrUH' const msgID1 = 'R5G9WtDAQrco4FABRdvrUH'
assert.equal( assert.equal(MsgV3.getMsgID(msg1), msgID1, 'getMsgID')
MsgV3.getMsgId(msg1),
`ppppp:message/v3/${account}/post/${msgHash1}`,
'getMsgId'
)
const tangle2 = new MsgV3.Tangle(rootHash) const tangle2 = new MsgV3.Tangle(mootID)
tangle2.add(rootHash, rootMsg) tangle2.add(mootID, moot)
tangle2.add(msgHash1, msg1) tangle2.add(msgID1, msg1)
const data2 = { text: 'Ola mundo!' } const data2 = { text: 'Ola mundo!' }
@ -151,7 +139,7 @@ test('MsgV3.create()', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle2, [mootID]: tangle2,
}, },
}) })
console.log(JSON.stringify(msg2, null, 2)) console.log(JSON.stringify(msg2, null, 2))
@ -177,22 +165,14 @@ test('MsgV3.create()', (t) => {
) )
assert.deepEqual(msg2.metadata.dataSize, 21, 'metadata.dataSize') assert.deepEqual(msg2.metadata.dataSize, 21, 'metadata.dataSize')
assert.equal(msg2.metadata.account, account, 'metadata.account') assert.equal(msg2.metadata.account, account, 'metadata.account')
assert.deepEqual( assert.deepEqual(msg2.metadata.accountTips, [account], 'metadata.accountTips')
msg2.metadata.accountTips,
[account],
'metadata.accountTips'
)
assert.deepEqual( assert.deepEqual(
Object.keys(msg2.metadata.tangles), Object.keys(msg2.metadata.tangles),
[rootHash], [mootID],
'metadata.tangles' 'metadata.tangles'
) )
assert.equal(msg2.metadata.tangles[rootHash].depth, 2, 'tangle depth') assert.equal(msg2.metadata.tangles[mootID].depth, 2, 'tangle depth')
assert.deepEqual( assert.deepEqual(msg2.metadata.tangles[mootID].prev, [msgID1], 'tangle prev')
msg2.metadata.tangles[rootHash].prev,
[msgHash1],
'tangle prev'
)
assert.equal(msg2.metadata.domain, 'post', 'metadata.domain') assert.equal(msg2.metadata.domain, 'post', 'metadata.domain')
assert.deepEqual(msg2.metadata.v, 3, 'metadata.v') assert.deepEqual(msg2.metadata.v, 3, 'metadata.v')
assert.equal( assert.equal(
@ -206,17 +186,13 @@ test('MsgV3.create()', (t) => {
'sig' 'sig'
) )
assert.deepEqual( assert.deepEqual(MsgV3.getMsgID(msg2), 'LxWgRRr4wXd29sLDNGNTkr', 'getMsgID')
MsgV3.getMsgId(msg2),
`ppppp:message/v3/${account}/post/LxWgRRr4wXd29sLDNGNTkr`,
'getMsgId'
)
}) })
test('create() handles DAG tips correctly', (t) => { test('create() handles DAG tips correctly', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
keypair, keypair,
@ -225,17 +201,17 @@ test('create() handles DAG tips correctly', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
assert.deepEqual( assert.deepEqual(
msg1.metadata.tangles[rootHash].prev, msg1.metadata.tangles[mootID].prev,
[MsgV3.getFeedRootHash(account, 'post')], [MsgV3.getMootID(account, 'post')],
'msg1.prev is root' 'msg1.prev is root'
) )
tangle.add(msgHash1, msg1) tangle.add(msgID1, msg1)
const msg2A = MsgV3.create({ const msg2A = MsgV3.create({
keypair, keypair,
@ -244,12 +220,12 @@ test('create() handles DAG tips correctly', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
assert.deepEqual( assert.deepEqual(
msg2A.metadata.tangles[rootHash].prev, msg2A.metadata.tangles[mootID].prev,
[msgHash1], [msgID1],
'msg2A.prev is msg1' 'msg2A.prev is msg1'
) )
@ -260,17 +236,17 @@ test('create() handles DAG tips correctly', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash2B = MsgV3.getMsgHash(msg2B) const msgID2B = MsgV3.getMsgID(msg2B)
assert.deepEqual( assert.deepEqual(
msg2B.metadata.tangles[rootHash].prev, msg2B.metadata.tangles[mootID].prev,
[msgHash1], [msgID1],
'msg2B.prev is msg1' 'msg2B.prev is msg1'
) )
tangle.add(msgHash2B, msg2B) tangle.add(msgID2B, msg2B)
const msg3 = MsgV3.create({ const msg3 = MsgV3.create({
keypair, keypair,
@ -279,19 +255,19 @@ test('create() handles DAG tips correctly', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash3 = MsgV3.getMsgHash(msg3) const msgID3 = MsgV3.getMsgID(msg3)
assert.deepEqual( assert.deepEqual(
msg3.metadata.tangles[rootHash].prev, msg3.metadata.tangles[mootID].prev,
[rootHash, msgHash2B].sort(), [mootID, msgID2B].sort(),
'msg3.prev is [root(lipmaa),msg2B(previous)], sorted' 'msg3.prev is [root(lipmaa),msg2B(previous)], sorted'
) )
tangle.add(msgHash3, msg3) tangle.add(msgID3, msg3)
const msgHash2A = MsgV3.getMsgHash(msg2A) const msgID2A = MsgV3.getMsgID(msg2A)
tangle.add(msgHash2A, msg2A) tangle.add(msgID2A, msg2A)
// t.pass('msg2A comes into awareness') // t.pass('msg2A comes into awareness')
const msg4 = MsgV3.create({ const msg4 = MsgV3.create({
@ -301,12 +277,12 @@ test('create() handles DAG tips correctly', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
assert.deepEqual( assert.deepEqual(
msg4.metadata.tangles[rootHash].prev, msg4.metadata.tangles[mootID].prev,
[msgHash3, msgHash2A].sort(), [msgID3, msgID2A].sort(),
'msg4.prev is [msg3(previous),msg2A(old fork as tip)], sorted' 'msg4.prev is [msg3(previous),msg2A(old fork as tip)], sorted'
) )
}) })

View File

@ -5,7 +5,7 @@ const Keypair = require('ppppp-keypair')
const MsgV3 = require('../../lib/msg-v3') const MsgV3 = require('../../lib/msg-v3')
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgHash( const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'MYNONCE') MsgV3.createAccount(keypair, 'person', 'MYNONCE')
) )
const pubkeys = new Set([keypair.public]) const pubkeys = new Set([keypair.public])
@ -13,11 +13,11 @@ const pubkeys = new Set([keypair.public])
test('invalid msg with non-array prev', (t) => { test('invalid msg with non-array prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg = MsgV3.create({ const msg = MsgV3.create({
keypair, keypair,
@ -26,13 +26,13 @@ test('invalid msg with non-array prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
msg.metadata.tangles[rootHash].prev = null msg.metadata.tangles[mootID].prev = null
const msgHash = MsgV3.getMsgHash(msg) const msgID = MsgV3.getMsgID(msg)
const err = MsgV3.validate(msg, tangle, pubkeys, msgHash, rootHash) const err = MsgV3.validate(msg, tangle, pubkeys, msgID, mootID)
assert.ok(err, 'invalid 2nd msg throws') assert.ok(err, 'invalid 2nd msg throws')
assert.match( assert.match(
err, err,
@ -44,11 +44,11 @@ test('invalid msg with non-array prev', (t) => {
test('invalid msg with bad prev', (t) => { test('invalid msg with bad prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
keypair, keypair,
@ -57,11 +57,11 @@ test('invalid msg with bad prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgHash1, msg1) tangle.add(msgID1, msg1)
const msg2 = MsgV3.create({ const msg2 = MsgV3.create({
keypair, keypair,
@ -70,14 +70,14 @@ test('invalid msg with bad prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
msg2.metadata.tangles[rootHash].depth = 1 msg2.metadata.tangles[mootID].depth = 1
msg2.metadata.tangles[rootHash].prev = [1234] msg2.metadata.tangles[mootID].prev = [1234]
const msgHash2 = MsgV3.getMsgHash(msg2) const msgID2 = MsgV3.getMsgID(msg2)
const err = MsgV3.validate(msg2, tangle, pubkeys, msgHash2, rootHash) const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
assert.ok(err, 'invalid 2nd msg throws') assert.ok(err, 'invalid 2nd msg throws')
assert.match( assert.match(
err, err,
@ -89,11 +89,11 @@ test('invalid msg with bad prev', (t) => {
test('invalid msg with URI in prev', (t) => { test('invalid msg with URI in prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
keypair, keypair,
@ -102,11 +102,11 @@ test('invalid msg with URI in prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgHash1, msg1) tangle.add(msgID1, msg1)
const msg2 = MsgV3.create({ const msg2 = MsgV3.create({
keypair, keypair,
@ -115,16 +115,16 @@ test('invalid msg with URI in prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash2 = MsgV3.getMsgHash(msg2) const msgID2 = MsgV3.getMsgID(msg2)
const randBuf = Buffer.alloc(16).fill(16) const randBuf = Buffer.alloc(16).fill(16)
const fakeMsgKey1 = `ppppp:message/v3/${base58.encode(randBuf)}` const fakeMsgKey1 = `ppppp:message/v3/${base58.encode(randBuf)}`
msg2.metadata.tangles[rootHash].depth = 1 msg2.metadata.tangles[mootID].depth = 1
msg2.metadata.tangles[rootHash].prev = [fakeMsgKey1] msg2.metadata.tangles[mootID].prev = [fakeMsgKey1]
const err = MsgV3.validate(msg2, tangle, pubkeys, msgHash2, rootHash) const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
assert.ok(err, 'invalid 2nd msg throws') assert.ok(err, 'invalid 2nd msg throws')
assert.match(err, /prev item ".*" is a URI/, 'invalid 2nd msg description') assert.match(err, /prev item ".*" is a URI/, 'invalid 2nd msg description')
}) })
@ -132,11 +132,11 @@ test('invalid msg with URI in prev', (t) => {
test('invalid msg with unknown prev', (t) => { test('invalid msg with unknown prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
keypair, keypair,
@ -145,11 +145,11 @@ test('invalid msg with unknown prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgHash1, msg1) tangle.add(msgID1, msg1)
const unknownMsg = MsgV3.create({ const unknownMsg = MsgV3.create({
keypair, keypair,
@ -158,15 +158,15 @@ test('invalid msg with unknown prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const unknownMsgHash = MsgV3.getMsgHash(unknownMsg) const unknownMsgID = MsgV3.getMsgID(unknownMsg)
const fakeRootHash = 'ABCDEabcde' + rootHash.substring(10) const fakeMootID = 'ABCDEabcde' + mootID.substring(10)
const tangle2 = new MsgV3.Tangle(fakeRootHash) const tangle2 = new MsgV3.Tangle(fakeMootID)
tangle2.add(fakeRootHash, rootMsg) tangle2.add(fakeMootID, moot)
tangle2.add(unknownMsgHash, unknownMsg) tangle2.add(unknownMsgID, unknownMsg)
const msg2 = MsgV3.create({ const msg2 = MsgV3.create({
keypair, keypair,
@ -175,12 +175,12 @@ test('invalid msg with unknown prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle2, [mootID]: tangle2,
}, },
}) })
const msgHash2 = MsgV3.getMsgHash(msg2) const msgID2 = MsgV3.getMsgID(msg2)
const err = MsgV3.validate(msg2, tangle, pubkeys, msgHash2, rootHash) const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
assert.ok(err, 'invalid 2nd msg throws') assert.ok(err, 'invalid 2nd msg throws')
assert.match( assert.match(
err, err,
@ -193,14 +193,14 @@ test('invalid feed msg with a different pubkey', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice') const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob') const keypairB = Keypair.generate('ed25519', 'bob')
const accountB = MsgV3.getMsgHash( const accountB = MsgV3.getMsgID(
MsgV3.createAccount(keypairB, 'person', 'MYNONCE') MsgV3.createAccount(keypairB, 'person', 'MYNONCE')
) )
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const feedTangle = new MsgV3.Tangle(rootHash) const feedTangle = new MsgV3.Tangle(mootID)
feedTangle.add(rootHash, rootMsg) feedTangle.add(mootID, moot)
const msg = MsgV3.create({ const msg = MsgV3.create({
keypair: keypairB, keypair: keypairB,
@ -209,12 +209,12 @@ test('invalid feed msg with a different pubkey', (t) => {
accountTips: [accountB], accountTips: [accountB],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: feedTangle, [mootID]: feedTangle,
}, },
}) })
const msgHash = MsgV3.getMsgHash(msg) const msgID = MsgV3.getMsgID(msg)
const err = MsgV3.validate(msg, feedTangle, pubkeys, msgHash, rootHash) const err = MsgV3.validate(msg, feedTangle, pubkeys, msgID, mootID)
assert.ok(err, 'invalid msg throws') assert.ok(err, 'invalid msg throws')
assert.match( assert.match(
err, err,
@ -226,10 +226,10 @@ test('invalid feed msg with a different pubkey', (t) => {
test('invalid feed msg with a different domain', (t) => { test('invalid feed msg with a different domain', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice') const keypairA = Keypair.generate('ed25519', 'alice')
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const feedTangle = new MsgV3.Tangle(rootHash) const feedTangle = new MsgV3.Tangle(mootID)
feedTangle.add(rootHash, rootMsg) feedTangle.add(mootID, moot)
const msg = MsgV3.create({ const msg = MsgV3.create({
keypair: keypairA, keypair: keypairA,
@ -238,12 +238,12 @@ test('invalid feed msg with a different domain', (t) => {
accountTips: [account], accountTips: [account],
domain: 'comment', domain: 'comment',
tangles: { tangles: {
[rootHash]: feedTangle, [mootID]: feedTangle,
}, },
}) })
const msgHash = MsgV3.getMsgHash(msg) const msgID = MsgV3.getMsgID(msg)
const err = MsgV3.validate(msg, feedTangle, pubkeys, msgHash, rootHash) const err = MsgV3.validate(msg, feedTangle, pubkeys, msgID, mootID)
assert.ok(err, 'invalid msg throws') assert.ok(err, 'invalid msg throws')
assert.match( assert.match(
err, err,
@ -255,11 +255,11 @@ test('invalid feed msg with a different domain', (t) => {
test('invalid feed msg with non-alphabetical prev', (t) => { test('invalid feed msg with non-alphabetical prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
keypair, keypair,
@ -268,10 +268,10 @@ test('invalid feed msg with non-alphabetical prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
const msg2 = MsgV3.create({ const msg2 = MsgV3.create({
keypair, keypair,
@ -280,13 +280,13 @@ test('invalid feed msg with non-alphabetical prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash2 = MsgV3.getMsgHash(msg2) const msgID2 = MsgV3.getMsgID(msg2)
tangle.add(msgHash1, msg1) tangle.add(msgID1, msg1)
tangle.add(msgHash2, msg2) tangle.add(msgID2, msg2)
const msg3 = MsgV3.create({ const msg3 = MsgV3.create({
keypair, keypair,
@ -295,20 +295,20 @@ test('invalid feed msg with non-alphabetical prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash3 = MsgV3.getMsgHash(msg3) const msgID3 = MsgV3.getMsgID(msg3)
let prevHashes = msg3.metadata.tangles[rootHash].prev let prevMsgIDs = msg3.metadata.tangles[mootID].prev
if (prevHashes[0] < prevHashes[1]) { if (prevMsgIDs[0] < prevMsgIDs[1]) {
prevHashes = [prevHashes[1], prevHashes[0]] prevMsgIDs = [prevMsgIDs[1], prevMsgIDs[0]]
} else { } else {
prevHashes = [prevHashes[0], prevHashes[1]] prevMsgIDs = [prevMsgIDs[0], prevMsgIDs[1]]
} }
msg3.metadata.tangles[rootHash].prev = prevHashes msg3.metadata.tangles[mootID].prev = prevMsgIDs
const err = MsgV3.validate(msg3, tangle, pubkeys, msgHash3, rootHash) const err = MsgV3.validate(msg3, tangle, pubkeys, msgID3, mootID)
assert.ok(err, 'invalid 3rd msg throws') assert.ok(err, 'invalid 3rd msg throws')
assert.match( assert.match(
err, err,
@ -320,11 +320,11 @@ test('invalid feed msg with non-alphabetical prev', (t) => {
test('invalid feed msg with duplicate prev', (t) => { test('invalid feed msg with duplicate prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
keypair, keypair,
@ -333,15 +333,15 @@ test('invalid feed msg with duplicate prev', (t) => {
accountTips: [account], accountTips: [account],
domain: 'post', domain: 'post',
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
const [prevHash] = msg1.metadata.tangles[rootHash].prev const [prevID] = msg1.metadata.tangles[mootID].prev
msg1.metadata.tangles[rootHash].prev = [prevHash, prevHash] msg1.metadata.tangles[mootID].prev = [prevID, prevID]
const err = MsgV3.validate(msg1, tangle, pubkeys, msgHash1, rootHash) const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
assert.ok(err, 'invalid 1st msg throws') assert.ok(err, 'invalid 1st msg throws')
assert.match(err, /prev ".*" contains duplicates/, 'invalid error message') assert.match(err, /prev ".*" contains duplicates/, 'invalid error message')
}) })

View File

@ -5,15 +5,15 @@ const MsgV3 = require('../../lib/msg-v3')
test('lipmaa prevs', (t) => { test('lipmaa prevs', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgHash( const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'MYNONCE') MsgV3.createAccount(keypair, 'person', 'MYNONCE')
) )
const data = { text: 'Hello world!' } const data = { text: 'Hello world!' }
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
account, account,
@ -21,16 +21,16 @@ test('lipmaa prevs', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
keypair, keypair,
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgHash1, msg1) tangle.add(msgID1, msg1)
assert.equal(msg1.metadata.tangles[rootHash].depth, 1, 'msg1 depth') assert.equal(msg1.metadata.tangles[mootID].depth, 1, 'msg1 depth')
assert.deepEqual( assert.deepEqual(
msg1.metadata.tangles[rootHash].prev, msg1.metadata.tangles[mootID].prev,
[rootHash], [mootID],
'msg1 prev' 'msg1 prev'
) )
@ -40,16 +40,16 @@ test('lipmaa prevs', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
keypair, keypair,
}) })
const msgHash2 = MsgV3.getMsgHash(msg2) const msgID2 = MsgV3.getMsgID(msg2)
tangle.add(msgHash2, msg2) tangle.add(msgID2, msg2)
assert.equal(msg2.metadata.tangles[rootHash].depth, 2, 'msg2 depth') assert.equal(msg2.metadata.tangles[mootID].depth, 2, 'msg2 depth')
assert.deepEqual( assert.deepEqual(
msg2.metadata.tangles[rootHash].prev, msg2.metadata.tangles[mootID].prev,
[msgHash1], [msgID1],
'msg2 prev' 'msg2 prev'
) )
@ -59,16 +59,16 @@ test('lipmaa prevs', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
keypair, keypair,
}) })
const msgHash3 = MsgV3.getMsgHash(msg3) const msgID3 = MsgV3.getMsgID(msg3)
tangle.add(msgHash3, msg3) tangle.add(msgID3, msg3)
assert.equal(msg3.metadata.tangles[rootHash].depth, 3, 'msg3 depth') assert.equal(msg3.metadata.tangles[mootID].depth, 3, 'msg3 depth')
assert.deepEqual( assert.deepEqual(
msg3.metadata.tangles[rootHash].prev, msg3.metadata.tangles[mootID].prev,
[rootHash, msgHash2].sort(), [mootID, msgID2].sort(),
'msg3 prev (has lipmaa!)' 'msg3 prev (has lipmaa!)'
) )
@ -78,16 +78,16 @@ test('lipmaa prevs', (t) => {
domain: 'post', domain: 'post',
keypair, keypair,
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
data, data,
}) })
const msgHash4 = MsgV3.getMsgHash(msg4) const msgID4 = MsgV3.getMsgID(msg4)
tangle.add(msgHash4, msg4) tangle.add(msgID4, msg4)
assert.equal(msg4.metadata.tangles[rootHash].depth, 4, 'msg4 depth') assert.equal(msg4.metadata.tangles[mootID].depth, 4, 'msg4 depth')
assert.deepEqual( assert.deepEqual(
msg4.metadata.tangles[rootHash].prev, msg4.metadata.tangles[mootID].prev,
[msgHash3], [msgID3],
'msg4 prev' 'msg4 prev'
) )
@ -97,16 +97,16 @@ test('lipmaa prevs', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
keypair, keypair,
}) })
const msgHash5 = MsgV3.getMsgHash(msg5) const msgID5 = MsgV3.getMsgID(msg5)
tangle.add(msgHash5, msg5) tangle.add(msgID5, msg5)
assert.equal(msg5.metadata.tangles[rootHash].depth, 5, 'msg5 depth') assert.equal(msg5.metadata.tangles[mootID].depth, 5, 'msg5 depth')
assert.deepEqual( assert.deepEqual(
msg5.metadata.tangles[rootHash].prev, msg5.metadata.tangles[mootID].prev,
[msgHash4], [msgID4],
'msg5 prev' 'msg5 prev'
) )
@ -116,16 +116,16 @@ test('lipmaa prevs', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
keypair, keypair,
}) })
const msgHash6 = MsgV3.getMsgHash(msg6) const msgID6 = MsgV3.getMsgID(msg6)
tangle.add(msgHash6, msg6) tangle.add(msgID6, msg6)
assert.equal(msg6.metadata.tangles[rootHash].depth, 6, 'msg6 depth') assert.equal(msg6.metadata.tangles[mootID].depth, 6, 'msg6 depth')
assert.deepEqual( assert.deepEqual(
msg6.metadata.tangles[rootHash].prev, msg6.metadata.tangles[mootID].prev,
[msgHash5], [msgID5],
'msg6 prev' 'msg6 prev'
) )
@ -135,16 +135,16 @@ test('lipmaa prevs', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
keypair, keypair,
}) })
const msgHash7 = MsgV3.getMsgHash(msg7) const msgID7 = MsgV3.getMsgID(msg7)
tangle.add(msgHash7, msg7) tangle.add(msgID7, msg7)
assert.equal(msg7.metadata.tangles[rootHash].depth, 7, 'msg7 depth') assert.equal(msg7.metadata.tangles[mootID].depth, 7, 'msg7 depth')
assert.deepEqual( assert.deepEqual(
msg7.metadata.tangles[rootHash].prev, msg7.metadata.tangles[mootID].prev,
[msgHash3, msgHash6].sort(), [msgID3, msgID6].sort(),
'msg7 prev (has lipmaa!)' 'msg7 prev (has lipmaa!)'
) )
}) })

View File

@ -6,22 +6,22 @@ const MsgV3 = require('../../lib/msg-v3')
test('simple multi-author tangle', (t) => { test('simple multi-author tangle', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice') const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob') const keypairB = Keypair.generate('ed25519', 'bob')
const accountA = MsgV3.getMsgHash( const accountA = MsgV3.getMsgID(
MsgV3.createAccount(keypairA, 'person', 'alice') MsgV3.createAccount(keypairA, 'person', 'alice')
) )
const accountB = MsgV3.getMsgHash( const accountB = MsgV3.getMsgID(
MsgV3.createAccount(keypairB, 'person', 'bob') MsgV3.createAccount(keypairB, 'person', 'bob')
) )
const rootMsgA = MsgV3.createRoot(accountA, 'post', keypairA) const mootA = MsgV3.createMoot(accountA, 'post', keypairA)
const rootHashA = MsgV3.getMsgHash(rootMsgA) const mootAID = MsgV3.getMsgID(mootA)
const tangleA = new MsgV3.Tangle(rootHashA) const tangleA = new MsgV3.Tangle(mootAID)
tangleA.add(rootHashA, rootMsgA) tangleA.add(mootAID, mootA)
const rootMsgB = MsgV3.createRoot(accountB, 'post', keypairB) const mootB = MsgV3.createMoot(accountB, 'post', keypairB)
const rootHashB = MsgV3.getMsgHash(rootMsgB) const mootBID = MsgV3.getMsgID(mootB)
const tangleB = new MsgV3.Tangle(rootHashB) const tangleB = new MsgV3.Tangle(mootBID)
tangleB.add(rootHashB, rootMsgB) tangleB.add(mootBID, mootB)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
account: accountA, account: accountA,
@ -29,19 +29,19 @@ test('simple multi-author tangle', (t) => {
domain: 'post', domain: 'post',
data: { text: 'Hello world!' }, data: { text: 'Hello world!' },
tangles: { tangles: {
[rootHashA]: tangleA, [mootAID]: tangleA,
}, },
keypair: keypairA, keypair: keypairA,
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
assert.deepEqual( assert.deepEqual(
Object.keys(msg1.metadata.tangles), Object.keys(msg1.metadata.tangles),
[rootHashA], [mootAID],
'msg1 has only feed tangle' 'msg1 has only feed tangle'
) )
const tangleX = new MsgV3.Tangle(msgHash1) const tangleX = new MsgV3.Tangle(msgID1)
tangleX.add(msgHash1, msg1) tangleX.add(msgID1, msg1)
const msg2 = MsgV3.create({ const msg2 = MsgV3.create({
account: accountB, account: accountB,
@ -49,36 +49,36 @@ test('simple multi-author tangle', (t) => {
domain: 'post', domain: 'post',
data: { text: 'Hello world!' }, data: { text: 'Hello world!' },
tangles: { tangles: {
[rootHashB]: tangleB, [mootBID]: tangleB,
[msgHash1]: tangleX, [msgID1]: tangleX,
}, },
keypair: keypairB, keypair: keypairB,
}) })
assert.deepEqual( assert.deepEqual(
Object.keys(msg2.metadata.tangles).sort(), Object.keys(msg2.metadata.tangles).sort(),
[rootHashB, msgHash1].sort(), [mootBID, msgID1].sort(),
'msg2 has feed tangle and misc tangle' 'msg2 has feed tangle and misc tangle'
) )
assert.equal( assert.equal(
msg2.metadata.tangles[rootHashB].depth, msg2.metadata.tangles[mootBID].depth,
1, 1,
'msg2 feed tangle depth' 'msg2 feed tangle depth'
) )
assert.deepEqual( assert.deepEqual(
msg2.metadata.tangles[rootHashB].prev, msg2.metadata.tangles[mootBID].prev,
[rootHashB], [mootBID],
'msg2 feed tangle prev' 'msg2 feed tangle prev'
) )
assert.equal( assert.equal(
msg2.metadata.tangles[msgHash1].depth, msg2.metadata.tangles[msgID1].depth,
1, 1,
'msg2 has tangle depth 1' 'msg2 has tangle depth 1'
) )
assert.deepEqual( assert.deepEqual(
msg2.metadata.tangles[msgHash1].prev, msg2.metadata.tangles[msgID1].prev,
[msgHash1], [msgID1],
'msg2 has tangle prev' 'msg2 has tangle prev'
) )
}) })
@ -86,24 +86,24 @@ test('simple multi-author tangle', (t) => {
test('lipmaa in multi-author tangle', (t) => { test('lipmaa in multi-author tangle', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice') const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob') const keypairB = Keypair.generate('ed25519', 'bob')
const accountA = MsgV3.getMsgHash( const accountA = MsgV3.getMsgID(
MsgV3.createAccount(keypairA, 'person', 'alice') MsgV3.createAccount(keypairA, 'person', 'alice')
) )
const accountB = MsgV3.getMsgHash( const accountB = MsgV3.getMsgID(
MsgV3.createAccount(keypairB, 'person', 'bob') MsgV3.createAccount(keypairB, 'person', 'bob')
) )
const data = { text: 'Hello world!' } const data = { text: 'Hello world!' }
const rootMsgA = MsgV3.createRoot(accountA, 'post', keypairA) const mootA = MsgV3.createMoot(accountA, 'post', keypairA)
const rootHashA = MsgV3.getMsgHash(rootMsgA) const mootAID = MsgV3.getMsgID(mootA)
const tangleA = new MsgV3.Tangle(rootHashA) const tangleA = new MsgV3.Tangle(mootAID)
tangleA.add(rootHashA, rootMsgA) tangleA.add(mootAID, mootA)
const rootMsgB = MsgV3.createRoot(accountB, 'post', keypairB) const mootB = MsgV3.createMoot(accountB, 'post', keypairB)
const rootHashB = MsgV3.getMsgHash(rootMsgB) const mootBID = MsgV3.getMsgID(mootB)
const tangleB = new MsgV3.Tangle(rootHashB) const tangleB = new MsgV3.Tangle(mootBID)
tangleB.add(rootHashB, rootMsgB) tangleB.add(mootBID, mootB)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
account: accountA, account: accountA,
@ -111,18 +111,18 @@ test('lipmaa in multi-author tangle', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHashA]: tangleA, [mootAID]: tangleA,
}, },
keypair: keypairA, keypair: keypairA,
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
tangleA.add(msgHash1, msg1) tangleA.add(msgID1, msg1)
const tangleThread = new MsgV3.Tangle(msgHash1) const tangleThread = new MsgV3.Tangle(msgID1)
tangleThread.add(msgHash1, msg1) tangleThread.add(msgID1, msg1)
assert.deepEqual( assert.deepEqual(
Object.keys(msg1.metadata.tangles), Object.keys(msg1.metadata.tangles),
[rootHashA], [mootAID],
'A:msg1 has only feed tangle' 'A:msg1 has only feed tangle'
) )
@ -132,18 +132,18 @@ test('lipmaa in multi-author tangle', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHashB]: tangleB, [mootBID]: tangleB,
[msgHash1]: tangleThread, [msgID1]: tangleThread,
}, },
keypair: keypairB, keypair: keypairB,
}) })
const msgHash2 = MsgV3.getMsgHash(msg2) const msgID2 = MsgV3.getMsgID(msg2)
tangleB.add(msgHash2, msg2) tangleB.add(msgID2, msg2)
tangleThread.add(msgHash2, msg2) tangleThread.add(msgID2, msg2)
assert.deepEqual( assert.deepEqual(
msg2.metadata.tangles[msgHash1].prev, msg2.metadata.tangles[msgID1].prev,
[msgHash1], [msgID1],
'B:msg2 points to A:msg1' 'B:msg2 points to A:msg1'
) )
@ -153,18 +153,18 @@ test('lipmaa in multi-author tangle', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHashB]: tangleB, [mootBID]: tangleB,
[msgHash1]: tangleThread, [msgID1]: tangleThread,
}, },
keypair: keypairB, keypair: keypairB,
}) })
const msgHash3 = MsgV3.getMsgHash(msg3) const msgID3 = MsgV3.getMsgID(msg3)
tangleB.add(msgHash3, msg3) tangleB.add(msgID3, msg3)
tangleThread.add(msgHash3, msg3) tangleThread.add(msgID3, msg3)
assert.deepEqual( assert.deepEqual(
msg3.metadata.tangles[msgHash1].prev, msg3.metadata.tangles[msgID1].prev,
[msgHash2], [msgID2],
'B:msg3 points to B:msg2' 'B:msg3 points to B:msg2'
) )
@ -174,18 +174,18 @@ test('lipmaa in multi-author tangle', (t) => {
domain: 'post', domain: 'post',
data, data,
tangles: { tangles: {
[rootHashA]: tangleA, [mootAID]: tangleA,
[msgHash1]: tangleThread, [msgID1]: tangleThread,
}, },
keypair: keypairA, keypair: keypairA,
}) })
const msgHash4 = MsgV3.getMsgHash(msg4) const msgID4 = MsgV3.getMsgID(msg4)
tangleB.add(msgHash4, msg4) tangleB.add(msgID4, msg4)
tangleThread.add(msgHash4, msg4) tangleThread.add(msgID4, msg4)
assert.deepEqual( assert.deepEqual(
msg4.metadata.tangles[msgHash1].prev, msg4.metadata.tangles[msgID1].prev,
[msgHash1, msgHash3].sort(), [msgID1, msgID3].sort(),
'A:msg4 points to A:msg1,B:msg3' 'A:msg4 points to A:msg1,B:msg3'
) )
}) })

View File

@ -5,16 +5,16 @@ const MsgV3 = require('../../lib/msg-v3')
test('validate root msg', (t) => { test('validate root msg', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgHash( const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice') MsgV3.createAccount(keypair, 'person', 'alice')
) )
const pubkeys = new Set([keypair.public]) const pubkeys = new Set([keypair.public])
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
const err = MsgV3.validate(rootMsg, tangle, pubkeys, rootHash, rootHash) const err = MsgV3.validate(moot, tangle, pubkeys, mootID, mootID)
assert.ifError(err, 'valid root msg') assert.ifError(err, 'valid root msg')
}) })
@ -24,8 +24,8 @@ test('validate account tangle', (t) => {
pubkeys.add(keypair1.public) pubkeys.add(keypair1.public)
const accountMsg0 = MsgV3.createAccount(keypair1, 'person', 'alice') const accountMsg0 = MsgV3.createAccount(keypair1, 'person', 'alice')
const account = MsgV3.getMsgHash(accountMsg0) const account = MsgV3.getMsgID(accountMsg0)
const accountMsg0Hash = account const accountMsg0ID = account
const tangle = new MsgV3.Tangle(account) const tangle = new MsgV3.Tangle(account)
@ -33,7 +33,7 @@ test('validate account tangle', (t) => {
accountMsg0, accountMsg0,
tangle, tangle,
pubkeys, pubkeys,
accountMsg0Hash, accountMsg0ID,
account account
) )
assert.ifError(err, 'valid account root msg') assert.ifError(err, 'valid account root msg')
@ -52,13 +52,13 @@ test('validate account tangle', (t) => {
}, },
keypair: keypair1, // announcing keypair2 but signing with keypair1 keypair: keypair1, // announcing keypair2 but signing with keypair1
}) })
const accountMsg1Hash = MsgV3.getMsgHash(accountMsg1) const accountMsg1ID = MsgV3.getMsgID(accountMsg1)
err = MsgV3.validate( err = MsgV3.validate(
accountMsg1, accountMsg1,
tangle, tangle,
pubkeys, pubkeys,
accountMsg1Hash, accountMsg1ID,
account account
) )
assert.ifError(err, 'valid account msg') assert.ifError(err, 'valid account msg')
@ -66,15 +66,15 @@ test('validate account tangle', (t) => {
test('validate 2nd msg with existing root', (t) => { test('validate 2nd msg with existing root', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgHash( const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice') MsgV3.createAccount(keypair, 'person', 'alice')
) )
const pubkeys = new Set([keypair.public]) const pubkeys = new Set([keypair.public])
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg1 = MsgV3.create({ const msg1 = MsgV3.create({
account, account,
@ -82,28 +82,28 @@ test('validate 2nd msg with existing root', (t) => {
domain: 'post', domain: 'post',
data: { text: 'Hello world!' }, data: { text: 'Hello world!' },
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
keypair, keypair,
}) })
const msgHash1 = MsgV3.getMsgHash(msg1) const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgHash1, msg1) tangle.add(msgID1, msg1)
const err = MsgV3.validate(msg1, tangle, pubkeys, msgHash1, rootHash) const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
assert.ifError(err, 'valid 2nd msg') assert.ifError(err, 'valid 2nd msg')
}) })
test('validate 2nd forked msg', (t) => { test('validate 2nd forked msg', (t) => {
const keypair = Keypair.generate('ed25519', 'alice') const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgHash( const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice') MsgV3.createAccount(keypair, 'person', 'alice')
) )
const pubkeys = new Set([keypair.public]) const pubkeys = new Set([keypair.public])
const rootMsg = MsgV3.createRoot(account, 'post', keypair) const moot = MsgV3.createMoot(account, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg) const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(rootHash) const tangle = new MsgV3.Tangle(mootID)
tangle.add(rootHash, rootMsg) tangle.add(mootID, moot)
const msg1A = MsgV3.create({ const msg1A = MsgV3.create({
account, account,
@ -111,11 +111,11 @@ test('validate 2nd forked msg', (t) => {
domain: 'post', domain: 'post',
data: { text: 'Hello world!' }, data: { text: 'Hello world!' },
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
keypair, keypair,
}) })
const msgHash1A = MsgV3.getMsgHash(msg1A) const msgID1A = MsgV3.getMsgID(msg1A)
const msg1B = MsgV3.create({ const msg1B = MsgV3.create({
account, account,
@ -123,14 +123,14 @@ test('validate 2nd forked msg', (t) => {
domain: 'post', domain: 'post',
data: { text: 'Hello world!' }, data: { text: 'Hello world!' },
tangles: { tangles: {
[rootHash]: tangle, [mootID]: tangle,
}, },
keypair, keypair,
}) })
const msgHash1B = MsgV3.getMsgHash(msg1B) const msgID1B = MsgV3.getMsgID(msg1B)
tangle.add(msgHash1A, msg1A) tangle.add(msgID1A, msg1A)
tangle.add(msgHash1B, msg1B) tangle.add(msgID1B, msg1B)
const err = MsgV3.validate(msg1B, tangle, pubkeys, msgHash1B, rootHash) const err = MsgV3.validate(msg1B, tangle, pubkeys, msgID1B, mootID)
assert.ifError(err, 'valid 2nd forked msg') assert.ifError(err, 'valid 2nd forked msg')
}) })

View File

@ -22,18 +22,18 @@ test('publish some msgs, close, re-open', async (t) => {
const account = await p(peer.db.account.create)({ domain: 'person' }) const account = await p(peer.db.account.create)({ domain: 'person' })
// t.pass('opened db') // t.pass('opened db')
const msgHashes = [] const msgIDs = []
for (let i = 0; i < 6; i++) { for (let i = 0; i < 6; i++) {
const rec = await p(peer.db.feed.publish)({ const rec = await p(peer.db.feed.publish)({
account, account,
domain: 'post', domain: 'post',
data: { text: 'hello ' + i }, data: { text: 'hello ' + i },
}) })
msgHashes.push(rec.hash) msgIDs.push(rec.id)
} }
// t.pass('created some msgs') // t.pass('created some msgs')
await p(peer.db.del)(msgHashes[2]) await p(peer.db.del)(msgIDs[2])
// t.pass('deleted the 3rd msg') // t.pass('deleted the 3rd msg')
await p(peer.close)(true) await p(peer.close)(true)