identity tangle always has metadata.identity=self

This commit is contained in:
Andre Staltz 2023-06-25 20:48:20 +03:00
parent 674e2ba66c
commit df98d499f1
No known key found for this signature in database
GPG Key ID: 9EDE23EA7E8A4890
23 changed files with 271 additions and 104 deletions

View File

@ -8,7 +8,7 @@ const b4a = require('b4a')
const base58 = require('bs58')
// @ts-ignore
const Obz = require('obz')
const MsgV2 = require('./msg-v3')
const MsgV3 = require('./msg-v3')
const { ReadyGate } = require('./utils')
const { decrypt } = require('./encryption')
@ -58,7 +58,7 @@ const { decrypt } = require('./encryption')
* @typedef {(...args: [Error] | []) => void} CBVoid
*/
class DBTangle extends MsgV2.Tangle {
class DBTangle extends MsgV3.Tangle {
/**
* @param {string} rootHash
* @param {Iterable<Rec>} recordsIter
@ -260,7 +260,7 @@ function initDB(peer, config) {
* @param {CB<Rec>} cb
*/
function add(msg, tangleRootHash, cb) {
const msgHash = MsgV2.getMsgHash(msg)
const msgHash = MsgV3.getMsgHash(msg)
// TODO: optimize this. Perhaps have a Map() of msgHash -> record
// Or even better, a bloom filter. If you just want to answer no/perhaps.
@ -272,7 +272,7 @@ function initDB(peer, config) {
const tangle = new DBTangle(tangleRootHash, records())
const pubkeys = new Set()
if (msg.metadata.identity) {
if (msg.metadata.identity && msg.metadata.identity !== 'self') {
const identityTangle = new DBTangle(msg.metadata.identity, records())
if (!identityTangle.has(msg.metadata.identity)) {
// prettier-ignore
@ -286,7 +286,7 @@ function initDB(peer, config) {
}
let err
if ((err = MsgV2.validate(msg, tangle, pubkeys, msgHash, tangleRootHash))) {
if ((err = MsgV3.validate(msg, tangle, pubkeys, msgHash, tangleRootHash))) {
return cb(new Error('add() failed msg validation', { cause: err }))
}
@ -308,8 +308,8 @@ function initDB(peer, config) {
const feedRootHash = getFeedId(identity, domain)
if (feedRootHash) return cb(null, feedRootHash)
const feedRoot = MsgV2.createRoot(identity, domain, keypair)
add(feedRoot, MsgV2.getMsgHash(feedRoot), (err, rec) => {
const feedRoot = MsgV3.createRoot(identity, domain, keypair)
add(feedRoot, MsgV3.getMsgHash(feedRoot), (err, rec) => {
// prettier-ignore
if (err) return cb(new Error('initializeFeed() failed to add root', { cause: err }));
const recHash = /** @type {string} */ (rec.hash)
@ -318,25 +318,109 @@ function initDB(peer, config) {
}
/**
* @param {{keypair?: Keypair, _nonce?: string} | null} opts
* @param {CB<Rec>} cb
* @param {Rec} rec
* @returns {string | null}
*/
function getIdentityId(rec) {
if (!rec.msg) return null
if (rec.msg.metadata.identity === 'self') {
for (const tangleId in rec.msg.metadata.tangles) {
return tangleId
}
return rec.hash
} else if (rec.msg.metadata.identity) {
return rec.msg.metadata.identity
} else {
return null
}
}
/**
* @param {{
* keypair?: Keypair;
* domain: string;
* }} opts
* @param {CB<string>} cb
*/
function findIdentity(opts, cb) {
if (!opts.domain)
return cb(new Error('identity.find() requires a `domain`'))
const keypair = opts?.keypair ?? config.keypair
const domain = opts.domain
for (let i = 0; i < recs.length; i++) {
const rec = recs[i]
if (!rec) continue
if (!rec.msg) continue
if (!rec.msg.data) continue
if (
rec.msg.metadata.identity === 'self' &&
rec.msg.data.add === keypair.public &&
rec.msg.metadata.domain === domain
) {
const identityId = getIdentityId(rec)
if (identityId) {
cb(null, identityId)
} else {
// prettier-ignore
cb(new Error(`identity.find() failed to find ID in ${JSON.stringify(rec.msg)}`))
}
break
}
}
// prettier-ignore
const err = new Error(`identity.find() failed for pubkey=${keypair.public} domain=${domain}`, { cause: 'ENOENT' });
cb(err)
}
/**
* @param {{
* keypair?: Keypair,
* domain: string,
* _nonce?: string
* }} opts
* @param {CB<string>} cb
*/
function createIdentity(opts, cb) {
if (!opts.domain)
return cb(new Error('identity.create() requires a `domain`'))
const keypair = opts?.keypair ?? config.keypair
const domain = opts.domain
let msg
try {
msg = MsgV2.createIdentity(keypair, opts?._nonce)
msg = MsgV3.createIdentity(keypair, domain, opts?._nonce)
} catch (err) {
return cb(new Error('identity.create() failed', { cause: err }))
}
const msgHash = MsgV2.getMsgHash(msg)
const msgHash = MsgV3.getMsgHash(msg)
logAppend(msgHash, msg, (err, rec) => {
// prettier-ignore
if (err) return cb(new Error('identity.create() failed in the log', { cause: err }))
onRecordAdded.set(rec)
cb(null, rec)
const recHash = /** @type {string} */ (rec.hash)
cb(null, recHash)
})
}
/**
* @param {{
* keypair?: Keypair,
* domain: string,
* _nonce?: string
* }} opts
* @param {CB<string>} cb
*/
function findOrCreateIdentity(opts, cb) {
findIdentity(opts, (err, identityId) => {
if (err?.cause === 'ENOENT') {
createIdentity(opts, cb)
} else if (err) {
cb(err)
} else {
cb(null, identityId)
}
})
}
@ -355,7 +439,7 @@ function initDB(peer, config) {
// Fill-in tangle opts:
const tangles = populateTangles([opts.identity])
const fullOpts = {
identity: null,
identity: 'self',
identityTips: null,
tangles,
keypair: signingKeypair,
@ -366,11 +450,11 @@ function initDB(peer, config) {
// Create the actual message:
let msg
try {
msg = MsgV2.create(fullOpts)
msg = MsgV3.create(fullOpts)
} catch (err) {
return cb(new Error('identity.add() failed', { cause: err }))
}
const msgHash = MsgV2.getMsgHash(msg)
const msgHash = MsgV3.getMsgHash(msg)
logAppend(msgHash, msg, (err, rec) => {
// prettier-ignore
@ -421,7 +505,7 @@ function initDB(peer, config) {
// If opts ask for encryption, encrypt and put ciphertext in opts.data
const recps = fullOpts.data.recps
if (Array.isArray(recps) && recps.length > 0) {
const plaintext = MsgV2.toPlaintextBuffer(fullOpts)
const plaintext = MsgV3.toPlaintextBuffer(fullOpts)
const encryptOpts = {
...fullOpts,
recps: recps.map(
@ -454,11 +538,11 @@ function initDB(peer, config) {
// Create the actual message:
let msg
try {
msg = MsgV2.create(fullOpts)
msg = MsgV3.create(fullOpts)
} catch (err) {
return cb(new Error('feed.publish() failed', { cause: err }))
}
const msgHash = MsgV2.getMsgHash(msg)
const msgHash = MsgV3.getMsgHash(msg)
// Encode the native message and append it to the log:
logAppend(msgHash, msg, (err, rec) => {
@ -475,9 +559,9 @@ function initDB(peer, config) {
* @param {string} findDomain
*/
function getFeedId(id, findDomain) {
const findIdentity = MsgV2.stripIdentity(id)
const findIdentity = MsgV3.stripIdentity(id)
for (const rec of records()) {
if (rec.msg && MsgV2.isFeedRoot(rec.msg, findIdentity, findDomain)) {
if (rec.msg && MsgV3.isFeedRoot(rec.msg, findIdentity, findDomain)) {
return rec.hash
}
}
@ -531,7 +615,7 @@ function initDB(peer, config) {
if (!rec) return cb()
if (!rec.msg) return cb()
if (!rec.msg.data) return cb()
recs[rec.misc.seq].msg = MsgV2.erase(rec.msg)
recs[rec.misc.seq].msg = MsgV3.erase(rec.msg)
// FIXME: persist this change to disk!! Not supported by AAOL yet
cb()
}
@ -564,7 +648,9 @@ function initDB(peer, config) {
loaded,
add,
identity: {
find: findIdentity,
create: createIdentity,
findOrCreate: findOrCreateIdentity,
add: addToIdentity,
},
feed: {

View File

@ -37,7 +37,7 @@ const Tangle = require('./tangle')
* metadata: {
* dataHash: string | null;
* dataSize: number;
* identity: string | null;
* identity: string | (typeof IDENTITY_SELF) | null;
* identityTips: Array<string> | null;
* tangles: Record<string, TangleMetadata>;
* domain: string;
@ -57,6 +57,8 @@ const Tangle = require('./tangle')
* }} CreateOpts
*/
const IDENTITY_SELF = /** @type {const} */ 'self'
/**
* @param {string} id
* @param {string} domain
@ -178,21 +180,23 @@ function createRoot(id, domain, keypair) {
/**
* @param {Keypair} keypair
* @param {string} domain
* @param {string | (() => string)} nonce
* @returns {Msg}
*/
function createIdentity(
keypair,
domain,
nonce = () => base58.encode(crypto.randomBytes(32))
) {
const actualNonce = typeof nonce === 'function' ? nonce() : nonce
return create({
data: { add: keypair.public, nonce: actualNonce },
identity: null,
identity: IDENTITY_SELF,
identityTips: null,
keypair,
tangles: {},
domain: 'identity',
domain,
})
}

View File

@ -20,7 +20,8 @@ function isEmptyObject(obj) {
* @param {string | 0} findDomain
*/
function isFeedRoot(msg, id = 0, findDomain = 0) {
const { dataHash, dataSize, identity, identityTips, tangles, domain } = msg.metadata
const { dataHash, dataSize, identity, identityTips, tangles, domain } =
msg.metadata
if (dataHash !== null) return false
if (dataSize !== 0) return false
if (id === 0 && !identity) return false

View File

@ -88,7 +88,11 @@ function validateIdentityPubkey(msg, pubkeys) {
// Unusual case: if the msg is a feed root, ignore the identity and pubkey
if (isFeedRoot(msg)) return
if (msg.metadata.identity && !pubkeys.has(msg.pubkey)) {
if (
msg.metadata.identity &&
msg.metadata.identity !== 'self' &&
!pubkeys.has(msg.pubkey)
) {
// prettier-ignore
return `invalid message: pubkey "${msg.pubkey}" should have been one of "${[...pubkeys]}" from the identity "${msg.metadata.identity}"\n` + JSON.stringify(msg)
}

View File

@ -24,7 +24,7 @@ interface Msg {
metadata: {
dataHash: ContentHash | null // blake3 hash of the `content` object serialized
dataSize: number // byte size (unsigned integer) of the `content` object serialized
identity: string | null // blake3 hash ofn a identity tangle root msg, or null
identity: string | 'self' | null // blake3 hash of an identity tangle root msg, or the string 'self', or null
identityTips: Array<string> | null // list of blake3 hashes of identity tangle tips, or null
tangles: {
// for each tangle this msg belongs to, identified by the tangle's root
@ -54,7 +54,7 @@ interface Msg {
metadata: {
dataHash: ContentHash
dataSize: number
identity: null // MUST be null
identity: 'self' // MUST be the string 'self'
identityTips: null // MUST be null
tangles: {
[identityTangleId: string]: {
@ -62,7 +62,7 @@ interface Msg {
prev: Array<MsgHash> // list of msg hashes of existing msgs, unique set and ordered alphabetically
}
}
domain: 'identity' // MUST be 'identity'
domain: string // alphanumeric string, at least 3 chars, max 100 chars
v: 2
}
pubkey: Pubkey

View File

@ -21,7 +21,7 @@ test('add()', async (t) => {
await peer.db.loaded()
const identityMsg0 = MsgV3.createIdentity(keypair)
const identityMsg0 = MsgV3.createIdentity(keypair, 'person')
const id = MsgV3.getMsgHash(identityMsg0)
await p(peer.db.add)(identityMsg0, id)

View File

@ -21,7 +21,7 @@ test('del', async (t) => {
await peer.db.loaded()
const id = (await p(peer.db.identity.create)(null)).hash
const id = await p(peer.db.identity.create)({ domain: 'person' })
const msgHashes = []
for (let i = 0; i < 5; i++) {
@ -35,16 +35,24 @@ test('del', async (t) => {
const before = []
for (const msg of peer.db.msgs()) {
if (msg.data && msg.metadata.identity) before.push(msg.data.text)
if (msg.data && msg.metadata.identity?.length > 4) {
before.push(msg.data.text)
}
}
assert.deepEqual(before, ['m0', 'm1', 'm2', 'm3', 'm4'], 'msgs before the delete')
assert.deepEqual(
before,
['m0', 'm1', 'm2', 'm3', 'm4'],
'msgs before the delete'
)
await p(peer.db.del)(msgHashes[2])
const after = []
for (const msg of peer.db.msgs()) {
if (msg.data && msg.metadata.identity) after.push(msg.data.text)
if (msg.data && msg.metadata.identity?.length > 4) {
after.push(msg.data.text)
}
}
assert.deepEqual(after, ['m0', 'm1', 'm3', 'm4'], 'msgs after the delete')
@ -83,7 +91,7 @@ test('del', async (t) => {
assert.deepEqual(
persistedMsgs
.filter((msg) => msg.data && msg.metadata.identity)
.filter((msg) => msg.data && msg.metadata.identity?.length > 4)
.map((msg) => msg.data.text),
['m0', 'm1', 'm3', 'm4'],
'msgs in disk after the delete'

View File

@ -21,7 +21,7 @@ test('erase', async (t) => {
await peer.db.loaded()
const id = (await p(peer.db.identity.create)(null)).hash
const id = await p(peer.db.identity.create)({ domain: 'person' })
const msgHashes = []
for (let i = 0; i < 5; i++) {
@ -35,7 +35,9 @@ test('erase', async (t) => {
const before = []
for (const msg of peer.db.msgs()) {
if (msg.data && msg.metadata.identity) before.push(msg.data.text)
if (msg.data && msg.metadata.identity?.length > 4) {
before.push(msg.data.text)
}
}
assert.deepEqual(
@ -48,7 +50,9 @@ test('erase', async (t) => {
const after = []
for (const msg of peer.db.msgs()) {
if (msg.data && msg.metadata.identity) after.push(msg.data.text)
if (msg.data && msg.metadata.identity?.length > 4) {
after.push(msg.data.text)
}
}
assert.deepEqual(after, ['m0', 'm1', 'm3', 'm4'], '4 msgs after the erase')

View File

@ -25,7 +25,7 @@ test('setup', async (t) => {
await peer.db.loaded()
id = (await p(peer.db.identity.create)(null)).hash
id = (await p(peer.db.identity.create)({domain: 'person'}))
rootMsg = MsgV3.createRoot(id, 'post', keypair)
rootHash = MsgV3.getMsgHash(rootMsg)

View File

@ -26,7 +26,7 @@ test('setup', async (t) => {
await peer.db.loaded()
id = (await p(peer.db.identity.create)(null)).hash
id = (await p(peer.db.identity.create)({domain: 'person'}))
rootMsg = MsgV3.createRoot(id, 'post', keypair)
rootHash = MsgV3.getMsgHash(rootMsg)
})

View File

@ -25,7 +25,7 @@ test('setup', async (t) => {
await peer.db.loaded()
id = (await p(peer.db.identity.create)(null)).hash
id = (await p(peer.db.identity.create)({domain: 'person'}))
const rec1 = await p(peer.db.feed.publish)({
identity: id,

View File

@ -26,7 +26,7 @@ test('setup', async (t) => {
await peer.db.loaded()
const id = (await p(peer.db.identity.create)(null)).hash
const id = (await p(peer.db.identity.create)({domain: 'person'}))
// Slow down append so that we can trigger msg creation in parallel
const originalAppend = peer.db._getLog().append

View File

@ -21,15 +21,20 @@ test('identity.add()', async (t) => {
.call(null, { keypair: keypair1, path: DIR })
await peer.db.loaded()
const identityRec0 = await p(peer.db.identity.create)({ keypair: keypair1 })
const id = identityRec0.hash
const id = await p(peer.db.identity.create)({
keypair: keypair1,
domain: 'person',
})
const identityRec1 = await p(peer.db.identity.add)({ identity: id, keypair: keypair2 })
const identityRec1 = await p(peer.db.identity.add)({
identity: id,
keypair: keypair2,
})
assert.ok(identityRec1, 'identityRec1 exists')
const { hash, msg } = identityRec1
assert.ok(hash, 'hash exists')
assert.equal(msg.data.add, keypair2.public, 'msg.data.add NEW KEY')
assert.equal(msg.metadata.identity, null, 'msg.metadata.identity')
assert.equal(msg.metadata.identity, 'self', 'msg.metadata.identity')
assert.equal(msg.metadata.identityTips, null, 'msg.metadata.identityTips')
assert.deepEqual(
msg.metadata.tangles,
@ -54,9 +59,15 @@ test('publish with a key in the identity', async (t) => {
await peer.db.loaded()
const identityRec0 = await p(peer.db.identity.create)({ keypair: keypair1 })
const identity = identityRec0.hash
const identityRec1 = await p(peer.db.identity.add)({ identity, keypair: keypair2 })
const identity = await p(peer.db.identity.create)({
keypair: keypair1,
domain: 'person',
})
const identityMsg0 = peer.db.get(identity)
const identityRec1 = await p(peer.db.identity.add)({
identity,
keypair: keypair2,
})
const postRec = await p(peer.db.feed.publish)({
identity,
@ -71,9 +82,11 @@ test('publish with a key in the identity', async (t) => {
const recs = [...peer.db.records()]
assert.equal(recs.length, 4, '4 records')
const [_identityRec0, _identityRec1, postsRoot, _post] = recs
assert.deepEqual(_identityRec0.msg, identityRec0.msg, 'identityMsg0')
assert.deepEqual(_identityRec0.msg, identityMsg0, 'identityMsg0')
assert.deepEqual(_identityRec1.msg, identityRec1.msg, 'identityMsg1')
assert.deepEqual(postsRoot.msg.metadata, {
assert.deepEqual(
postsRoot.msg.metadata,
{
dataHash: null,
dataSize: 0,
identity,
@ -81,7 +94,9 @@ test('publish with a key in the identity', async (t) => {
tangles: {},
domain: 'post',
v: 3,
}, 'postsRoot')
},
'postsRoot'
)
assert.deepEqual(_post.msg, postRec.msg, 'postMsg')
await p(peer.close)()
@ -97,7 +112,7 @@ test('publish with a key in the identity', async (t) => {
await carol.db.loaded()
await p(carol.db.add)(identityRec0.msg, identity)
await p(carol.db.add)(identityMsg0, identity)
await p(carol.db.add)(identityRec1.msg, identity)
await p(carol.db.add)(postsRoot.msg, postsId)
await p(carol.db.add)(postRec.msg, postsId)

View File

@ -11,7 +11,7 @@ const Keypair = require('ppppp-keypair')
const DIR = path.join(os.tmpdir(), 'ppppp-db-identity-create')
rimraf.sync(DIR)
test('identity.create() without args', async (t) => {
test('identity.create() with just "domain"', async (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
@ -19,20 +19,23 @@ test('identity.create() without args', async (t) => {
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const identityRec0 = await p(peer.db.identity.create)({})
assert.ok(identityRec0, 'identityRec0 exists')
const { hash, msg } = identityRec0
assert.ok(hash, 'hash exists')
const identity = await p(peer.db.identity.create)({ domain: 'person' })
assert.ok(identity, 'identityRec0 exists')
const msg = peer.db.get(identity)
assert.equal(msg.data.add, keypair.public, 'msg.data.add')
assert.equal(msg.metadata.identity, null, 'msg.metadata.identity')
assert.equal(msg.metadata.identity, 'self', 'msg.metadata.identity')
assert.equal(msg.metadata.identityTips, null, 'msg.metadata.identityTips')
assert.deepEqual(Object.keys(msg.metadata.tangles), [], 'msg.metadata.tangles')
assert.deepEqual(
Object.keys(msg.metadata.tangles),
[],
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
await p(peer.close)()
})
test('identity.create() with "keypair" arg', async (t) => {
test('identity.create() with "keypair" and "domain"', async (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const peer = SecretStack({ appKey: caps.shse })
@ -41,14 +44,20 @@ test('identity.create() with "keypair" arg', async (t) => {
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const identityRec0 = await p(peer.db.identity.create)({ keypair })
assert.ok(identityRec0, 'identityRec0 exists')
const { hash, msg } = identityRec0
assert.ok(hash, 'hash exists')
const identity = await p(peer.db.identity.create)({
keypair,
domain: 'person',
})
assert.ok(identity, 'identity created')
const msg = peer.db.get(identity)
assert.equal(msg.data.add, keypair.public, 'msg.data.add')
assert.equal(msg.metadata.identity, null, 'msg.metadata.identity')
assert.equal(msg.metadata.identity, 'self', 'msg.metadata.identity')
assert.equal(msg.metadata.identityTips, null, 'msg.metadata.identityTips')
assert.deepEqual(Object.keys(msg.metadata.tangles), [], 'msg.metadata.tangles')
assert.deepEqual(
Object.keys(msg.metadata.tangles),
[],
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
await p(peer.close)()

View File

@ -7,21 +7,21 @@ let identity
test('MsgV3.createIdentity()', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const identityMsg0 = MsgV3.createIdentity(keypair, 'MYNONCE')
const identityMsg0 = MsgV3.createIdentity(keypair, 'person', 'MYNONCE')
console.log(JSON.stringify(identityMsg0, null, 2))
assert.equal(identityMsg0.data.add, keypair.public, 'data.add')
assert.equal(identityMsg0.metadata.dataHash, 'THi3VkJeaf8aTkLSNJUdFD', 'hash')
assert.equal(identityMsg0.metadata.dataSize, 72, 'size')
assert.equal(identityMsg0.metadata.identity, null, 'identity')
assert.equal(identityMsg0.metadata.identity, 'self', 'identity')
assert.equal(identityMsg0.metadata.identityTips, null, 'identityTips')
assert.deepEqual(identityMsg0.metadata.tangles, {}, 'tangles')
assert.equal(identityMsg0.metadata.domain, 'identity', 'domain')
assert.equal(identityMsg0.metadata.domain, 'person', 'domain')
assert.equal(identityMsg0.metadata.v, 3, 'v')
assert.equal(identityMsg0.pubkey, keypair.public, 'pubkey')
identity = MsgV3.getMsgHash(identityMsg0)
assert.equal(identity, 'WnAX17Lm2ktfPUJ5ARXq73', 'identity ID')
assert.equal(identity, 'v7vBrnrCTahjgkpoaZrWm', 'identity ID')
})
let rootMsg = null
@ -43,7 +43,7 @@ test('MsgV3.createRoot()', (t) => {
assert.equal(rootMsg.pubkey, keypair.public, 'pubkey')
rootHash = MsgV3.getMsgHash(rootMsg)
assert.equal(rootHash, '5G4FJTWaGr7ZBUJGge6Qeg', 'root hash')
assert.equal(rootHash, 'HPtwPD552ajEurwpgQRfTX', 'root hash')
})
test('MsgV3.create()', (t) => {
@ -95,11 +95,11 @@ test('MsgV3.create()', (t) => {
)
assert.equal(
msg1.sig,
'xZGu2Kb19XicfoihgBZ84jRs4XuNgVBd2bK45Cum2fdVDNJUE3f8Ejf6apfZFyE8iAfPDEVWFNAJB6E52EaWEAm',
'2FhnKsDKCxEV4JUM1nmPp3oSFJ8zL7r4SjMNogDHeAzCWQLgVmKiexgUDSE4k9C3eT4Uy3SZbBhRY75WJAqvtHHf',
'sig'
)
const msgHash1 = 'NF389yT2td9gz5TvRuZMB6'
const msgHash1 = 'FK4jCKFZDGwecydC8bitgR'
assert.equal(
MsgV3.getMsgId(msg1),
@ -155,13 +155,13 @@ test('MsgV3.create()', (t) => {
)
assert.equal(
msg2.sig,
'2XHQcG8KeNbdz8m5fDs2QtT7jcxgEqHxv7SkSYVpKQAJ1S8HGn3dmLxw3J5vWmu1vhYhWS6GDE1hfMtvmfiCAy54',
'3B6WQvDdKvRhZeZDfE9LY4HrnhZTJHRJ86FazBg1xxco2S1eHG44UwR9TSpthiXQ1X51h2VeDeGPV6Fdma69BMN9',
'sig'
)
assert.deepEqual(
MsgV3.getMsgId(msg2),
`ppppp:message/v3/${identity}/post/HNQp1oUu3zmgD1s11xiR7y`,
`ppppp:message/v3/${identity}/post/AYXun8rEc3SNGZYM252TAS`,
'getMsgId'
)
})

View File

@ -5,7 +5,9 @@ const Keypair = require('ppppp-keypair')
const MsgV3 = require('../../lib/msg-v3')
const keypair = Keypair.generate('ed25519', 'alice')
const identity = MsgV3.getMsgHash(MsgV3.createIdentity(keypair, 'MYNONCE'))
const identity = MsgV3.getMsgHash(
MsgV3.createIdentity(keypair, 'person', 'MYNONCE')
)
const pubkeys = new Set([keypair.public])
test('invalid msg with non-array prev', (t) => {
@ -180,14 +182,20 @@ test('invalid msg with unknown prev', (t) => {
const err = MsgV3.validate(msg2, tangle, pubkeys, msgHash2, rootHash)
assert.ok(err, 'invalid 2nd msg throws')
assert.match(err, /all prev are locally unknown/, 'invalid 2nd msg description')
assert.match(
err,
/all prev are locally unknown/,
'invalid 2nd msg description'
)
})
test('invalid feed msg with a different pubkey', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob')
const identityB = MsgV3.getMsgHash(MsgV3.createIdentity(keypairB, 'MYNONCE'))
const identityB = MsgV3.getMsgHash(
MsgV3.createIdentity(keypairB, 'person', 'MYNONCE')
)
const rootMsg = MsgV3.createRoot(identity, 'post', keypair)
const rootHash = MsgV3.getMsgHash(rootMsg)

View File

@ -5,7 +5,9 @@ const MsgV3 = require('../../lib/msg-v3')
test('lipmaa prevs', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const identity = MsgV3.getMsgHash(MsgV3.createIdentity(keypair, 'MYNONCE'))
const identity = MsgV3.getMsgHash(
MsgV3.createIdentity(keypair, 'person', 'MYNONCE')
)
const data = { text: 'Hello world!' }
const rootMsg = MsgV3.createRoot(identity, 'post', keypair)

View File

@ -6,8 +6,12 @@ const MsgV3 = require('../../lib/msg-v3')
test('simple multi-author tangle', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob')
const identityA = MsgV3.getMsgHash(MsgV3.createIdentity(keypairA, 'alice'))
const identityB = MsgV3.getMsgHash(MsgV3.createIdentity(keypairB, 'bob'))
const identityA = MsgV3.getMsgHash(
MsgV3.createIdentity(keypairA, 'person', 'alice')
)
const identityB = MsgV3.getMsgHash(
MsgV3.createIdentity(keypairB, 'person', 'bob')
)
const rootMsgA = MsgV3.createRoot(identityA, 'post', keypairA)
const rootHashA = MsgV3.getMsgHash(rootMsgA)
@ -82,8 +86,12 @@ test('simple multi-author tangle', (t) => {
test('lipmaa in multi-author tangle', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob')
const identityA = MsgV3.getMsgHash(MsgV3.createIdentity(keypairA, 'alice'))
const identityB = MsgV3.getMsgHash(MsgV3.createIdentity(keypairB, 'bob'))
const identityA = MsgV3.getMsgHash(
MsgV3.createIdentity(keypairA, 'person', 'alice')
)
const identityB = MsgV3.getMsgHash(
MsgV3.createIdentity(keypairB, 'person', 'bob')
)
const data = { text: 'Hello world!' }

View File

@ -5,7 +5,9 @@ const MsgV3 = require('../../lib/msg-v3')
test('validate root msg', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const identity = MsgV3.getMsgHash(MsgV3.createIdentity(keypair, 'alice'))
const identity = MsgV3.getMsgHash(
MsgV3.createIdentity(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
const rootMsg = MsgV3.createRoot(identity, 'post', keypair)
@ -21,13 +23,19 @@ test('validate identity tangle', (t) => {
const keypair1 = Keypair.generate('ed25519', 'alice')
pubkeys.add(keypair1.public)
const identityMsg0 = MsgV3.createIdentity(keypair1, 'alice')
const identityMsg0 = MsgV3.createIdentity(keypair1, 'person', 'alice')
const identity = MsgV3.getMsgHash(identityMsg0)
const identityMsg0Hash = identity
const tangle = new MsgV3.Tangle(identity)
let err = MsgV3.validate(identityMsg0, tangle, pubkeys, identityMsg0Hash, identity)
let err = MsgV3.validate(
identityMsg0,
tangle,
pubkeys,
identityMsg0Hash,
identity
)
assert.ifError(err, 'valid identity root msg')
tangle.add(identity, identityMsg0)
@ -46,13 +54,21 @@ test('validate identity tangle', (t) => {
})
const identityMsg1Hash = MsgV3.getMsgHash(identityMsg1)
err = MsgV3.validate(identityMsg1, tangle, pubkeys, identityMsg1Hash, identity)
err = MsgV3.validate(
identityMsg1,
tangle,
pubkeys,
identityMsg1Hash,
identity
)
assert.ifError(err, 'valid identity msg')
})
test('validate 2nd msg with existing root', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const identity = MsgV3.getMsgHash(MsgV3.createIdentity(keypair, 'alice'))
const identity = MsgV3.getMsgHash(
MsgV3.createIdentity(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
const rootMsg = MsgV3.createRoot(identity, 'post', keypair)
@ -79,7 +95,9 @@ test('validate 2nd msg with existing root', (t) => {
test('validate 2nd forked msg', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const identity = MsgV3.getMsgHash(MsgV3.createIdentity(keypair, 'alice'))
const identity = MsgV3.getMsgHash(
MsgV3.createIdentity(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
const rootMsg = MsgV3.createRoot(identity, 'post', keypair)

View File

@ -19,7 +19,7 @@ test('msgs() iterator', async (t) => {
await peer.db.loaded()
const identity = (await p(peer.db.identity.create)(null)).hash
const identity = (await p(peer.db.identity.create)({domain: 'person'}))
for (let i = 0; i < 6; i++) {
await p(peer.db.feed.publish)({

View File

@ -19,7 +19,7 @@ test('onRecordAdded', async (t) => {
await peer.db.loaded()
const identity = (await p(peer.db.identity.create)(null)).hash
const identity = (await p(peer.db.identity.create)({domain: 'person'}))
const listened = []
var remove = peer.db.onRecordAdded((ev) => {
@ -36,7 +36,7 @@ test('onRecordAdded', async (t) => {
await p(setTimeout)(500)
assert.equal(listened.length, 3)
assert.equal(listened[0].msg.metadata.identity, null, 'identity root')
assert.equal(listened[0].msg.metadata.identity, 'self', 'identity root')
assert.equal(listened[1].msg.data, null, 'root')
assert.equal(listened[1].msg.metadata.dataSize, 0, 'root')
assert.deepEqual(listened[2], rec1, 'actual record')

View File

@ -19,7 +19,7 @@ test('publish some msgs, close, re-open', async (t) => {
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const identity = (await p(peer.db.identity.create)(null)).hash
const identity = await p(peer.db.identity.create)({ domain: 'person' })
// t.pass('opened db')
const msgHashes = []
@ -49,7 +49,7 @@ test('publish some msgs, close, re-open', async (t) => {
const texts = []
for (const msg of peer2.db.msgs()) {
if (!msg.data || !msg.metadata.identity) continue
if (!msg.data || !(msg.metadata.identity?.length > 4)) continue
texts.push(msg.data.text)
}

View File

@ -18,7 +18,7 @@ test('records() iterator', async (t) => {
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const identity = (await p(peer.db.identity.create)(null)).hash
const identity = (await p(peer.db.identity.create)({ domain: 'person' }))
for (let i = 0; i < 6; i++) {
await p(peer.db.feed.publish)({
@ -34,7 +34,7 @@ test('records() iterator', async (t) => {
let count = 0
for (const rec of peer.db.records()) {
if (!rec.msg.data) continue
if (!rec.msg.metadata.identity) continue
if (rec.msg.metadata.identity === 'self') continue
assert.ok(rec.misc.size > rec.msg.metadata.dataSize, 'size > dataSize')
count++
}