rename this package from record=>dict

This commit is contained in:
Andre Staltz 2023-10-26 13:15:28 +03:00
parent edaffa7626
commit 46dafa436e
No known key found for this signature in database
GPG Key ID: 9EDE23EA7E8A4890
6 changed files with 111 additions and 106 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@ node_modules
pnpm-lock.yaml pnpm-lock.yaml
package-lock.json package-lock.json
coverage coverage
**/*.d.ts
*~ *~
# For misc scripts and experiments: # For misc scripts and experiments:

View File

@ -5,5 +5,5 @@
We're not on npm yet. In your package.json, include this as We're not on npm yet. In your package.json, include this as
```js ```js
"ppppp-record": "github:staltz/ppppp-record" "ppppp-dict": "github:staltz/ppppp-dict"
``` ```

View File

@ -1,6 +1,6 @@
const MsgV3 = require('ppppp-db/msg-v3') const MsgV3 = require('ppppp-db/msg-v3')
const PREFIX = 'record_v1__' const PREFIX = 'dict_v1__'
/** /**
* @typedef {ReturnType<import('ppppp-db').init>} PPPPPDB * @typedef {ReturnType<import('ppppp-db').init>} PPPPPDB
@ -18,11 +18,13 @@ const PREFIX = 'record_v1__'
* @typedef {string} MsgID * @typedef {string} MsgID
* @typedef {`${Subdomain}.${string}`} SubdomainField * @typedef {`${Subdomain}.${string}`} SubdomainField
* @typedef {{ * @typedef {{
* update: Record<string, any>, * update: {
* [field in string]: any
* },
* supersedes: Array<MsgID>, * supersedes: Array<MsgID>,
* }} RecordData * }} DictMsgData
* @typedef {{ * @typedef {{
* record?: { * dict?: {
* ghostSpan?: number * ghostSpan?: number
* } * }
* }} Config * }} Config
@ -65,18 +67,18 @@ function fromSubdomain(subdomain) {
* @returns {asserts peer is { db: PPPPPDB, close: ClosableHook }} * @returns {asserts peer is { db: PPPPPDB, close: ClosableHook }}
*/ */
function assertDBPlugin(peer) { function assertDBPlugin(peer) {
if (!peer.db) throw new Error('record plugin requires ppppp-db plugin') if (!peer.db) throw new Error('dict plugin requires ppppp-db plugin')
} }
/** /**
* @param {{ db: PPPPPDB | null, close: ClosableHook }} peer * @param {{ db: PPPPPDB | null, close: ClosableHook }} peer
* @param {Config} config * @param {Config} config
*/ */
function initRecord(peer, config) { function initDict(peer, config) {
assertDBPlugin(peer) assertDBPlugin(peer)
const ghostSpan = config.record?.ghostSpan ?? 32 const ghostSpan = config.dict?.ghostSpan ?? 32
if (ghostSpan < 1) throw new Error('config.record.ghostSpan must be >= 0') if (ghostSpan < 1) throw new Error('config.dict.ghostSpan must be >= 0')
//#region state //#region state
let accountID = /** @type {string | null} */ (null) let accountID = /** @type {string | null} */ (null)
@ -96,10 +98,10 @@ function initRecord(peer, config) {
}, },
/** /**
* @param {string} subdomain * @param {string} subdomain
* @returns {Record<string, Array<MsgID>>} * @returns {{[field in string]: Array<MsgID>}}
*/ */
getAll(subdomain) { getAll(subdomain) {
const out = /** @type {Record<string, Array<MsgID>>} */ ({}) const out = /** @type {{[field in string]: Array<MsgID>}} */ ({})
for (const [key, value] of this._map.entries()) { for (const [key, value] of this._map.entries()) {
if (key.startsWith(subdomain + '.')) { if (key.startsWith(subdomain + '.')) {
const field = key.slice(subdomain.length + 1) const field = key.slice(subdomain.length + 1)
@ -160,7 +162,7 @@ function initRecord(peer, config) {
* @param {Msg | null | undefined} msg * @param {Msg | null | undefined} msg
* @returns {msg is Msg} * @returns {msg is Msg}
*/ */
function isValidRecordMoot(msg) { function isValidDictMoot(msg) {
if (!msg) return false if (!msg) return false
if (msg.metadata.account !== accountID) return false if (msg.metadata.account !== accountID) return false
const domain = msg.metadata.domain const domain = msg.metadata.domain
@ -171,9 +173,9 @@ function initRecord(peer, config) {
/** /**
* @private * @private
* @param {Msg | null | undefined} msg * @param {Msg | null | undefined} msg
* @returns {msg is Msg<RecordData>} * @returns {msg is Msg<DictMsgData>}
*/ */
function isValidRecordMsg(msg) { function isValidDictMsg(msg) {
if (!msg) return false if (!msg) return false
if (!msg.data) return false if (!msg.data) return false
if (msg.metadata.account !== accountID) return false if (msg.metadata.account !== accountID) return false
@ -190,7 +192,7 @@ function initRecord(peer, config) {
* @param {string} mootID * @param {string} mootID
* @param {Msg} moot * @param {Msg} moot
*/ */
function learnRecordMoot(mootID, moot) { function learnDictMoot(mootID, moot) {
const subdomain = toSubdomain(moot.metadata.domain) const subdomain = toSubdomain(moot.metadata.domain)
const tangle = tangles.get(subdomain) ?? new MsgV3.Tangle(mootID) const tangle = tangles.get(subdomain) ?? new MsgV3.Tangle(mootID)
tangle.add(mootID, moot) tangle.add(mootID, moot)
@ -200,9 +202,9 @@ function initRecord(peer, config) {
/** /**
* @private * @private
* @param {string} msgID * @param {string} msgID
* @param {Msg<RecordData>} msg * @param {Msg<DictMsgData>} msg
*/ */
function learnRecordUpdate(msgID, msg) { function learnDictUpdate(msgID, msg) {
const { account, domain } = msg.metadata const { account, domain } = msg.metadata
const mootID = MsgV3.getMootID(account, domain) const mootID = MsgV3.getMootID(account, domain)
const subdomain = toSubdomain(domain) const subdomain = toSubdomain(domain)
@ -232,14 +234,14 @@ function initRecord(peer, config) {
* @param {string} msgID * @param {string} msgID
* @param {Msg} msg * @param {Msg} msg
*/ */
function maybeLearnAboutRecord(msgID, msg) { function maybeLearnAboutDict(msgID, msg) {
if (msg.metadata.account !== accountID) return if (msg.metadata.account !== accountID) return
if (isValidRecordMoot(msg)) { if (isValidDictMoot(msg)) {
learnRecordMoot(msgID, msg) learnDictMoot(msgID, msg)
return return
} }
if (isValidRecordMsg(msg)) { if (isValidDictMsg(msg)) {
learnRecordUpdate(msgID, msg) learnDictUpdate(msgID, msg)
return return
} }
} }
@ -279,7 +281,7 @@ function initRecord(peer, config) {
/** /**
* @param {string} subdomain * @param {string} subdomain
* @param {Record<string, any>} update * @param {{[field in string]: any}} update
* @param {CB<boolean>} cb * @param {CB<boolean>} cb
*/ */
function forceUpdate(subdomain, update, cb) { function forceUpdate(subdomain, update, cb) {
@ -298,7 +300,7 @@ function initRecord(peer, config) {
{ account: accountID, domain, data: { update, supersedes } }, { account: accountID, domain, data: { update, supersedes } },
(err, rec) => { (err, rec) => {
// prettier-ignore // prettier-ignore
if (err) return cb(new Error('Failed to create msg when force updating Record', { cause: err })) if (err) return cb(new Error('Failed to create msg when force-updating Dict', { cause: err }))
// @ts-ignore // @ts-ignore
cb(null, true) cb(null, true)
} }
@ -317,12 +319,12 @@ function initRecord(peer, config) {
loadPromise = new Promise((resolve, reject) => { loadPromise = new Promise((resolve, reject) => {
for (const rec of peer.db.records()) { for (const rec of peer.db.records()) {
if (!rec.msg) continue if (!rec.msg) continue
maybeLearnAboutRecord(rec.id, rec.msg) maybeLearnAboutDict(rec.id, rec.msg)
} }
cancelOnRecordAdded = peer.db.onRecordAdded( cancelOnRecordAdded = peer.db.onRecordAdded(
(/** @type {RecPresent} */ rec) => { (/** @type {RecPresent} */ rec) => {
try { try {
maybeLearnAboutRecord(rec.id, rec.msg) maybeLearnAboutDict(rec.id, rec.msg)
} catch (err) { } catch (err) {
console.error(err) console.error(err)
} }
@ -355,7 +357,7 @@ function initRecord(peer, config) {
const domain = rootMsg.metadata.domain const domain = rootMsg.metadata.domain
// prettier-ignore // prettier-ignore
if (!domain.startsWith(PREFIX)) throw new Error(`"${tangleID}" is not a record moot`) if (!domain.startsWith(PREFIX)) throw new Error(`"${tangleID}" is not a dict moot`)
// Discover field roots // Discover field roots
const fieldRoots = new Set() const fieldRoots = new Set()
@ -393,7 +395,7 @@ function initRecord(peer, config) {
* @public * @public
* @param {string} id * @param {string} id
* @param {string} subdomain * @param {string} subdomain
* @returns {Record<string, any> | null} * @returns {{[field in string]: any} | null}
*/ */
function read(id, subdomain) { function read(id, subdomain) {
assertDBPlugin(peer) assertDBPlugin(peer)
@ -405,15 +407,15 @@ function initRecord(peer, config) {
else return null else return null
} }
const msgIDs = tangle.topoSort() const msgIDs = tangle.topoSort()
const record = /** @type {Record<string, any>}*/ ({}) const dict = /** @type {{[field in string]: any}} */ ({})
for (const msgID of msgIDs) { for (const msgID of msgIDs) {
const msg = peer.db.get(msgID) const msg = peer.db.get(msgID)
if (isValidRecordMsg(msg)) { if (isValidDictMsg(msg)) {
const { update } = msg.data const { update } = msg.data
Object.assign(record, update) Object.assign(dict, update)
} }
} }
return record return dict
} }
/** /**
@ -445,7 +447,7 @@ function initRecord(peer, config) {
// prettier-ignore // prettier-ignore
if (!msg) throw new Error(`isGhostable() msgID "${ghostableMsgID}" does not exist in the database`) if (!msg) throw new Error(`isGhostable() msgID "${ghostableMsgID}" does not exist in the database`)
// prettier-ignore // prettier-ignore
if (!isValidRecordMoot(tangle.root)) throw new Error(`isGhostable() tangleID "${tangleID}" is not a record`) if (!isValidDictMoot(tangle.root)) throw new Error(`isGhostable() tangleID "${tangleID}" is not a dict`)
// Discover field roots // Discover field roots
const fieldRootIDs = new Set() const fieldRootIDs = new Set()
@ -486,7 +488,7 @@ function initRecord(peer, config) {
/** /**
* @public * @public
* @param {string} subdomain * @param {string} subdomain
* @param {Record<string, any>} update * @param {{[field in string]: any}} update
* @param {CB<boolean>} cb * @param {CB<boolean>} cb
*/ */
function update(subdomain, update, cb) { function update(subdomain, update, cb) {
@ -494,13 +496,13 @@ function initRecord(peer, config) {
loaded(() => { loaded(() => {
if (!accountID) return cb(new Error('Expected account to be loaded')) if (!accountID) return cb(new Error('Expected account to be loaded'))
const record = read(accountID, subdomain) const dict = read(accountID, subdomain)
// prettier-ignore // prettier-ignore
if (!record) return cb(new Error(`Cannot update non-existent record "${subdomain}`)) if (!dict) return cb(new Error(`Cannot update non-existent dict "${subdomain}`))
let hasChanges = false let hasChanges = false
for (const [field, value] of Object.entries(update)) { for (const [field, value] of Object.entries(update)) {
if (value !== record[field]) { if (value !== dict[field]) {
hasChanges = true hasChanges = true
break break
} }
@ -521,12 +523,12 @@ function initRecord(peer, config) {
loaded(() => { loaded(() => {
if (!accountID) return cb(new Error('Expected account to be loaded')) if (!accountID) return cb(new Error('Expected account to be loaded'))
const record = read(accountID, subdomain) const dict = read(accountID, subdomain)
// prettier-ignore // prettier-ignore
if (!record) return cb(new Error(`Cannot squeeze non-existent record "${subdomain}`)) if (!dict) return cb(new Error(`Cannot squeeze non-existent Dict "${subdomain}"`))
forceUpdate(subdomain, record, (err, _forceUpdated) => { forceUpdate(subdomain, dict, (err, _forceUpdated) => {
// prettier-ignore // prettier-ignore
if (err) return cb(new Error('Failed to force update when squeezing Record', { cause: err })) if (err) return cb(new Error(`Failed to force update when squeezing Dict "${subdomain}"`, { cause: err }))
// @ts-ignore // @ts-ignore
cb(null, true) cb(null, true)
}) })
@ -550,5 +552,5 @@ function initRecord(peer, config) {
} }
} }
exports.name = 'record' exports.name = 'dict'
exports.init = initRecord exports.init = initDict

View File

@ -1,13 +1,13 @@
{ {
"name": "ppppp-record", "name": "ppppp-dict",
"version": "1.0.0", "version": "1.0.0",
"description": "Record data structure over append-only logs with pruning", "description": "Dictionary data structure over append-only logs with pruning",
"author": "Andre Staltz <contact@staltz.com>", "author": "Andre Staltz <contact@staltz.com>",
"license": "MIT", "license": "MIT",
"homepage": "https://github.com/staltz/ppppp-record", "homepage": "https://github.com/staltz/ppppp-dict",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git@github.com:staltz/ppppp-record.git" "url": "git@github.com:staltz/ppppp-dict.git"
}, },
"main": "index.js", "main": "index.js",
"files": [ "files": [

View File

@ -18,12 +18,12 @@ E-->D & C
classDef default fill:#bbb,stroke:#fff0,color:#000 classDef default fill:#bbb,stroke:#fff0,color:#000
``` ```
Reducing the tangle above in a topological sort allows you to build a record Reducing the tangle above in a topological sort allows you to build a dict
(a JSON object) `{age, name}`. (a JSON object) `{age, name}`.
## Msg metadata domain ## Msg metadata domain
`msg.metadata.domain` MUST start with `record_v1__`. E.g. `record_v1__profile`. `msg.metadata.domain` MUST start with `dict_v1__`. E.g. `dict_v1__profile`.
## Msg data ## Msg data
@ -31,7 +31,9 @@ Reducing the tangle above in a topological sort allows you to build a record
```typescript ```typescript
interface MsgData { interface MsgData {
update: Record<string, any>, update: {
[field in string]: any,
},
supersedes: Array<MsgHash>, supersedes: Array<MsgHash>,
} }
``` ```
@ -40,11 +42,11 @@ RECOMMENDED that the `msg.data.update` is as flat as possible (no nesting).
## Supersedes links ## Supersedes links
When you update a field in a record, in the `supersedes` array you MUST point When you update a field in a dict, in the `supersedes` array you MUST point
to the currently-known highest-depth msg that updated that field. to the currently-known highest-depth msg that updated that field.
The set of *not-transitively-superseded-by-anyone* msgs comprise the The set of *not-transitively-superseded-by-anyone* msgs comprise the
"field roots" of the record. To allow pruning the tangle, we can delete "field roots" of the dict. To allow pruning the tangle, we can delete
(or, if we want to keep metadata, "erase") all msgs preceding the field roots. (or, if we want to keep metadata, "erase") all msgs preceding the field roots.
Suppose the tangle is grown in the order below, then the field roots are Suppose the tangle is grown in the order below, then the field roots are

View File

@ -8,7 +8,7 @@ const Keypair = require('ppppp-keypair')
const p = require('util').promisify const p = require('util').promisify
const { createPeer } = require('./util') const { createPeer } = require('./util')
const DIR = path.join(os.tmpdir(), 'ppppp-record') const DIR = path.join(os.tmpdir(), 'ppppp-dict')
rimraf.sync(DIR) rimraf.sync(DIR)
const aliceKeypair = Keypair.generate('ed25519', 'alice') const aliceKeypair = Keypair.generate('ed25519', 'alice')
@ -19,7 +19,7 @@ test('setup', async (t) => {
peer = createPeer({ peer = createPeer({
keypair: aliceKeypair, keypair: aliceKeypair,
path: DIR, path: DIR,
record: { ghostSpan: 4 }, dict: { ghostSpan: 4 },
}) })
await peer.db.loaded() await peer.db.loaded()
@ -28,143 +28,143 @@ test('setup', async (t) => {
domain: 'account', domain: 'account',
_nonce: 'alice', _nonce: 'alice',
}) })
await p(peer.record.load)(aliceID) await p(peer.dict.load)(aliceID)
assert.equal(peer.record.getGhostSpan(), 4, 'getGhostSpan') assert.equal(peer.dict.getGhostSpan(), 4, 'getGhostSpan')
}) })
test('Record update() and get()', async (t) => { test('Dict update() and get()', async (t) => {
assert( assert(
await p(peer.record.update)('profile', { name: 'alice' }), await p(peer.dict.update)('profile', { name: 'alice' }),
'update .name' 'update .name'
) )
assert.deepEqual( assert.deepEqual(
peer.record.read(aliceID, 'profile'), peer.dict.read(aliceID, 'profile'),
{ name: 'alice' }, { name: 'alice' },
'get' 'get'
) )
const fieldRoots1 = peer.record._getFieldRoots('profile') const fieldRoots1 = peer.dict._getFieldRoots('profile')
assert.deepEqual( assert.deepEqual(
fieldRoots1, fieldRoots1,
{ name: ['PbwnLbJS4oninQ1RPCdgRn'] }, { name: ['QZSb3GMTRWWUUVLtueNB7Q'] },
'fieldRoots' 'fieldRoots'
) )
assert(await p(peer.record.update)('profile', { age: 20 }), 'update .age') assert(await p(peer.dict.update)('profile', { age: 20 }), 'update .age')
assert.deepEqual( assert.deepEqual(
peer.record.read(aliceID, 'profile'), peer.dict.read(aliceID, 'profile'),
{ name: 'alice', age: 20 }, { name: 'alice', age: 20 },
'get' 'get'
) )
const fieldRoots2 = peer.record._getFieldRoots('profile') const fieldRoots2 = peer.dict._getFieldRoots('profile')
assert.deepEqual( assert.deepEqual(
fieldRoots2, fieldRoots2,
{ name: ['PbwnLbJS4oninQ1RPCdgRn'], age: ['9iTTqNabtnXmw4AiZxNMRq'] }, { name: ['QZSb3GMTRWWUUVLtueNB7Q'], age: ['98QTF8Zip6NYJgmcf96L2K'] },
'fieldRoots' 'fieldRoots'
) )
assert.equal( assert.equal(
await p(peer.record.update)('profile', { name: 'alice' }), await p(peer.dict.update)('profile', { name: 'alice' }),
false, false,
'redundant update .name' 'redundant update .name'
) )
assert.deepEqual( assert.deepEqual(
peer.record.read(aliceID, 'profile'), peer.dict.read(aliceID, 'profile'),
{ name: 'alice', age: 20 }, { name: 'alice', age: 20 },
'get' 'get'
) )
assert.equal( assert.equal(
await p(peer.record.update)('profile', { name: 'Alice' }), await p(peer.dict.update)('profile', { name: 'Alice' }),
true, true,
'update .name' 'update .name'
) )
assert.deepEqual( assert.deepEqual(
peer.record.read(aliceID, 'profile'), peer.dict.read(aliceID, 'profile'),
{ name: 'Alice', age: 20 }, { name: 'Alice', age: 20 },
'get' 'get'
) )
const fieldRoots3 = peer.record._getFieldRoots('profile') const fieldRoots3 = peer.dict._getFieldRoots('profile')
assert.deepEqual( assert.deepEqual(
fieldRoots3, fieldRoots3,
{ age: ['9iTTqNabtnXmw4AiZxNMRq'], name: ['M2JhM7TE2KX5T5rfnxBh6M'] }, { age: ['98QTF8Zip6NYJgmcf96L2K'], name: ['49rg6mJFDgdq6kZTE8uedr'] },
'fieldRoots' 'fieldRoots'
) )
}) })
test('Record squeeze', async (t) => { test('Dict squeeze', async (t) => {
assert(await p(peer.record.update)('profile', { age: 21 }), 'update .age') assert(await p(peer.dict.update)('profile', { age: 21 }), 'update .age')
assert(await p(peer.record.update)('profile', { age: 22 }), 'update .age') assert(await p(peer.dict.update)('profile', { age: 22 }), 'update .age')
assert(await p(peer.record.update)('profile', { age: 23 }), 'update .age') assert(await p(peer.dict.update)('profile', { age: 23 }), 'update .age')
const fieldRoots4 = peer.record._getFieldRoots('profile') const fieldRoots4 = peer.dict._getFieldRoots('profile')
assert.deepEqual( assert.deepEqual(
fieldRoots4, fieldRoots4,
{ name: ['M2JhM7TE2KX5T5rfnxBh6M'], age: ['S3xiydrT6Y34Bp1vg6wN7P'] }, { name: ['49rg6mJFDgdq6kZTE8uedr'], age: ['GE9KcJc5efunBhSTDjy6zX'] },
'fieldRoots' 'fieldRoots'
) )
assert.equal( assert.equal(
peer.record._squeezePotential('profile'), peer.dict._squeezePotential('profile'),
3, 3,
'squeezePotential=3' 'squeezePotential=3'
) )
assert.equal(await p(peer.record.squeeze)('profile'), true, 'squeezed') assert.equal(await p(peer.dict.squeeze)('profile'), true, 'squeezed')
const fieldRoots5 = peer.record._getFieldRoots('profile') const fieldRoots5 = peer.dict._getFieldRoots('profile')
assert.deepEqual( assert.deepEqual(
fieldRoots5, fieldRoots5,
{ name: ['Y4JkpPCHN8Avtz4VALaAmK'], age: ['Y4JkpPCHN8Avtz4VALaAmK'] }, { name: ['Xr7DZdwaANzPByUdRYGb2E'], age: ['Xr7DZdwaANzPByUdRYGb2E'] },
'fieldRoots' 'fieldRoots'
) )
assert.equal( assert.equal(
peer.record._squeezePotential('profile'), peer.dict._squeezePotential('profile'),
0, 0,
'squeezePotential=0' 'squeezePotential=0'
) )
assert.equal( assert.equal(
await p(peer.record.squeeze)('profile'), await p(peer.dict.squeeze)('profile'),
false, false,
'squeeze idempotent' 'squeeze idempotent'
) )
const fieldRoots6 = peer.record._getFieldRoots('profile') const fieldRoots6 = peer.dict._getFieldRoots('profile')
assert.deepEqual(fieldRoots6, fieldRoots5, 'fieldRoots') assert.deepEqual(fieldRoots6, fieldRoots5, 'fieldRoots')
}) })
test('Record isGhostable', (t) => { test('Dict isGhostable', (t) => {
const moot = MsgV3.createMoot(aliceID, 'record_v1__profile', aliceKeypair) const moot = MsgV3.createMoot(aliceID, 'dict_v1__profile', aliceKeypair)
const mootID = MsgV3.getMsgID(moot) const mootID = MsgV3.getMsgID(moot)
assert.equal(mootID, peer.record.getFeedID('profile'), 'getFeedID') assert.equal(mootID, peer.dict.getFeedID('profile'), 'getFeedID')
const tangle = peer.db.getTangle(mootID) const tangle = peer.db.getTangle(mootID)
const msgIDs = tangle.topoSort() const msgIDs = tangle.topoSort()
const fieldRoots = peer.record._getFieldRoots('profile') const fieldRoots = peer.dict._getFieldRoots('profile')
assert.deepEqual(fieldRoots.age, [msgIDs[7]]) assert.deepEqual(fieldRoots.age, [msgIDs[7]])
// Remember from the setup, that ghostSpan=4 // Remember from the setup, that ghostSpan=4
assert.equal(msgIDs.length, 8) assert.equal(msgIDs.length, 8)
assert.equal(peer.record.isGhostable(msgIDs[0], mootID), false) // moot assert.equal(peer.dict.isGhostable(msgIDs[0], mootID), false) // moot
assert.equal(peer.record.isGhostable(msgIDs[1], mootID), false) assert.equal(peer.dict.isGhostable(msgIDs[1], mootID), false)
assert.equal(peer.record.isGhostable(msgIDs[2], mootID), false) assert.equal(peer.dict.isGhostable(msgIDs[2], mootID), false)
assert.equal(peer.record.isGhostable(msgIDs[3], mootID), true) // in ghostSpan assert.equal(peer.dict.isGhostable(msgIDs[3], mootID), true) // in ghostSpan
assert.equal(peer.record.isGhostable(msgIDs[4], mootID), true) // in ghostSpan assert.equal(peer.dict.isGhostable(msgIDs[4], mootID), true) // in ghostSpan
assert.equal(peer.record.isGhostable(msgIDs[5], mootID), true) // in ghostSpan assert.equal(peer.dict.isGhostable(msgIDs[5], mootID), true) // in ghostSpan
assert.equal(peer.record.isGhostable(msgIDs[6], mootID), true) // in ghostSpan assert.equal(peer.dict.isGhostable(msgIDs[6], mootID), true) // in ghostSpan
assert.equal(peer.record.isGhostable(msgIDs[7], mootID), false) // field root assert.equal(peer.dict.isGhostable(msgIDs[7], mootID), false) // field root
}) })
test('Record receives old branched update', async (t) => { test('Dict receives old branched update', async (t) => {
const moot = MsgV3.createMoot(aliceID, 'record_v1__profile', aliceKeypair) const moot = MsgV3.createMoot(aliceID, 'dict_v1__profile', aliceKeypair)
const mootID = MsgV3.getMsgID(moot) const mootID = MsgV3.getMsgID(moot)
assert.equal(peer.record.minRequiredDepth(mootID), 7, 'minRequiredDepth') assert.equal(peer.dict.minRequiredDepth(mootID), 7, 'minRequiredDepth')
const tangle = new MsgV3.Tangle(mootID) const tangle = new MsgV3.Tangle(mootID)
tangle.add(mootID, moot) tangle.add(mootID, moot)
@ -172,7 +172,7 @@ test('Record receives old branched update', async (t) => {
const msg = MsgV3.create({ const msg = MsgV3.create({
keypair: aliceKeypair, keypair: aliceKeypair,
domain: 'record_v1__profile', domain: 'dict_v1__profile',
account: aliceID, account: aliceID,
accountTips: [aliceID], accountTips: [aliceID],
data: { update: { age: 2 }, supersedes: [] }, data: { update: { age: 2 }, supersedes: [] },
@ -181,22 +181,22 @@ test('Record receives old branched update', async (t) => {
}, },
}) })
const rec = await p(peer.db.add)(msg, mootID) const rec = await p(peer.db.add)(msg, mootID)
assert.equal(rec.id, 'XZWr3DZFG253awsWXgSkS2', 'msg ID') assert.equal(rec.id, 'PBq5dgfK9icRVx7SLhyaC5', 'msg ID')
const fieldRoots7 = peer.record._getFieldRoots('profile') const fieldRoots7 = peer.dict._getFieldRoots('profile')
assert.deepEqual( assert.deepEqual(
fieldRoots7, fieldRoots7,
{ {
name: ['Y4JkpPCHN8Avtz4VALaAmK'], name: ['Xr7DZdwaANzPByUdRYGb2E'],
age: ['Y4JkpPCHN8Avtz4VALaAmK', rec.id], age: ['Xr7DZdwaANzPByUdRYGb2E', rec.id],
}, },
'fieldRoots' 'fieldRoots'
) )
assert.equal(peer.record.minRequiredDepth(mootID), 1, 'minRequiredDepth') assert.equal(peer.dict.minRequiredDepth(mootID), 1, 'minRequiredDepth')
assert.equal( assert.equal(
peer.record._squeezePotential('profile'), peer.dict._squeezePotential('profile'),
6, 6,
'squeezePotential=6' 'squeezePotential=6'
) )