refactor/prettify tests

This commit is contained in:
Andre Staltz 2023-11-10 11:06:19 +02:00
parent 9356b9b3d9
commit f40ea71ff9
No known key found for this signature in database
GPG Key ID: 9EDE23EA7E8A4890
14 changed files with 1533 additions and 1519 deletions

View File

@ -12,217 +12,219 @@ const DIR = path.join(os.tmpdir(), 'ppppp-db-account-add')
rimraf.sync(DIR)
test('account.add()', async (t) => {
const keypair1 = Keypair.generate('ed25519', 'alice')
const keypair2 = Keypair.generate('ed25519', 'bob')
await t.test('Basic usage', async (t) => {
const keypair1 = Keypair.generate('ed25519', 'alice')
const keypair2 = Keypair.generate('ed25519', 'bob')
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair1, path: DIR })
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair1, path: DIR })
await peer.db.loaded()
const account = await p(peer.db.account.create)({
keypair: keypair1,
domain: 'person',
})
await peer.db.loaded()
const account = await p(peer.db.account.create)({
keypair: keypair1,
domain: 'person',
})
assert.equal(peer.db.account.has({ account, keypair: keypair2 }), false)
assert.equal(peer.db.account.has({ account, keypair: keypair2 }), false)
const consent = peer.db.account.consent({ account, keypair: keypair2 })
const consent = peer.db.account.consent({ account, keypair: keypair2 })
const accountRec1 = await p(peer.db.account.add)({
account,
keypair: keypair2,
consent,
powers: ['box'],
})
assert.ok(accountRec1, 'accountRec1 exists')
const { id, msg } = accountRec1
assert.ok(account, 'id exists')
assert.deepEqual(
msg.data,
{
action: 'add',
add: {
key: {
purpose: 'sig',
algorithm: 'ed25519',
bytes: keypair2.public,
const accountRec1 = await p(peer.db.account.add)({
account,
keypair: keypair2,
consent,
powers: ['box'],
})
assert.ok(accountRec1, 'accountRec1 exists')
const { id, msg } = accountRec1
assert.ok(account, 'id exists')
assert.deepEqual(
msg.data,
{
action: 'add',
add: {
key: {
purpose: 'sig',
algorithm: 'ed25519',
bytes: keypair2.public,
},
consent,
powers: ['box'],
},
consent,
powers: ['box'],
},
},
'msg.data.add NEW KEY'
)
assert.equal(msg.metadata.account, 'self', 'msg.metadata.account')
assert.equal(msg.metadata.accountTips, null, 'msg.metadata.accountTips')
assert.equal(msg.metadata.domain, 'person', 'msg.metadata.domain')
assert.deepEqual(
msg.metadata.tangles,
{ [account]: { depth: 1, prev: [account] } },
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair1.public, 'msg.pubkey OLD KEY')
'msg.data.add NEW KEY'
)
assert.equal(msg.metadata.account, 'self', 'msg.metadata.account')
assert.equal(msg.metadata.accountTips, null, 'msg.metadata.accountTips')
assert.equal(msg.metadata.domain, 'person', 'msg.metadata.domain')
assert.deepEqual(
msg.metadata.tangles,
{ [account]: { depth: 1, prev: [account] } },
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair1.public, 'msg.pubkey OLD KEY')
assert.equal(peer.db.account.has({ account, keypair: keypair2 }), true)
assert.equal(peer.db.account.has({ account, keypair: keypair2 }), true)
await p(peer.close)()
})
test('keypair with no "add" powers cannot account.add()', async (t) => {
rimraf.sync(DIR)
const keypair1 = Keypair.generate('ed25519', 'alice')
const keypair2 = Keypair.generate('ed25519', 'bob')
const keypair3 = Keypair.generate('ed25519', 'carol')
const peer1 = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair1, path: DIR })
await peer1.db.loaded()
const id = await p(peer1.db.account.create)({
keypair: keypair1,
domain: 'account',
await p(peer.close)()
})
const msg1 = peer1.db.get(id)
const { msg: msg2 } = await p(peer1.db.account.add)({
account: id,
keypair: keypair2,
powers: [],
})
assert.equal(msg2.data.add.key.bytes, keypair2.public)
await t.test('keypair with no "add" powers cannot add', async (t) => {
rimraf.sync(DIR)
const keypair1 = Keypair.generate('ed25519', 'alice')
const keypair2 = Keypair.generate('ed25519', 'bob')
const keypair3 = Keypair.generate('ed25519', 'carol')
assert.equal(peer1.db.account.has({ account: id, keypair: keypair2 }), true)
const peer1 = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair1, path: DIR })
await p(peer1.close)()
rimraf.sync(DIR)
await peer1.db.loaded()
const id = await p(peer1.db.account.create)({
keypair: keypair1,
domain: 'account',
})
const msg1 = peer1.db.get(id)
const peer2 = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair2, path: DIR })
const { msg: msg2 } = await p(peer1.db.account.add)({
account: id,
keypair: keypair2,
powers: [],
})
assert.equal(msg2.data.add.key.bytes, keypair2.public)
await peer2.db.loaded()
await p(peer2.db.add)(msg1, id)
await p(peer2.db.add)(msg2, id)
assert.equal(peer1.db.account.has({ account: id, keypair: keypair2 }), true)
// Test author-side power validation
assert.rejects(
p(peer2.db.account.add)({
await p(peer1.close)()
rimraf.sync(DIR)
const peer2 = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair2, path: DIR })
await peer2.db.loaded()
await p(peer2.db.add)(msg1, id)
await p(peer2.db.add)(msg2, id)
// Test author-side power validation
assert.rejects(
p(peer2.db.account.add)({
account: id,
keypair: keypair3,
powers: [],
}),
/signing keypair does not have the "add" power/
)
// Make the author disobey power validation
const { msg: msg3 } = await p(peer2.db.account.add)({
account: id,
keypair: keypair3,
powers: [],
}),
/signing keypair does not have the "add" power/
)
_disobey: true,
})
// Make the author disobey power validation
const { msg: msg3 } = await p(peer2.db.account.add)({
account: id,
keypair: keypair3,
powers: [],
_disobey: true,
assert.equal(msg3.data.add.key.bytes, keypair3.public)
await p(peer2.close)()
rimraf.sync(DIR)
const peer1again = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair1, path: DIR })
await peer1again.db.loaded()
await p(peer1again.db.add)(msg1, id) // re-add because lost during rimraf
await p(peer1again.db.add)(msg2, id) // re-add because lost during rimraf
// Test replicator-side power validation
assert.rejects(
p(peer1again.db.add)(msg3, id),
/add\(\) failed to verify msg/
)
await p(peer1again.close)()
})
assert.equal(msg3.data.add.key.bytes, keypair3.public)
await t.test('publish with a key in the account', async (t) => {
rimraf.sync(DIR)
await p(peer2.close)()
rimraf.sync(DIR)
const keypair1 = Keypair.generate('ed25519', 'alice')
const keypair2 = Keypair.generate('ed25519', 'bob')
const peer1again = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair1, path: DIR })
let peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair1, path: DIR })
await peer1again.db.loaded()
await p(peer1again.db.add)(msg1, id) // re-add because lost during rimraf
await p(peer1again.db.add)(msg2, id) // re-add because lost during rimraf
await peer.db.loaded()
// Test replicator-side power validation
assert.rejects(
p(peer1again.db.add)(msg3, id),
/add\(\) failed to verify msg/
)
const account = await p(peer.db.account.create)({
keypair: keypair1,
domain: 'person',
})
const accountMsg0 = peer.db.get(account)
await p(peer1again.close)()
})
test('publish with a key in the account', async (t) => {
rimraf.sync(DIR)
const keypair1 = Keypair.generate('ed25519', 'alice')
const keypair2 = Keypair.generate('ed25519', 'bob')
let peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair1, path: DIR })
await peer.db.loaded()
const account = await p(peer.db.account.create)({
keypair: keypair1,
domain: 'person',
})
const accountMsg0 = peer.db.get(account)
// Consent is implicitly created because keypair2 has .private
const accountRec1 = await p(peer.db.account.add)({
account,
keypair: keypair2,
})
const postRec = await p(peer.db.feed.publish)({
account,
domain: 'post',
data: { text: 'hello' },
keypair: keypair2,
})
assert.equal(postRec.msg.data.text, 'hello', 'post text correct')
const postsID = peer.db.feed.getID(account, 'post')
assert.ok(postsID, 'postsID exists')
const recs = [...peer.db.records()]
assert.equal(recs.length, 4, '4 records')
const [_accountRec0, _accountRec1, postsRoot, _post] = recs
assert.deepEqual(_accountRec0.msg, accountMsg0, 'accountMsg0')
assert.deepEqual(_accountRec1.msg, accountRec1.msg, 'accountMsg1')
assert.deepEqual(
postsRoot.msg.metadata,
{
dataHash: null,
dataSize: 0,
// Consent is implicitly created because keypair2 has .private
const accountRec1 = await p(peer.db.account.add)({
account,
keypair: keypair2,
})
const postRec = await p(peer.db.feed.publish)({
account,
accountTips: null,
tangles: {},
domain: 'post',
v: 3,
},
'postsRoot'
)
assert.deepEqual(_post.msg, postRec.msg, 'postMsg')
data: { text: 'hello' },
keypair: keypair2,
})
assert.equal(postRec.msg.data.text, 'hello', 'post text correct')
const postsID = peer.db.feed.getID(account, 'post')
assert.ok(postsID, 'postsID exists')
await p(peer.close)()
const recs = [...peer.db.records()]
assert.equal(recs.length, 4, '4 records')
const [_accountRec0, _accountRec1, postsRoot, _post] = recs
assert.deepEqual(_accountRec0.msg, accountMsg0, 'accountMsg0')
assert.deepEqual(_accountRec1.msg, accountRec1.msg, 'accountMsg1')
assert.deepEqual(
postsRoot.msg.metadata,
{
dataHash: null,
dataSize: 0,
account,
accountTips: null,
tangles: {},
domain: 'post',
v: 3,
},
'postsRoot'
)
assert.deepEqual(_post.msg, postRec.msg, 'postMsg')
// Re-load as Carol, add the msgs to validate them
rimraf.sync(DIR)
const keypair3 = Keypair.generate('ed25519', 'carol')
await p(peer.close)()
const carol = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair3, path: DIR })
// Re-load as Carol, add the msgs to validate them
rimraf.sync(DIR)
const keypair3 = Keypair.generate('ed25519', 'carol')
await carol.db.loaded()
const carol = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypair3, path: DIR })
await p(carol.db.add)(accountMsg0, account)
await p(carol.db.add)(accountRec1.msg, account)
await p(carol.db.add)(postsRoot.msg, postsID)
await p(carol.db.add)(postRec.msg, postsID)
// t.pass('carol added all msgs successfully')
await carol.db.loaded()
await p(carol.close)()
await p(carol.db.add)(accountMsg0, account)
await p(carol.db.add)(accountRec1.msg, account)
await p(carol.db.add)(postsRoot.msg, postsID)
await p(carol.db.add)(postRec.msg, postsID)
// t.pass('carol added all msgs successfully')
await p(carol.close)()
})
})

View File

@ -11,148 +11,150 @@ const Keypair = require('ppppp-keypair')
const DIR = path.join(os.tmpdir(), 'ppppp-db-account-create')
rimraf.sync(DIR)
test('account.create() with just "domain"', async (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
test('account.create() ', async (t) => {
await t.test('create with just "domain"', async (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const account = await p(peer.db.account.create)({
domain: 'person',
_nonce: 'MYNONCE',
})
assert.ok(account, 'accountRec0 exists')
const msg = peer.db.get(account)
assert.deepEqual(
msg.data,
{
action: 'add',
add: {
key: {
purpose: 'sig',
algorithm: 'ed25519',
bytes: keypair.public,
await peer.db.loaded()
const account = await p(peer.db.account.create)({
domain: 'person',
_nonce: 'MYNONCE',
})
assert.ok(account, 'accountRec0 exists')
const msg = peer.db.get(account)
assert.deepEqual(
msg.data,
{
action: 'add',
add: {
key: {
purpose: 'sig',
algorithm: 'ed25519',
bytes: keypair.public,
},
nonce: 'MYNONCE',
powers: ['add', 'del', 'box'],
},
nonce: 'MYNONCE',
powers: ['add', 'del', 'box'],
},
},
'msg.data.add'
)
assert.equal(msg.metadata.account, 'self', 'msg.metadata.account')
assert.equal(msg.metadata.accountTips, null, 'msg.metadata.accountTips')
assert.deepEqual(
Object.keys(msg.metadata.tangles),
[],
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
'msg.data.add'
)
assert.equal(msg.metadata.account, 'self', 'msg.metadata.account')
assert.equal(msg.metadata.accountTips, null, 'msg.metadata.accountTips')
assert.deepEqual(
Object.keys(msg.metadata.tangles),
[],
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
await p(peer.close)()
})
test('account.create() with "keypair" and "domain"', async (t) => {
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const account = await p(peer.db.account.create)({
keypair,
domain: 'person',
await p(peer.close)()
})
assert.ok(account, 'account created')
const msg = peer.db.get(account)
assert.equal(msg.data.add.key.bytes, keypair.public, 'msg.data.add')
assert.equal(msg.metadata.account, 'self', 'msg.metadata.account')
assert.equal(msg.metadata.accountTips, null, 'msg.metadata.accountTips')
assert.deepEqual(
Object.keys(msg.metadata.tangles),
[],
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
await p(peer.close)()
})
await t.test('create with "keypair" and "domain"', async (t) => {
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
test('account.find() can find', async (t) => {
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
const domain = 'person'
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const account = await p(peer.db.account.create)({
keypair,
domain: 'person',
})
assert.ok(account, 'account created')
const msg = peer.db.get(account)
assert.equal(msg.data.add.key.bytes, keypair.public, 'msg.data.add')
assert.equal(msg.metadata.account, 'self', 'msg.metadata.account')
assert.equal(msg.metadata.accountTips, null, 'msg.metadata.accountTips')
assert.deepEqual(
Object.keys(msg.metadata.tangles),
[],
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
await peer.db.loaded()
const account = await p(peer.db.account.create)({ keypair, domain })
assert.ok(account, 'account created')
const found = await p(peer.db.account.find)({ keypair, domain })
assert.equal(found, account, 'found')
await p(peer.close)()
})
test('account.findOrCreate() can find', async (t) => {
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
const domain = 'person'
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const account = await p(peer.db.account.create)({ keypair, domain })
assert.ok(account, 'account created')
const found = await p(peer.db.account.findOrCreate)({ keypair, domain })
assert.equal(found, account, 'found')
await p(peer.close)()
})
test('account.findOrCreate() can create', async (t) => {
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
const domain = 'person'
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
let gotError = false
await p(peer.db.account.find)({ keypair, domain }).catch((err) => {
assert.equal(err.cause, 'ENOENT')
gotError = true
await p(peer.close)()
})
assert.ok(gotError, 'account not found')
const account = await p(peer.db.account.findOrCreate)({ keypair, domain })
assert.ok(account, 'account created')
const msg = peer.db.get(account)
assert.equal(msg.data.add.key.bytes, keypair.public, 'msg.data.add')
assert.equal(msg.metadata.account, 'self', 'msg.metadata.account')
assert.equal(msg.metadata.accountTips, null, 'msg.metadata.accountTips')
assert.deepEqual(
Object.keys(msg.metadata.tangles),
[],
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
await t.test('account.find() can find', async (t) => {
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
const domain = 'person'
await p(peer.close)()
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const account = await p(peer.db.account.create)({ keypair, domain })
assert.ok(account, 'account created')
const found = await p(peer.db.account.find)({ keypair, domain })
assert.equal(found, account, 'found')
await p(peer.close)()
})
await t.test('account.findOrCreate() can find', async (t) => {
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
const domain = 'person'
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
const account = await p(peer.db.account.create)({ keypair, domain })
assert.ok(account, 'account created')
const found = await p(peer.db.account.findOrCreate)({ keypair, domain })
assert.equal(found, account, 'found')
await p(peer.close)()
})
await t.test('account.findOrCreate() can create', async (t) => {
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
const domain = 'person'
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
let gotError = false
await p(peer.db.account.find)({ keypair, domain }).catch((err) => {
assert.equal(err.cause, 'ENOENT')
gotError = true
})
assert.ok(gotError, 'account not found')
const account = await p(peer.db.account.findOrCreate)({ keypair, domain })
assert.ok(account, 'account created')
const msg = peer.db.get(account)
assert.equal(msg.data.add.key.bytes, keypair.public, 'msg.data.add')
assert.equal(msg.metadata.account, 'self', 'msg.metadata.account')
assert.equal(msg.metadata.accountTips, null, 'msg.metadata.accountTips')
assert.deepEqual(
Object.keys(msg.metadata.tangles),
[],
'msg.metadata.tangles'
)
assert.equal(msg.pubkey, keypair.public, 'msg.pubkey')
await p(peer.close)()
})
})

View File

@ -6,14 +6,13 @@ const p = require('node:util').promisify
const rimraf = require('rimraf')
const SecretStack = require('secret-stack')
const Log = require('../lib/log')
const push = require('push-stream')
const caps = require('ppppp-caps')
const Keypair = require('ppppp-keypair')
const DIR = path.join(os.tmpdir(), 'ppppp-db-del')
rimraf.sync(DIR)
test('del', async (t) => {
test('del()', async (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))

View File

@ -13,7 +13,7 @@ const Keypair = require('ppppp-keypair')
const DIR = path.join(os.tmpdir(), 'ppppp-db-erase')
rimraf.sync(DIR)
test('erase', async (t) => {
test('erase()', async (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))

View File

@ -12,31 +12,23 @@ const MsgV3 = require('../lib/msg-v3')
const DIR = path.join(os.tmpdir(), 'ppppp-db-feed-publish')
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
let peer
let id
let moot
let mootID
test('setup', async (t) => {
peer = SecretStack({ appKey: caps.shse })
test('feed.getID()', async (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
id = (await p(peer.db.account.create)({domain: 'person'}))
moot = MsgV3.createMoot(id, 'post', keypair)
mootID = MsgV3.getMsgID(moot)
const id = await p(peer.db.account.create)({ domain: 'person' })
const moot = MsgV3.createMoot(id, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
await p(peer.db.add)(moot, mootID)
})
test('feed.getID()', async (t) => {
const feedID = peer.db.feed.getID(id, 'post')
assert.equal(feedID, mootID, 'feed.getID() returns moot ID')
})
test('teardown', (t) => {
peer.close(t.end)
await p(peer.close)(true)
})

View File

@ -12,148 +12,151 @@ const MsgV3 = require('../lib/msg-v3')
const DIR = path.join(os.tmpdir(), 'ppppp-db-feed-publish')
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
const bobKeypair = Keypair.generate('ed25519', 'bob')
let peer
let id
let moot
let mootID
test('setup', async (t) => {
peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
id = (await p(peer.db.account.create)({domain: 'person'}))
moot = MsgV3.createMoot(id, 'post', keypair)
mootID = MsgV3.getMsgID(moot)
})
let msgID1
let rec1
let msgID2
test('feed.publish()', async (t) => {
rec1 = await p(peer.db.feed.publish)({
account: id,
domain: 'post',
data: { text: 'I am 1st post' },
})
assert.equal(rec1.msg.data.text, 'I am 1st post', 'msg1 text correct')
assert.equal(
rec1.msg.metadata.tangles[mootID].depth,
1,
'msg1 tangle depth correct'
)
assert.deepEqual(
rec1.msg.metadata.tangles[mootID].prev,
[mootID],
'msg1 tangle prev correct'
)
const keypair = Keypair.generate('ed25519', 'alice')
const bobKeypair = Keypair.generate('ed25519', 'bob')
let peer
let id
let moot
let mootID
msgID1 = MsgV3.getMsgID(rec1.msg)
// Setup
{
peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
const rec2 = await p(peer.db.feed.publish)({
account: id,
domain: 'post',
data: { text: 'I am 2nd post' },
await peer.db.loaded()
id = await p(peer.db.account.create)({ domain: 'person' })
moot = MsgV3.createMoot(id, 'post', keypair)
mootID = MsgV3.getMsgID(moot)
}
let msgID1
let rec1
let msgID2
await t.test('can add new msgs to the db', async (t) => {
rec1 = await p(peer.db.feed.publish)({
account: id,
domain: 'post',
data: { text: 'I am 1st post' },
})
assert.equal(rec1.msg.data.text, 'I am 1st post', 'msg1 text correct')
assert.equal(
rec1.msg.metadata.tangles[mootID].depth,
1,
'msg1 tangle depth correct'
)
assert.deepEqual(
rec1.msg.metadata.tangles[mootID].prev,
[mootID],
'msg1 tangle prev correct'
)
msgID1 = MsgV3.getMsgID(rec1.msg)
const rec2 = await p(peer.db.feed.publish)({
account: id,
domain: 'post',
data: { text: 'I am 2nd post' },
})
assert.equal(rec2.msg.data.text, 'I am 2nd post', 'msg2 text correct')
assert.equal(
rec2.msg.metadata.tangles[mootID].depth,
2,
'msg2 tangle depth correct'
)
assert.deepEqual(
rec2.msg.metadata.tangles[mootID].prev,
[msgID1],
'msg2 tangle prev correct'
)
msgID2 = MsgV3.getMsgID(rec2.msg)
})
assert.equal(rec2.msg.data.text, 'I am 2nd post', 'msg2 text correct')
assert.equal(
rec2.msg.metadata.tangles[mootID].depth,
2,
'msg2 tangle depth correct'
)
assert.deepEqual(
rec2.msg.metadata.tangles[mootID].prev,
[msgID1],
'msg2 tangle prev correct'
)
msgID2 = MsgV3.getMsgID(rec2.msg)
})
test('add() forked then feed.publish() merged', async (t) => {
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
tangle.add(rec1.id, rec1.msg)
const msg3 = MsgV3.create({
keypair,
account: id,
accountTips: [id],
domain: 'post',
data: { text: '3rd post forked from 1st' },
tangles: {
[mootID]: tangle,
},
})
const rec3 = await p(peer.db.add)(msg3, mootID)
const msgID3 = MsgV3.getMsgID(rec3.msg)
const rec4 = await p(peer.db.feed.publish)({
account: id,
domain: 'post',
data: { text: 'I am 4th post' },
})
assert.ok(rec4, '4th post published')
assert.equal(
rec4.msg.metadata.tangles[mootID].prev.length,
3,
'msg4 prev has 3' // is root, msg2 and msg3'
)
assert.ok(
rec4.msg.metadata.tangles[mootID].prev.includes(mootID),
'msg4 prev has root'
)
assert.ok(
rec4.msg.metadata.tangles[mootID].prev.includes(msgID2),
'msg4 prev has msg2'
)
assert.ok(
rec4.msg.metadata.tangles[mootID].prev.includes(msgID3),
'msg4 prev has msg3'
)
})
test('feed.publish() encrypted with box', async (t) => {
const recEncrypted = await p(peer.db.feed.publish)({
account: id,
domain: 'post',
data: { text: 'I am chewing food', recps: [keypair.public] },
encryptionFormat: 'box',
})
assert.equal(typeof recEncrypted.msg.data, 'string')
assert.ok(recEncrypted.msg.data.endsWith('.box'), '.box')
const msgDecrypted = peer.db.get(recEncrypted.id)
assert.equal(msgDecrypted.data.text, 'I am chewing food')
})
test('feed.publish() with tangles', async (t) => {
const recA = await p(peer.db.feed.publish)({
account: id,
domain: 'comment',
data: { text: 'I am root' },
})
assert.equal(recA.msg.data.text, 'I am root', 'root text correct')
const recB = await p(peer.db.feed.publish)({
account: id,
domain: 'comment',
data: { text: 'I am comment 1' },
tangles: [recA.id],
keypair: bobKeypair,
})
assert.equal(recB.msg.metadata.tangles[recA.id].depth, 1, 'tangle depth 1')
assert.deepEqual(
recB.msg.metadata.tangles[recA.id].prev,
[recA.id],
'tangle prev'
)
})
test('teardown', (t) => {
peer.close(t.end)
await t.test('merges tangle after a forked add()', async (t) => {
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
tangle.add(rec1.id, rec1.msg)
const msg3 = MsgV3.create({
keypair,
account: id,
accountTips: [id],
domain: 'post',
data: { text: '3rd post forked from 1st' },
tangles: {
[mootID]: tangle,
},
})
const rec3 = await p(peer.db.add)(msg3, mootID)
const msgID3 = MsgV3.getMsgID(rec3.msg)
const rec4 = await p(peer.db.feed.publish)({
account: id,
domain: 'post',
data: { text: 'I am 4th post' },
})
assert.ok(rec4, '4th post published')
assert.equal(
rec4.msg.metadata.tangles[mootID].prev.length,
3,
'msg4 prev has 3' // is root, msg2 and msg3'
)
assert.ok(
rec4.msg.metadata.tangles[mootID].prev.includes(mootID),
'msg4 prev has root'
)
assert.ok(
rec4.msg.metadata.tangles[mootID].prev.includes(msgID2),
'msg4 prev has msg2'
)
assert.ok(
rec4.msg.metadata.tangles[mootID].prev.includes(msgID3),
'msg4 prev has msg3'
)
})
await t.test('publish encrypted with box', async (t) => {
const recEncrypted = await p(peer.db.feed.publish)({
account: id,
domain: 'post',
data: { text: 'I am chewing food', recps: [keypair.public] },
encryptionFormat: 'box',
})
assert.equal(typeof recEncrypted.msg.data, 'string')
assert.ok(recEncrypted.msg.data.endsWith('.box'), '.box')
const msgDecrypted = peer.db.get(recEncrypted.id)
assert.equal(msgDecrypted.data.text, 'I am chewing food')
})
await t.test('publish with tangles', async (t) => {
const recA = await p(peer.db.feed.publish)({
account: id,
domain: 'comment',
data: { text: 'I am root' },
})
assert.equal(recA.msg.data.text, 'I am root', 'root text correct')
const recB = await p(peer.db.feed.publish)({
account: id,
domain: 'comment',
data: { text: 'I am comment 1' },
tangles: [recA.id],
keypair: bobKeypair,
})
assert.equal(recB.msg.metadata.tangles[recA.id].depth, 1, 'tangle depth 1')
assert.deepEqual(
recB.msg.metadata.tangles[recA.id].prev,
[recA.id],
'tangle prev'
)
})
await p(peer.close)(true)
})

View File

@ -12,34 +12,27 @@ const MsgV3 = require('../lib/msg-v3')
const DIR = path.join(os.tmpdir(), 'ppppp-db-get')
rimraf.sync(DIR)
const keypair = Keypair.generate('ed25519', 'alice')
let peer
let id
let msgID1
test('setup', async (t) => {
peer = SecretStack({ appKey: caps.shse })
test('get()', async (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair, path: DIR })
await peer.db.loaded()
id = (await p(peer.db.account.create)({domain: 'person'}))
const id = await p(peer.db.account.create)({ domain: 'person' })
const rec1 = await p(peer.db.feed.publish)({
account: id,
domain: 'post',
data: { text: 'I am 1st post' },
})
msgID1 = MsgV3.getMsgID(rec1.msg)
})
const msgID1 = MsgV3.getMsgID(rec1.msg)
test('get() supports msg IDs', async (t) => {
const msg = peer.db.get(msgID1)
assert.ok(msg, 'msg exists')
assert.equal(msg.data.text, 'I am 1st post')
})
test('teardown', (t) => {
peer.close(t.end)
await p(peer.close)(true)
})

View File

@ -11,263 +11,280 @@ const Keypair = require('ppppp-keypair')
const DIR = path.join(os.tmpdir(), 'ppppp-db-tangle')
rimraf.sync(DIR)
let peer
let rootPost, reply1Lo, reply1Hi, reply2, reply3Lo, reply3Hi
let tangle
test('setup', async (t) => {
const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob')
const keypairC = Keypair.generate('ed25519', 'carol')
test('getTangle()', async (t) => {
let peer
let rootPost, reply1Lo, reply1Hi, reply2, reply3Lo, reply3Hi
let tangle
peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypairA, path: DIR })
// Setup
{
const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob')
const keypairC = Keypair.generate('ed25519', 'carol')
await peer.db.loaded()
peer = SecretStack({ appKey: caps.shse })
.use(require('../lib'))
.use(require('ssb-box'))
.call(null, { keypair: keypairA, path: DIR })
const id = await p(peer.db.account.create)({ domain: 'person' })
await peer.db.loaded()
// Slow down append so that we can trigger msg creation in parallel
const originalAppend = peer.db._getLog().append
peer.db._getLog().append = function (...args) {
setTimeout(originalAppend, 20, ...args)
const id = await p(peer.db.account.create)({ domain: 'person' })
// Slow down append so that we can trigger msg creation in parallel
const originalAppend = peer.db._getLog().append
peer.db._getLog().append = function (...args) {
setTimeout(originalAppend, 20, ...args)
}
rootPost = (
await p(peer.db.feed.publish)({
account: id,
keypair: keypairA,
domain: 'comment',
data: { text: 'root' },
})
).id
const [{ id: reply1B }, { id: reply1C }] = await Promise.all([
p(peer.db.feed.publish)({
account: id,
keypair: keypairB,
domain: 'comment',
data: { text: 'reply 1B' },
tangles: [rootPost],
}),
p(peer.db.feed.publish)({
account: id,
keypair: keypairC,
domain: 'comment',
data: { text: 'reply 1C' },
tangles: [rootPost],
}),
])
reply1Lo = reply1B.localeCompare(reply1C) < 0 ? reply1B : reply1C
reply1Hi = reply1B.localeCompare(reply1C) < 0 ? reply1C : reply1B
reply2 = (
await p(peer.db.feed.publish)({
account: id,
keypair: keypairA,
domain: 'comment',
data: { text: 'reply 2' },
tangles: [rootPost],
})
).id
const [{ id: reply3B }, { id: reply3C }] = await Promise.all([
p(peer.db.feed.publish)({
account: id,
keypair: keypairB,
domain: 'comment',
data: { text: 'reply 3B' },
tangles: [rootPost],
}),
p(peer.db.feed.publish)({
account: id,
keypair: keypairC,
domain: 'comment',
data: { text: 'reply 3C' },
tangles: [rootPost],
}),
])
reply3Lo = reply3B.localeCompare(reply3C) < 0 ? reply3B : reply3C
reply3Hi = reply3B.localeCompare(reply3C) < 0 ? reply3C : reply3B
tangle = peer.db.getTangle(rootPost)
}
rootPost = (
await p(peer.db.feed.publish)({
account: id,
keypair: keypairA,
domain: 'comment',
data: { text: 'root' },
})
).id
await t.test('Tangle.has', (t) => {
assert.equal(tangle.has(rootPost), true, 'has rootPost')
assert.equal(tangle.has(reply1Lo), true, 'has reply1Lo')
assert.equal(tangle.has(reply1Hi), true, 'has reply1Hi')
assert.equal(tangle.has(reply2), true, 'has reply2A')
assert.equal(tangle.has(reply3Lo), true, 'has reply3Lo')
assert.equal(tangle.has(reply3Hi), true, 'has reply3Hi')
assert.equal(tangle.has('nonsense'), false, 'does not have nonsense')
})
const [{ id: reply1B }, { id: reply1C }] = await Promise.all([
p(peer.db.feed.publish)({
account: id,
keypair: keypairB,
domain: 'comment',
data: { text: 'reply 1B' },
tangles: [rootPost],
}),
p(peer.db.feed.publish)({
account: id,
keypair: keypairC,
domain: 'comment',
data: { text: 'reply 1C' },
tangles: [rootPost],
}),
])
reply1Lo = reply1B.localeCompare(reply1C) < 0 ? reply1B : reply1C
reply1Hi = reply1B.localeCompare(reply1C) < 0 ? reply1C : reply1B
await t.test('Tangle.getDepth', (t) => {
assert.equal(tangle.getDepth(rootPost), 0, 'depth of rootPost is 0')
assert.equal(tangle.getDepth(reply1Lo), 1, 'depth of reply1Lo is 1')
assert.equal(tangle.getDepth(reply1Hi), 1, 'depth of reply1Hi is 1')
assert.equal(tangle.getDepth(reply2), 2, 'depth of reply2A is 2')
assert.equal(tangle.getDepth(reply3Lo), 3, 'depth of reply3Lo is 3')
assert.equal(tangle.getDepth(reply3Hi), 3, 'depth of reply3Hi is 3')
})
reply2 = (
await p(peer.db.feed.publish)({
account: id,
keypair: keypairA,
domain: 'comment',
data: { text: 'reply 2' },
tangles: [rootPost],
})
).id
await t.test('Tangle.maxDepth', (t) => {
assert.equal(tangle.maxDepth, 3, 'max depth is 3')
})
const [{ id: reply3B }, { id: reply3C }] = await Promise.all([
p(peer.db.feed.publish)({
account: id,
keypair: keypairB,
domain: 'comment',
data: { text: 'reply 3B' },
tangles: [rootPost],
}),
p(peer.db.feed.publish)({
account: id,
keypair: keypairC,
domain: 'comment',
data: { text: 'reply 3C' },
tangles: [rootPost],
}),
])
reply3Lo = reply3B.localeCompare(reply3C) < 0 ? reply3B : reply3C
reply3Hi = reply3B.localeCompare(reply3C) < 0 ? reply3C : reply3B
await t.test('Tangle.topoSort', (t) => {
const sorted = tangle.topoSort()
tangle = peer.db.getTangle(rootPost)
})
assert.deepEqual(sorted, [
rootPost,
reply1Lo,
reply1Hi,
reply2,
reply3Lo,
reply3Hi,
])
})
test('Tangle.has', (t) => {
assert.equal(tangle.has(rootPost), true, 'has rootPost')
assert.equal(tangle.has(reply1Lo), true, 'has reply1Lo')
assert.equal(tangle.has(reply1Hi), true, 'has reply1Hi')
assert.equal(tangle.has(reply2), true, 'has reply2A')
assert.equal(tangle.has(reply3Lo), true, 'has reply3Lo')
assert.equal(tangle.has(reply3Hi), true, 'has reply3Hi')
assert.equal(tangle.has('nonsense'), false, 'does not have nonsense')
})
await t.test('Tangle.precedes', (t) => {
assert.equal(
tangle.precedes(rootPost, reply1Lo),
true,
'rootPost precedes reply1Lo'
)
assert.equal(
tangle.precedes(rootPost, reply1Hi),
true,
'rootPost precedes reply1Hi'
)
assert.equal(
tangle.precedes(reply1Hi, rootPost),
false,
'reply1Hi doesnt precede rootPost'
)
assert.equal(
tangle.precedes(reply1Lo, reply1Hi),
false,
'reply1Lo doesnt precede reply1Hi'
)
assert.equal(
tangle.precedes(reply1Lo, reply1Lo),
false,
'reply1Lo doesnt precede itself'
)
assert.equal(
tangle.precedes(reply1Lo, reply3Hi),
true,
'reply1Lo precedes reply3Hi'
)
assert.equal(
tangle.precedes(reply1Hi, reply2),
true,
'reply1Hi precedes reply2A'
)
assert.equal(
tangle.precedes(reply3Lo, reply1Hi),
false,
'reply3Lo doesnt precede reply1Hi'
)
})
test('Tangle.getDepth', (t) => {
assert.equal(tangle.getDepth(rootPost), 0, 'depth of rootPost is 0')
assert.equal(tangle.getDepth(reply1Lo), 1, 'depth of reply1Lo is 1')
assert.equal(tangle.getDepth(reply1Hi), 1, 'depth of reply1Hi is 1')
assert.equal(tangle.getDepth(reply2), 2, 'depth of reply2A is 2')
assert.equal(tangle.getDepth(reply3Lo), 3, 'depth of reply3Lo is 3')
assert.equal(tangle.getDepth(reply3Hi), 3, 'depth of reply3Hi is 3')
})
await t.test('Tangle.tips', (t) => {
const tips = tangle.tips
test('Tangle.maxDepth', (t) => {
assert.equal(tangle.maxDepth, 3, 'max depth is 3')
})
assert.equal(tips.size, 2, 'there are 2 tips')
assert.equal(tips.has(reply3Lo), true, 'tips contains reply3Lo')
assert.equal(tips.has(reply3Hi), true, 'tips contains reply3Hi')
})
test('Tangle.topoSort', (t) => {
const sorted = tangle.topoSort()
await t.test('Tangle.getLipmaaSet', (t) => {
assert.equal(tangle.getLipmaaSet(0).size, 0, 'lipmaa 0 (empty)')
assert.deepEqual(sorted, [
rootPost,
reply1Lo,
reply1Hi,
reply2,
reply3Lo,
reply3Hi,
])
})
assert.equal(tangle.getLipmaaSet(1).size, 1, 'lipmaa 1 (-1)')
assert.equal(tangle.getLipmaaSet(1).has(rootPost), true, 'lipmaa 1 (-1)')
test('Tangle.precedes', (t) => {
assert.equal(
tangle.precedes(rootPost, reply1Lo),
true,
'rootPost precedes reply1Lo'
)
assert.equal(
tangle.precedes(rootPost, reply1Hi),
true,
'rootPost precedes reply1Hi'
)
assert.equal(
tangle.precedes(reply1Hi, rootPost),
false,
'reply1Hi doesnt precede rootPost'
)
assert.equal(
tangle.precedes(reply1Lo, reply1Hi),
false,
'reply1Lo doesnt precede reply1Hi'
)
assert.equal(
tangle.precedes(reply1Lo, reply1Lo),
false,
'reply1Lo doesnt precede itself'
)
assert.equal(
tangle.precedes(reply1Lo, reply3Hi),
true,
'reply1Lo precedes reply3Hi'
)
assert.equal(
tangle.precedes(reply1Hi, reply2),
true,
'reply1Hi precedes reply2A'
)
assert.equal(
tangle.precedes(reply3Lo, reply1Hi),
false,
'reply3Lo doesnt precede reply1Hi'
)
})
assert.equal(tangle.getLipmaaSet(2).size, 2, 'lipmaa 2 (-1)')
assert.equal(tangle.getLipmaaSet(2).has(reply1Lo), true, 'lipmaa 2 (-1)')
assert.equal(tangle.getLipmaaSet(2).has(reply1Hi), true, 'lipmaa 2 (-1)')
test('Tangle.tips', (t) => {
const tips = tangle.tips
assert.equal(tangle.getLipmaaSet(3).size, 1, 'lipmaa 3 (leap!)')
assert.equal(tangle.getLipmaaSet(3).has(rootPost), true, 'lipmaa 3 (leap!)')
assert.equal(tips.size, 2, 'there are 2 tips')
assert.equal(tips.has(reply3Lo), true, 'tips contains reply3Lo')
assert.equal(tips.has(reply3Hi), true, 'tips contains reply3Hi')
})
assert.equal(tangle.getLipmaaSet(4).size, 2, 'lipmaa 4 (-1)')
assert.equal(tangle.getLipmaaSet(4).has(reply3Lo), true, 'lipmaa 4 (-1)')
assert.equal(tangle.getLipmaaSet(4).has(reply3Hi), true, 'lipmaa 4 (-1)')
test('Tangle.getLipmaaSet', (t) => {
assert.equal(tangle.getLipmaaSet(0).size, 0, 'lipmaa 0 (empty)')
assert.equal(tangle.getLipmaaSet(5).size, 0, 'lipmaa 5 (empty)')
})
assert.equal(tangle.getLipmaaSet(1).size, 1, 'lipmaa 1 (-1)')
assert.equal(tangle.getLipmaaSet(1).has(rootPost), true, 'lipmaa 1 (-1)')
await t.test('Tangle.getDeletablesAndErasables basic', (t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(reply2)
assert.equal(tangle.getLipmaaSet(2).size, 2, 'lipmaa 2 (-1)')
assert.equal(tangle.getLipmaaSet(2).has(reply1Lo), true, 'lipmaa 2 (-1)')
assert.equal(tangle.getLipmaaSet(2).has(reply1Hi), true, 'lipmaa 2 (-1)')
assert.deepEqual([...deletables], [reply1Hi], 'deletables')
assert.deepEqual([...erasables], [reply1Lo, rootPost], 'erasables')
})
assert.equal(tangle.getLipmaaSet(3).size, 1, 'lipmaa 3 (leap!)')
assert.equal(tangle.getLipmaaSet(3).has(rootPost), true, 'lipmaa 3 (leap!)')
await t.test('Tangle.getDeletablesAndErasables with many inputs', (t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(
reply3Lo,
reply2
)
assert.equal(tangle.getLipmaaSet(4).size, 2, 'lipmaa 4 (-1)')
assert.equal(tangle.getLipmaaSet(4).has(reply3Lo), true, 'lipmaa 4 (-1)')
assert.equal(tangle.getLipmaaSet(4).has(reply3Hi), true, 'lipmaa 4 (-1)')
assert.deepEqual([...deletables], [reply1Hi], 'deletables')
assert.deepEqual([...erasables], [reply1Lo, rootPost], 'erasables')
})
assert.equal(tangle.getLipmaaSet(5).size, 0, 'lipmaa 5 (empty)')
})
await t.test(
'Tangle.getDeletablesAndErasables with many inputs again',
(t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(
reply3Lo,
reply3Hi
)
test('Tangle.getDeletablesAndErasables basic', (t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(reply2)
assert.deepEqual([...deletables], [reply1Hi], 'deletables')
assert.deepEqual([...erasables], [reply1Lo, rootPost], 'erasables')
})
test('Tangle.getDeletablesAndErasables with many inputs', (t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(
reply3Lo,
reply2
assert.deepEqual(
[...deletables],
[reply1Lo, reply1Hi, reply2],
'deletables'
)
assert.deepEqual([...erasables], [rootPost], 'erasables')
}
)
assert.deepEqual([...deletables], [reply1Hi], 'deletables')
assert.deepEqual([...erasables], [reply1Lo, rootPost], 'erasables')
})
await t.test('Tangle.getDeletablesAndErasables with lipmaa', (t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(reply3Lo)
test('Tangle.getDeletablesAndErasables with many inputs again', (t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(
reply3Lo,
reply3Hi
assert.deepEqual(
[...deletables],
[reply1Lo, reply1Hi, reply2],
'deletables'
)
assert.deepEqual([...erasables], [rootPost], 'erasables')
})
await t.test('Tangle.getMinimumAmong', (t) => {
const actual1 = tangle.getMinimumAmong([reply1Lo, reply1Hi])
const expected1 = [reply1Lo, reply1Hi]
assert.deepEqual(actual1, expected1)
const actual2 = tangle.getMinimumAmong([reply1Lo, reply1Hi, reply2])
const expected2 = [reply1Lo, reply1Hi]
assert.deepEqual(actual2, expected2)
const actual3 = tangle.getMinimumAmong([reply2, reply3Lo, reply3Hi])
const expected3 = [reply2]
assert.deepEqual(actual3, expected3)
const actual4 = tangle.getMinimumAmong([reply1Hi, reply3Lo])
const expected4 = [reply1Hi]
assert.deepEqual(actual4, expected4)
})
await t.test(
'Tangle.topoSort after some have been deleted and erased',
async (t) => {
const { deletables, erasables } =
tangle.getDeletablesAndErasables(reply3Lo)
for (const msgID of deletables) {
await p(peer.db.del)(msgID)
}
for (const msgID of erasables) {
await p(peer.db.erase)(msgID)
}
const tangle2 = peer.db.getTangle(rootPost)
const sorted = tangle2.topoSort()
assert.deepEqual(sorted, [rootPost, reply3Lo, reply3Hi])
}
)
assert.deepEqual([...deletables], [reply1Lo, reply1Hi, reply2], 'deletables')
assert.deepEqual([...erasables], [rootPost], 'erasables')
})
test('Tangle.getDeletablesAndErasables with lipmaa', (t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(reply3Lo)
assert.deepEqual([...deletables], [reply1Lo, reply1Hi, reply2], 'deletables')
assert.deepEqual([...erasables], [rootPost], 'erasables')
})
test('Tangle.getMinimumAmong', (t) => {
const actual1 = tangle.getMinimumAmong([reply1Lo, reply1Hi])
const expected1 = [reply1Lo, reply1Hi]
assert.deepEqual(actual1, expected1)
const actual2 = tangle.getMinimumAmong([reply1Lo, reply1Hi, reply2])
const expected2 = [reply1Lo, reply1Hi]
assert.deepEqual(actual2, expected2)
const actual3 = tangle.getMinimumAmong([reply2, reply3Lo, reply3Hi])
const expected3 = [reply2]
assert.deepEqual(actual3, expected3)
const actual4 = tangle.getMinimumAmong([reply1Hi, reply3Lo])
const expected4 = [reply1Hi]
assert.deepEqual(actual4, expected4)
})
test('Tangle.topoSort after some have been deleted and erased', async (t) => {
const { deletables, erasables } = tangle.getDeletablesAndErasables(reply3Lo)
for (const msgID of deletables) {
await p(peer.db.del)(msgID)
}
for (const msgID of erasables) {
await p(peer.db.erase)(msgID)
}
const tangle2 = peer.db.getTangle(rootPost)
const sorted = tangle2.topoSort()
assert.deepEqual(sorted, [rootPost, reply3Lo, reply3Hi])
})
test('teardown', async (t) => {
await p(peer.close)(true)
})

View File

@ -4,74 +4,76 @@ const fs = require('node:fs')
const p = require('node:util').promisify
const Log = require('../../lib/log')
test('Log handles basic binary records', async function (t) {
const file = '/tmp/ppppp-db-log-test-basic-binary.log'
try {
fs.unlinkSync(file)
} catch (_) {}
const log = Log(file, { blockSize: 2 * 1024 })
test('Log basics', async function (t) {
await t.test('Log handles basic binary records', async function (t) {
const file = '/tmp/ppppp-db-log-test-basic-binary.log'
try {
fs.unlinkSync(file)
} catch (_) {}
const log = Log(file, { blockSize: 2 * 1024 })
const msg1 = Buffer.from('testing')
const msg2 = Buffer.from('testing2')
const msg1 = Buffer.from('testing')
const msg2 = Buffer.from('testing2')
const offset1 = await p(log.append)(msg1)
assert.equal(offset1, 0)
const offset1 = await p(log.append)(msg1)
assert.equal(offset1, 0)
const offset2 = await p(log.append)(msg2)
assert.equal(offset2, msg1.length + 2)
const offset2 = await p(log.append)(msg2)
assert.equal(offset2, msg1.length + 2)
const b1 = await p(log._get)(offset1)
assert.equal(b1.toString(), msg1.toString())
const b1 = await p(log._get)(offset1)
assert.equal(b1.toString(), msg1.toString())
const b2 = await p(log._get)(offset2)
assert.equal(b2.toString(), msg2.toString())
const b2 = await p(log._get)(offset2)
assert.equal(b2.toString(), msg2.toString())
await p(log.close)()
})
const json1 = { text: 'testing' }
const json2 = { test: 'testing2' }
test('Log handles basic json records', async function (t) {
const file = '/tmp/ppppp-db-log-test-basic-json.log'
try {
fs.unlinkSync(file)
} catch (_) {}
const log = Log(file, {
blockSize: 2 * 1024,
codec: require('flumecodec/json'),
await p(log.close)()
})
const offset1 = await p(log.append)(json1)
assert.equal(offset1, 0)
const json1 = { text: 'testing' }
const json2 = { test: 'testing2' }
const offset2 = await p(log.append)(json2)
assert.equal(offset2, 20)
await t.test('Log handles basic json records', async function (t) {
const file = '/tmp/ppppp-db-log-test-basic-json.log'
try {
fs.unlinkSync(file)
} catch (_) {}
const log = Log(file, {
blockSize: 2 * 1024,
codec: require('flumecodec/json'),
})
const rec1 = await p(log._get)(offset1)
assert.deepEqual(rec1, json1)
const offset1 = await p(log.append)(json1)
assert.equal(offset1, 0)
const rec2 = await p(log._get)(offset2)
assert.deepEqual(rec2, json2)
const offset2 = await p(log.append)(json2)
assert.equal(offset2, 20)
await p(log.close)()
})
const rec1 = await p(log._get)(offset1)
assert.deepEqual(rec1, json1)
test('Log handles basic json record re-reading', async function (t) {
const file = '/tmp/ppppp-db-log-test-basic-json.log'
const log = Log(file, {
blockSize: 2 * 1024,
codec: require('flumecodec/json'),
const rec2 = await p(log._get)(offset2)
assert.deepEqual(rec2, json2)
await p(log.close)()
})
await p(log.onDrain)()
assert.equal(log.since.value, 20)
await t.test('Log handles basic json record re-reading', async function (t) {
const file = '/tmp/ppppp-db-log-test-basic-json.log'
const log = Log(file, {
blockSize: 2 * 1024,
codec: require('flumecodec/json'),
})
const rec1 = await p(log._get)(0)
assert.deepEqual(rec1, json1)
await p(log.onDrain)()
assert.equal(log.since.value, 20)
const rec2 = await p(log._get)(20)
assert.deepEqual(rec2, json2)
const rec1 = await p(log._get)(0)
assert.deepEqual(rec1, json1)
await p(log.close)()
const rec2 = await p(log._get)(20)
assert.deepEqual(rec2, json2)
await p(log.close)()
})
})

View File

@ -14,176 +14,178 @@ const msg3 = Buffer.from(
'hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db hello offsetty db'
)
test('Log performing simple delete', async (t) => {
const file = '/tmp/ppppp-db-log-test-del.log'
try {
fs.unlinkSync(file)
} catch (_) {}
const log = Log(file, { blockSize: 2 * 1024 })
test('Log deletes', async (t) => {
await t.test('Simple delete', async (t) => {
const file = '/tmp/ppppp-db-log-test-del.log'
try {
fs.unlinkSync(file)
} catch (_) {}
const log = Log(file, { blockSize: 2 * 1024 })
const offset1 = await p(log.append)(msg1)
assert.equal(offset1, 0)
const offset2 = await p(log.append)(msg2)
assert.ok(offset2 > offset1)
const offset3 = await p(log.append)(msg3)
assert.ok(offset3 > offset2)
const offset1 = await p(log.append)(msg1)
assert.equal(offset1, 0)
const offset2 = await p(log.append)(msg2)
assert.ok(offset2 > offset1)
const offset3 = await p(log.append)(msg3)
assert.ok(offset3 > offset2)
const buf1 = await p(log._get)(offset1)
assert.equal(buf1.toString(), msg1.toString())
const buf2 = await p(log._get)(offset2)
assert.equal(buf2.toString(), msg2.toString())
const buf3 = await p(log._get)(offset3)
assert.equal(buf3.toString(), msg3.toString())
const buf1 = await p(log._get)(offset1)
assert.equal(buf1.toString(), msg1.toString())
const buf2 = await p(log._get)(offset2)
assert.equal(buf2.toString(), msg2.toString())
const buf3 = await p(log._get)(offset3)
assert.equal(buf3.toString(), msg3.toString())
await p(log.del)(offset2)
await p(log.onDeletesFlushed)()
await assert.rejects(p(log._get)(offset2), (err) => {
assert.ok(err)
assert.equal(err.message, 'Record has been deleted')
assert.equal(err.code, 'ERR_AAOL_DELETED_RECORD')
return true
await p(log.del)(offset2)
await p(log.onDeletesFlushed)()
await assert.rejects(p(log._get)(offset2), (err) => {
assert.ok(err)
assert.equal(err.message, 'Record has been deleted')
assert.equal(err.code, 'ERR_AAOL_DELETED_RECORD')
return true
})
await p(log.close)()
})
await p(log.close)()
})
await t.test('Deleted records are not invalid upon re-opening', async (t) => {
const file = '/tmp/ppppp-db-log-test-del-invalid.log'
try {
fs.unlinkSync(file)
} catch (_) {}
test('Log deleted records are not invalid upon re-opening', async (t) => {
const file = '/tmp/ppppp-db-log-test-del-invalid.log'
try {
fs.unlinkSync(file)
} catch (_) {}
const opts = {
blockSize: 2 * 1024,
codec: {
encode(msg) {
return Buffer.from(JSON.stringify(msg), 'utf8')
const opts = {
blockSize: 2 * 1024,
codec: {
encode(msg) {
return Buffer.from(JSON.stringify(msg), 'utf8')
},
decode(buf) {
return JSON.parse(buf.toString('utf8'))
},
},
decode(buf) {
return JSON.parse(buf.toString('utf8'))
},
},
validateRecord(buf) {
try {
JSON.parse(buf.toString('utf8'))
return true
} catch {
return false
}
},
}
const log = Log(file, opts)
const offset1 = await p(log.append)({ text: 'm0' })
const offset2 = await p(log.append)({ text: 'm1' })
const offset3 = await p(log.append)({ text: 'm2' })
await p(log.del)(offset2)
await p(log.onDeletesFlushed)()
await p(log.close)()
const log2 = Log(file, opts)
let arr = []
await new Promise((resolve) => {
log2.scan(
(offset, value, size) => {
arr.push(value)
},
(err) => {
assert.ifError(err)
assert.deepEqual(arr, [{ text: 'm0' }, null, { text: 'm2' }])
resolve()
}
)
})
await assert.rejects(p(log2._get)(offset2), (err) => {
assert.ok(err)
assert.equal(err.message, 'Record has been deleted')
assert.equal(err.code, 'ERR_AAOL_DELETED_RECORD')
return true
})
await p(log2.close)()
})
test('Log deletes are handled by scan()', async (t) => {
const file = '/tmp/offset-test_' + Date.now() + '.log'
const log = Log(file, { blockSize: 64 * 1024 })
const buf1 = Buffer.from('hello one')
const buf2 = Buffer.from('hello two')
const offset1 = await p(log.append)(buf1)
const offset2 = await p(log.append)(buf2)
await p(log.del)(offset1)
await p(log.onDrain)()
await p(log.onDeletesFlushed)()
const arr = []
await new Promise((resolve) => {
log.scan(
(offset, rec, length) => {
arr.push(rec)
},
(err) => {
assert.ifError(err)
resolve()
}
)
})
assert.deepEqual(arr, [null, buf2])
await p(log.close)()
})
test('Log can handle many deleted records', { timeout: 60e3 }, async (t) => {
const file = '/tmp/aaol-test-delete-many' + Date.now() + '.log'
const log = Log(file, { blockSize: 64 * 1024 })
const TOTAL = 100000
const offsets = []
const logAppend = p(log.append)
if (process.env.VERBOSE) console.time('append ' + TOTAL)
for (let i = 0; i < TOTAL; i += 1) {
const offset = await logAppend(Buffer.from(`hello ${i}`))
offsets.push(offset)
}
assert('appended records')
if (process.env.VERBOSE) console.timeEnd('append ' + TOTAL)
await p(log.onDrain)()
const logDel = p(log.del)
if (process.env.VERBOSE) console.time('delete ' + TOTAL / 2)
for (let i = 0; i < TOTAL; i += 2) {
await logDel(offsets[i])
}
if (process.env.VERBOSE) console.timeEnd('delete ' + TOTAL / 2)
assert('deleted messages')
await p(log.onDeletesFlushed)()
await new Promise((resolve) => {
let i = 0
log.scan(
(offset, rec, length) => {
if (i % 2 === 0) {
if (rec !== null) assert.fail('record ' + i + ' should be deleted')
} else {
if (rec === null) assert.fail('record ' + i + ' should be present')
validateRecord(buf) {
try {
JSON.parse(buf.toString('utf8'))
return true
} catch {
return false
}
i += 1
},
(err) => {
assert.ifError(err)
resolve()
}
)
}
const log = Log(file, opts)
const offset1 = await p(log.append)({ text: 'm0' })
const offset2 = await p(log.append)({ text: 'm1' })
const offset3 = await p(log.append)({ text: 'm2' })
await p(log.del)(offset2)
await p(log.onDeletesFlushed)()
await p(log.close)()
const log2 = Log(file, opts)
let arr = []
await new Promise((resolve) => {
log2.scan(
(offset, value, size) => {
arr.push(value)
},
(err) => {
assert.ifError(err)
assert.deepEqual(arr, [{ text: 'm0' }, null, { text: 'm2' }])
resolve()
}
)
})
await assert.rejects(p(log2._get)(offset2), (err) => {
assert.ok(err)
assert.equal(err.message, 'Record has been deleted')
assert.equal(err.code, 'ERR_AAOL_DELETED_RECORD')
return true
})
await p(log2.close)()
})
await p(log.close)()
await t.test('Deletes are noticed by scan()', async (t) => {
const file = '/tmp/offset-test_' + Date.now() + '.log'
const log = Log(file, { blockSize: 64 * 1024 })
const buf1 = Buffer.from('hello one')
const buf2 = Buffer.from('hello two')
const offset1 = await p(log.append)(buf1)
const offset2 = await p(log.append)(buf2)
await p(log.del)(offset1)
await p(log.onDrain)()
await p(log.onDeletesFlushed)()
const arr = []
await new Promise((resolve) => {
log.scan(
(offset, rec, length) => {
arr.push(rec)
},
(err) => {
assert.ifError(err)
resolve()
}
)
})
assert.deepEqual(arr, [null, buf2])
await p(log.close)()
})
await t.test('Many deleted records', { timeout: 60e3 }, async (t) => {
const file = '/tmp/aaol-test-delete-many' + Date.now() + '.log'
const log = Log(file, { blockSize: 64 * 1024 })
const TOTAL = 100000
const offsets = []
const logAppend = p(log.append)
if (process.env.VERBOSE) console.time('append ' + TOTAL)
for (let i = 0; i < TOTAL; i += 1) {
const offset = await logAppend(Buffer.from(`hello ${i}`))
offsets.push(offset)
}
assert('appended records')
if (process.env.VERBOSE) console.timeEnd('append ' + TOTAL)
await p(log.onDrain)()
const logDel = p(log.del)
if (process.env.VERBOSE) console.time('delete ' + TOTAL / 2)
for (let i = 0; i < TOTAL; i += 2) {
await logDel(offsets[i])
}
if (process.env.VERBOSE) console.timeEnd('delete ' + TOTAL / 2)
assert('deleted messages')
await p(log.onDeletesFlushed)()
await new Promise((resolve) => {
let i = 0
log.scan(
(offset, rec, length) => {
if (i % 2 === 0) {
if (rec !== null) assert.fail('record ' + i + ' should be deleted')
} else {
if (rec === null) assert.fail('record ' + i + ' should be present')
}
i += 1
},
(err) => {
assert.ifError(err)
resolve()
}
)
})
await p(log.close)()
})
})

View File

@ -9,58 +9,60 @@ var file = '/tmp/ds-test_restart.log'
var msg1 = { text: 'hello world hello world' }
var msg2 = { text: 'hello world hello world 2' }
test('Log (fix buggy write) simple', async (t) => {
try {
fs.unlinkSync(file)
} catch (_) {}
const log = Log(file, {
block: 16 * 1024,
codec: require('flumecodec/json'),
test('Log fix buggy write', async (t) => {
await t.test('Simple', async (t) => {
try {
fs.unlinkSync(file)
} catch (_) {}
const log = Log(file, {
block: 16 * 1024,
codec: require('flumecodec/json'),
})
const offset1 = await p(log.append)(msg1)
assert.equal(offset1, 0)
const offset2 = await p(log.append)(msg2)
assert.equal(offset2, 36)
await p(log.onDrain)()
let arr = []
await new Promise((resolve) => {
log.scan(
(offset, msg, size) => {
arr.push(msg)
},
(err) => {
assert.ifError(err)
resolve()
}
)
})
assert.deepEqual(arr, [msg1, msg2])
await p(log.close)()
})
const offset1 = await p(log.append)(msg1)
assert.equal(offset1, 0)
const offset2 = await p(log.append)(msg2)
assert.equal(offset2, 36)
await t.test('Re-read', async (t) => {
const log = Log(file, {
block: 16 * 1024,
codec: require('flumecodec/json'),
})
await p(log.onDrain)()
let arr = []
await new Promise((resolve) => {
log.scan(
(offset, msg, size) => {
arr.push(msg)
},
(err) => {
assert.ifError(err)
resolve()
}
)
await p(log.onDrain)()
let arr = []
await new Promise((resolve) => {
log.scan(
(offset, msg, size) => {
arr.push(msg)
},
(err) => {
assert.ifError(err)
resolve()
}
)
})
assert.deepEqual(arr, [msg1, msg2])
await p(log.close)()
})
assert.deepEqual(arr, [msg1, msg2])
await p(log.close)()
})
test('Log (fix buggy write) reread', async (t) => {
const log = Log(file, {
block: 16 * 1024,
codec: require('flumecodec/json'),
})
await p(log.onDrain)()
let arr = []
await new Promise((resolve) => {
log.scan(
(offset, msg, size) => {
arr.push(msg)
},
(err) => {
assert.ifError(err)
resolve()
}
)
})
assert.deepEqual(arr, [msg1, msg2])
await p(log.close)()
})

View File

@ -3,82 +3,84 @@ const assert = require('node:assert')
const Keypair = require('ppppp-keypair')
const MsgV3 = require('../../lib/msg-v3')
test('MsgV3 invalid domain not a string', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
test('MsgV3 domain validation', async (t) => {
await t.test('Not a string', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 123,
})
},
/invalid domain/,
'not a string'
)
})
test('MsgV3 invalid domain with "/" character', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 'group/init',
})
},
/invalid domain/,
'invalid domain if contains /'
)
})
test('MsgV3 invalid domain with "*" character', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 'star*',
})
},
/invalid domain/,
'invalid domain if contains *'
)
})
test('MsgV3 invalid domain too short', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 'xy',
})
},
/shorter than 3/,
'invalid domain if too short'
)
})
test('MsgV3 invalid domain too long', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 'a'.repeat(120),
})
},
/100\+ characters long/,
'invalid domain if too long'
)
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 123,
})
},
/invalid domain/,
'not a string'
)
})
await t.test('"/" character', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 'group/init',
})
},
/invalid domain/,
'invalid domain if contains /'
)
})
await t.test('"*" character', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 'star*',
})
},
/invalid domain/,
'invalid domain if contains *'
)
})
await t.test('Too short', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 'xy',
})
},
/shorter than 3/,
'invalid domain if too short'
)
})
await t.test('too long', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
assert.throws(
() => {
MsgV3.create({
keypair,
data: { text: 'Hello world!' },
domain: 'a'.repeat(120),
})
},
/100\+ characters long/,
'invalid domain if too long'
)
})
})

View File

@ -10,338 +10,340 @@ const account = MsgV3.getMsgID(
)
const pubkeys = new Set([keypair.public])
test('MsgV3 invalid msg with non-array prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
test('MsgV3 tangles prev validation', async (t) => {
await t.test('Non-array is a bad prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
const msg = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
msg.metadata.tangles[mootID].prev = null
const msgID = MsgV3.getMsgID(msg)
const err = MsgV3.validate(msg, tangle, pubkeys, msgID, mootID)
assert.ok(err, 'invalid 2nd msg throws')
assert.match(
err,
/prev ".*" should have been an array/,
'invalid 2nd msg description'
)
})
msg.metadata.tangles[mootID].prev = null
const msgID = MsgV3.getMsgID(msg)
const err = MsgV3.validate(msg, tangle, pubkeys, msgID, mootID)
assert.ok(err, 'invalid 2nd msg throws')
assert.match(
err,
/prev ".*" should have been an array/,
'invalid 2nd msg description'
)
})
test('MsgV3 invalid msg with bad prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgID1, msg1)
const msg2 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
msg2.metadata.tangles[mootID].depth = 1
msg2.metadata.tangles[mootID].prev = [1234]
const msgID2 = MsgV3.getMsgID(msg2)
const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
assert.ok(err, 'invalid 2nd msg throws')
assert.match(
err,
/prev item ".*" should have been a string/,
'invalid 2nd msg description'
)
})
test('MsgV3 invalid msg with URI in prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgID1, msg1)
const msg2 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID2 = MsgV3.getMsgID(msg2)
const randBuf = Buffer.alloc(16).fill(16)
const fakeMsgKey1 = `ppppp:message/v3/${base58.encode(randBuf)}`
msg2.metadata.tangles[mootID].depth = 1
msg2.metadata.tangles[mootID].prev = [fakeMsgKey1]
const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
assert.ok(err, 'invalid 2nd msg throws')
assert.match(err, /prev item ".*" is a URI/, 'invalid 2nd msg description')
})
test('MsgV3 invalid msg with unknown prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgID1, msg1)
const unknownMsg = MsgV3.create({
keypair,
data: { text: 'Alien' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const unknownMsgID = MsgV3.getMsgID(unknownMsg)
const fakeMootID = 'ABCDEabcde' + mootID.substring(10)
const tangle2 = new MsgV3.Tangle(fakeMootID)
tangle2.add(fakeMootID, moot)
tangle2.add(unknownMsgID, unknownMsg)
const msg2 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle2,
},
})
const msgID2 = MsgV3.getMsgID(msg2)
const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
assert.ok(err, 'invalid 2nd msg throws')
assert.match(
err,
/all prev are locally unknown/,
'invalid 2nd msg description'
)
})
test('MsgV3 invalid feed msg with a different pubkey', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob')
const accountB = MsgV3.getMsgID(
MsgV3.createAccount(keypairB, 'person', 'MYNONCE')
)
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const feedTangle = new MsgV3.Tangle(mootID)
feedTangle.add(mootID, moot)
const msg = MsgV3.create({
keypair: keypairB,
data: { text: 'Hello world!' },
account: accountB,
accountTips: [accountB],
domain: 'post',
tangles: {
[mootID]: feedTangle,
},
})
const msgID = MsgV3.getMsgID(msg)
const err = MsgV3.validate(msg, feedTangle, pubkeys, msgID, mootID)
assert.ok(err, 'invalid msg throws')
assert.match(
err,
/pubkey ".*" should have been one of ".*" from the account ".*"/,
'invalid msg'
)
})
test('MsgV3 invalid feed msg with a different domain', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const feedTangle = new MsgV3.Tangle(mootID)
feedTangle.add(mootID, moot)
const msg = MsgV3.create({
keypair: keypairA,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'comment',
tangles: {
[mootID]: feedTangle,
},
})
const msgID = MsgV3.getMsgID(msg)
const err = MsgV3.validate(msg, feedTangle, pubkeys, msgID, mootID)
assert.ok(err, 'invalid msg throws')
assert.match(
err,
/domain "comment" should have been feed domain "post"/,
'invalid feed msg'
)
})
test('MsgV3 invalid feed msg with non-alphabetical prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: '1' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
const msg2 = MsgV3.create({
keypair,
data: { text: '2' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID2 = MsgV3.getMsgID(msg2)
tangle.add(msgID1, msg1)
tangle.add(msgID2, msg2)
const msg3 = MsgV3.create({
keypair,
data: { text: '3' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID3 = MsgV3.getMsgID(msg3)
let prevMsgIDs = msg3.metadata.tangles[mootID].prev
if (prevMsgIDs[0] < prevMsgIDs[1]) {
prevMsgIDs = [prevMsgIDs[1], prevMsgIDs[0]]
} else {
prevMsgIDs = [prevMsgIDs[0], prevMsgIDs[1]]
}
msg3.metadata.tangles[mootID].prev = prevMsgIDs
const err = MsgV3.validate(msg3, tangle, pubkeys, msgID3, mootID)
assert.ok(err, 'invalid 3rd msg throws')
assert.match(
err,
/prev ".*" should have been alphabetically sorted/,
'invalid error message'
)
})
test('MsgV3 invalid feed msg with duplicate prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: '1' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
const [prevID] = msg1.metadata.tangles[mootID].prev
msg1.metadata.tangles[mootID].prev = [prevID, prevID]
const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
assert.ok(err, 'invalid 1st msg throws')
assert.match(err, /prev ".*" contains duplicates/, 'invalid error message')
await t.test('Number not allowed in prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgID1, msg1)
const msg2 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
msg2.metadata.tangles[mootID].depth = 1
msg2.metadata.tangles[mootID].prev = [1234]
const msgID2 = MsgV3.getMsgID(msg2)
const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
assert.ok(err, 'invalid 2nd msg throws')
assert.match(
err,
/prev item ".*" should have been a string/,
'invalid 2nd msg description'
)
})
await t.test('URI not allowed in prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgID1, msg1)
const msg2 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID2 = MsgV3.getMsgID(msg2)
const randBuf = Buffer.alloc(16).fill(16)
const fakeMsgKey1 = `ppppp:message/v3/${base58.encode(randBuf)}`
msg2.metadata.tangles[mootID].depth = 1
msg2.metadata.tangles[mootID].prev = [fakeMsgKey1]
const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
assert.ok(err, 'invalid 2nd msg throws')
assert.match(err, /prev item ".*" is a URI/, 'invalid 2nd msg description')
})
await t.test('Locally unknown prev msgID', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgID1, msg1)
const unknownMsg = MsgV3.create({
keypair,
data: { text: 'Alien' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const unknownMsgID = MsgV3.getMsgID(unknownMsg)
const fakeMootID = 'ABCDEabcde' + mootID.substring(10)
const tangle2 = new MsgV3.Tangle(fakeMootID)
tangle2.add(fakeMootID, moot)
tangle2.add(unknownMsgID, unknownMsg)
const msg2 = MsgV3.create({
keypair,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle2,
},
})
const msgID2 = MsgV3.getMsgID(msg2)
const err = MsgV3.validate(msg2, tangle, pubkeys, msgID2, mootID)
assert.ok(err, 'invalid 2nd msg throws')
assert.match(
err,
/all prev are locally unknown/,
'invalid 2nd msg description'
)
})
await t.test('Feed msg with the wrong pubkey', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice')
const keypairB = Keypair.generate('ed25519', 'bob')
const accountB = MsgV3.getMsgID(
MsgV3.createAccount(keypairB, 'person', 'MYNONCE')
)
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const feedTangle = new MsgV3.Tangle(mootID)
feedTangle.add(mootID, moot)
const msg = MsgV3.create({
keypair: keypairB,
data: { text: 'Hello world!' },
account: accountB,
accountTips: [accountB],
domain: 'post',
tangles: {
[mootID]: feedTangle,
},
})
const msgID = MsgV3.getMsgID(msg)
const err = MsgV3.validate(msg, feedTangle, pubkeys, msgID, mootID)
assert.ok(err, 'invalid msg throws')
assert.match(
err,
/pubkey ".*" should have been one of ".*" from the account ".*"/,
'invalid msg'
)
})
await t.test('Feed msg with the wrong domain', (t) => {
const keypairA = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const feedTangle = new MsgV3.Tangle(mootID)
feedTangle.add(mootID, moot)
const msg = MsgV3.create({
keypair: keypairA,
data: { text: 'Hello world!' },
account,
accountTips: [account],
domain: 'comment',
tangles: {
[mootID]: feedTangle,
},
})
const msgID = MsgV3.getMsgID(msg)
const err = MsgV3.validate(msg, feedTangle, pubkeys, msgID, mootID)
assert.ok(err, 'invalid msg throws')
assert.match(
err,
/domain "comment" should have been feed domain "post"/,
'invalid feed msg'
)
})
await t.test('Feed msg with non-alphabetically sorted prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: '1' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
const msg2 = MsgV3.create({
keypair,
data: { text: '2' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID2 = MsgV3.getMsgID(msg2)
tangle.add(msgID1, msg1)
tangle.add(msgID2, msg2)
const msg3 = MsgV3.create({
keypair,
data: { text: '3' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID3 = MsgV3.getMsgID(msg3)
let prevMsgIDs = msg3.metadata.tangles[mootID].prev
if (prevMsgIDs[0] < prevMsgIDs[1]) {
prevMsgIDs = [prevMsgIDs[1], prevMsgIDs[0]]
} else {
prevMsgIDs = [prevMsgIDs[0], prevMsgIDs[1]]
}
msg3.metadata.tangles[mootID].prev = prevMsgIDs
const err = MsgV3.validate(msg3, tangle, pubkeys, msgID3, mootID)
assert.ok(err, 'invalid 3rd msg throws')
assert.match(
err,
/prev ".*" should have been alphabetically sorted/,
'invalid error message'
)
})
await t.test('Feed msg with duplicate prev', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
keypair,
data: { text: '1' },
account,
accountTips: [account],
domain: 'post',
tangles: {
[mootID]: tangle,
},
})
const msgID1 = MsgV3.getMsgID(msg1)
const [prevID] = msg1.metadata.tangles[mootID].prev
msg1.metadata.tangles[mootID].prev = [prevID, prevID]
const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
assert.ok(err, 'invalid 1st msg throws')
assert.match(err, /prev ".*" contains duplicates/, 'invalid error message')
})
})

View File

@ -3,165 +3,161 @@ const assert = require('node:assert')
const Keypair = require('ppppp-keypair')
const MsgV3 = require('../../lib/msg-v3')
test('MsgV3 validate root msg', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
test('MsgV3 validation', async (t) => {
await t.test('Correct root msg', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const err = MsgV3.validate(moot, tangle, pubkeys, mootID, mootID)
assert.ifError(err, 'valid root msg')
})
test('MsgV3 validate account tangle', (t) => {
const pubkeys = new Set()
const keypair1 = Keypair.generate('ed25519', 'alice')
pubkeys.add(keypair1.public)
const accountMsg0 = MsgV3.createAccount(keypair1, 'person', 'alice')
const account = MsgV3.getMsgID(accountMsg0)
const accountMsg0ID = account
const tangle = new MsgV3.Tangle(account)
tangle.add(accountMsg0ID, accountMsg0)
let err = MsgV3.validate(
accountMsg0,
tangle,
pubkeys,
accountMsg0ID,
account
)
assert.ifError(err, 'valid account root msg')
tangle.add(account, accountMsg0)
const keypair2 = Keypair.generate('ed25519', 'bob')
const accountMsg1 = MsgV3.create({
account: 'self',
accountTips: null,
domain: 'account',
data: { add: keypair2.public },
tangles: {
[account]: tangle,
},
keypair: keypair1, // announcing keypair2 but signing with keypair1
const err = MsgV3.validate(moot, tangle, pubkeys, mootID, mootID)
assert.ifError(err, 'valid root msg')
})
const accountMsg1ID = MsgV3.getMsgID(accountMsg1)
err = MsgV3.validate(
accountMsg1,
tangle,
pubkeys,
accountMsg1ID,
account
)
assert.ifError(err, 'valid account msg')
})
await t.test('Correct account tangle', (t) => {
const pubkeys = new Set()
const keypair1 = Keypair.generate('ed25519', 'alice')
pubkeys.add(keypair1.public)
test('MsgV3 validate 2nd msg with existing root', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
const accountMsg0 = MsgV3.createAccount(keypair1, 'person', 'alice')
const account = MsgV3.getMsgID(accountMsg0)
const accountMsg0ID = account
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const tangle = new MsgV3.Tangle(account)
tangle.add(accountMsg0ID, accountMsg0)
const msg1 = MsgV3.create({
account,
accountTips: [account],
domain: 'post',
data: { text: 'Hello world!' },
tangles: {
[mootID]: tangle,
},
keypair,
let err = MsgV3.validate(
accountMsg0,
tangle,
pubkeys,
accountMsg0ID,
account
)
assert.ifError(err, 'valid account root msg')
tangle.add(account, accountMsg0)
const keypair2 = Keypair.generate('ed25519', 'bob')
const accountMsg1 = MsgV3.create({
account: 'self',
accountTips: null,
domain: 'account',
data: { add: keypair2.public },
tangles: {
[account]: tangle,
},
keypair: keypair1, // announcing keypair2 but signing with keypair1
})
const accountMsg1ID = MsgV3.getMsgID(accountMsg1)
err = MsgV3.validate(accountMsg1, tangle, pubkeys, accountMsg1ID, account)
assert.ifError(err, 'valid account msg')
})
const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgID1, msg1)
const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
assert.ifError(err, 'valid 2nd msg')
})
await t.test('2nd msg correct with existing root', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
test('MsgV3 validate 2nd forked msg', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
account,
accountTips: [account],
domain: 'post',
data: { text: 'Hello world!' },
tangles: {
[mootID]: tangle,
},
keypair,
})
const msgID1 = MsgV3.getMsgID(msg1)
tangle.add(msgID1, msg1)
const msg1A = MsgV3.create({
account,
accountTips: [account],
domain: 'post',
data: { text: 'Hello world!' },
tangles: {
[mootID]: tangle,
},
keypair,
const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
assert.ifError(err, 'valid 2nd msg')
})
const msgID1A = MsgV3.getMsgID(msg1A)
const msg1B = MsgV3.create({
account,
accountTips: [account],
domain: 'post',
data: { text: 'Hello world!' },
tangles: {
[mootID]: tangle,
},
keypair,
await t.test('2nd forked msg correct', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1A = MsgV3.create({
account,
accountTips: [account],
domain: 'post',
data: { text: 'Hello world!' },
tangles: {
[mootID]: tangle,
},
keypair,
})
const msgID1A = MsgV3.getMsgID(msg1A)
const msg1B = MsgV3.create({
account,
accountTips: [account],
domain: 'post',
data: { text: 'Hello world!' },
tangles: {
[mootID]: tangle,
},
keypair,
})
const msgID1B = MsgV3.getMsgID(msg1B)
tangle.add(msgID1A, msg1A)
tangle.add(msgID1B, msg1B)
const err = MsgV3.validate(msg1B, tangle, pubkeys, msgID1B, mootID)
assert.ifError(err, 'valid 2nd forked msg')
})
const msgID1B = MsgV3.getMsgID(msg1B)
tangle.add(msgID1A, msg1A)
tangle.add(msgID1B, msg1B)
const err = MsgV3.validate(msg1B, tangle, pubkeys, msgID1B, mootID)
assert.ifError(err, 'valid 2nd forked msg')
})
await t.test('Correct erased msg', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
test('MsgV3 validate erased msg', (t) => {
const keypair = Keypair.generate('ed25519', 'alice')
const account = MsgV3.getMsgID(
MsgV3.createAccount(keypair, 'person', 'alice')
)
const pubkeys = new Set([keypair.public])
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const moot = MsgV3.createMoot(account, 'post', keypair)
const mootID = MsgV3.getMsgID(moot)
const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot)
const msg1 = MsgV3.create({
account,
accountTips: [account],
domain: 'post',
data: { text: 'Hello world!' },
tangles: {
[mootID]: tangle,
},
keypair,
})
msg1.data = null
const msgID1 = MsgV3.getMsgID(msg1)
const msg1 = MsgV3.create({
account,
accountTips: [account],
domain: 'post',
data: { text: 'Hello world!' },
tangles: {
[mootID]: tangle,
},
keypair,
const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
assert.ifError(err, 'valid erased msg')
})
msg1.data = null
const msgID1 = MsgV3.getMsgID(msg1)
const err = MsgV3.validate(msg1, tangle, pubkeys, msgID1, mootID)
assert.ifError(err, 'valid erased msg')
})