mirror of https://codeberg.org/pzp/pzp-db.git
msg-v4
This commit is contained in:
parent
fd2e50438a
commit
3a2bfe25d0
|
@ -1,6 +1,6 @@
|
||||||
const base58 = require('bs58')
|
const base58 = require('bs58')
|
||||||
const b4a = require('b4a')
|
const b4a = require('b4a')
|
||||||
const MsgV3 = require('./msg-v3')
|
const MsgV4 = require('./msg-v4')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('./index').Msg} Msg
|
* @typedef {import('./index').Msg} Msg
|
||||||
|
@ -68,7 +68,7 @@ function decrypt(rec, peer, config) {
|
||||||
if (!plaintextBuf) return rec
|
if (!plaintextBuf) return rec
|
||||||
|
|
||||||
// Reconstruct KVT in JS encoding
|
// Reconstruct KVT in JS encoding
|
||||||
const msgDecrypted = MsgV3.fromPlaintextBuffer(plaintextBuf, msgEncrypted)
|
const msgDecrypted = MsgV4.fromPlaintextBuffer(plaintextBuf, msgEncrypted)
|
||||||
|
|
||||||
const recDecrypted = {
|
const recDecrypted = {
|
||||||
...rec,
|
...rec,
|
||||||
|
|
76
lib/index.js
76
lib/index.js
|
@ -6,13 +6,13 @@ const base58 = require('bs58')
|
||||||
const Obz = require('obz')
|
const Obz = require('obz')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const Log = require('./log')
|
const Log = require('./log')
|
||||||
const MsgV3 = require('./msg-v3')
|
const MsgV4 = require('./msg-v4')
|
||||||
const {
|
const {
|
||||||
SIGNATURE_TAG_ACCOUNT_ADD,
|
SIGNATURE_TAG_ACCOUNT_ADD,
|
||||||
ACCOUNT_SELF,
|
ACCOUNT_SELF,
|
||||||
ACCOUNT_ANY,
|
ACCOUNT_ANY,
|
||||||
ACCOUNT_DOMAIN_PREFIX,
|
ACCOUNT_DOMAIN_PREFIX,
|
||||||
} = require('./msg-v3/constants')
|
} = require('./msg-v4/constants')
|
||||||
const ReadyGate = require('./utils/ready-gate')
|
const ReadyGate = require('./utils/ready-gate')
|
||||||
const Ghosts = require('./ghosts')
|
const Ghosts = require('./ghosts')
|
||||||
const { decrypt } = require('./encryption')
|
const { decrypt } = require('./encryption')
|
||||||
|
@ -22,11 +22,11 @@ const { decrypt } = require('./encryption')
|
||||||
* @typedef {import('ppppp-keypair').KeypairPublicSlice} KeypairPublicSlice
|
* @typedef {import('ppppp-keypair').KeypairPublicSlice} KeypairPublicSlice
|
||||||
* @typedef {import('ppppp-keypair').KeypairPrivateSlice} KeypairPrivateSlice
|
* @typedef {import('ppppp-keypair').KeypairPrivateSlice} KeypairPrivateSlice
|
||||||
* @typedef {string} MsgID
|
* @typedef {string} MsgID
|
||||||
* @typedef {import('./msg-v3').Msg} Msg
|
* @typedef {import('./msg-v4').Msg} Msg
|
||||||
* @typedef {import('./msg-v3').AccountData} AccountData
|
* @typedef {import('./msg-v4').AccountData} AccountData
|
||||||
* @typedef {import('./msg-v3').AccountPower} AccountPower
|
* @typedef {import('./msg-v4').AccountPower} AccountPower
|
||||||
|
* @typedef {import('./msg-v4/tangle')} Tangle
|
||||||
* @typedef {import('./encryption').EncryptionFormat} EncryptionFormat
|
* @typedef {import('./encryption').EncryptionFormat} EncryptionFormat
|
||||||
* @typedef {import('./msg-v3/tangle')} Tangle
|
|
||||||
* @typedef {Buffer | Uint8Array} B4A
|
* @typedef {Buffer | Uint8Array} B4A
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* db: {
|
* db: {
|
||||||
|
@ -85,7 +85,7 @@ function assertValidConfig(config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DBTangle extends MsgV3.Tangle {
|
class DBTangle extends MsgV4.Tangle {
|
||||||
/** @type {(msgID: MsgID) => Msg | undefined} */
|
/** @type {(msgID: MsgID) => Msg | undefined} */
|
||||||
#getMsg
|
#getMsg
|
||||||
|
|
||||||
|
@ -354,15 +354,15 @@ function initDB(peer, config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find which pubkeys are authorized to sign this msg given the account.
|
* Find which sigkeys are authorized to sign this msg given the account.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Tangle | null} accountTangle
|
* @param {Tangle | null} accountTangle
|
||||||
* @returns {Set<string>}
|
* @returns {Set<string>}
|
||||||
*/
|
*/
|
||||||
function getPubkeysInAccount(accountTangle) {
|
function getSigkeysInAccount(accountTangle) {
|
||||||
const pubkeys = new Set()
|
const sigkeys = new Set()
|
||||||
if (!accountTangle) return pubkeys
|
if (!accountTangle) return sigkeys
|
||||||
// TODO: prune the accountTangle beyond msg.metadata.accountTips
|
// TODO: prune the accountTangle beyond msg.metadata.accountTips
|
||||||
for (const msgID of accountTangle.topoSort()) {
|
for (const msgID of accountTangle.topoSort()) {
|
||||||
const msg = get(msgID)
|
const msg = get(msgID)
|
||||||
|
@ -373,9 +373,9 @@ function initDB(peer, config) {
|
||||||
const purpose = data.key?.purpose
|
const purpose = data.key?.purpose
|
||||||
if (purpose !== 'sig' && purpose !== 'shs-and-sig') continue
|
if (purpose !== 'sig' && purpose !== 'shs-and-sig') continue
|
||||||
if (data.key.algorithm !== 'ed25519') continue
|
if (data.key.algorithm !== 'ed25519') continue
|
||||||
pubkeys.add(data.key.bytes)
|
sigkeys.add(data.key.bytes)
|
||||||
}
|
}
|
||||||
return pubkeys
|
return sigkeys
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -405,7 +405,7 @@ function initDB(peer, config) {
|
||||||
tangle.add(rec.id, rec.msg)
|
tangle.add(rec.id, rec.msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify the account and its pubkeys:
|
// Identify the account and its sigkeys:
|
||||||
/** @type {Tangle | null} */
|
/** @type {Tangle | null} */
|
||||||
let accountTangle
|
let accountTangle
|
||||||
try {
|
try {
|
||||||
|
@ -413,7 +413,7 @@ function initDB(peer, config) {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return new Error('Unknown account tangle owning this msg', { cause: err })
|
return new Error('Unknown account tangle owning this msg', { cause: err })
|
||||||
}
|
}
|
||||||
const pubkeys = getPubkeysInAccount(accountTangle)
|
const sigkeys = getSigkeysInAccount(accountTangle)
|
||||||
|
|
||||||
// Don't accept ghosts to come back, unless they are trail msgs
|
// Don't accept ghosts to come back, unless they are trail msgs
|
||||||
if (!!rec.msg.data && ghosts.read(tangleID).has(rec.id)) {
|
if (!!rec.msg.data && ghosts.read(tangleID).has(rec.id)) {
|
||||||
|
@ -421,7 +421,7 @@ function initDB(peer, config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let err
|
let err
|
||||||
if ((err = MsgV3.validate(rec.msg, tangle, pubkeys, rec.id, tangleID))) {
|
if ((err = MsgV4.validate(rec.msg, tangle, sigkeys, rec.id, tangleID))) {
|
||||||
return new Error('Invalid msg', { cause: err })
|
return new Error('Invalid msg', { cause: err })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,9 +436,9 @@ function initDB(peer, config) {
|
||||||
// Unwrap encrypted inner msg and verify it too
|
// Unwrap encrypted inner msg and verify it too
|
||||||
if (typeof rec.msg.data === 'string') {
|
if (typeof rec.msg.data === 'string') {
|
||||||
const recDecrypted = decrypt(rec, peer, config)
|
const recDecrypted = decrypt(rec, peer, config)
|
||||||
if (MsgV3.isMsg(recDecrypted.msg.data)) {
|
if (MsgV4.isMsg(recDecrypted.msg.data)) {
|
||||||
const innerMsg = /** @type {Msg} */ (recDecrypted.msg.data)
|
const innerMsg = /** @type {Msg} */ (recDecrypted.msg.data)
|
||||||
const innerMsgID = MsgV3.getMsgID(innerMsg)
|
const innerMsgID = MsgV4.getMsgID(innerMsg)
|
||||||
const innerRec = { id: innerMsgID, msg: innerMsg }
|
const innerRec = { id: innerMsgID, msg: innerMsg }
|
||||||
try {
|
try {
|
||||||
verifyRec(innerRec, innerMsgID)
|
verifyRec(innerRec, innerMsgID)
|
||||||
|
@ -456,7 +456,7 @@ function initDB(peer, config) {
|
||||||
* @returns {MsgID}
|
* @returns {MsgID}
|
||||||
*/
|
*/
|
||||||
function inferTangleID(rec) {
|
function inferTangleID(rec) {
|
||||||
if (MsgV3.isRoot(rec.msg)) return rec.id
|
if (MsgV4.isRoot(rec.msg)) return rec.id
|
||||||
let tangleID = /**@type {string | null}*/ (null)
|
let tangleID = /**@type {string | null}*/ (null)
|
||||||
for (const id in rec.msg.metadata.tangles) {
|
for (const id in rec.msg.metadata.tangles) {
|
||||||
if (tangleID) {
|
if (tangleID) {
|
||||||
|
@ -478,7 +478,7 @@ function initDB(peer, config) {
|
||||||
* @param {CB<RecPresent>} cb
|
* @param {CB<RecPresent>} cb
|
||||||
*/
|
*/
|
||||||
function add(msg, tangleID, cb) {
|
function add(msg, tangleID, cb) {
|
||||||
const msgID = MsgV3.getMsgID(msg)
|
const msgID = MsgV4.getMsgID(msg)
|
||||||
|
|
||||||
// TODO: optimize this. Perhaps have a Map() of msgID -> 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.
|
||||||
|
@ -512,19 +512,19 @@ function initDB(peer, config) {
|
||||||
* @returns {string | undefined}
|
* @returns {string | undefined}
|
||||||
*/
|
*/
|
||||||
function validateAccountMsg(msg, accountTangle) {
|
function validateAccountMsg(msg, accountTangle) {
|
||||||
if (!MsgV3.isRoot(msg)) {
|
if (!MsgV4.isRoot(msg)) {
|
||||||
/** @type {AccountData} */
|
/** @type {AccountData} */
|
||||||
const data = msg.data
|
const data = msg.data
|
||||||
if (data.action === 'add') {
|
if (data.action === 'add') {
|
||||||
// Does this msg.pubkey have the "add" power?
|
// Does this msg.sigkey have the "add" power?
|
||||||
const keypair = {
|
const keypair = {
|
||||||
curve: /** @type {const} */ ('ed25519'),
|
curve: /** @type {const} */ ('ed25519'),
|
||||||
public: msg.pubkey,
|
public: msg.sigkey,
|
||||||
}
|
}
|
||||||
const powers = getAccountPowers(accountTangle, keypair)
|
const powers = getAccountPowers(accountTangle, keypair)
|
||||||
if (!powers.has('add')) {
|
if (!powers.has('add')) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return `invalid account msg: pubkey "${msg.pubkey}" does not have "add" power`
|
return `invalid account msg: sigkey "${msg.sigkey}" does not have "add" power`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO validate 'del'
|
// TODO validate 'del'
|
||||||
|
@ -542,8 +542,8 @@ function initDB(peer, config) {
|
||||||
const mootID = findMoot(account, domain)?.id
|
const mootID = findMoot(account, domain)?.id
|
||||||
if (mootID) return cb(null, mootID)
|
if (mootID) return cb(null, mootID)
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, domain, keypair)
|
const moot = MsgV4.createMoot(account, domain, keypair)
|
||||||
add(moot, MsgV3.getMsgID(moot), (err, rec) => {
|
add(moot, MsgV4.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 }));
|
||||||
cb(null, rec.id)
|
cb(null, rec.id)
|
||||||
|
@ -607,7 +607,7 @@ function initDB(peer, config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const err = new Error(`account.find() failed for pubkey=${keypair.public} subdomain=${opts.subdomain}`, { cause: 'ENOENT' });
|
const err = new Error(`account.find() failed for sigkey=${keypair.public} subdomain=${opts.subdomain}`, { cause: 'ENOENT' });
|
||||||
cb(err)
|
cb(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,11 +660,11 @@ function initDB(peer, config) {
|
||||||
|
|
||||||
let msg
|
let msg
|
||||||
try {
|
try {
|
||||||
msg = MsgV3.createAccount(keypair, domain, opts?._nonce)
|
msg = MsgV4.createAccount(keypair, domain, opts?._nonce)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return cb(new Error('account.create() failed', { cause: err }))
|
return cb(new Error('account.create() failed', { cause: err }))
|
||||||
}
|
}
|
||||||
const msgID = MsgV3.getMsgID(msg)
|
const msgID = MsgV4.getMsgID(msg)
|
||||||
|
|
||||||
logAppend(msgID, msg, (err, rec) => {
|
logAppend(msgID, msg, (err, rec) => {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
|
@ -857,11 +857,11 @@ function initDB(peer, config) {
|
||||||
// Create the actual message:
|
// Create the actual message:
|
||||||
let msg
|
let msg
|
||||||
try {
|
try {
|
||||||
msg = MsgV3.create(fullOpts)
|
msg = MsgV4.create(fullOpts)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return cb(new Error('account.add() failed', { cause: err }))
|
return cb(new Error('account.add() failed', { cause: err }))
|
||||||
}
|
}
|
||||||
const msgID = MsgV3.getMsgID(msg)
|
const msgID = MsgV4.getMsgID(msg)
|
||||||
|
|
||||||
logAppend(msgID, msg, (err, rec) => {
|
logAppend(msgID, msg, (err, rec) => {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
|
@ -927,7 +927,7 @@ function initDB(peer, config) {
|
||||||
// If opts ask for encryption, encrypt and put ciphertext in opts.data
|
// If opts ask for encryption, encrypt and put ciphertext in opts.data
|
||||||
const recps = fullOpts.data.recps
|
const recps = fullOpts.data.recps
|
||||||
if (Array.isArray(recps) && recps.length > 0) {
|
if (Array.isArray(recps) && recps.length > 0) {
|
||||||
const plaintext = MsgV3.toPlaintextBuffer(fullOpts)
|
const plaintext = MsgV4.toPlaintextBuffer(fullOpts)
|
||||||
const encryptOpts = {
|
const encryptOpts = {
|
||||||
...fullOpts,
|
...fullOpts,
|
||||||
recps: recps.map(
|
recps: recps.map(
|
||||||
|
@ -959,12 +959,12 @@ function initDB(peer, config) {
|
||||||
// Create the actual message:
|
// Create the actual message:
|
||||||
let msg
|
let msg
|
||||||
try {
|
try {
|
||||||
msg = MsgV3.create(fullOpts)
|
msg = MsgV4.create(fullOpts)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return cb(new Error('feed.publish() failed to create message', { cause: err }))
|
return cb(new Error('feed.publish() failed to create message', { cause: err }))
|
||||||
}
|
}
|
||||||
const msgID = MsgV3.getMsgID(msg)
|
const msgID = MsgV4.getMsgID(msg)
|
||||||
|
|
||||||
// Encode the native message and append it to the log:
|
// Encode the native message and append it to the log:
|
||||||
logAppend(msgID, msg, (err, rec) => {
|
logAppend(msgID, msg, (err, rec) => {
|
||||||
|
@ -982,9 +982,9 @@ function initDB(peer, config) {
|
||||||
* @returns {RecPresent | null}
|
* @returns {RecPresent | null}
|
||||||
*/
|
*/
|
||||||
function findMoot(id, findDomain) {
|
function findMoot(id, findDomain) {
|
||||||
const findAccount = MsgV3.stripAccount(id)
|
const findAccount = MsgV4.stripAccount(id)
|
||||||
for (const rec of records()) {
|
for (const rec of records()) {
|
||||||
if (rec.msg && MsgV3.isMoot(rec.msg, findAccount, findDomain)) {
|
if (rec.msg && MsgV4.isMoot(rec.msg, findAccount, findDomain)) {
|
||||||
return rec
|
return rec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1113,7 +1113,7 @@ function initDB(peer, config) {
|
||||||
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()
|
||||||
rec.msg = MsgV3.erase(rec.msg)
|
rec.msg = MsgV4.erase(rec.msg)
|
||||||
const misc = miscRegistry.get(rec)
|
const misc = miscRegistry.get(rec)
|
||||||
const seq = misc?.seq ?? -1
|
const seq = misc?.seq ?? -1
|
||||||
const offset = misc?.offset ?? -1
|
const offset = misc?.offset ?? -1
|
||||||
|
@ -1163,7 +1163,7 @@ function initDB(peer, config) {
|
||||||
},
|
},
|
||||||
feed: {
|
feed: {
|
||||||
publish: publishToFeed,
|
publish: publishToFeed,
|
||||||
getID: MsgV3.getMootID,
|
getID: MsgV4.getMootID,
|
||||||
findMoot,
|
findMoot,
|
||||||
},
|
},
|
||||||
getRecord,
|
getRecord,
|
||||||
|
|
|
@ -7,6 +7,6 @@ module.exports = {
|
||||||
|
|
||||||
ACCOUNT_DOMAIN_PREFIX: 'account__',
|
ACCOUNT_DOMAIN_PREFIX: 'account__',
|
||||||
|
|
||||||
SIGNATURE_TAG_MSG_V3: ':msg-v3:',
|
SIGNATURE_TAG_MSG_V4: ':msg-v4:',
|
||||||
SIGNATURE_TAG_ACCOUNT_ADD: ':account-add:',
|
SIGNATURE_TAG_ACCOUNT_ADD: ':account-add:',
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
const b4a = require('b4a')
|
const b4a = require('b4a')
|
||||||
const blake3 = require('blake3')
|
const crypto = require('crypto')
|
||||||
const base58 = require('bs58')
|
const base58 = require('bs58')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const stringify = require('json-canon')
|
const stringify = require('json-canon')
|
||||||
|
@ -15,8 +15,8 @@ const stringify = require('json-canon')
|
||||||
*/
|
*/
|
||||||
function getMsgHashBuf(msg) {
|
function getMsgHashBuf(msg) {
|
||||||
const metadataBuf = b4a.from(stringify(msg.metadata), 'utf8')
|
const metadataBuf = b4a.from(stringify(msg.metadata), 'utf8')
|
||||||
const longHash = b4a.from(blake3.hash(metadataBuf))
|
const metadataHash = crypto.createHash('sha512').update(metadataBuf).digest()
|
||||||
return longHash.subarray(0, 16)
|
return b4a.from(metadataHash.subarray(0, 32))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +25,7 @@ function getMsgHashBuf(msg) {
|
||||||
*/
|
*/
|
||||||
function getMsgID(x) {
|
function getMsgID(x) {
|
||||||
if (typeof x === 'string') {
|
if (typeof x === 'string') {
|
||||||
if (x.startsWith('ppppp:message/v3/')) {
|
if (x.startsWith('ppppp:message/v4/')) {
|
||||||
const msgUri = x
|
const msgUri = x
|
||||||
const parts = msgUri.split('/')
|
const parts = msgUri.split('/')
|
||||||
return parts[parts.length - 1]
|
return parts[parts.length - 1]
|
||||||
|
@ -48,9 +48,9 @@ function getMsgURI(msg) {
|
||||||
const { account, domain } = msg.metadata
|
const { account, domain } = msg.metadata
|
||||||
const msgHash = getMsgID(msg)
|
const msgHash = getMsgID(msg)
|
||||||
if (domain) {
|
if (domain) {
|
||||||
return `ppppp:message/v3/${account}/${domain}/${msgHash}`
|
return `ppppp:message/v4/${account}/${domain}/${msgHash}`
|
||||||
} else {
|
} else {
|
||||||
return `ppppp:message/v3/${account}/${msgHash}`
|
return `ppppp:message/v4/${account}/${msgHash}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ const Tangle = require('./tangle')
|
||||||
const {
|
const {
|
||||||
ACCOUNT_SELF,
|
ACCOUNT_SELF,
|
||||||
ACCOUNT_ANY,
|
ACCOUNT_ANY,
|
||||||
SIGNATURE_TAG_MSG_V3,
|
SIGNATURE_TAG_MSG_V4,
|
||||||
} = require('./constants')
|
} = require('./constants')
|
||||||
const { isEmptyObject } = require('./util')
|
const { isEmptyObject } = require('./util')
|
||||||
|
|
||||||
|
@ -42,9 +42,9 @@ const { isEmptyObject } = require('./util')
|
||||||
* [tangleID in string]: TangleMetadata
|
* [tangleID in string]: TangleMetadata
|
||||||
* };
|
* };
|
||||||
* domain: string;
|
* domain: string;
|
||||||
* v: 3;
|
* v: 4;
|
||||||
* };
|
* };
|
||||||
* pubkey: string;
|
* sigkey: string;
|
||||||
* sig: string;
|
* sig: string;
|
||||||
* }} Msg
|
* }} Msg
|
||||||
*/
|
*/
|
||||||
|
@ -62,9 +62,9 @@ const { isEmptyObject } = require('./util')
|
||||||
* [tangleID in string]: TangleMetadata
|
* [tangleID in string]: TangleMetadata
|
||||||
* };
|
* };
|
||||||
* domain: string;
|
* domain: string;
|
||||||
* v: 3;
|
* v: 4;
|
||||||
* };
|
* };
|
||||||
* pubkey: string;
|
* sigkey: string;
|
||||||
* sig: string;
|
* sig: string;
|
||||||
* }} FeedMsg
|
* }} FeedMsg
|
||||||
*/
|
*/
|
||||||
|
@ -142,9 +142,9 @@ function getMootID(id, domain) {
|
||||||
accountTips: null,
|
accountTips: null,
|
||||||
tangles: {},
|
tangles: {},
|
||||||
domain,
|
domain,
|
||||||
v: 3,
|
v: 4,
|
||||||
},
|
},
|
||||||
pubkey: '',
|
sigkey: '',
|
||||||
sig: '',
|
sig: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,15 +192,15 @@ function create(opts) {
|
||||||
accountTips,
|
accountTips,
|
||||||
tangles,
|
tangles,
|
||||||
domain: opts.domain,
|
domain: opts.domain,
|
||||||
v: 3,
|
v: 4,
|
||||||
},
|
},
|
||||||
pubkey: opts.keypair.public,
|
sigkey: opts.keypair.public,
|
||||||
sig: '',
|
sig: '',
|
||||||
}
|
}
|
||||||
if ((err = validateData(msg))) throw err
|
if ((err = validateData(msg))) throw err
|
||||||
|
|
||||||
const signableBuf = b4a.from(
|
const signableBuf = b4a.from(
|
||||||
SIGNATURE_TAG_MSG_V3 + stringify(msg.metadata),
|
SIGNATURE_TAG_MSG_V4 + stringify(msg.metadata),
|
||||||
'utf8'
|
'utf8'
|
||||||
)
|
)
|
||||||
msg.sig = Keypair.sign(opts.keypair, signableBuf)
|
msg.sig = Keypair.sign(opts.keypair, signableBuf)
|
||||||
|
@ -228,14 +228,14 @@ function createMoot(id, domain, keypair) {
|
||||||
accountTips: null,
|
accountTips: null,
|
||||||
tangles: {},
|
tangles: {},
|
||||||
domain,
|
domain,
|
||||||
v: 3,
|
v: 4,
|
||||||
},
|
},
|
||||||
pubkey: keypair.public,
|
sigkey: keypair.public,
|
||||||
sig: '',
|
sig: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
const signableBuf = b4a.from(
|
const signableBuf = b4a.from(
|
||||||
SIGNATURE_TAG_MSG_V3 + stringify(msg.metadata),
|
SIGNATURE_TAG_MSG_V4 + stringify(msg.metadata),
|
||||||
'utf8'
|
'utf8'
|
||||||
)
|
)
|
||||||
msg.sig = Keypair.sign(keypair, signableBuf)
|
msg.sig = Keypair.sign(keypair, signableBuf)
|
|
@ -1,4 +1,4 @@
|
||||||
const blake3 = require('blake3')
|
const crypto = require('crypto')
|
||||||
const b4a = require('b4a')
|
const b4a = require('b4a')
|
||||||
const base58 = require('bs58')
|
const base58 = require('bs58')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -14,8 +14,8 @@ const stringify = require('json-canon')
|
||||||
*/
|
*/
|
||||||
function representData(data) {
|
function representData(data) {
|
||||||
const dataBuf = b4a.from(stringify(data), 'utf8')
|
const dataBuf = b4a.from(stringify(data), 'utf8')
|
||||||
const fullHash = /** @type {B4A} */ (blake3.hash(dataBuf))
|
const fullHash = crypto.createHash('sha512').update(dataBuf).digest()
|
||||||
const dataHash = base58.encode(fullHash.subarray(0, 16))
|
const dataHash = base58.encode(fullHash.subarray(0, 32))
|
||||||
const dataSize = dataBuf.length
|
const dataSize = dataBuf.length
|
||||||
return [dataHash, dataSize]
|
return [dataHash, dataSize]
|
||||||
}
|
}
|
|
@ -7,8 +7,8 @@
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function stripAccount(id) {
|
function stripAccount(id) {
|
||||||
if (id.startsWith('ppppp:account/v3/') === false) return id
|
if (id.startsWith('ppppp:account/v4/') === false) return id
|
||||||
const withoutPrefix = id.replace('ppppp:account/v3/', '')
|
const withoutPrefix = id.replace('ppppp:account/v4/', '')
|
||||||
return withoutPrefix.split('/')[0]
|
return withoutPrefix.split('/')[0]
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ const Tangle = require('./tangle')
|
||||||
const representData = require('./represent-data')
|
const representData = require('./represent-data')
|
||||||
const isMoot = require('./is-moot')
|
const isMoot = require('./is-moot')
|
||||||
const {
|
const {
|
||||||
SIGNATURE_TAG_MSG_V3,
|
SIGNATURE_TAG_MSG_V4,
|
||||||
ACCOUNT_SELF,
|
ACCOUNT_SELF,
|
||||||
ACCOUNT_ANY,
|
ACCOUNT_ANY,
|
||||||
} = require('./constants')
|
} = require('./constants')
|
||||||
|
@ -49,8 +49,8 @@ function validateShape(msg) {
|
||||||
if (!('domain' in msg.metadata)) {
|
if (!('domain' in msg.metadata)) {
|
||||||
return 'invalid msg: must have metadata.domain\n' + JSON.stringify(msg)
|
return 'invalid msg: must have metadata.domain\n' + JSON.stringify(msg)
|
||||||
}
|
}
|
||||||
if (msg.metadata.v !== 3) {
|
if (msg.metadata.v !== 4) {
|
||||||
return 'invalid msg: must have metadata.v=3\n' + JSON.stringify(msg)
|
return 'invalid msg: must have metadata.v=4\n' + JSON.stringify(msg)
|
||||||
}
|
}
|
||||||
if (typeof msg.sig !== 'string') {
|
if (typeof msg.sig !== 'string') {
|
||||||
return 'invalid msg: must have sig\n' + JSON.stringify(msg)
|
return 'invalid msg: must have sig\n' + JSON.stringify(msg)
|
||||||
|
@ -61,21 +61,21 @@ function validateShape(msg) {
|
||||||
* @param {Msg} msg
|
* @param {Msg} msg
|
||||||
* @returns {string | undefined}
|
* @returns {string | undefined}
|
||||||
*/
|
*/
|
||||||
function validatePubkey(msg) {
|
function validateSigkey(msg) {
|
||||||
const { pubkey } = msg
|
const { sigkey } = msg
|
||||||
if (typeof pubkey !== 'string') {
|
if (typeof sigkey !== 'string') {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return `invalid msg: pubkey "${pubkey}" should have been a string\n` + JSON.stringify(msg)
|
return `invalid msg: sigkey "${sigkey}" should have been a string\n` + JSON.stringify(msg)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const pubkeyBuf = base58.decode(pubkey)
|
const sigkeyBuf = base58.decode(sigkey)
|
||||||
if (pubkeyBuf.length !== 32) {
|
if (sigkeyBuf.length !== 32) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return `invalid msg: decoded "pubkey" should be 32 bytes but was ${pubkeyBuf.length}\n` + JSON.stringify(msg)
|
return `invalid msg: decoded "sigkey" should be 32 bytes but was ${sigkeyBuf.length}\n` + JSON.stringify(msg)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return `invalid msg: pubkey "${pubkey}" should have been a base58 string\n` + JSON.stringify(msg)
|
return `invalid msg: sigkey "${sigkey}" should have been a base58 string\n` + JSON.stringify(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,18 +83,18 @@ function validatePubkey(msg) {
|
||||||
*
|
*
|
||||||
* @param {Msg} msg
|
* @param {Msg} msg
|
||||||
* @param {Tangle} tangle
|
* @param {Tangle} tangle
|
||||||
* @param {Set<string>} pubkeys
|
* @param {Set<string>} sigkeys
|
||||||
* @returns {string | undefined}
|
* @returns {string | undefined}
|
||||||
*/
|
*/
|
||||||
function validatePubkeyAndAccount(msg, tangle, pubkeys) {
|
function validateSigkeyAndAccount(msg, tangle, sigkeys) {
|
||||||
if (tangle.type === 'feed' || tangle.type === 'weave') {
|
if (tangle.type === 'feed' || tangle.type === 'weave') {
|
||||||
if (msg.metadata.account === ACCOUNT_SELF) {
|
if (msg.metadata.account === ACCOUNT_SELF) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return `invalid msg: account "${msg.metadata.account}" cannot be "self" in a feed tangle\n` + JSON.stringify(msg)
|
return `invalid msg: account "${msg.metadata.account}" cannot be "self" in a feed tangle\n` + JSON.stringify(msg)
|
||||||
}
|
}
|
||||||
if (msg.metadata.account !== ACCOUNT_ANY && !pubkeys.has(msg.pubkey)) {
|
if (msg.metadata.account !== ACCOUNT_ANY && !sigkeys.has(msg.sigkey)) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return `invalid msg: pubkey "${msg.pubkey}" should have been one of "${[...pubkeys]}" from the account "${msg.metadata.account}"\n` + JSON.stringify(msg)
|
return `invalid msg: sigkey "${msg.sigkey}" should have been one of "${[...sigkeys]}" from the account "${msg.metadata.account}"\n` + JSON.stringify(msg)
|
||||||
}
|
}
|
||||||
} else if (tangle.type === 'account') {
|
} else if (tangle.type === 'account') {
|
||||||
if (msg.metadata.account !== ACCOUNT_SELF) {
|
if (msg.metadata.account !== ACCOUNT_SELF) {
|
||||||
|
@ -115,9 +115,9 @@ function validatePubkeyAndAccount(msg, tangle, pubkeys) {
|
||||||
function validateMsgID(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 !== 32) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return `invalid msgID "${str}": should have 16 bytes but has ${hashBuf.length}`
|
return `invalid msgID "${str}": should have 32 bytes but has ${hashBuf.length}`
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return `invalid msgID "${str}": should have been a base58 string`
|
return `invalid msgID "${str}": should have been a base58 string`
|
||||||
|
@ -147,12 +147,12 @@ function validateSignature(msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const signableBuf = b4a.from(
|
const signableBuf = b4a.from(
|
||||||
SIGNATURE_TAG_MSG_V3 + stringify(msg.metadata),
|
SIGNATURE_TAG_MSG_V4 + stringify(msg.metadata),
|
||||||
'utf8'
|
'utf8'
|
||||||
)
|
)
|
||||||
const keypair = {
|
const keypair = {
|
||||||
curve: /** @type {const} */ ('ed25519'),
|
curve: /** @type {const} */ ('ed25519'),
|
||||||
public: msg.pubkey,
|
public: msg.sigkey,
|
||||||
}
|
}
|
||||||
const verified = Keypair.verify(keypair, signableBuf, sig)
|
const verified = Keypair.verify(keypair, signableBuf, sig)
|
||||||
if (!verified) {
|
if (!verified) {
|
||||||
|
@ -322,21 +322,21 @@ function validateDataSizeHash(msg) {
|
||||||
/**
|
/**
|
||||||
* @param {Msg} msg
|
* @param {Msg} msg
|
||||||
* @param {Tangle} tangle
|
* @param {Tangle} tangle
|
||||||
* @param {Set<string>} pubkeys
|
* @param {Set<string>} sigkeys
|
||||||
* @param {string} msgID
|
* @param {string} msgID
|
||||||
* @param {string} rootID
|
* @param {string} rootID
|
||||||
*/
|
*/
|
||||||
function validate(msg, tangle, pubkeys, msgID, rootID) {
|
function validate(msg, tangle, sigkeys, 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 = validateSigkey(msg))) return err
|
||||||
if ((err = validateData(msg))) return err
|
if ((err = validateData(msg))) return err
|
||||||
|
|
||||||
if (tangle.type === 'feed' && isMoot(msg)) return // nothing else to check
|
if (tangle.type === 'feed' && isMoot(msg)) return // nothing else to check
|
||||||
|
|
||||||
if ((err = validateDataSizeHash(msg))) return err
|
if ((err = validateDataSizeHash(msg))) return err
|
||||||
if ((err = validateDomain(msg.metadata.domain))) return err
|
if ((err = validateDomain(msg.metadata.domain))) return err
|
||||||
if ((err = validatePubkeyAndAccount(msg, tangle, pubkeys))) return err
|
if ((err = validateSigkeyAndAccount(msg, tangle, sigkeys))) return err
|
||||||
if (msgID === rootID) {
|
if (msgID === rootID) {
|
||||||
if ((err = validateTangleRoot(msg, msgID, rootID))) return err
|
if ((err = validateTangleRoot(msg, msgID, rootID))) return err
|
||||||
} else {
|
} else {
|
182
protospec.md
182
protospec.md
|
@ -1,3 +1,181 @@
|
||||||
|
# Msg V4
|
||||||
|
|
||||||
|
Background: https://github.com/ssbc/ssb2-discussion-forum/issues/24
|
||||||
|
|
||||||
|
## Terminology
|
||||||
|
|
||||||
|
- **Hash** = base58 encoded string of the first 32 bytes of a sha512 hash
|
||||||
|
- **Msg** = `{data,metadata,sigkey,sig}` published by a peer
|
||||||
|
- **Msg ID** = `hash(msg.metadata)`
|
||||||
|
- **Tangle** = a single-root DAG of msgs that can be replicated by peers
|
||||||
|
- **Root** = the origin msg of a tangle
|
||||||
|
- **Tangle Tips** = tangle msgs that are not yet referenced by any other msg in the tangle
|
||||||
|
- **Tangle ID** = Msg ID of the tangle's root msg
|
||||||
|
- **Account** = tangle with msgs that add (or remove?) cryptographic keys
|
||||||
|
- **Account ID** = tangle ID of the account tangle
|
||||||
|
- **Feed** = tangle with msgs authored by (any sigkey in) an account
|
||||||
|
- **Moot** = the root of a feed, a msg that is deterministically predictable and empty, so to allow others to pre-know its msg ID, and thus the feed ID
|
||||||
|
- **Feed ID** = ID of the moot of a feed (Msg ID of the feed's root msg)
|
||||||
|
|
||||||
|
JSON
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface Msg {
|
||||||
|
data: Record<string, any> | string | null // a plaintext object, or ciphertext string, or null
|
||||||
|
metadata: {
|
||||||
|
account: string | 'self' | 'any' // msg ID of account root, or the string 'self', or the string 'any'
|
||||||
|
accountTips: Array<string> | null // list (of unique items sorted lexicographically) of msg IDs of account tangle tips, or null
|
||||||
|
dataHash: string | null // hash of the `data` object serialized
|
||||||
|
dataSize: number // byte size (unsigned integer) of the `data` object serialized
|
||||||
|
domain: string // alphanumeric string, at least 3 chars, max 100 chars
|
||||||
|
tangles: {
|
||||||
|
// for each tangle this msg belongs to, identified by the tangle's ID
|
||||||
|
[tangleID: string]: {
|
||||||
|
depth: number // maximum distance (positive integer) from this msg to the root
|
||||||
|
prev: Array<MsgID> // list (of unique items sorted lexicographically) of msg IDs of existing msgs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v: 4 // hard-coded at 4, indicates the version of the feed format
|
||||||
|
}
|
||||||
|
sigkey: Sigkey // base58 encoded string for the author's public key
|
||||||
|
sig: Signature // Signs the `metadata` object
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Depth:** we NEED this field because it is the most reliable way of calculating lipmaa distances between msgs, in the face of sliced replication. For example, given that older messages (except the certificate pool) would be deleted, the "graph depth" calculation for a msg may change over time, but we need a way of keeping this calculation stable and deterministic.
|
||||||
|
|
||||||
|
## Account tangle msgs
|
||||||
|
|
||||||
|
Msgs in an account tangle are special because they have empty `account` and `accountTips` fields.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface Msg {
|
||||||
|
data: AccountData
|
||||||
|
metadata: {
|
||||||
|
account: 'self' // MUST be the string 'self'
|
||||||
|
accountTips: null // MUST be null
|
||||||
|
dataHash: string
|
||||||
|
dataSize: number
|
||||||
|
domain: string // alphanumeric string, must start with "account__"
|
||||||
|
tangles: {
|
||||||
|
[accountTangleID: string]: {
|
||||||
|
depth: number
|
||||||
|
prev: Array<MsgID>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v: 4
|
||||||
|
}
|
||||||
|
sigkey: Sigkey
|
||||||
|
sig: Signature
|
||||||
|
}
|
||||||
|
|
||||||
|
type AccountData = AccountAdd | AccountDel
|
||||||
|
|
||||||
|
// (if key is sig) "add" means this key can validly add more keys to the account
|
||||||
|
// (if key is sig) "del" means this key can validly revoke keys from the account
|
||||||
|
// (if key is shs) "internal-encryption" means this peer can get symmetric key
|
||||||
|
// (if key is shs) "external-encryption" means this peer can get asymmetric key
|
||||||
|
type AccountPower = 'add' | 'del' | 'internal-encryption' | 'external-encryption'
|
||||||
|
|
||||||
|
type AccountAdd = {
|
||||||
|
action: 'add'
|
||||||
|
key: Key
|
||||||
|
nonce?: string // nonce required only on the account tangle's root
|
||||||
|
consent?: string // base58 encoded signature of the string `:account-add:<ID>` where `<ID>` is the account's ID, required only on non-root msgs
|
||||||
|
accountPowers?: Array<AccountPower> // list of powers granted to this key, defaults to []
|
||||||
|
}
|
||||||
|
|
||||||
|
type AccountDel = {
|
||||||
|
action: 'del'
|
||||||
|
key: Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type Key =
|
||||||
|
| {
|
||||||
|
purpose: 'shs-and-sig' // secret-handshake and digital signatures
|
||||||
|
algorithm: 'ed25519' // libsodium crypto_sign_detached
|
||||||
|
bytes: string // base58 encoded string for the public key
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
purpose: 'external-encryption' // asymmetric encryption
|
||||||
|
algorithm: 'x25519-xsalsa20-poly1305' // libsodium crypto_box_easy
|
||||||
|
bytes: string // base58 encoded string of the public key
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
purpose: 'sig' // secret-handshake and digital signatures
|
||||||
|
algorithm: 'ed25519' // libsodium crypto_sign_detached
|
||||||
|
bytes: string // base58 encoded string for the public key
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Examples of `AccountData`:
|
||||||
|
|
||||||
|
- Registering the first public key:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "add",
|
||||||
|
"key": {
|
||||||
|
"purpose": "shs-and-sig",
|
||||||
|
"algorithm": "ed25519",
|
||||||
|
"bytes": "3JrJiHEQzRFMzEqWawfBgq2DSZDyihP1NHXshqcL8pB9"
|
||||||
|
},
|
||||||
|
"nonce": "6GHR1ZFFSB3C5qAGwmSwVH8f7byNo8Cqwn5PcyG3qDvS"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Revoking a public key:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "del",
|
||||||
|
"key": {
|
||||||
|
"purpose": "shs-and-sig",
|
||||||
|
"algorithm": "ed25519",
|
||||||
|
"bytes": "3JrJiHEQzRFMzEqWawfBgq2DSZDyihP1NHXshqcL8pB9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Feed root
|
||||||
|
|
||||||
|
The root msg for a feed is special, its `metadata` is predictable and can be constructed by any peer. It is a data-less msg with the following shape:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface Msg {
|
||||||
|
data: null // MUST be null
|
||||||
|
metadata: {
|
||||||
|
dataHash: null // MUST be null
|
||||||
|
dataSize: 0 // MUST be 0
|
||||||
|
account: string // MUST be an ID
|
||||||
|
accountTips: null // MUST be null
|
||||||
|
tangles: {} // MUST be empty object
|
||||||
|
domain: string
|
||||||
|
v: 4
|
||||||
|
}
|
||||||
|
sigkey: Sigkey
|
||||||
|
sig: Signature
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Thus, given a `account` and a `domain`, any peer can construct the `metadata` part of the feed root msg, and thus can derive the "msg ID" for the root based on that `metadata`.
|
||||||
|
|
||||||
|
Given the root msg ID, any peer can thus refer to the feed tangle, because the root msg ID is the tangle ID for the feed tangle.
|
||||||
|
|
||||||
|
Note also that _any peer_ can construct the root msg and sign it! Which renders the signatures for feed roots meaningless and ignorable. Thus the name "moot".
|
||||||
|
|
||||||
|
## Prev links
|
||||||
|
|
||||||
|
A msg can refer to 0 or more prev msgs. The prev links are used to build the tangle.
|
||||||
|
|
||||||
|
The `prev` array for a tangle should list:
|
||||||
|
|
||||||
|
- All current "tips" (msgs that are not yet listed inside any `prev`) of this tangle
|
||||||
|
- All msgs that are at the previous "lipmaa" depth relative to this `depth`
|
||||||
|
|
||||||
|
## JSON serialization
|
||||||
|
|
||||||
|
Whenever we need to serialize any JSON in the context of creating a Msg V4 message, we follow the "JSON Canonicalization Scheme" (JSC) defined by [RFC 8785](https://tools.ietf.org/html/rfc8785).
|
||||||
|
|
||||||
|
A serialized msg must not be larger than 65535 UTF-8 bytes.
|
||||||
|
|
||||||
# Msg V3
|
# Msg V3
|
||||||
|
|
||||||
Background: https://github.com/ssbc/ssb2-discussion-forum/issues/24
|
Background: https://github.com/ssbc/ssb2-discussion-forum/issues/24
|
||||||
|
@ -37,7 +215,7 @@ interface Msg {
|
||||||
v: 3 // hard-coded at 3, indicates the version of the feed format
|
v: 3 // hard-coded at 3, indicates the version of the feed format
|
||||||
}
|
}
|
||||||
pubkey: Pubkey // base58 encoded string for the author's public key
|
pubkey: Pubkey // base58 encoded string for the author's public key
|
||||||
sig: Signature // Signs the `metadata` object
|
sig: Signature // base58 encoded string of the signature of the UTF8 string ":msg-v4:<METADATA>" where `<METADATA>` is the msg.metadata object serialized
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -64,7 +242,7 @@ interface Msg {
|
||||||
}
|
}
|
||||||
v: 3
|
v: 3
|
||||||
}
|
}
|
||||||
pubkey: Pubkey
|
sigkey: Pubkey
|
||||||
sig: Signature
|
sig: Signature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ test('account.add()', async (t) => {
|
||||||
{ [account]: { depth: 1, prev: [account] } },
|
{ [account]: { depth: 1, prev: [account] } },
|
||||||
'msg.metadata.tangles'
|
'msg.metadata.tangles'
|
||||||
)
|
)
|
||||||
assert.equal(msg.pubkey, keypair1.public, 'msg.pubkey OLD KEY')
|
assert.equal(msg.sigkey, keypair1.public, 'msg.sigkey OLD KEY')
|
||||||
|
|
||||||
assert.equal(peer.db.account.has({ account, keypair: keypair2 }), true)
|
assert.equal(peer.db.account.has({ account, keypair: keypair2 }), true)
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ test('account.add()', async (t) => {
|
||||||
accountTips: null,
|
accountTips: null,
|
||||||
tangles: {},
|
tangles: {},
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
v: 3,
|
v: 4,
|
||||||
},
|
},
|
||||||
'postsRoot'
|
'postsRoot'
|
||||||
)
|
)
|
||||||
|
|
|
@ -47,7 +47,7 @@ test('account.create() ', async (t) => {
|
||||||
[],
|
[],
|
||||||
'msg.metadata.tangles'
|
'msg.metadata.tangles'
|
||||||
)
|
)
|
||||||
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
|
assert.equal(msg.sigkey, keypair.public, 'msg.sigkey')
|
||||||
|
|
||||||
await p(peer.close)()
|
await p(peer.close)()
|
||||||
})
|
})
|
||||||
|
@ -76,7 +76,7 @@ test('account.create() ', async (t) => {
|
||||||
[],
|
[],
|
||||||
'msg.metadata.tangles'
|
'msg.metadata.tangles'
|
||||||
)
|
)
|
||||||
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
|
assert.equal(msg.sigkey, keypair.public, 'msg.sigkey')
|
||||||
|
|
||||||
await p(peer.close)()
|
await p(peer.close)()
|
||||||
})
|
})
|
||||||
|
@ -154,7 +154,7 @@ test('account.create() ', async (t) => {
|
||||||
[],
|
[],
|
||||||
'msg.metadata.tangles'
|
'msg.metadata.tangles'
|
||||||
)
|
)
|
||||||
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
|
assert.equal(msg.sigkey, keypair.public, 'msg.sigkey')
|
||||||
|
|
||||||
await p(peer.close)()
|
await p(peer.close)()
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,7 @@ const rimraf = require('rimraf')
|
||||||
const SecretStack = require('secret-stack')
|
const SecretStack = require('secret-stack')
|
||||||
const caps = require('ppppp-caps')
|
const caps = require('ppppp-caps')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../lib/msg-v3')
|
const MsgV4 = require('../lib/msg-v4')
|
||||||
|
|
||||||
const DIR = path.join(os.tmpdir(), 'ppppp-db-add')
|
const DIR = path.join(os.tmpdir(), 'ppppp-db-add')
|
||||||
rimraf.sync(DIR)
|
rimraf.sync(DIR)
|
||||||
|
@ -21,20 +21,20 @@ test('add()', async (t) => {
|
||||||
|
|
||||||
await peer.db.loaded()
|
await peer.db.loaded()
|
||||||
|
|
||||||
const accountMsg0 = MsgV3.createAccount(keypair, 'person', 'aliceNonce')
|
const accountMsg0 = MsgV4.createAccount(keypair, 'person', 'aliceNonce')
|
||||||
const id = MsgV3.getMsgID(accountMsg0)
|
const id = MsgV4.getMsgID(accountMsg0)
|
||||||
|
|
||||||
await p(peer.db.add)(accountMsg0, id)
|
await p(peer.db.add)(accountMsg0, id)
|
||||||
|
|
||||||
const rootMsg = MsgV3.createMoot(id, 'post', keypair)
|
const rootMsg = MsgV4.createMoot(id, 'post', keypair)
|
||||||
const rootID = MsgV3.getMsgID(rootMsg)
|
const rootID = MsgV4.getMsgID(rootMsg)
|
||||||
|
|
||||||
const recRoot = await p(peer.db.add)(rootMsg, rootID)
|
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(rootID)
|
const tangle = new MsgV4.Tangle(rootID)
|
||||||
tangle.add(recRoot.id, recRoot.msg)
|
tangle.add(recRoot.id, recRoot.msg)
|
||||||
|
|
||||||
const inputMsg = MsgV3.create({
|
const inputMsg = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
data: { text: 'This is the first post!' },
|
data: { text: 'This is the first post!' },
|
||||||
|
@ -49,7 +49,7 @@ test('add()', async (t) => {
|
||||||
assert.equal(rec.msg.data.text, 'This is the first post!')
|
assert.equal(rec.msg.data.text, 'This is the first post!')
|
||||||
|
|
||||||
const stats = await p(peer.db.log.stats)()
|
const stats = await p(peer.db.log.stats)()
|
||||||
assert.deepEqual(stats, { totalBytes: 1450, deletedBytes: 0 })
|
assert.deepEqual(stats, { totalBytes: 1662, deletedBytes: 0 })
|
||||||
|
|
||||||
await p(peer.close)(true)
|
await p(peer.close)(true)
|
||||||
})
|
})
|
||||||
|
|
|
@ -51,7 +51,7 @@ test('del()', async (t) => {
|
||||||
const stats1 = await p(peer.db.log.stats)()
|
const stats1 = await p(peer.db.log.stats)()
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
stats1,
|
stats1,
|
||||||
{ totalBytes: 3399, deletedBytes: 0 },
|
{ totalBytes: 4158, deletedBytes: 0 },
|
||||||
'stats before delete and compact'
|
'stats before delete and compact'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ test('del()', async (t) => {
|
||||||
const stats2 = await p(log.stats)()
|
const stats2 = await p(log.stats)()
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
stats2,
|
stats2,
|
||||||
{ totalBytes: 2889, deletedBytes: 0 },
|
{ totalBytes: 3495, deletedBytes: 0 },
|
||||||
'stats after delete and compact'
|
'stats after delete and compact'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ test('erase()', async (t) => {
|
||||||
'5 msgs before the erase'
|
'5 msgs before the erase'
|
||||||
)
|
)
|
||||||
|
|
||||||
const EXPECTED_TOTAL_BYTES = 3399
|
const EXPECTED_TOTAL_BYTES = 4158
|
||||||
const stats1 = await p(peer.db.log.stats)()
|
const stats1 = await p(peer.db.log.stats)()
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
stats1,
|
stats1,
|
||||||
|
|
|
@ -7,7 +7,7 @@ const rimraf = require('rimraf')
|
||||||
const SecretStack = require('secret-stack')
|
const SecretStack = require('secret-stack')
|
||||||
const caps = require('ppppp-caps')
|
const caps = require('ppppp-caps')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../lib/msg-v3')
|
const MsgV4 = require('../lib/msg-v4')
|
||||||
|
|
||||||
const DIR = path.join(os.tmpdir(), 'ppppp-db-feed-find-moot')
|
const DIR = path.join(os.tmpdir(), 'ppppp-db-feed-find-moot')
|
||||||
rimraf.sync(DIR)
|
rimraf.sync(DIR)
|
||||||
|
@ -22,8 +22,8 @@ test('feed.findMoot()', async (t) => {
|
||||||
await peer.db.loaded()
|
await peer.db.loaded()
|
||||||
|
|
||||||
const id = await p(peer.db.account.create)({ subdomain: 'person' })
|
const id = await p(peer.db.account.create)({ subdomain: 'person' })
|
||||||
const moot = MsgV3.createMoot(id, 'post', keypair)
|
const moot = MsgV4.createMoot(id, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
|
|
||||||
await p(peer.db.add)(moot, mootID)
|
await p(peer.db.add)(moot, mootID)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ const rimraf = require('rimraf')
|
||||||
const SecretStack = require('secret-stack')
|
const SecretStack = require('secret-stack')
|
||||||
const caps = require('ppppp-caps')
|
const caps = require('ppppp-caps')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../lib/msg-v3')
|
const MsgV4 = require('../lib/msg-v4')
|
||||||
|
|
||||||
const DIR = path.join(os.tmpdir(), 'ppppp-db-feed-get-id')
|
const DIR = path.join(os.tmpdir(), 'ppppp-db-feed-get-id')
|
||||||
rimraf.sync(DIR)
|
rimraf.sync(DIR)
|
||||||
|
@ -22,8 +22,8 @@ test('feed.getID()', async (t) => {
|
||||||
await peer.db.loaded()
|
await peer.db.loaded()
|
||||||
|
|
||||||
const id = await p(peer.db.account.create)({ subdomain: 'person' })
|
const id = await p(peer.db.account.create)({ subdomain: 'person' })
|
||||||
const moot = MsgV3.createMoot(id, 'post', keypair)
|
const moot = MsgV4.createMoot(id, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
peer.db.feed.getID(id, 'post'),
|
peer.db.feed.getID(id, 'post'),
|
||||||
|
|
|
@ -7,7 +7,7 @@ const rimraf = require('rimraf')
|
||||||
const SecretStack = require('secret-stack')
|
const SecretStack = require('secret-stack')
|
||||||
const caps = require('ppppp-caps')
|
const caps = require('ppppp-caps')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../lib/msg-v3')
|
const MsgV4 = require('../lib/msg-v4')
|
||||||
|
|
||||||
const DIR = path.join(os.tmpdir(), 'ppppp-db-feed-publish')
|
const DIR = path.join(os.tmpdir(), 'ppppp-db-feed-publish')
|
||||||
rimraf.sync(DIR)
|
rimraf.sync(DIR)
|
||||||
|
@ -30,8 +30,8 @@ test('feed.publish()', async (t) => {
|
||||||
await peer.db.loaded()
|
await peer.db.loaded()
|
||||||
|
|
||||||
id = await p(peer.db.account.create)({ subdomain: 'person' })
|
id = await p(peer.db.account.create)({ subdomain: 'person' })
|
||||||
moot = MsgV3.createMoot(id, 'post', keypair)
|
moot = MsgV4.createMoot(id, 'post', keypair)
|
||||||
mootID = MsgV3.getMsgID(moot)
|
mootID = MsgV4.getMsgID(moot)
|
||||||
}
|
}
|
||||||
|
|
||||||
let msgID1
|
let msgID1
|
||||||
|
@ -56,7 +56,7 @@ test('feed.publish()', async (t) => {
|
||||||
'msg1 tangle prev correct'
|
'msg1 tangle prev correct'
|
||||||
)
|
)
|
||||||
|
|
||||||
msgID1 = MsgV3.getMsgID(rec1.msg)
|
msgID1 = MsgV4.getMsgID(rec1.msg)
|
||||||
|
|
||||||
const rec2 = await p(peer.db.feed.publish)({
|
const rec2 = await p(peer.db.feed.publish)({
|
||||||
account: id,
|
account: id,
|
||||||
|
@ -74,15 +74,15 @@ test('feed.publish()', async (t) => {
|
||||||
[msgID1],
|
[msgID1],
|
||||||
'msg2 tangle prev correct'
|
'msg2 tangle prev correct'
|
||||||
)
|
)
|
||||||
msgID2 = MsgV3.getMsgID(rec2.msg)
|
msgID2 = MsgV4.getMsgID(rec2.msg)
|
||||||
})
|
})
|
||||||
|
|
||||||
await t.test('merges tangle after a forked add()', async (t) => {
|
await t.test('merges tangle after a forked add()', async (t) => {
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
tangle.add(rec1.id, rec1.msg)
|
tangle.add(rec1.id, rec1.msg)
|
||||||
|
|
||||||
const msg3 = MsgV3.create({
|
const msg3 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
account: id,
|
account: id,
|
||||||
accountTips: [id],
|
accountTips: [id],
|
||||||
|
@ -94,7 +94,7 @@ test('feed.publish()', async (t) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const rec3 = await p(peer.db.add)(msg3, mootID)
|
const rec3 = await p(peer.db.add)(msg3, mootID)
|
||||||
const msgID3 = MsgV3.getMsgID(rec3.msg)
|
const msgID3 = MsgV4.getMsgID(rec3.msg)
|
||||||
|
|
||||||
const rec4 = await p(peer.db.feed.publish)({
|
const rec4 = await p(peer.db.feed.publish)({
|
||||||
account: id,
|
account: id,
|
||||||
|
|
|
@ -7,7 +7,7 @@ const rimraf = require('rimraf')
|
||||||
const SecretStack = require('secret-stack')
|
const SecretStack = require('secret-stack')
|
||||||
const caps = require('ppppp-caps')
|
const caps = require('ppppp-caps')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../lib/msg-v3')
|
const MsgV4 = require('../lib/msg-v4')
|
||||||
|
|
||||||
const DIR = path.join(os.tmpdir(), 'ppppp-db-get')
|
const DIR = path.join(os.tmpdir(), 'ppppp-db-get')
|
||||||
rimraf.sync(DIR)
|
rimraf.sync(DIR)
|
||||||
|
@ -28,7 +28,7 @@ test('get()', async (t) => {
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
data: { text: 'I am 1st post' },
|
data: { text: 'I am 1st post' },
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(rec1.msg)
|
const msgID1 = MsgV4.getMsgID(rec1.msg)
|
||||||
|
|
||||||
const msg = peer.db.get(msgID1)
|
const msg = peer.db.get(msgID1)
|
||||||
assert.ok(msg, 'msg exists')
|
assert.ok(msg, 'msg exists')
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
const test = require('node:test')
|
const test = require('node:test')
|
||||||
const assert = require('node:assert')
|
const assert = require('node:assert')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../../lib/msg-v3')
|
const MsgV4 = require('../../lib/msg-v4')
|
||||||
|
|
||||||
let account
|
let account
|
||||||
test('MsgV3.createAccount()', (t) => {
|
test('MsgV4.createAccount()', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
const accountMsg0 = MsgV3.createAccount(keypair, 'person', 'MYNONCE')
|
const accountMsg0 = MsgV4.createAccount(keypair, 'person', 'MYNONCE')
|
||||||
if (process.env.VERBOSE) console.log(JSON.stringify(accountMsg0, null, 2))
|
if (process.env.VERBOSE) console.log(JSON.stringify(accountMsg0, null, 2))
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
|
@ -24,26 +24,34 @@ test('MsgV3.createAccount()', (t) => {
|
||||||
},
|
},
|
||||||
'data'
|
'data'
|
||||||
)
|
)
|
||||||
assert.equal(accountMsg0.metadata.dataHash, 'NxJZecVcVUWmUkk6cAn9JV', 'hash')
|
assert.equal(
|
||||||
|
accountMsg0.metadata.dataHash,
|
||||||
|
'4dDbfLtNMjzMgvvCA71tp6CiLjAa5bzzeHsbYuC4dpMT',
|
||||||
|
'hash'
|
||||||
|
)
|
||||||
assert.equal(accountMsg0.metadata.dataSize, 210, 'size')
|
assert.equal(accountMsg0.metadata.dataSize, 210, 'size')
|
||||||
assert.equal(accountMsg0.metadata.account, 'self', 'account')
|
assert.equal(accountMsg0.metadata.account, 'self', 'account')
|
||||||
assert.equal(accountMsg0.metadata.accountTips, null, 'accountTips')
|
assert.equal(accountMsg0.metadata.accountTips, null, 'accountTips')
|
||||||
assert.deepEqual(accountMsg0.metadata.tangles, {}, 'tangles')
|
assert.deepEqual(accountMsg0.metadata.tangles, {}, 'tangles')
|
||||||
assert.equal(accountMsg0.metadata.domain, 'person', 'domain')
|
assert.equal(accountMsg0.metadata.domain, 'person', 'domain')
|
||||||
assert.equal(accountMsg0.metadata.v, 3, 'v')
|
assert.equal(accountMsg0.metadata.v, 4, 'v')
|
||||||
assert.equal(accountMsg0.pubkey, keypair.public, 'pubkey')
|
assert.equal(accountMsg0.sigkey, keypair.public, 'sigkey')
|
||||||
assert.equal(MsgV3.isFeedMsg(accountMsg0), false, 'not a feed msg')
|
assert.equal(MsgV4.isFeedMsg(accountMsg0), false, 'not a feed msg')
|
||||||
|
|
||||||
account = MsgV3.getMsgID(accountMsg0)
|
account = MsgV4.getMsgID(accountMsg0)
|
||||||
assert.equal(account, 'UQN1Qmxr4rr9nCMQKs9u8P', 'account ID')
|
assert.equal(
|
||||||
|
account,
|
||||||
|
'Lq6xwbdvGVmSsY3oYRugpZ3DY8chX9SLhRhjJKyZHQn',
|
||||||
|
'account ID'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
let moot = null
|
let moot = null
|
||||||
let mootID = null
|
let mootID = null
|
||||||
test('MsgV3.createMoot()', (t) => {
|
test('MsgV4.createMoot()', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
moot = MsgV3.createMoot(account, 'post', keypair)
|
moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
if (process.env.VERBOSE) console.log(JSON.stringify(moot, null, 2))
|
if (process.env.VERBOSE) console.log(JSON.stringify(moot, null, 2))
|
||||||
|
|
||||||
assert.equal(moot.data, null, 'data')
|
assert.equal(moot.data, null, 'data')
|
||||||
|
@ -53,22 +61,26 @@ test('MsgV3.createMoot()', (t) => {
|
||||||
assert.equal(moot.metadata.accountTips, null, 'accountTips')
|
assert.equal(moot.metadata.accountTips, null, 'accountTips')
|
||||||
assert.deepEqual(moot.metadata.tangles, {}, 'tangles')
|
assert.deepEqual(moot.metadata.tangles, {}, 'tangles')
|
||||||
assert.equal(moot.metadata.domain, 'post', 'domain')
|
assert.equal(moot.metadata.domain, 'post', 'domain')
|
||||||
assert.equal(moot.metadata.v, 3, 'v')
|
assert.equal(moot.metadata.v, 4, 'v')
|
||||||
assert.equal(moot.pubkey, keypair.public, 'pubkey')
|
assert.equal(moot.sigkey, keypair.public, 'sigkey')
|
||||||
assert.equal(MsgV3.isFeedMsg(moot), false, 'not a feed msg')
|
assert.equal(MsgV4.isFeedMsg(moot), false, 'not a feed msg')
|
||||||
|
|
||||||
mootID = MsgV3.getMsgID(moot)
|
mootID = MsgV4.getMsgID(moot)
|
||||||
assert.equal(mootID, 'AP2rJSfm9TwpNcMmbUsnRa', 'moot ID')
|
assert.equal(
|
||||||
|
mootID,
|
||||||
|
'HH3P5muTjZkQC7uRKpzczGWbPNZBtk4BR4msyCNjwxpU',
|
||||||
|
'moot ID'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('MsgV3.create()', (t) => {
|
test('MsgV4.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(mootID)
|
const tangle1 = new MsgV4.Tangle(mootID)
|
||||||
tangle1.add(mootID, moot)
|
tangle1.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data,
|
data,
|
||||||
account,
|
account,
|
||||||
|
@ -96,7 +108,7 @@ test('MsgV3.create()', (t) => {
|
||||||
)
|
)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
msg1.metadata.dataHash,
|
msg1.metadata.dataHash,
|
||||||
'9R7XmBhHF5ooPg34j9TQcz',
|
'APwSxrZUBx5wTHcT42fJTyddEjqkEAPXVMwaczTSuHTJ',
|
||||||
'metadata.dataHash'
|
'metadata.dataHash'
|
||||||
)
|
)
|
||||||
assert.deepEqual(msg1.metadata.dataSize, 23, 'metadata.dataSize')
|
assert.deepEqual(msg1.metadata.dataSize, 23, 'metadata.dataSize')
|
||||||
|
@ -110,30 +122,30 @@ test('MsgV3.create()', (t) => {
|
||||||
assert.equal(msg1.metadata.tangles[mootID].depth, 1, 'tangle depth')
|
assert.equal(msg1.metadata.tangles[mootID].depth, 1, 'tangle depth')
|
||||||
assert.deepEqual(msg1.metadata.tangles[mootID].prev, [mootID], 'tangle prev')
|
assert.deepEqual(msg1.metadata.tangles[mootID].prev, [mootID], '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, 4, 'metadata.v')
|
||||||
assert.equal(
|
assert.equal(
|
||||||
msg1.pubkey,
|
msg1.sigkey,
|
||||||
'4mjQ5aJu378cEu6TksRG3uXAiKFiwGjYQtWAjfVjDAJW',
|
'4mjQ5aJu378cEu6TksRG3uXAiKFiwGjYQtWAjfVjDAJW',
|
||||||
'pubkey'
|
'sigkey'
|
||||||
)
|
)
|
||||||
assert.equal(
|
assert.equal(
|
||||||
msg1.sig,
|
msg1.sig,
|
||||||
'rh8bc8QY7ju7yi4rt6y9njCyS3TVV1SBjn5dWGpKKRrC3XDMBc9KeNJgVCJLK8b8uiU5F49avAWt35P9kNaWZYH',
|
'58LBLLJtqqRUteQRS5djhK2xxTG4VKjwibjKirqXU4LQKijD59NnrnHag5JsL54srJdhseSYaDhQoaWacbMd82v3',
|
||||||
'sig'
|
'sig'
|
||||||
)
|
)
|
||||||
assert.equal(MsgV3.isFeedMsg(msg1), true, 'is a feed msg')
|
assert.equal(MsgV4.isFeedMsg(msg1), true, 'is a feed msg')
|
||||||
|
|
||||||
const msgID1 = 'MUvfNDk3gMPRy9CpTDEuvW'
|
const msgID1 = '4hFeNiBSrRaxW1PKxJd6QDju4B1kZGT8g2LBHwGSpz6M'
|
||||||
|
|
||||||
assert.equal(MsgV3.getMsgID(msg1), msgID1, 'getMsgID')
|
assert.equal(MsgV4.getMsgID(msg1), msgID1, 'getMsgID')
|
||||||
|
|
||||||
const tangle2 = new MsgV3.Tangle(mootID)
|
const tangle2 = new MsgV4.Tangle(mootID)
|
||||||
tangle2.add(mootID, moot)
|
tangle2.add(mootID, moot)
|
||||||
tangle2.add(msgID1, msg1)
|
tangle2.add(msgID1, msg1)
|
||||||
|
|
||||||
const data2 = { text: 'Ola mundo!' }
|
const data2 = { text: 'Ola mundo!' }
|
||||||
|
|
||||||
const msg2 = MsgV3.create({
|
const msg2 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: data2,
|
data: data2,
|
||||||
account,
|
account,
|
||||||
|
@ -161,7 +173,7 @@ test('MsgV3.create()', (t) => {
|
||||||
)
|
)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
msg2.metadata.dataHash,
|
msg2.metadata.dataHash,
|
||||||
'XuZEzH1Dhy1yuRMcviBBcN',
|
'D8AD5odaS2YizdvmqZacQ1XVNmRxgw9hXoEvSuPYpa8G',
|
||||||
'metadata.dataHash'
|
'metadata.dataHash'
|
||||||
)
|
)
|
||||||
assert.deepEqual(msg2.metadata.dataSize, 21, 'metadata.dataSize')
|
assert.deepEqual(msg2.metadata.dataSize, 21, 'metadata.dataSize')
|
||||||
|
@ -175,27 +187,31 @@ test('MsgV3.create()', (t) => {
|
||||||
assert.equal(msg2.metadata.tangles[mootID].depth, 2, 'tangle depth')
|
assert.equal(msg2.metadata.tangles[mootID].depth, 2, 'tangle depth')
|
||||||
assert.deepEqual(msg2.metadata.tangles[mootID].prev, [msgID1], 'tangle prev')
|
assert.deepEqual(msg2.metadata.tangles[mootID].prev, [msgID1], '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, 4, 'metadata.v')
|
||||||
assert.equal(
|
assert.equal(
|
||||||
msg2.pubkey,
|
msg2.sigkey,
|
||||||
'4mjQ5aJu378cEu6TksRG3uXAiKFiwGjYQtWAjfVjDAJW',
|
'4mjQ5aJu378cEu6TksRG3uXAiKFiwGjYQtWAjfVjDAJW',
|
||||||
'pubkey'
|
'sigkey'
|
||||||
)
|
)
|
||||||
assert.equal(
|
assert.equal(
|
||||||
msg2.sig,
|
msg2.sig,
|
||||||
'3NscyRLJZP8mtq4DhhNPfwtw8yzoWsFytxGxD2QAqjW64RMeRLP5czN5mMYm4nCqRtXvzRgRhqgN1qtz9hWW14S4',
|
'5KEQBLYg5iYhd3R8rSTtH4uPwVAQvwuXhNE9wmNEFiJtNCkHkNdrZ8X85bRsdekqgewvmPtue27QcqgcT2m4gjmS',
|
||||||
'sig'
|
'sig'
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.deepEqual(MsgV3.getMsgID(msg2), 'XMeQ6sbW3mjLYRLR4dAmKD', 'getMsgID')
|
assert.deepEqual(
|
||||||
|
MsgV4.getMsgID(msg2),
|
||||||
|
'CrMez268VffqRiHvSZe6DtGVSfBhXWqfEh7D2ftPEbQ3',
|
||||||
|
'getMsgID'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('MsgV3.create() handles DAG tips correctly', (t) => {
|
test('MsgV4.create() handles DAG tips correctly', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: '1' },
|
data: { text: '1' },
|
||||||
account,
|
account,
|
||||||
|
@ -205,16 +221,16 @@ test('MsgV3.create() handles DAG tips correctly', (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
msg1.metadata.tangles[mootID].prev,
|
msg1.metadata.tangles[mootID].prev,
|
||||||
[MsgV3.getMootID(account, 'post')],
|
[MsgV4.getMootID(account, 'post')],
|
||||||
'msg1.prev is root'
|
'msg1.prev is root'
|
||||||
)
|
)
|
||||||
|
|
||||||
tangle.add(msgID1, msg1)
|
tangle.add(msgID1, msg1)
|
||||||
|
|
||||||
const msg2A = MsgV3.create({
|
const msg2A = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: '2A' },
|
data: { text: '2A' },
|
||||||
account,
|
account,
|
||||||
|
@ -230,7 +246,7 @@ test('MsgV3.create() handles DAG tips correctly', (t) => {
|
||||||
'msg2A.prev is msg1'
|
'msg2A.prev is msg1'
|
||||||
)
|
)
|
||||||
|
|
||||||
const msg2B = MsgV3.create({
|
const msg2B = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: '2B' },
|
data: { text: '2B' },
|
||||||
account,
|
account,
|
||||||
|
@ -240,7 +256,7 @@ test('MsgV3.create() handles DAG tips correctly', (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID2B = MsgV3.getMsgID(msg2B)
|
const msgID2B = MsgV4.getMsgID(msg2B)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
msg2B.metadata.tangles[mootID].prev,
|
msg2B.metadata.tangles[mootID].prev,
|
||||||
[msgID1],
|
[msgID1],
|
||||||
|
@ -249,7 +265,7 @@ test('MsgV3.create() handles DAG tips correctly', (t) => {
|
||||||
|
|
||||||
tangle.add(msgID2B, msg2B)
|
tangle.add(msgID2B, msg2B)
|
||||||
|
|
||||||
const msg3 = MsgV3.create({
|
const msg3 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: '3' },
|
data: { text: '3' },
|
||||||
account,
|
account,
|
||||||
|
@ -259,7 +275,7 @@ test('MsgV3.create() handles DAG tips correctly', (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID3 = MsgV3.getMsgID(msg3)
|
const msgID3 = MsgV4.getMsgID(msg3)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
msg3.metadata.tangles[mootID].prev,
|
msg3.metadata.tangles[mootID].prev,
|
||||||
[mootID, msgID2B].sort(),
|
[mootID, msgID2B].sort(),
|
||||||
|
@ -267,11 +283,11 @@ test('MsgV3.create() handles DAG tips correctly', (t) => {
|
||||||
)
|
)
|
||||||
tangle.add(msgID3, msg3)
|
tangle.add(msgID3, msg3)
|
||||||
|
|
||||||
const msgID2A = MsgV3.getMsgID(msg2A)
|
const msgID2A = MsgV4.getMsgID(msg2A)
|
||||||
tangle.add(msgID2A, msg2A)
|
tangle.add(msgID2A, msg2A)
|
||||||
// t.pass('msg2A comes into awareness')
|
// t.pass('msg2A comes into awareness')
|
||||||
|
|
||||||
const msg4 = MsgV3.create({
|
const msg4 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: '4' },
|
data: { text: '4' },
|
||||||
account,
|
account,
|
|
@ -1,15 +1,15 @@
|
||||||
const test = require('node:test')
|
const test = require('node:test')
|
||||||
const assert = require('node:assert')
|
const assert = require('node:assert')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../../lib/msg-v3')
|
const MsgV4 = require('../../lib/msg-v4')
|
||||||
|
|
||||||
test('MsgV3 domain validation', async (t) => {
|
test('MsgV4 domain validation', async (t) => {
|
||||||
await t.test('Not a string', (t) => {
|
await t.test('Not a string', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => {
|
() => {
|
||||||
MsgV3.create({
|
MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
domain: 123,
|
domain: 123,
|
||||||
|
@ -25,7 +25,7 @@ test('MsgV3 domain validation', async (t) => {
|
||||||
|
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => {
|
() => {
|
||||||
MsgV3.create({
|
MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
domain: 'group/init',
|
domain: 'group/init',
|
||||||
|
@ -41,7 +41,7 @@ test('MsgV3 domain validation', async (t) => {
|
||||||
|
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => {
|
() => {
|
||||||
MsgV3.create({
|
MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
domain: 'star*',
|
domain: 'star*',
|
||||||
|
@ -57,7 +57,7 @@ test('MsgV3 domain validation', async (t) => {
|
||||||
|
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => {
|
() => {
|
||||||
MsgV3.create({
|
MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
domain: 'xy',
|
domain: 'xy',
|
||||||
|
@ -73,7 +73,7 @@ test('MsgV3 domain validation', async (t) => {
|
||||||
|
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => {
|
() => {
|
||||||
MsgV3.create({
|
MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
domain: 'a'.repeat(120),
|
domain: 'a'.repeat(120),
|
|
@ -2,25 +2,25 @@ const test = require('node:test')
|
||||||
const assert = require('node:assert')
|
const assert = require('node:assert')
|
||||||
const base58 = require('bs58')
|
const base58 = require('bs58')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../../lib/msg-v3')
|
const MsgV4 = require('../../lib/msg-v4')
|
||||||
|
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
const account = MsgV3.getMsgID(
|
const account = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypair, 'person', 'MYNONCE')
|
MsgV4.createAccount(keypair, 'person', 'MYNONCE')
|
||||||
)
|
)
|
||||||
const pubkeys = new Set([keypair.public])
|
const sigkeys = new Set([keypair.public])
|
||||||
|
|
||||||
test('MsgV3 tangles prev validation', async (t) => {
|
test('MsgV4 tangles prev validation', async (t) => {
|
||||||
await t.test('Non-array is a bad prev', (t) => {
|
await t.test('Non-array is a bad prev', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
|
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg = MsgV3.create({
|
const msg = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
account,
|
account,
|
||||||
|
@ -31,9 +31,9 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
msg.metadata.tangles[mootID].prev = null
|
msg.metadata.tangles[mootID].prev = null
|
||||||
const msgID = MsgV3.getMsgID(msg)
|
const msgID = MsgV4.getMsgID(msg)
|
||||||
|
|
||||||
const err = MsgV3.validate(msg, tangle, pubkeys, msgID, mootID)
|
const err = MsgV4.validate(msg, tangle, sigkeys, msgID, mootID)
|
||||||
assert.ok(err, 'invalid 2nd msg throws')
|
assert.ok(err, 'invalid 2nd msg throws')
|
||||||
assert.match(
|
assert.match(
|
||||||
err,
|
err,
|
||||||
|
@ -45,13 +45,13 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
await t.test('Number not allowed in prev', (t) => {
|
await t.test('Number not allowed in prev', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
|
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
account,
|
account,
|
||||||
|
@ -61,10 +61,10 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
tangle.add(msgID1, msg1)
|
tangle.add(msgID1, msg1)
|
||||||
|
|
||||||
const msg2 = MsgV3.create({
|
const msg2 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
account,
|
account,
|
||||||
|
@ -76,9 +76,9 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
})
|
})
|
||||||
msg2.metadata.tangles[mootID].depth = 1
|
msg2.metadata.tangles[mootID].depth = 1
|
||||||
msg2.metadata.tangles[mootID].prev = [1234]
|
msg2.metadata.tangles[mootID].prev = [1234]
|
||||||
const msgID2 = MsgV3.getMsgID(msg2)
|
const msgID2 = MsgV4.getMsgID(msg2)
|
||||||
|
|
||||||
const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
|
const err = MsgV4.validate(msg2, tangle, sigkeys, msgID2, mootID)
|
||||||
assert.ok(err, 'invalid 2nd msg throws')
|
assert.ok(err, 'invalid 2nd msg throws')
|
||||||
assert.match(
|
assert.match(
|
||||||
err,
|
err,
|
||||||
|
@ -90,13 +90,13 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
await t.test('URI not allowed in prev', (t) => {
|
await t.test('URI not allowed in prev', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
|
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
account,
|
account,
|
||||||
|
@ -106,10 +106,10 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
tangle.add(msgID1, msg1)
|
tangle.add(msgID1, msg1)
|
||||||
|
|
||||||
const msg2 = MsgV3.create({
|
const msg2 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
account,
|
account,
|
||||||
|
@ -119,13 +119,13 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID2 = MsgV3.getMsgID(msg2)
|
const msgID2 = MsgV4.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/v4/${base58.encode(randBuf)}`
|
||||||
msg2.metadata.tangles[mootID].depth = 1
|
msg2.metadata.tangles[mootID].depth = 1
|
||||||
msg2.metadata.tangles[mootID].prev = [fakeMsgKey1]
|
msg2.metadata.tangles[mootID].prev = [fakeMsgKey1]
|
||||||
|
|
||||||
const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
|
const err = MsgV4.validate(msg2, tangle, sigkeys, 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')
|
||||||
})
|
})
|
||||||
|
@ -133,13 +133,13 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
await t.test('Locally unknown prev msgID', (t) => {
|
await t.test('Locally unknown prev msgID', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
|
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
account,
|
account,
|
||||||
|
@ -149,10 +149,10 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
tangle.add(msgID1, msg1)
|
tangle.add(msgID1, msg1)
|
||||||
|
|
||||||
const unknownMsg = MsgV3.create({
|
const unknownMsg = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Alien' },
|
data: { text: 'Alien' },
|
||||||
account,
|
account,
|
||||||
|
@ -162,14 +162,14 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const unknownMsgID = MsgV3.getMsgID(unknownMsg)
|
const unknownMsgID = MsgV4.getMsgID(unknownMsg)
|
||||||
|
|
||||||
const fakeMootID = 'ABCDEabcde' + mootID.substring(10)
|
const fakeMootID = 'ABCDEabcde' + mootID.substring(10)
|
||||||
const tangle2 = new MsgV3.Tangle(fakeMootID)
|
const tangle2 = new MsgV4.Tangle(fakeMootID)
|
||||||
tangle2.add(fakeMootID, moot)
|
tangle2.add(fakeMootID, moot)
|
||||||
tangle2.add(unknownMsgID, unknownMsg)
|
tangle2.add(unknownMsgID, unknownMsg)
|
||||||
|
|
||||||
const msg2 = MsgV3.create({
|
const msg2 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
account,
|
account,
|
||||||
|
@ -179,9 +179,9 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle2,
|
[mootID]: tangle2,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID2 = MsgV3.getMsgID(msg2)
|
const msgID2 = MsgV4.getMsgID(msg2)
|
||||||
|
|
||||||
const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
|
const err = MsgV4.validate(msg2, tangle, sigkeys, msgID2, mootID)
|
||||||
assert.ok(err, 'invalid 2nd msg throws')
|
assert.ok(err, 'invalid 2nd msg throws')
|
||||||
assert.match(
|
assert.match(
|
||||||
err,
|
err,
|
||||||
|
@ -190,20 +190,20 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
await t.test('Feed msg with the wrong pubkey', (t) => {
|
await t.test('Feed msg with the wrong sigkey', (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.getMsgID(
|
const accountB = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypairB, 'person', 'MYNONCE')
|
MsgV4.createAccount(keypairB, 'person', 'MYNONCE')
|
||||||
)
|
)
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
const feedTangle = new MsgV3.Tangle(mootID)
|
const feedTangle = new MsgV4.Tangle(mootID)
|
||||||
feedTangle.add(mootID, moot)
|
feedTangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg = MsgV3.create({
|
const msg = MsgV4.create({
|
||||||
keypair: keypairB,
|
keypair: keypairB,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
account: accountB,
|
account: accountB,
|
||||||
|
@ -213,13 +213,13 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: feedTangle,
|
[mootID]: feedTangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID = MsgV3.getMsgID(msg)
|
const msgID = MsgV4.getMsgID(msg)
|
||||||
|
|
||||||
const err = MsgV3.validate(msg, feedTangle, pubkeys, msgID, mootID)
|
const err = MsgV4.validate(msg, feedTangle, sigkeys, msgID, mootID)
|
||||||
assert.ok(err, 'invalid msg throws')
|
assert.ok(err, 'invalid msg throws')
|
||||||
assert.match(
|
assert.match(
|
||||||
err,
|
err,
|
||||||
/pubkey ".*" should have been one of ".*" from the account ".*"/,
|
/sigkey ".*" should have been one of ".*" from the account ".*"/,
|
||||||
'invalid msg'
|
'invalid msg'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -227,12 +227,12 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
await t.test('Feed msg with the wrong domain', (t) => {
|
await t.test('Feed msg with the wrong domain', (t) => {
|
||||||
const keypairA = Keypair.generate('ed25519', 'alice')
|
const keypairA = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
const feedTangle = new MsgV3.Tangle(mootID)
|
const feedTangle = new MsgV4.Tangle(mootID)
|
||||||
feedTangle.add(mootID, moot)
|
feedTangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg = MsgV3.create({
|
const msg = MsgV4.create({
|
||||||
keypair: keypairA,
|
keypair: keypairA,
|
||||||
data: { text: 'Hello world!' },
|
data: { text: 'Hello world!' },
|
||||||
account,
|
account,
|
||||||
|
@ -242,9 +242,9 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: feedTangle,
|
[mootID]: feedTangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID = MsgV3.getMsgID(msg)
|
const msgID = MsgV4.getMsgID(msg)
|
||||||
|
|
||||||
const err = MsgV3.validate(msg, feedTangle, pubkeys, msgID, mootID)
|
const err = MsgV4.validate(msg, feedTangle, sigkeys, msgID, mootID)
|
||||||
assert.ok(err, 'invalid msg throws')
|
assert.ok(err, 'invalid msg throws')
|
||||||
assert.match(
|
assert.match(
|
||||||
err,
|
err,
|
||||||
|
@ -256,13 +256,13 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
await t.test('Feed msg with non-alphabetically sorted prev', (t) => {
|
await t.test('Feed msg with non-alphabetically sorted prev', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
|
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: '1' },
|
data: { text: '1' },
|
||||||
account,
|
account,
|
||||||
|
@ -272,9 +272,9 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
|
|
||||||
const msg2 = MsgV3.create({
|
const msg2 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: '2' },
|
data: { text: '2' },
|
||||||
account,
|
account,
|
||||||
|
@ -284,12 +284,12 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID2 = MsgV3.getMsgID(msg2)
|
const msgID2 = MsgV4.getMsgID(msg2)
|
||||||
|
|
||||||
tangle.add(msgID1, msg1)
|
tangle.add(msgID1, msg1)
|
||||||
tangle.add(msgID2, msg2)
|
tangle.add(msgID2, msg2)
|
||||||
|
|
||||||
const msg3 = MsgV3.create({
|
const msg3 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: '3' },
|
data: { text: '3' },
|
||||||
account,
|
account,
|
||||||
|
@ -299,7 +299,7 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID3 = MsgV3.getMsgID(msg3)
|
const msgID3 = MsgV4.getMsgID(msg3)
|
||||||
|
|
||||||
let prevMsgIDs = msg3.metadata.tangles[mootID].prev
|
let prevMsgIDs = msg3.metadata.tangles[mootID].prev
|
||||||
if (prevMsgIDs[0] < prevMsgIDs[1]) {
|
if (prevMsgIDs[0] < prevMsgIDs[1]) {
|
||||||
|
@ -309,7 +309,7 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
}
|
}
|
||||||
msg3.metadata.tangles[mootID].prev = prevMsgIDs
|
msg3.metadata.tangles[mootID].prev = prevMsgIDs
|
||||||
|
|
||||||
const err = MsgV3.validate(msg3, tangle, pubkeys, msgID3, mootID)
|
const err = MsgV4.validate(msg3, tangle, sigkeys, msgID3, mootID)
|
||||||
assert.ok(err, 'invalid 3rd msg throws')
|
assert.ok(err, 'invalid 3rd msg throws')
|
||||||
assert.match(
|
assert.match(
|
||||||
err,
|
err,
|
||||||
|
@ -321,13 +321,13 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
await t.test('Feed msg with duplicate prev', (t) => {
|
await t.test('Feed msg with duplicate prev', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
|
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
keypair,
|
keypair,
|
||||||
data: { text: '1' },
|
data: { text: '1' },
|
||||||
account,
|
account,
|
||||||
|
@ -337,12 +337,12 @@ test('MsgV3 tangles prev validation', async (t) => {
|
||||||
[mootID]: tangle,
|
[mootID]: tangle,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
|
|
||||||
const [prevID] = msg1.metadata.tangles[mootID].prev
|
const [prevID] = msg1.metadata.tangles[mootID].prev
|
||||||
msg1.metadata.tangles[mootID].prev = [prevID, prevID]
|
msg1.metadata.tangles[mootID].prev = [prevID, prevID]
|
||||||
|
|
||||||
const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
|
const err = MsgV4.validate(msg1, tangle, sigkeys, 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')
|
||||||
})
|
})
|
|
@ -1,21 +1,21 @@
|
||||||
const test = require('node:test')
|
const test = require('node:test')
|
||||||
const assert = require('node:assert')
|
const assert = require('node:assert')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../../lib/msg-v3')
|
const MsgV4 = require('../../lib/msg-v4')
|
||||||
|
|
||||||
test('MsgV3 lipmaa prevs', (t) => {
|
test('MsgV4 lipmaa prevs', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
const account = MsgV3.getMsgID(
|
const account = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypair, 'person', 'MYNONCE')
|
MsgV4.createAccount(keypair, 'person', 'MYNONCE')
|
||||||
)
|
)
|
||||||
const data = { text: 'Hello world!' }
|
const data = { text: 'Hello world!' }
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -25,12 +25,12 @@ test('MsgV3 lipmaa prevs', (t) => {
|
||||||
},
|
},
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
tangle.add(msgID1, msg1)
|
tangle.add(msgID1, msg1)
|
||||||
assert.equal(msg1.metadata.tangles[mootID].depth, 1, 'msg1 depth')
|
assert.equal(msg1.metadata.tangles[mootID].depth, 1, 'msg1 depth')
|
||||||
assert.deepEqual(msg1.metadata.tangles[mootID].prev, [mootID], 'msg1 prev')
|
assert.deepEqual(msg1.metadata.tangles[mootID].prev, [mootID], 'msg1 prev')
|
||||||
|
|
||||||
const msg2 = MsgV3.create({
|
const msg2 = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -40,12 +40,12 @@ test('MsgV3 lipmaa prevs', (t) => {
|
||||||
},
|
},
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
const msgID2 = MsgV3.getMsgID(msg2)
|
const msgID2 = MsgV4.getMsgID(msg2)
|
||||||
tangle.add(msgID2, msg2)
|
tangle.add(msgID2, msg2)
|
||||||
assert.equal(msg2.metadata.tangles[mootID].depth, 2, 'msg2 depth')
|
assert.equal(msg2.metadata.tangles[mootID].depth, 2, 'msg2 depth')
|
||||||
assert.deepEqual(msg2.metadata.tangles[mootID].prev, [msgID1], 'msg2 prev')
|
assert.deepEqual(msg2.metadata.tangles[mootID].prev, [msgID1], 'msg2 prev')
|
||||||
|
|
||||||
const msg3 = MsgV3.create({
|
const msg3 = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -55,7 +55,7 @@ test('MsgV3 lipmaa prevs', (t) => {
|
||||||
},
|
},
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
const msgID3 = MsgV3.getMsgID(msg3)
|
const msgID3 = MsgV4.getMsgID(msg3)
|
||||||
tangle.add(msgID3, msg3)
|
tangle.add(msgID3, msg3)
|
||||||
assert.equal(msg3.metadata.tangles[mootID].depth, 3, 'msg3 depth')
|
assert.equal(msg3.metadata.tangles[mootID].depth, 3, 'msg3 depth')
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
|
@ -64,7 +64,7 @@ test('MsgV3 lipmaa prevs', (t) => {
|
||||||
'msg3 prev (has lipmaa!)'
|
'msg3 prev (has lipmaa!)'
|
||||||
)
|
)
|
||||||
|
|
||||||
const msg4 = MsgV3.create({
|
const msg4 = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -74,12 +74,12 @@ test('MsgV3 lipmaa prevs', (t) => {
|
||||||
},
|
},
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
const msgID4 = MsgV3.getMsgID(msg4)
|
const msgID4 = MsgV4.getMsgID(msg4)
|
||||||
tangle.add(msgID4, msg4)
|
tangle.add(msgID4, msg4)
|
||||||
assert.equal(msg4.metadata.tangles[mootID].depth, 4, 'msg4 depth')
|
assert.equal(msg4.metadata.tangles[mootID].depth, 4, 'msg4 depth')
|
||||||
assert.deepEqual(msg4.metadata.tangles[mootID].prev, [msgID3], 'msg4 prev')
|
assert.deepEqual(msg4.metadata.tangles[mootID].prev, [msgID3], 'msg4 prev')
|
||||||
|
|
||||||
const msg5 = MsgV3.create({
|
const msg5 = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -89,12 +89,12 @@ test('MsgV3 lipmaa prevs', (t) => {
|
||||||
},
|
},
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
const msgID5 = MsgV3.getMsgID(msg5)
|
const msgID5 = MsgV4.getMsgID(msg5)
|
||||||
tangle.add(msgID5, msg5)
|
tangle.add(msgID5, msg5)
|
||||||
assert.equal(msg5.metadata.tangles[mootID].depth, 5, 'msg5 depth')
|
assert.equal(msg5.metadata.tangles[mootID].depth, 5, 'msg5 depth')
|
||||||
assert.deepEqual(msg5.metadata.tangles[mootID].prev, [msgID4], 'msg5 prev')
|
assert.deepEqual(msg5.metadata.tangles[mootID].prev, [msgID4], 'msg5 prev')
|
||||||
|
|
||||||
const msg6 = MsgV3.create({
|
const msg6 = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -104,12 +104,12 @@ test('MsgV3 lipmaa prevs', (t) => {
|
||||||
},
|
},
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
const msgID6 = MsgV3.getMsgID(msg6)
|
const msgID6 = MsgV4.getMsgID(msg6)
|
||||||
tangle.add(msgID6, msg6)
|
tangle.add(msgID6, msg6)
|
||||||
assert.equal(msg6.metadata.tangles[mootID].depth, 6, 'msg6 depth')
|
assert.equal(msg6.metadata.tangles[mootID].depth, 6, 'msg6 depth')
|
||||||
assert.deepEqual(msg6.metadata.tangles[mootID].prev, [msgID5], 'msg6 prev')
|
assert.deepEqual(msg6.metadata.tangles[mootID].prev, [msgID5], 'msg6 prev')
|
||||||
|
|
||||||
const msg7 = MsgV3.create({
|
const msg7 = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -119,7 +119,7 @@ test('MsgV3 lipmaa prevs', (t) => {
|
||||||
},
|
},
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
const msgID7 = MsgV3.getMsgID(msg7)
|
const msgID7 = MsgV4.getMsgID(msg7)
|
||||||
tangle.add(msgID7, msg7)
|
tangle.add(msgID7, msg7)
|
||||||
assert.equal(msg7.metadata.tangles[mootID].depth, 7, 'msg7 depth')
|
assert.equal(msg7.metadata.tangles[mootID].depth, 7, 'msg7 depth')
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
|
@ -1,32 +1,32 @@
|
||||||
const test = require('node:test')
|
const test = require('node:test')
|
||||||
const assert = require('node:assert')
|
const assert = require('node:assert')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../../lib/msg-v3')
|
const MsgV4 = require('../../lib/msg-v4')
|
||||||
|
|
||||||
test('MsgV3.Tangle simple multi-author tangle', (t) => {
|
test('MsgV4.Tangle 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.getMsgID(
|
const accountA = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypairA, 'person', 'alice')
|
MsgV4.createAccount(keypairA, 'person', 'alice')
|
||||||
)
|
)
|
||||||
const accountB = MsgV3.getMsgID(
|
const accountB = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypairB, 'person', 'bob')
|
MsgV4.createAccount(keypairB, 'person', 'bob')
|
||||||
)
|
)
|
||||||
|
|
||||||
const mootA = MsgV3.createMoot(accountA, 'post', keypairA)
|
const mootA = MsgV4.createMoot(accountA, 'post', keypairA)
|
||||||
const mootAID = MsgV3.getMsgID(mootA)
|
const mootAID = MsgV4.getMsgID(mootA)
|
||||||
const tangleA = new MsgV3.Tangle(mootAID)
|
const tangleA = new MsgV4.Tangle(mootAID)
|
||||||
tangleA.add(mootAID, mootA)
|
tangleA.add(mootAID, mootA)
|
||||||
|
|
||||||
assert.equal(tangleA.id, mootAID, 'tangle.id')
|
assert.equal(tangleA.id, mootAID, 'tangle.id')
|
||||||
assert.equal(tangleA.root, mootA, 'tangle.root')
|
assert.equal(tangleA.root, mootA, 'tangle.root')
|
||||||
|
|
||||||
const mootB = MsgV3.createMoot(accountB, 'post', keypairB)
|
const mootB = MsgV4.createMoot(accountB, 'post', keypairB)
|
||||||
const mootBID = MsgV3.getMsgID(mootB)
|
const mootBID = MsgV4.getMsgID(mootB)
|
||||||
const tangleB = new MsgV3.Tangle(mootBID)
|
const tangleB = new MsgV4.Tangle(mootBID)
|
||||||
tangleB.add(mootBID, mootB)
|
tangleB.add(mootBID, mootB)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
account: accountA,
|
account: accountA,
|
||||||
accountTips: [accountA],
|
accountTips: [accountA],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -36,17 +36,17 @@ test('MsgV3.Tangle simple multi-author tangle', (t) => {
|
||||||
},
|
},
|
||||||
keypair: keypairA,
|
keypair: keypairA,
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
Object.keys(msg1.metadata.tangles),
|
Object.keys(msg1.metadata.tangles),
|
||||||
[mootAID],
|
[mootAID],
|
||||||
'msg1 has only feed tangle'
|
'msg1 has only feed tangle'
|
||||||
)
|
)
|
||||||
|
|
||||||
const tangleX = new MsgV3.Tangle(msgID1)
|
const tangleX = new MsgV4.Tangle(msgID1)
|
||||||
tangleX.add(msgID1, msg1)
|
tangleX.add(msgID1, msg1)
|
||||||
|
|
||||||
const msg2 = MsgV3.create({
|
const msg2 = MsgV4.create({
|
||||||
account: accountB,
|
account: accountB,
|
||||||
accountTips: [accountB],
|
accountTips: [accountB],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -86,29 +86,29 @@ test('MsgV3.Tangle simple multi-author tangle', (t) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('MsgV3.Tangle lipmaa in multi-author tangle', (t) => {
|
test('MsgV4.Tangle 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.getMsgID(
|
const accountA = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypairA, 'person', 'alice')
|
MsgV4.createAccount(keypairA, 'person', 'alice')
|
||||||
)
|
)
|
||||||
const accountB = MsgV3.getMsgID(
|
const accountB = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypairB, 'person', 'bob')
|
MsgV4.createAccount(keypairB, 'person', 'bob')
|
||||||
)
|
)
|
||||||
|
|
||||||
const data = { text: 'Hello world!' }
|
const data = { text: 'Hello world!' }
|
||||||
|
|
||||||
const mootA = MsgV3.createMoot(accountA, 'post', keypairA)
|
const mootA = MsgV4.createMoot(accountA, 'post', keypairA)
|
||||||
const mootAID = MsgV3.getMsgID(mootA)
|
const mootAID = MsgV4.getMsgID(mootA)
|
||||||
const tangleA = new MsgV3.Tangle(mootAID)
|
const tangleA = new MsgV4.Tangle(mootAID)
|
||||||
tangleA.add(mootAID, mootA)
|
tangleA.add(mootAID, mootA)
|
||||||
|
|
||||||
const mootB = MsgV3.createMoot(accountB, 'post', keypairB)
|
const mootB = MsgV4.createMoot(accountB, 'post', keypairB)
|
||||||
const mootBID = MsgV3.getMsgID(mootB)
|
const mootBID = MsgV4.getMsgID(mootB)
|
||||||
const tangleB = new MsgV3.Tangle(mootBID)
|
const tangleB = new MsgV4.Tangle(mootBID)
|
||||||
tangleB.add(mootBID, mootB)
|
tangleB.add(mootBID, mootB)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
account: accountA,
|
account: accountA,
|
||||||
accountTips: [accountA],
|
accountTips: [accountA],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -118,9 +118,9 @@ test('MsgV3.Tangle lipmaa in multi-author tangle', (t) => {
|
||||||
},
|
},
|
||||||
keypair: keypairA,
|
keypair: keypairA,
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
tangleA.add(msgID1, msg1)
|
tangleA.add(msgID1, msg1)
|
||||||
const tangleThread = new MsgV3.Tangle(msgID1)
|
const tangleThread = new MsgV4.Tangle(msgID1)
|
||||||
tangleThread.add(msgID1, msg1)
|
tangleThread.add(msgID1, msg1)
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
|
@ -129,7 +129,7 @@ test('MsgV3.Tangle lipmaa in multi-author tangle', (t) => {
|
||||||
'A:msg1 has only feed tangle'
|
'A:msg1 has only feed tangle'
|
||||||
)
|
)
|
||||||
|
|
||||||
const msg2 = MsgV3.create({
|
const msg2 = MsgV4.create({
|
||||||
account: accountB,
|
account: accountB,
|
||||||
accountTips: [accountB],
|
accountTips: [accountB],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -140,7 +140,7 @@ test('MsgV3.Tangle lipmaa in multi-author tangle', (t) => {
|
||||||
},
|
},
|
||||||
keypair: keypairB,
|
keypair: keypairB,
|
||||||
})
|
})
|
||||||
const msgID2 = MsgV3.getMsgID(msg2)
|
const msgID2 = MsgV4.getMsgID(msg2)
|
||||||
tangleB.add(msgID2, msg2)
|
tangleB.add(msgID2, msg2)
|
||||||
tangleThread.add(msgID2, msg2)
|
tangleThread.add(msgID2, msg2)
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ test('MsgV3.Tangle lipmaa in multi-author tangle', (t) => {
|
||||||
'B:msg2 points to A:msg1'
|
'B:msg2 points to A:msg1'
|
||||||
)
|
)
|
||||||
|
|
||||||
const msg3 = MsgV3.create({
|
const msg3 = MsgV4.create({
|
||||||
account: accountB,
|
account: accountB,
|
||||||
accountTips: [accountB],
|
accountTips: [accountB],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -161,7 +161,7 @@ test('MsgV3.Tangle lipmaa in multi-author tangle', (t) => {
|
||||||
},
|
},
|
||||||
keypair: keypairB,
|
keypair: keypairB,
|
||||||
})
|
})
|
||||||
const msgID3 = MsgV3.getMsgID(msg3)
|
const msgID3 = MsgV4.getMsgID(msg3)
|
||||||
tangleB.add(msgID3, msg3)
|
tangleB.add(msgID3, msg3)
|
||||||
tangleThread.add(msgID3, msg3)
|
tangleThread.add(msgID3, msg3)
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ test('MsgV3.Tangle lipmaa in multi-author tangle', (t) => {
|
||||||
'B:msg3 points to B:msg2'
|
'B:msg3 points to B:msg2'
|
||||||
)
|
)
|
||||||
|
|
||||||
const msg4 = MsgV3.create({
|
const msg4 = MsgV4.create({
|
||||||
account: accountA,
|
account: accountA,
|
||||||
accountTips: [accountA],
|
accountTips: [accountA],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -182,7 +182,7 @@ test('MsgV3.Tangle lipmaa in multi-author tangle', (t) => {
|
||||||
},
|
},
|
||||||
keypair: keypairA,
|
keypair: keypairA,
|
||||||
})
|
})
|
||||||
const msgID4 = MsgV3.getMsgID(msg4)
|
const msgID4 = MsgV4.getMsgID(msg4)
|
||||||
tangleB.add(msgID4, msg4)
|
tangleB.add(msgID4, msg4)
|
||||||
tangleThread.add(msgID4, msg4)
|
tangleThread.add(msgID4, msg4)
|
||||||
|
|
|
@ -1,41 +1,41 @@
|
||||||
const test = require('node:test')
|
const test = require('node:test')
|
||||||
const assert = require('node:assert')
|
const assert = require('node:assert')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const MsgV3 = require('../../lib/msg-v3')
|
const MsgV4 = require('../../lib/msg-v4')
|
||||||
|
|
||||||
test('MsgV3 validation', async (t) => {
|
test('MsgV4 validation', async (t) => {
|
||||||
await t.test('Correct root msg', (t) => {
|
await t.test('Correct root msg', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
const account = MsgV3.getMsgID(
|
const account = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypair, 'person', 'alice')
|
MsgV4.createAccount(keypair, 'person', 'alice')
|
||||||
)
|
)
|
||||||
const pubkeys = new Set([keypair.public])
|
const sigkeys = new Set([keypair.public])
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const err = MsgV3.validate(moot, tangle, pubkeys, mootID, mootID)
|
const err = MsgV4.validate(moot, tangle, sigkeys, mootID, mootID)
|
||||||
assert.ifError(err, 'valid root msg')
|
assert.ifError(err, 'valid root msg')
|
||||||
})
|
})
|
||||||
|
|
||||||
await t.test('Correct account tangle', (t) => {
|
await t.test('Correct account tangle', (t) => {
|
||||||
const pubkeys = new Set()
|
const sigkeys = new Set()
|
||||||
const keypair1 = Keypair.generate('ed25519', 'alice')
|
const keypair1 = Keypair.generate('ed25519', 'alice')
|
||||||
pubkeys.add(keypair1.public)
|
sigkeys.add(keypair1.public)
|
||||||
|
|
||||||
const accountMsg0 = MsgV3.createAccount(keypair1, 'person', 'alice')
|
const accountMsg0 = MsgV4.createAccount(keypair1, 'person', 'alice')
|
||||||
const account = MsgV3.getMsgID(accountMsg0)
|
const account = MsgV4.getMsgID(accountMsg0)
|
||||||
const accountMsg0ID = account
|
const accountMsg0ID = account
|
||||||
|
|
||||||
const tangle = new MsgV3.Tangle(account)
|
const tangle = new MsgV4.Tangle(account)
|
||||||
tangle.add(accountMsg0ID, accountMsg0)
|
tangle.add(accountMsg0ID, accountMsg0)
|
||||||
|
|
||||||
let err = MsgV3.validate(
|
let err = MsgV4.validate(
|
||||||
accountMsg0,
|
accountMsg0,
|
||||||
tangle,
|
tangle,
|
||||||
pubkeys,
|
sigkeys,
|
||||||
accountMsg0ID,
|
accountMsg0ID,
|
||||||
account
|
account
|
||||||
)
|
)
|
||||||
|
@ -45,7 +45,7 @@ test('MsgV3 validation', async (t) => {
|
||||||
|
|
||||||
const keypair2 = Keypair.generate('ed25519', 'bob')
|
const keypair2 = Keypair.generate('ed25519', 'bob')
|
||||||
|
|
||||||
const accountMsg1 = MsgV3.create({
|
const accountMsg1 = MsgV4.create({
|
||||||
account: 'self',
|
account: 'self',
|
||||||
accountTips: null,
|
accountTips: null,
|
||||||
domain: 'account',
|
domain: 'account',
|
||||||
|
@ -55,25 +55,25 @@ test('MsgV3 validation', async (t) => {
|
||||||
},
|
},
|
||||||
keypair: keypair1, // announcing keypair2 but signing with keypair1
|
keypair: keypair1, // announcing keypair2 but signing with keypair1
|
||||||
})
|
})
|
||||||
const accountMsg1ID = MsgV3.getMsgID(accountMsg1)
|
const accountMsg1ID = MsgV4.getMsgID(accountMsg1)
|
||||||
|
|
||||||
err = MsgV3.validate(accountMsg1, tangle, pubkeys, accountMsg1ID, account)
|
err = MsgV4.validate(accountMsg1, tangle, sigkeys, accountMsg1ID, account)
|
||||||
assert.ifError(err, 'valid account msg')
|
assert.ifError(err, 'valid account msg')
|
||||||
})
|
})
|
||||||
|
|
||||||
await t.test('2nd msg correct with existing root', (t) => {
|
await t.test('2nd msg correct with existing root', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
const account = MsgV3.getMsgID(
|
const account = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypair, 'person', 'alice')
|
MsgV4.createAccount(keypair, 'person', 'alice')
|
||||||
)
|
)
|
||||||
const pubkeys = new Set([keypair.public])
|
const sigkeys = new Set([keypair.public])
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -83,26 +83,26 @@ test('MsgV3 validation', async (t) => {
|
||||||
},
|
},
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
tangle.add(msgID1, msg1)
|
tangle.add(msgID1, msg1)
|
||||||
|
|
||||||
const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
|
const err = MsgV4.validate(msg1, tangle, sigkeys, msgID1, mootID)
|
||||||
assert.ifError(err, 'valid 2nd msg')
|
assert.ifError(err, 'valid 2nd msg')
|
||||||
})
|
})
|
||||||
|
|
||||||
await t.test('2nd forked msg correct', (t) => {
|
await t.test('2nd forked msg correct', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
const account = MsgV3.getMsgID(
|
const account = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypair, 'person', 'alice')
|
MsgV4.createAccount(keypair, 'person', 'alice')
|
||||||
)
|
)
|
||||||
const pubkeys = new Set([keypair.public])
|
const sigkeys = new Set([keypair.public])
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1A = MsgV3.create({
|
const msg1A = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -112,9 +112,9 @@ test('MsgV3 validation', async (t) => {
|
||||||
},
|
},
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
const msgID1A = MsgV3.getMsgID(msg1A)
|
const msgID1A = MsgV4.getMsgID(msg1A)
|
||||||
|
|
||||||
const msg1B = MsgV3.create({
|
const msg1B = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -124,27 +124,27 @@ test('MsgV3 validation', async (t) => {
|
||||||
},
|
},
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
const msgID1B = MsgV3.getMsgID(msg1B)
|
const msgID1B = MsgV4.getMsgID(msg1B)
|
||||||
|
|
||||||
tangle.add(msgID1A, msg1A)
|
tangle.add(msgID1A, msg1A)
|
||||||
tangle.add(msgID1B, msg1B)
|
tangle.add(msgID1B, msg1B)
|
||||||
const err = MsgV3.validate(msg1B, tangle, pubkeys, msgID1B, mootID)
|
const err = MsgV4.validate(msg1B, tangle, sigkeys, msgID1B, mootID)
|
||||||
assert.ifError(err, 'valid 2nd forked msg')
|
assert.ifError(err, 'valid 2nd forked msg')
|
||||||
})
|
})
|
||||||
|
|
||||||
await t.test('Correct erased msg', (t) => {
|
await t.test('Correct erased msg', (t) => {
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
const account = MsgV3.getMsgID(
|
const account = MsgV4.getMsgID(
|
||||||
MsgV3.createAccount(keypair, 'person', 'alice')
|
MsgV4.createAccount(keypair, 'person', 'alice')
|
||||||
)
|
)
|
||||||
const pubkeys = new Set([keypair.public])
|
const sigkeys = new Set([keypair.public])
|
||||||
|
|
||||||
const moot = MsgV3.createMoot(account, 'post', keypair)
|
const moot = MsgV4.createMoot(account, 'post', keypair)
|
||||||
const mootID = MsgV3.getMsgID(moot)
|
const mootID = MsgV4.getMsgID(moot)
|
||||||
const tangle = new MsgV3.Tangle(mootID)
|
const tangle = new MsgV4.Tangle(mootID)
|
||||||
tangle.add(mootID, moot)
|
tangle.add(mootID, moot)
|
||||||
|
|
||||||
const msg1 = MsgV3.create({
|
const msg1 = MsgV4.create({
|
||||||
account,
|
account,
|
||||||
accountTips: [account],
|
accountTips: [account],
|
||||||
domain: 'post',
|
domain: 'post',
|
||||||
|
@ -155,9 +155,9 @@ test('MsgV3 validation', async (t) => {
|
||||||
keypair,
|
keypair,
|
||||||
})
|
})
|
||||||
msg1.data = null
|
msg1.data = null
|
||||||
const msgID1 = MsgV3.getMsgID(msg1)
|
const msgID1 = MsgV4.getMsgID(msg1)
|
||||||
|
|
||||||
const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
|
const err = MsgV4.validate(msg1, tangle, sigkeys, msgID1, mootID)
|
||||||
assert.ifError(err, 'valid erased msg')
|
assert.ifError(err, 'valid erased msg')
|
||||||
})
|
})
|
||||||
})
|
})
|
Loading…
Reference in New Issue