From 3686f5de24eeb4c26d6bd732e8be31a234d1f9a4 Mon Sep 17 00:00:00 2001 From: Andre Staltz Date: Mon, 17 Apr 2023 18:39:33 +0300 Subject: [PATCH] add metadata.v, rename metadata.proof to metadata.hash --- lib/feed-v1/index.js | 11 +++++++---- lib/feed-v1/tangle.js | 2 +- lib/feed-v1/validation.js | 21 ++++++++++++++++----- test/erase.test.js | 2 +- test/feed-v1-create.test.js | 18 +++++++++--------- 5 files changed, 34 insertions(+), 20 deletions(-) diff --git a/lib/feed-v1/index.js b/lib/feed-v1/index.js index 574b078..46928ec 100644 --- a/lib/feed-v1/index.js +++ b/lib/feed-v1/index.js @@ -39,10 +39,11 @@ function isEmptyObject(obj) { * @typedef {Object} Msg * @property {*} content * @property {Object} metadata - * @property {string} metadata.proof + * @property {string} metadata.hash * @property {number} metadata.size * @property {Record} metadata.tangles * @property {string} metadata.type + * @property {1} metadata.v * @property {string} metadata.who * @property {string} sig */ @@ -115,7 +116,7 @@ function create(opts) { if ((err = validateType(opts.type))) throw err if (!opts.tangles) throw new Error('opts.tangles is required') - const [proof, size] = representContent(opts.content) + const [hash, size] = representContent(opts.content) const tangles = {} if (opts.tangles) { @@ -136,10 +137,11 @@ function create(opts) { const msg = { content: opts.content, metadata: { - proof, + hash, size, tangles, type: opts.type, + v: 1, who: stripAuthor(opts.keys.id), }, sig: '', @@ -168,10 +170,11 @@ function createRoot(keys, type) { const msg = { content: null, metadata: { - proof: '', + hash: null, size: 0, tangles: {}, type, + v: 1, who: stripAuthor(keys.id), }, sig: '', diff --git a/lib/feed-v1/tangle.js b/lib/feed-v1/tangle.js index 6de070d..d59ef87 100644 --- a/lib/feed-v1/tangle.js +++ b/lib/feed-v1/tangle.js @@ -167,7 +167,7 @@ class Tangle { isFeed() { if (this.#rootMsg.content) return false const metadata = this.#rootMsg.metadata - return metadata.size === 0 && metadata.proof === '' + return metadata.size === 0 && metadata.hash === null } getFeed() { diff --git a/lib/feed-v1/validation.js b/lib/feed-v1/validation.js index 85630fb..289de52 100644 --- a/lib/feed-v1/validation.js +++ b/lib/feed-v1/validation.js @@ -2,6 +2,7 @@ const base58 = require('bs58') const ed25519 = require('ssb-keys/sodium') const stringify = require('fast-json-stable-stringify') const Tangle = require('./tangle') +const representContent = require('./represent-content') function validateShape(msg) { if (!msg || typeof msg !== 'object') { @@ -13,11 +14,14 @@ function validateShape(msg) { if (typeof msg.metadata.who === 'undefined') { return new Error('invalid message: must have metadata.who') } + if (msg.metadata.v !== 1) { + return new Error('invalid message: must have metadata.v 1') + } if (typeof msg.metadata.tangles !== 'object') { return new Error('invalid message: must have metadata.tangles') } - if (typeof msg.metadata.proof === 'undefined') { - return new Error('invalid message: must have metadata.proof') + if (typeof msg.metadata.hash === 'undefined') { + return new Error('invalid message: must have metadata.hash') } if (typeof msg.metadata.size === 'undefined') { return new Error('invalid message: must have metadata.size') @@ -162,10 +166,8 @@ function validateType(type) { } function validateContent(msg) { - // FIXME: if content exists, check it against `proof` and `size` - // FIXME: if content does not exist, do nothing const { content } = msg - if (!content) { + if (content === null) { return } if (Array.isArray(content)) { @@ -175,6 +177,15 @@ function validateContent(msg) { // prettier-ignore return new Error('invalid message: content must be an object or string, on feed: ' + msg.metadata.who); } + const [hash, size] = representContent(content) + if (hash !== msg.metadata.hash) { + // prettier-ignore + return new Error('invalid message: content hash does not match metadata.hash, on feed: ' + msg.metadata.who); + } + if (size !== msg.metadata.size) { + // prettier-ignore + return new Error('invalid message: content size does not match metadata.size, on feed: ' + msg.metadata.who); + } } // FIXME: validateDepth should be +1 of the max of prev depth diff --git a/test/erase.test.js b/test/erase.test.js index 454a4ea..e721a7f 100644 --- a/test/erase.test.js +++ b/test/erase.test.js @@ -20,7 +20,7 @@ test('erase', async (t) => { await peer.db.loaded() - const rootHash = 'PGwQiuwFnB7EySQHBit2mA' + const rootHash = 'Nf2kuXAYsLBHEgU9eonYdn' const msgHashes = [] for (let i = 0; i < 5; i++) { const rec = await p(peer.db.create)({ diff --git a/test/feed-v1-create.test.js b/test/feed-v1-create.test.js index 707869b..3b87768 100644 --- a/test/feed-v1-create.test.js +++ b/test/feed-v1-create.test.js @@ -8,14 +8,14 @@ tape('FeedV1.createRoot()', (t) => { const keys = generateKeypair('alice') rootMsg = FeedV1.createRoot(keys, 'post') t.equals(rootMsg.content, null, 'content') - t.equals(rootMsg.metadata.proof, '', 'proof') + t.equals(rootMsg.metadata.hash, null, 'hash') t.equals(rootMsg.metadata.size, 0, 'size') t.equals(rootMsg.metadata.type, 'post', 'type') t.equals(rootMsg.metadata.who, FeedV1.stripAuthor(keys.id), 'who') t.deepEquals(rootMsg.metadata.tangles, {}, 'tangles') rootHash = FeedV1.getMsgHash(rootMsg) - t.equals(rootHash, 'PGwQiuwFnB7EySQHBit2mA', 'root hash') + t.equals(rootHash, 'Nf2kuXAYsLBHEgU9eonYdn', 'root hash') t.end() }) @@ -36,7 +36,7 @@ tape('FeedV1.create()', (t) => { }) t.deepEquals( Object.keys(msg1.metadata), - ['proof', 'size', 'tangles', 'type', 'who'], + ['hash', 'size', 'tangles', 'type', 'v', 'who'], 'metadata fields' ) t.equals( @@ -45,7 +45,7 @@ tape('FeedV1.create()', (t) => { 'metadata.who' ) t.equals(msg1.metadata.type, 'post', 'metadata.type') - t.deepEquals(msg1.metadata.proof, '9R7XmBhHF5ooPg34j9TQcz', 'metadata.proof') + t.deepEquals(msg1.metadata.hash, '9R7XmBhHF5ooPg34j9TQcz', 'metadata.hash') t.deepEquals(Object.keys(msg1.metadata.tangles), [rootHash], 'tangles') t.equals(msg1.metadata.tangles[rootHash].depth, 1, 'tangle depth') t.deepEquals(msg1.metadata.tangles[rootHash].prev, [rootHash], 'tangle prev') @@ -54,7 +54,7 @@ tape('FeedV1.create()', (t) => { console.log(msg1) - const msgHash1 = 'M31mLeV2wNDwp9ZRkkF8pL' + const msgHash1 = 'SktCiaHrUxz2mXS1SRSDmj' t.equals( FeedV1.getMsgId(msg1), @@ -79,7 +79,7 @@ tape('FeedV1.create()', (t) => { }) t.deepEquals( Object.keys(msg2.metadata), - ['proof', 'size', 'tangles', 'type', 'who'], + ['hash', 'size', 'tangles', 'type', 'v', 'who'], 'metadata keys' ) t.equals( @@ -91,7 +91,7 @@ tape('FeedV1.create()', (t) => { t.deepEquals(Object.keys(msg1.metadata.tangles), [rootHash], 'tangles') t.equals(msg2.metadata.tangles[rootHash].depth, 2, 'tangle depth') t.deepEquals(msg2.metadata.tangles[rootHash].prev, [msgHash1], 'tangle prev') - t.deepEquals(msg2.metadata.proof, 'XuZEzH1Dhy1yuRMcviBBcN', 'metadata.proof') + t.deepEquals(msg2.metadata.hash, 'XuZEzH1Dhy1yuRMcviBBcN', 'metadata.hash') t.deepEquals(msg2.metadata.size, 21, 'metadata.size') t.deepEqual(msg2.content, content2, 'content is correct') @@ -99,7 +99,7 @@ tape('FeedV1.create()', (t) => { t.deepEqual( FeedV1.getMsgId(msg2), - 'ppppp:message/v1/4mjQ5aJu378cEu6TksRG3uXAiKFiwGjYQtWAjfVjDAJW/post/MHLPVrHFzCLXVeXUkY1W4a', + 'ppppp:message/v1/4mjQ5aJu378cEu6TksRG3uXAiKFiwGjYQtWAjfVjDAJW/post/Nej4ibHrxryTduWqDeCJE4', 'getMsgId' ) @@ -122,7 +122,7 @@ tape('create() handles DAG tips correctly', (t) => { const msgHash1 = FeedV1.getMsgHash(msg1) t.deepEquals( msg1.metadata.tangles[rootHash].prev, - ['PGwQiuwFnB7EySQHBit2mA'], + ['Nf2kuXAYsLBHEgU9eonYdn'], 'msg1.prev is root' )