diff --git a/lib/msg-v4/tangle.js b/lib/msg-v4/tangle.js index 9e0c6fa..ff3373f 100644 --- a/lib/msg-v4/tangle.js +++ b/lib/msg-v4/tangle.js @@ -93,6 +93,7 @@ class Tangle { * @param {Msg} msg */ add(msgID, msg) { + // Add the root msg if (msgID === this.#rootID && !this.#rootMsg) { this.#tips.add(msgID) this.#perDepth.set(0, [msgID]) @@ -101,10 +102,20 @@ class Tangle { return } + // Add affix msg const tangles = msg.metadata.tangles if (msgID !== this.#rootID && tangles[this.#rootID]) { if (this.#depth.has(msgID)) return - this.#tips.add(msgID) + let hasSuccessor = false + for (const prevs of this.#prev.values()) { + if (prevs.includes(msgID)) { + hasSuccessor = true + break + } + } + if (!hasSuccessor) { + this.#tips.add(msgID) + } const prev = tangles[this.#rootID].prev for (const p of prev) { this.#tips.delete(p) diff --git a/test/msg-v4/tangles.test.js b/test/msg-v4/tangles.test.js index 48103c8..1697655 100644 --- a/test/msg-v4/tangles.test.js +++ b/test/msg-v4/tangles.test.js @@ -192,3 +192,49 @@ test('MsgV4.Tangle lipmaa in multi-author tangle', (t) => { 'A:msg4 points to A:msg1,B:msg3' ) }) + +test('MsgV4.Tangle can add msgs in random order', (t) => { + const keypairA = Keypair.generate('ed25519', 'alice') + const accountA = MsgV4.getMsgID( + MsgV4.createAccount(keypairA, 'person', 'alice') + ) + const mootA = MsgV4.createMoot(accountA, 'post', keypairA) + const mootAID = MsgV4.getMsgID(mootA) + + const tangleBuilder = new MsgV4.Tangle(mootAID) + tangleBuilder.add(mootAID, mootA) + + const msg1 = MsgV4.create({ + account: accountA, + accountTips: [accountA], + domain: 'post', + data: { text: 'Hello world!' }, + tangles: { + [mootAID]: tangleBuilder, + }, + keypair: keypairA, + }) + const msgID1 = MsgV4.getMsgID(msg1) + tangleBuilder.add(msgID1, msg1) + + const msg2 = MsgV4.create({ + account: accountA, + accountTips: [accountA], + domain: 'post', + data: { text: 'Hello world!' }, + tangles: { + [mootAID]: tangleBuilder, + }, + keypair: keypairA, + }) + const msgID2 = MsgV4.getMsgID(msg2) + tangleBuilder.add(msgID1, msg1) + + const tangle = new MsgV4.Tangle(mootAID) + tangle.add(mootAID, mootA) + tangle.add(msgID2, msg2) + tangle.add(msgID1, msg1) + + assert.deepEqual(tangle.topoSort(), [mootAID, msgID1, msgID2]); + assert.deepEqual([...tangle.tips], [msgID2], 'tangle tips') +}) \ No newline at end of file