mirror of https://codeberg.org/pzp/pzp-db.git
identity tangle always has metadata.identity=self
This commit is contained in:
parent
674e2ba66c
commit
df98d499f1
128
lib/index.js
128
lib/index.js
|
@ -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: {
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)()
|
||||
|
|
|
@ -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'
|
||||
)
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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!' }
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)({
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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++
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue