Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

epidemic-broadcast-trees

Package Overview
Dependencies
Maintainers
9
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

epidemic-broadcast-trees - npm Package Compare versions

Comparing version 9.0.3 to 9.0.4

361

events.js
'use strict'
module.exports = function (version) {
const { note, getReceive, getReplicate, getSequence } = version
var exports = {
const exports = {
note,

@@ -15,11 +14,11 @@ getReceive,

function isEmpty (o) {
for (var k in o) return false
return true
if (o == null) return true
return Object.keys(o).length === 0
}
function isObject (o) {
return o && 'object' === typeof o
return o && typeof o === 'object'
}
function isBlocked(state, id, target) {
function isBlocked (state, id, target) {
return state.blocks[id] && state.blocks[id][target]

@@ -32,7 +31,7 @@ }

//check if a feed is already being replicated on another peer from ignoreId
function isAlreadyReplicating(state, feedId, ignoreId) {
for (var id in state.peers) {
// check if a feed is already being replicated on another peer from ignoreId
function isAlreadyReplicating (state, feedId, ignoreId) {
for (const id in state.peers) {
if (id !== ignoreId) {
var peer = state.peers[id]
const peer = state.peers[id]
if (peer.notes && getReceive(peer.notes[id])) return id

@@ -42,3 +41,3 @@

// this fixed a partial replication bug where a node is unable to send the full log
var idHasSent = peer.replicating && peer.replicating[id] && peer.replicating[id].sent != -1
const idHasSent = peer.replicating && peer.replicating[id] && peer.replicating[id].sent !== -1
if (peer.replicating && peer.replicating[feedId] && peer.replicating[feedId].rx && idHasSent) return id

@@ -54,4 +53,4 @@ }

if (local == null) return remote
if (local == -1 || remote == -1) return remote
if (remote == 0) return 0
if (local === -1 || remote === -1) return remote
if (remote === 0) return 0
if (remote > 0 && local > 0 && remote < local) return remote

@@ -61,12 +60,13 @@ return Math.max(local, remote)

//check if a feed is available from a peer apart from ignoreId
// check if a feed is available from a peer apart from ignoreId
function isAvailable(state, feedId, ignoreId) {
for (var peerId in state.peers) {
if (peerId != ignoreId) {
var peer = state.peers[peerId]
//BLOCK: check wether id has blocked this peer
if ((peer.clock && peer.clock[feedId] || 0) > (state.clock[feedId] || 0) && isShared(state, feedId, peerId)) {
return true
}
function isAvailable (state, feedId, ignoreId) {
for (const peerId in state.peers) {
if (peerId !== ignoreId) {
const peer = state.peers[peerId]
// BLOCK: check wether id has blocked this peer
if (
((peer.clock && peer.clock[feedId]) || 0) > (state.clock[feedId] || 0) &&
isShared(state, feedId, peerId)
) return true
}

@@ -76,14 +76,14 @@ }

//jump to a particular key in a list, then iterate from there
//back around to the key. this is used for switching away from
//peers that stall so that you'll rotate through all the peers
//not just swich between two different peers.
// jump to a particular key in a list, then iterate from there
// back around to the key. this is used for switching away from
// peers that stall so that you'll rotate through all the peers
// not just swich between two different peers.
function eachFrom(keys, key, iter) {
var i = keys.indexOf(key)
function eachFrom (keys, key, iter) {
const i = keys.indexOf(key)
if (!~i) return
//start at 1 because we want to visit all keys but key.
for (var j = 1; j < keys.length; j++)
if (iter(keys[(j+i) % keys.length], j))
return
// start at 1 because we want to visit all keys but key.
for (let j = 1; j < keys.length; j++) {
if (iter(keys[(j + i) % keys.length], j)) { return }
}
}

@@ -95,3 +95,3 @@

var rep = peer.replicating[feed]
const rep = peer.replicating[feed]
if (rep) {

@@ -104,6 +104,6 @@ rep.rx = rx

// defaults for backwards compatibility
exports.getMsgAuthor = function(msg) {
exports.getMsgAuthor = function (msg) {
return msg.author
}
exports.getMsgSequence = function(msg) {
exports.getMsgSequence = function (msg) {
return msg.sequence

@@ -113,9 +113,7 @@ }

exports.initialize = function (id, getMsgAuthor, getMsgSequence) {
if (getMsgAuthor)
exports.getMsgAuthor = getMsgAuthor
if (getMsgSequence)
exports.getMsgSequence = getMsgSequence
if (getMsgAuthor) { exports.getMsgAuthor = getMsgAuthor }
if (getMsgSequence) { exports.getMsgSequence = getMsgSequence }
return {
id: id,
id,
clock: null,

@@ -135,4 +133,4 @@ follows: {},

exports.connect = function (state, ev) {
if (state.peers[ev.id]) throw new Error('already connected to peer:'+ev.id)
if (typeof ev.client != 'boolean') throw new Error('connect.client must be boolean')
if (state.peers[ev.id]) throw new Error('already connected to peer:' + ev.id)
if (typeof ev.client !== 'boolean') throw new Error('connect.client must be boolean')

@@ -148,5 +146,5 @@ // if (isBlocked(state, state.id, ev.id)) return state

notes: null,
//if we are client, wait until we receive notes to send code.
//this is a weird way of doing it! shouldn't we just have a bit of state
//for wether we have received a vector clock
// if we are client, wait until we receive notes to send code.
// this is a weird way of doing it! shouldn't we just have a bit of state
// for wether we have received a vector clock
replicating: ev.client ? null : {}

@@ -163,32 +161,30 @@ }

//this is when the stored peer clock has been loaded from the local database.
//note, this must be handled before any messages are received.
// this is when the stored peer clock has been loaded from the local database.
// note, this must be handled before any messages are received.
exports.peerClock = function (state, ev) {
if (!state.peers[ev.id])
throw new Error('peerClock called for:'+ev.id + ' but only connected to:'+ Object.keys(state.peers))
var peer = state.peers[ev.id]
var clock = peer.clock = ev.value
if (!state.peers[ev.id]) { throw new Error('peerClock called for:' + ev.id + ' but only connected to:' + Object.keys(state.peers)) }
const peer = state.peers[ev.id]
const clock = peer.clock = ev.value
//client should wait for the server notes, so that stream
//can error before a peer sends a massive handshake.
// client should wait for the server notes, so that stream
// can error before a peer sends a massive handshake.
if (peer.replicating == null) return state
//always set an empty clock here, so that if we don't have anything
//to send, we still send this empty clock. This only happens on a new connection.
//in every other situation, clock is only sent if there is something in it.
// always set an empty clock here, so that if we don't have anything
// to send, we still send this empty clock. This only happens on a new connection.
// in every other situation, clock is only sent if there is something in it.
peer.notes = peer.notes || {}
//iterate over following and create replications.
//if we want to replicate a peer that has changed since their clock,
//create a replication for that peer.
// iterate over following and create replications.
// if we want to replicate a peer that has changed since their clock,
// create a replication for that peer.
for (var id in state.follows) {
var seq = clock[id] || 0, lseq = state.clock[id] || 0
//BLOCK: check wether id has blocked this peer
for (const id in state.follows) {
const seq = clock[id] || 0; const lseq = state.clock[id] || 0
// BLOCK: check wether id has blocked this peer
if (isShared(state, id, ev.id) && seq !== -1 && seq !== state.clock[id]) {
//if we are already replicating, and this feed is at zero, ask for it anyway,
//XXX if a feed is at zero, but we are replicating on another peer
//just don't ask for it yet?
var replicating = isAlreadyReplicating(state, id, ev.id)// && lseq
// if we are already replicating, and this feed is at zero, ask for it anyway,
// XXX if a feed is at zero, but we are replicating on another peer
// just don't ask for it yet?
const replicating = isAlreadyReplicating(state, id, ev.id)// && lseq
peer.replicating = peer.replicating || {}

@@ -208,15 +204,15 @@ peer.replicating[id] = {

//XXX handle replicating with only one peer.
// XXX handle replicating with only one peer.
exports.follow = function (state, ev) {
//set to true once we have asked for this feed from someone.
var replicating = false
// set to true once we have asked for this feed from someone.
let replicating = false
if (!!state.follows[ev.id] !== ev.value) {
state.follows[ev.id] = ev.value
for (var id in state.peers) {
var peer = state.peers[id]
for (const id in state.peers) {
const peer = state.peers[id]
if (!peer.clock || !peer.replicating || !isShared(state, ev.id, id)) continue
//BLOCK: check wether this feed has has blocked this peer.
//..... don't replicate feeds with peers that have blocked them at all?
// BLOCK: check wether this feed has has blocked this peer.
// ..... don't replicate feeds with peers that have blocked them at all?
//cases:
// cases:
// don't have feed

@@ -226,13 +222,13 @@ // do have feed

// peer rejects feed
var seq = peer.clock[ev.id] || 0, lseq = state.clock[ev.id] || 0
const seq = peer.clock[ev.id] || 0; const lseq = state.clock[ev.id] || 0
if (seq === -1) {
//peer explicitly does not replicate this feed, don't ask for it.
}
else if (ev.value === false) { //unfollow
// peer explicitly does not replicate this feed, don't ask for it.
} else if (ev.value === false) { // unfollow
setNotes(peer, ev.id, -1, false)
}
else if (ev.value === true && seq !== state.clock[ev.id]) {
} else if (ev.value === true && seq !== state.clock[ev.id]) {
peer.replicating[ev.id] = {
rx: true, tx: false,
sent: -1, requested: lseq
rx: true,
tx: false,
sent: -1,
requested: lseq
}

@@ -248,10 +244,10 @@ setNotes(peer, ev.id, lseq, !replicating)

exports.retrive = function (state, msg) {
//check if any peer requires this msg
for (var id in state.peers) {
var peer = state.peers[id]
// check if any peer requires this msg
for (const id in state.peers) {
const peer = state.peers[id]
if (!peer.replicating) continue
//BLOCK: check wether id has blocked this peer
// BLOCK: check wether id has blocked this peer
const author = exports.getMsgAuthor(msg)
const sequence = exports.getMsgSequence(msg)
var rep = peer.replicating[author]
const rep = peer.replicating[author]

@@ -262,3 +258,3 @@ if (rep && rep.tx && rep.sent === sequence - 1) {

if (rep.sent < state.clock[author]) {
//use continue, not return because we still need to loop through other peers.
// use continue, not return because we still need to loop through other peers.
if (~peer.retrive.indexOf(author)) continue

@@ -272,3 +268,3 @@ peer.retrive.push(author)

function isAhead(seq1, seq2) {
function isAhead (seq1, seq2) {
if (seq2 === -1) return false

@@ -282,26 +278,24 @@ if (seq2 == null) return true

const sequence = exports.getMsgSequence(msg)
//check if any peer requires this msg
if (state.clock[author] != null && state.clock[author] !== sequence - 1)
return state //ignore
// check if any peer requires this msg
if (state.clock[author] != null && state.clock[author] !== sequence - 1) { return state } // ignore
var lseq = state.clock[author] = sequence
for (var id in state.peers) {
var peer = state.peers[id]
const lseq = state.clock[author] = sequence
for (const id in state.peers) {
const peer = state.peers[id]
if (!peer.clock || !peer.replicating || !isShared(state, author, id)) continue
//BLOCK: check wether msg.author has blocked this peer
// BLOCK: check wether msg.author has blocked this peer
var seq = peer.clock[author]
const seq = peer.clock[author]
var rep = peer.replicating[author]
const rep = peer.replicating[author]
if (rep && rep.tx && rep.sent == lseq - 1 && lseq > seq) {
if (rep && rep.tx && rep.sent === lseq - 1 && lseq > seq) {
peer.msgs.push(msg)
rep.sent++
}
//if we are ahead of this peer, and not in tx mode, let them know that.
} // eslint-disable-line
// if we are ahead of this peer, and not in tx mode, let them know that.
else if (
isAhead(lseq, seq) &&
(rep ? !rep.tx && rep.sent != null : state.follows[author])
)
setNotes(peer, author, sequence, false)
) { setNotes(peer, author, sequence, false) }
}

@@ -312,21 +306,21 @@

//XXX if we only receive from a single peer,
//then we shouldn't really get known messages?
//except during the race when we have disabled a peer
//but they havn't noticed yet.
// XXX if we only receive from a single peer,
// then we shouldn't really get known messages?
// except during the race when we have disabled a peer
// but they havn't noticed yet.
exports.receive = function (state, ev) {
var msg = ev.value
//receive a message, validate and append.
//if this message is forked, disable this feed
const msg = ev.value
// receive a message, validate and append.
// if this message is forked, disable this feed
if (!state.peers[ev.id]) throw new Error('lost peer state:'+ev.id)
if (!state.peers[ev.id]) throw new Error('lost peer state:' + ev.id)
//we _know_ that this peer is upto at least this message now.
//(but maybe they already told us they where ahead further)
// we _know_ that this peer is upto at least this message now.
// (but maybe they already told us they where ahead further)
const author = exports.getMsgAuthor(msg)
const sequence = exports.getMsgSequence(msg)
var peer = state.peers[ev.id]
var rep = peer.replicating[author]
const peer = state.peers[ev.id]
const rep = peer.replicating[author]
//if we havn't asked for this, ignore it. (this is remote speaking protocol wrong!)
// if we havn't asked for this, ignore it. (this is remote speaking protocol wrong!)
if (!rep) return state

@@ -337,3 +331,3 @@

//if this message has already been seen, ignore.
// if this message has already been seen, ignore.
if (state.clock[author] >= sequence) {

@@ -343,13 +337,12 @@ if (rep.rx) {

}
//XXX activate some other peer?
// XXX activate some other peer?
return state
}
//remember the time of the last message received
// remember the time of the last message received
state.peers[ev.id].ts = ev.ts
//FORKS ignore additional messages if we have already found an invalid one.
if (isShared(state, author, ev.id))
state.receive.push(ev)
//Q: possibly update the receiving mode?
// FORKS ignore additional messages if we have already found an invalid one.
if (isShared(state, author, ev.id)) { state.receive.push(ev) }
// Q: possibly update the receiving mode?

@@ -359,43 +352,40 @@ return state

//XXX check if we are already receiving a feed
//and if so put this into lazy mode.
// XXX check if we are already receiving a feed
// and if so put this into lazy mode.
exports.notes = function (state, ev) {
//update replicating modes
var clock = ev.value
// update replicating modes
let clock = ev.value
//support sending clocks inside a thing with additional properties.
//this is to allow room for backwards compatible upgrades.
if (isObject(ev.value.clock))
clock = ev.value.clock
// support sending clocks inside a thing with additional properties.
// this is to allow room for backwards compatible upgrades.
if (isObject(ev.value.clock)) { clock = ev.value.clock }
var peer = state.peers[ev.id]
if (!peer) throw new Error('lost state of peer:'+ev.id)
const peer = state.peers[ev.id]
if (!peer) throw new Error('lost state of peer:' + ev.id)
if (!peer.clock) throw new Error("received notes, but has not set the peer's clock yet")
var count = 0
let count = 0
//if we are client, and this is the first notes we receive
// if we are client, and this is the first notes we receive
if (!peer.replicating) {
peer.replicating = {}
state = exports.peerClock(state, {id: ev.id, value: state.peers[ev.id].clock})
state = exports.peerClock(state, { id: ev.id, value: state.peers[ev.id].clock })
}
for (var id in clock) {
for (const id in clock) {
count++
var seq = peer.clock[id] = fixSeq(peer.clock[id], getSequence(clock[id]))
var tx = getReceive(clock[id]) // is even
var isReplicate = getReplicate(clock[id]) // !== -1
const seq = peer.clock[id] = fixSeq(peer.clock[id], getSequence(clock[id]))
const tx = getReceive(clock[id]) // is even
const isReplicate = getReplicate(clock[id]) // !== -1
var lseq = state.clock[id] || 0
const lseq = state.clock[id] || 0
//check if we are not following this feed.
//BLOCK: or wether id has blocked this peer
// check if we are not following this feed.
// BLOCK: or wether id has blocked this peer
if (!isShared(state, id, ev.id)) {
if (!peer.replicating[id])
setNotes(peer, id, -1, false)
peer.replicating[id] = {tx: false, rx: false, sent: -1, requested: -1}
}
else {
var rep = peer.replicating[id]
var replicating = isAlreadyReplicating(state, id, ev.id)
if (!peer.replicating[id]) { setNotes(peer, id, -1, false) }
peer.replicating[id] = { tx: false, rx: false, sent: -1, requested: -1 }
} else {
let rep = peer.replicating[id]
const replicating = isAlreadyReplicating(state, id, ev.id)
if (!rep) {

@@ -409,12 +399,11 @@ rep = peer.replicating[id] = {

setNotes(peer, id, lseq, lseq < seq && !replicating)
}
else if (!rep.rx && seq > lseq) {
} else if (!rep.rx && seq > lseq) {
if (!replicating) {
peer.ts = ev.ts //remember ts, so we can switch this feed if necessary
peer.ts = ev.ts // remember ts, so we can switch this feed if necessary
setNotes(peer, id, lseq, true)
} else {
//if we are already replicating this via another peer
//switch to this peer if it is further ahead.
//(todo?: switch if the other peer's timestamp is old?)
var _peer = state.peers[replicating]
// if we are already replicating this via another peer
// switch to this peer if it is further ahead.
// (todo?: switch if the other peer's timestamp is old?)
const _peer = state.peers[replicating]
// note: _peer.clock[id] may be undefined, if we have

@@ -426,3 +415,3 @@ // just connected to them and sent our notes but not

setNotes(peer, id, lseq, true)
setNotes(_peer, id, lseq, false) //deactivate the previous peer
setNotes(_peer, id, lseq, false) // deactivate the previous peer
}

@@ -432,5 +421,5 @@ }

//positive seq means "send this to me please"
// positive seq means "send this to me please"
rep.tx = tx
//in the case we are already ahead, get ready to send them messages.
// in the case we are already ahead, get ready to send them messages.
rep.sent = seq

@@ -449,15 +438,14 @@ if (lseq > seq) {

exports.timeout = function (state, ev) {
var want = {}
const want = {}
for (var peerId in state.peers) {
var peer = state.peers[peerId]
//check if the peer hasn't received a message recently.
for (const peerId in state.peers) {
const peer = state.peers[peerId]
// check if the peer hasn't received a message recently.
//if we havn't received a message from this peer recently
// if we havn't received a message from this peer recently
if ((peer.ts || 0) + state.timeout < ev.ts) {
//check if they have claimed a higher sequence, but not sent us
for (var id in peer.replicating) {
var rep = peer.replicating[id]
//if yes, prepare to switch this feed to that peer
// check if they have claimed a higher sequence, but not sent us
for (const id in peer.replicating) {
const rep = peer.replicating[id]
// if yes, prepare to switch this feed to that peer
if (rep.rx && isAvailable(state, id, peerId)) {

@@ -471,8 +459,8 @@ want[id] = peerId

var peerIds = Object.keys(state.peers)
for (var feedId in want) {
var ignoreId = want[feedId]
const peerIds = Object.keys(state.peers)
for (const feedId in want) {
const ignoreId = want[feedId]
eachFrom(peerIds, ignoreId, function (peerId) {
var peer = state.peers[peerId]
if (peer.clock && peer.clock[feedId] || 0 > state.clock[feedId] || 0) {
const peer = state.peers[peerId]
if ((peer.clock && peer.clock[feedId]) || state.clock[feedId] < 0 || 0) {
peer.replicating = peer.replicating || {}

@@ -484,3 +472,3 @@ peer.replicating[feedId] = peer.replicating[feedId] || {

peer.ts = ev.ts
//returning true triggers the end of eachFrom
// returning true triggers the end of eachFrom
return true

@@ -497,21 +485,18 @@ }

if (state.blocks[ev.id]) delete state.blocks[ev.id][ev.target]
if (isEmpty(state.blocks[ev.id]))
delete state.blocks[ev.id]
}
else {
if (isEmpty(state.blocks[ev.id])) { delete state.blocks[ev.id] }
} else {
state.blocks[ev.id] = state.blocks[ev.id] || {}
state.blocks[ev.id][ev.target] = true
//if we blocked this peer, and we are also connected to them.
//then stop replicating immediately.
// if we blocked this peer, and we are also connected to them.
// then stop replicating immediately.
if (state.id === ev.id && state.peers[ev.target]) {
//end replication immediately.
// end replication immediately.
state.peers[ev.target].blocked = ev.value
}
for (var id in state.peers) {
var peer = state.peers[id]
for (const id in state.peers) {
const peer = state.peers[id]
if (!peer.replicating) continue
if (id === ev.target && peer.replicating[ev.id])
setNotes(peer, ev.id, -1, false)
if (id === ev.target && peer.replicating[ev.id]) { setNotes(peer, ev.id, -1, false) }
}

@@ -518,0 +503,0 @@ }

@@ -14,3 +14,3 @@ const Events = require('./events')

var state = events.initialize(opts.id, opts.getMsgAuthor, opts.getMsgSequence)
const state = events.initialize(opts.id, opts.getMsgAuthor, opts.getMsgSequence)
state.timeout = opts.timeout || 3000

@@ -20,12 +20,12 @@ state.clock = {}

if (!opts.isMsg) {
opts.isMsg = function(m) {
opts.isMsg = function (m) {
return Number.isInteger(m.sequence) && m.sequence > 0 &&
typeof m.author == 'string' && m.content
typeof m.author === 'string' && m.content
}
}
var self = {
const self = {
id: opts.id,
streams: {},
state: state,
state,
logging: opts.logging,

@@ -37,28 +37,26 @@ progress: function () {

if (opts.isFeed && !opts.isFeed(id)) return
self.state = events.follow(self.state, {id: id, value: follows !== false, ts: timestamp()})
self.state = events.follow(self.state, { id, value: follows !== false, ts: timestamp() })
self.update()
},
pause: function (id, paused) {
self.state = events.pause(self.state, {id, paused: paused !== false})
self.state = events.pause(self.state, { id, paused: paused !== false })
self.update()
},
block: function (id, target, value) {
self.state = events.block(self.state, {id, target, value: value !== false, ts: timestamp()})
self.state = events.block(self.state, { id, target, value: value !== false, ts: timestamp() })
self.update()
},
createStream: function (remoteId, version, client) {
if (self.streams[remoteId])
self.streams[remoteId].end({name: 'Error', message: 'reconnected to peer', stack: ''})
if (self.streams[remoteId]) { self.streams[remoteId].end({ name: 'Error', message: 'reconnected to peer', stack: '' }) }
if (self.logging) console.log('EBT:conn', remoteId)
function onClose(peerState) {
function onClose (peerState) {
opts.setClock(remoteId, peerState.clock)
}
var stream = new Stream(this, remoteId, version, client, opts.isMsg, onClose)
const stream = new Stream(this, remoteId, version, client, opts.isMsg, onClose)
self.streams[remoteId] = stream
opts.getClock(remoteId, (err, clock) => {
//check if peer exists in state, because we may
//have disconect in the meantime
if (self.state.peers[remoteId])
stream.clock(err ? {} : clock)
// check if peer exists in state, because we may
// have disconect in the meantime
if (self.state.peers[remoteId]) { stream.clock(err ? {} : clock) }
})

@@ -73,4 +71,4 @@

} else {
//this should never happen.
//replication for this feed is in bad state now.
// this should never happen.
// replication for this feed is in bad state now.
console.log('could not retrive msg:', err)

@@ -84,15 +82,16 @@ }

update: function () {
//retrive next messages.
//TODO: respond to back pressure from streams to each peer.
//if a given stream is paused, don't retrive more msgs
//for that peer/stream.
for (var peer in self.state.peers) {
var state = self.state.peers[peer]
// retrive next messages.
// TODO: respond to back pressure from streams to each peer.
// if a given stream is paused, don't retrive more msgs
// for that peer/stream.
for (const peer in self.state.peers) {
const state = self.state.peers[peer]
while (state.retrive.length) {
var id = state.retrive.shift()
if (state.replicating[id])
const id = state.retrive.shift()
if (state.replicating[id]) {
opts.getAt({
id,
sequence: state.replicating[id].sent+1
sequence: state.replicating[id].sent + 1
}, self._retrive)
}
}

@@ -102,3 +101,3 @@ }

if (self.state.receive.length) {
var ev = self.state.receive.shift()
const ev = self.state.receive.shift()
opts.append(ev.value, function (err) {

@@ -112,9 +111,8 @@ if (err) {

for (var k in self.streams)
self.streams[k].resume()
},
for (const k in self.streams) { self.streams[k].resume() }
}
}
var int = setInterval(() => {
self.state = events.timeout(self.state, {ts: timestamp()})
const int = setInterval(() => {
self.state = events.timeout(self.state, { ts: timestamp() })
self.update()

@@ -121,0 +119,0 @@ }, state.timeout)

{
"name": "epidemic-broadcast-trees",
"description": "bandwidth efficient broadcast gossip",
"version": "9.0.3",
"version": "9.0.4",
"homepage": "https://github.com/dominictarr/epidemic-broadcast-trees",

@@ -10,2 +10,6 @@ "repository": {

},
"scripts": {
"test": "tape test/*.js | tap-arc",
"lint": "standard --fix"
},
"dependencies": {

@@ -15,11 +19,10 @@ "push-stream": "^11.0.0"

"devDependencies": {
"bipf": "^1.3.0",
"rng": "^0.2.2",
"bipf": "^1.3.0",
"standard": "^17.0.0",
"tap-arc": "^0.3.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "set -e; for t in test/*.js; do node $t; done"
},
"author": "'Dominic Tarr' <dominic.tarr@gmail.com> (http://dominictarr.com)",
"license": "MIT"
}

@@ -0,1 +1,2 @@

/* eslint-disable camelcase */
/*

@@ -11,9 +12,9 @@ better progress algorithm:

module.exports = function (state) {
var prog = { start: 0, current: 0, target: 0 }
for (var peer_id in state.peers) {
var peer = state.peers[peer_id]
const prog = { start: 0, current: 0, target: 0 }
for (const peer_id in state.peers) {
const peer = state.peers[peer_id]
for (var feed_id in peer.replicating) {
var rep = peer.replicating[feed_id]
//progress for sending initial note
for (const feed_id in peer.replicating) {
const rep = peer.replicating[feed_id]
// progress for sending initial note
prog.target++

@@ -25,4 +26,4 @@ if (rep.sent != null) prog.current++

var seq = peer.clock[feed_id]
var lseq = state.clock[feed_id] || 0
const seq = peer.clock[feed_id]
const lseq = state.clock[feed_id] || 0

@@ -29,0 +30,0 @@ if (rep.rx && rep.requested != null && rep.requested > -1 && lseq < seq) {

@@ -9,3 +9,3 @@ const v3 = require('./v3')

function EBTStream (peer, remote, version, client, isMsg, onClose) {
this.paused = true //start out paused
this.paused = true // start out paused
this.remote = remote

@@ -17,3 +17,3 @@ this.peer = peer

ts: timestamp(),
client: client
client
})

@@ -39,9 +39,6 @@ this.ended = false

if (this.peer.logging) {
if (Buffer.isBuffer(data))
console.log("EBT:recv binary (" + this.peer.id + ")", "0x" + data.toString('hex'))
else
console.log("EBT:recv json (" + this.peer.id + ")", JSON.stringify(data, null, 2))
if (Buffer.isBuffer(data)) { console.log('EBT:recv binary (' + this.peer.id + ')', '0x' + data.toString('hex')) } else { console.log('EBT:recv json (' + this.peer.id + ')', JSON.stringify(data, null, 2)) }
}
if (this.ended) throw new Error('write after ebt stream ended:'+this.remote)
if (this.ended) throw new Error('write after ebt stream ended:' + this.remote)

@@ -67,3 +64,3 @@ if (this.isMsg(data)) {

this.ended = true
//check if we have already ended
// check if we have already ended
if (!this.peer.state.peers[this.remote]) return

@@ -73,3 +70,3 @@

var peerState = this.peer.state.peers[this.remote]
const peerState = this.peer.state.peers[this.remote]
this.peer.state = events.disconnect(this.peer.state, {

@@ -80,3 +77,3 @@ id: this.remote,

if (this._onClose) this._onClose(peerState)
//remove from the peer...
// remove from the peer...
delete this.peer.streams[this.remote]

@@ -88,11 +85,10 @@ if (this.source && !this.source.ended) this.source.abort(err)

EBTStream.prototype.canSend = function () {
var state = this.peer.state.peers[this.remote]
const state = this.peer.state.peers[this.remote]
return (
this.sink &&
!this.sink.paused &&
!this.ended && (
//missing state means this peer was blocked,
//end immediately.
state.blocked || state.msgs.length || state.notes
)
!this.sink.paused &&
!this.ended &&
// missing state means this peer was blocked,
// end immediately.
(state.blocked || state.msgs.length || state.notes)
)

@@ -104,3 +100,3 @@ }

var state = this.peer.state.peers[this.remote]
const state = this.peer.state.peers[this.remote]
while (this.canSend()) {

@@ -111,14 +107,15 @@ if (state.blocked) {

if (this.peer.logging) {
if (Buffer.isBuffer(state.msgs[0]))
console.log("EBT:send binary (" + this.peer.id + ")", "0x" + state.msgs[0].toString('hex'))
else
console.log("EBT:send json (" + this.peer.id + ")", JSON.stringify(state.msgs[0], null, 2))
if (Buffer.isBuffer(state.msgs[0])) {
console.log('EBT:send binary (' + this.peer.id + ')', '0x' + state.msgs[0].toString('hex'))
} else {
console.log('EBT:send json (' + this.peer.id + ')', JSON.stringify(state.msgs[0], null, 2))
}
}
this.sink.write(state.msgs.shift())
} else {
var notes = state.notes
const notes = state.notes
state.notes = null
if (this.peer.logging) {
const formattedNotes = {}
for (let feed in notes) {
for (const feed in notes) {
const seq = notes[feed]

@@ -131,3 +128,3 @@ formattedNotes[feed] = {

}
console.log("EBT:send notes (" + this.peer.id + ")", formattedNotes)
console.log('EBT:send notes (' + this.peer.id + ')', formattedNotes)
}

@@ -134,0 +131,0 @@ this.sink.write(notes)

@@ -1,8 +0,8 @@

var createSimulator = require('./simulator')
var bipf = require("bipf")
var events = require('../events')(require('../v3'))
const createSimulator = require('./simulator')
const bipf = require('bipf')
const events = require('../events')(require('../v3'))
function encode(data) {
var len = bipf.encodingLength(data)
var b = Buffer.alloc(len)
function encode (data) {
const len = bipf.encodingLength(data)
const b = Buffer.alloc(len)
bipf.encode(data, b, 0)

@@ -12,4 +12,4 @@ return b

function getMsgAuthor(msg) {
var p = 0 // note you pass in p!
function getMsgAuthor (msg) {
let p = 0 // note you pass in p!
p = bipf.seekKey(msg, p, Buffer.from('author'))

@@ -19,4 +19,4 @@ return bipf.decode(msg, p)

function getMsgSequence(msg) {
var p = 0 // note you pass in p!
function getMsgSequence (msg) {
let p = 0 // note you pass in p!
p = bipf.seekKey(msg, p, Buffer.from('sequence'))

@@ -29,14 +29,14 @@ return bipf.decode(msg, p)

var test = require('tape')
const test = require('tape')
test('binary test', function (t) {
var tick = createSimulator(0, true, events)
const tick = createSimulator(0, true, events)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')
alice.append = function(msg) {
var ary = alice.store[getMsgAuthor(msg)] = alice.store[getMsgAuthor(msg)] || []
if(getMsgSequence(msg) === ary.length + 1) {
alice.append = function (msg) {
const ary = alice.store[getMsgAuthor(msg)] = alice.store[getMsgAuthor(msg)] || []
if (getMsgSequence(msg) === ary.length + 1) {
ary.push(msg)

@@ -46,5 +46,5 @@ alice.state = events.append(alice.state, msg)

}
bob.append = function(msg) {
var ary = bob.store[getMsgAuthor(msg)] = bob.store[getMsgAuthor(msg)] || []
if(getMsgSequence(msg) === ary.length + 1) {
bob.append = function (msg) {
const ary = bob.store[getMsgAuthor(msg)] = bob.store[getMsgAuthor(msg)] || []
if (getMsgSequence(msg) === ary.length + 1) {
ary.push(msg)

@@ -54,9 +54,9 @@ bob.state = events.append(bob.state, msg)

}
alice.init({})
bob.init({})
alice.append(encode({author: 'alice', sequence: 1, text: "test"}))
alice.append(encode({author: 'alice', sequence: 2, text: "test2"}))
alice.append(encode({author: 'alice', sequence: 3, text: "test3"}))
alice.append(encode({ author: 'alice', sequence: 1, text: 'test' }))
alice.append(encode({ author: 'alice', sequence: 2, text: 'test2' }))
alice.append(encode({ author: 'alice', sequence: 3, text: 'test3' }))

@@ -68,3 +68,3 @@ alice.follow('alice')

while(tick(network)) ;
while (tick(network)) ;

@@ -71,0 +71,0 @@ t.deepEqual(bob.store, alice.store)

@@ -1,35 +0,34 @@

var test = require('tape')
const test = require('tape')
var events = require('../events')(require('./options'))
const events = require('../events')(require('./options'))
var note = events.note
const note = events.note
test('blocks', function (t) {
let state = events.initialize('alice')
var state = events.initialize('alice')
state.clock = { alice: 3, charles: 3, dawn: 3 }
state.clock = {alice: 3, charles: 3, dawn: 3}
state = events.follow(state, { id: 'alice', value: true })
state = events.follow(state, { id: 'charles', value: true })
state = events.follow(state, { id: 'dawn', value: true })
state = events.follow(state, {id: 'alice', value: true})
state = events.follow(state, {id: 'charles', value: true})
state = events.follow(state, {id: 'dawn', value: true})
state = events.block(state, {id: 'alice', target: 'bob', value: true})
t.deepEqual(state.blocks, {alice: {bob:true}})
state = events.block(state, {id: 'alice', target: 'bob', value: false})
state = events.block(state, { id: 'alice', target: 'bob', value: true })
t.deepEqual(state.blocks, { alice: { bob: true } })
state = events.block(state, { id: 'alice', target: 'bob', value: false })
t.deepEqual(state.blocks, {})
//do not allow connection to someone we block.
state = events.block(state, {id: 'alice', target: 'bob', value: true})
state = events.block(state, {id: 'charles', target: 'dawn', value: true})
// do not allow connection to someone we block.
state = events.block(state, { id: 'alice', target: 'bob', value: true })
state = events.block(state, { id: 'charles', target: 'dawn', value: true })
console.log(state)
state = events.connect(state, {id: 'bob', client: false})
state = events.connect(state, { id: 'bob', client: false })
t.equal(state.peers.bob.blocked, true)
state = events.connect(state, {id: 'dawn', client: false})
state = events.connect(state, { id: 'dawn', client: false })
state = events.peerClock(state, {id: 'dawn', value:{}})
state = events.peerClock(state, { id: 'dawn', value: {} })
//charles has blocked dawn, so do not give dawn charle's messages
// charles has blocked dawn, so do not give dawn charle's messages
t.deepEqual(state.peers.dawn.notes, {

@@ -39,8 +38,11 @@ alice: note(3, true), dawn: note(3, true)

//but dawn asks for charles anyway.
state = events.notes(state, {id: 'dawn', value: {
alice: note(2, true), dawn: note(2, true), charles: note(1, true)
}})
// but dawn asks for charles anyway.
state = events.notes(state, {
id: 'dawn',
value: {
alice: note(2, true), dawn: note(2, true), charles: note(1, true)
}
})
//charles has blocked dawn, so do not give dawn charles' messages
// charles has blocked dawn, so do not give dawn charles' messages
t.deepEqual(state.peers.dawn.notes, {

@@ -54,10 +56,10 @@ alice: note(3, true), dawn: note(3, true), charles: note(-1, false)

test("don't send retrived message to blocked peer", function (t) {
var state = events.initialize('alice')
state.clock = {alice: 3, charles: 2}
// state.block = {charles: {bob: true}} //charles blocks bob
state = events.block(state, {id: 'charles', target: 'bob', value: true})
state = events.connect(state, {id: 'bob', ts: 1, client: false})
let state = events.initialize('alice')
state.clock = { alice: 3, charles: 2 }
// state.block = {charles: {bob: true}} //charles blocks bob
state = events.block(state, { id: 'charles', target: 'bob', value: true })
state = events.connect(state, { id: 'bob', ts: 1, client: false })
console.log(state)
state = events.peerClock(state, {id: 'bob', value: {}})
state = events.notes(state, {id: 'bob', value: {charles: 1}})
state = events.peerClock(state, { id: 'bob', value: {} })
state = events.notes(state, { id: 'bob', value: { charles: 1 } })
t.equal(state.peers.bob.replicating.charles.tx, false)

@@ -67,3 +69,3 @@ t.equal(state.peers.bob.replicating.charles.sent, -1)

//it's already in a state that the peer should be blocked.
// it's already in a state that the peer should be blocked.

@@ -74,9 +76,9 @@ t.end()

test("don't send retrived message to blocked peer", function (t) {
var state = events.initialize('alice')
state.clock = {alice: 3, charles: 2}
state = events.connect(state, {id: 'bob', ts: 1, client: false})
state = events.peerClock(state, {id: 'bob', value: {}})
let state = events.initialize('alice')
state.clock = { alice: 3, charles: 2 }
state = events.connect(state, { id: 'bob', ts: 1, client: false })
state = events.peerClock(state, { id: 'bob', value: {} })
state = events.notes(state, {id: 'bob', value: {charles: 1}})
state = events.block(state, {id: 'charles', target: 'bob', value: true})
state = events.notes(state, { id: 'bob', value: { charles: 1 } })
state = events.block(state, { id: 'charles', target: 'bob', value: true })

@@ -89,22 +91,19 @@ t.equal(state.peers.bob.replicating.charles.tx, false)

test("blocking false on a connected peer does nothing", function (t) {
var state = events.initialize('alice')
state.clock = {alice: 3, charles: 2}
state = events.connect(state, {id: 'charles', ts: 1, client: false})
//state = events.peerClock(state, {id: 'charles', value: { charles: 2 }})
state = events.peerClock(state, {id: 'charles', value: {'alice': 0, 'charles': 0}})
test('blocking false on a connected peer does nothing', function (t) {
let state = events.initialize('alice')
state.clock = { alice: 3, charles: 2 }
state = events.connect(state, { id: 'charles', ts: 1, client: false })
// state = events.peerClock(state, {id: 'charles', value: { charles: 2 }})
state = events.peerClock(state, { id: 'charles', value: { alice: 0, charles: 0 } })
state = events.follow(state, {id: 'alice', value: true})
state = events.follow(state, {id: 'charles', value: true})
state = events.follow(state, { id: 'alice', value: true })
state = events.follow(state, { id: 'charles', value: true })
state = events.notes(state, {id: 'charles', value: {charles: 2}})
const existingNote = state.peers['charles'].notes['alice']
state = events.notes(state, { id: 'charles', value: { charles: 2 } })
const existingNote = state.peers.charles.notes.alice
// this should not change anything
state = events.block(state, {id: 'alice', target: 'charles', value: false})
t.equal(state.peers['charles'].notes['alice'], existingNote)
state = events.block(state, { id: 'alice', target: 'charles', value: false })
t.equal(state.peers.charles.notes.alice, existingNote)
t.end()
})
var createSimulator = require('./simulator')
var options = require('./options')
var progress = require('../progress')
const createSimulator = require('./simulator')
const options = require('./options')
const progress = require('../progress')
var test = require('tape')
const test = require('tape')
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log, options)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
var charles = network['charles'] = tick.createPeer('charles')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')
const charles = network.charles = tick.createPeer('charles')

@@ -21,5 +21,5 @@ alice.init({})

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })

@@ -33,5 +33,5 @@ alice.follow('alice')

while(tick(network)) ;
while (tick(network)) ;
//should have set up peer.replicatings to tx/rx alice
// should have set up peer.replicatings to tx/rx alice

@@ -42,3 +42,3 @@ t.deepEqual(bob.store, alice.store, 'alice<->bob')

function isComplete (peer) {
var prog = progress(peer.state)
const prog = progress(peer.state)
t.equal(prog.current, prog.target)

@@ -55,12 +55,5 @@ }

var seed = process.argv[2]
if(isNaN(seed))
for(var i = 0; i < 100; i++)
createTest(i, false)
else
createTest(+seed, true)
const seed = process.argv[2]
if (isNaN(seed)) {
for (let i = 0; i < 100; i++) { createTest(i, false) }
} else { createTest(+seed, true) }

@@ -1,16 +0,16 @@

var test = require('tape')
const test = require('tape')
var events = require('../events')(require('./options'))
const events = require('../events')(require('./options'))
var note = events.note
const note = events.note
test('client does not send {} until received it', function (t) {
var state = events.initialize('alice')
state = events.connect(state, {id: 'bob', client: true})
state.follows = {alice: true, bob: true}
state.clock = {alice:1, bob: 1}
state = events.peerClock(state, {id: 'bob', value: {}})
let state = events.initialize('alice')
state = events.connect(state, { id: 'bob', client: true })
state.follows = { alice: true, bob: true }
state.clock = { alice: 1, bob: 1 }
state = events.peerClock(state, { id: 'bob', value: {} })
t.equal(state.peers.bob.notes, null)
state = events.notes(state, {id: 'bob', value: {}})
t.deepEqual(state.peers.bob.notes, {alice: note(1, true), bob: note(1, true)})
state = events.notes(state, { id: 'bob', value: {} })
t.deepEqual(state.peers.bob.notes, { alice: note(1, true), bob: note(1, true) })

@@ -23,9 +23,9 @@ state.peers.bob.notes = null

test('client does not send {} until received it, but will send empty note, one time', function (t) {
var state = events.initialize('alice')
state = events.connect(state, {id: 'bob', client: true})
state = events.peerClock(state, {id: 'bob', value: {}})
let state = events.initialize('alice')
state = events.connect(state, { id: 'bob', client: true })
state = events.peerClock(state, { id: 'bob', value: {} })
t.equal(state.peers.bob.notes, null)
state = events.notes(state, {id: 'bob', value: {}})
state = events.notes(state, { id: 'bob', value: {} })
t.deepEqual(state.peers.bob.notes, {})
t.end()
})
var createSimulator = require('./simulator')
var _events = require('../events')(require('./options'))
var test = require('tape')
var progress = require('../progress')
var events = {}
for(var k in _events) (function (fn, k) {
events[k] = function (state, ev) {
if(state.stalled) return state
return fn(state, ev)
}
})(_events[k], k)
const createSimulator = require('./simulator')
const _events = require('../events')(require('./options'))
const test = require('tape')
const progress = require('../progress')
const events = {}
for (const k in _events) {
(function (fn, k) {
events[k] = function (state, ev) {
if (state.stalled) return state
return fn(state, ev)
}
})(_events[k], k)
}
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
var carl = network['carl'] = tick.createPeer('carl')
var dawn = network['dawn'] = tick.createPeer('dawn')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')
const carl = network.carl = tick.createPeer('carl')
const dawn = network.dawn = tick.createPeer('dawn')

@@ -31,6 +32,6 @@ alice.state.timeout = bob.state.timeout = dawn.state.timeout = 2

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
bob.append({author: 'bob', sequence: 1, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })
bob.append({ author: 'bob', sequence: 1, content: {} })

@@ -53,11 +54,10 @@ alice.follow('alice')

tick.run(network)
// carl.state.stalled = true
// carl.state.stalled = true
// alice.disconnect(carl)
// alice.disconnect(carl)
bob.disconnect(carl)
// dawn.disconnect(carl)
// dawn.disconnect(carl)
alice.append({author: 'alice', sequence: 4, content: {}})
alice.append({ author: 'alice', sequence: 4, content: {} })
tick.run(network)

@@ -69,4 +69,4 @@

function isComplete (peer, name) {
var prog = progress(peer.state)
t.equal(prog.current, prog.target, name +' is complete')
const prog = progress(peer.state)
t.equal(prog.current, prog.target, name + ' is complete')
}

@@ -82,5 +82,3 @@

var seed = process.argv[2]
if(isNaN(seed))
for(var i = 0; i < 100; i++) createTest(i)
else createTest(+seed, true)
const seed = process.argv[2]
if (isNaN(seed)) { for (let i = 0; i < 100; i++) createTest(i) } else createTest(+seed, true)

@@ -1,67 +0,65 @@

var createSimulator = require('./simulator')
var options = require('./options')
var progress = require('../progress')
const createSimulator = require('./simulator')
const options = require('./options')
const progress = require('../progress')
var test = require('tape')
const test = require('tape')
function validate (queue, msg) {
var sum = queue.reduce(function (a, b) {
const sum = queue.reduce(function (a, b) {
return a + b.content.value
}, 0)
if(sum != msg.content.sum) throw new Error('invalid sum:'+msg.content.sum+', expected:'+sum)
if (sum !== msg.content.sum) throw new Error('invalid sum:' + msg.content.sum + ', expected:' + sum)
}
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log, options)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice', validate)
var bob = network['bob'] = tick.createPeer('bob', validate)
// var charles = network['charles'] = tick.createPeer('charles', validate)
const network = {}
const alice = network.alice = tick.createPeer('alice', validate)
const bob = network.bob = tick.createPeer('bob', validate)
// var charles = network['charles'] = tick.createPeer('charles', validate)
alice.init({})
bob.init({})
// charles.init({})
// charles.init({})
alice.append({author: 'alice', sequence: 1, content: {sum: 0, value: 1}})
alice.append({author: 'alice', sequence: 2, content: {sum: 1, value: 2}})
alice.append({author: 'alice', sequence: 3, content: {sum: 3, value: 3}})
alice.append({author: 'alice', sequence: 4, content: {sum: 6, value: 4}})
alice.append({author: 'alice', sequence: 5, content: {sum: 10, value: 5}})
alice.append({author: 'alice', sequence: 6, content: {sum: 15, value: 6}})
alice.append({author: 'alice', sequence: 7, content: {sum: 21, value: 7}})
alice.append({ author: 'alice', sequence: 1, content: { sum: 0, value: 1 } })
alice.append({ author: 'alice', sequence: 2, content: { sum: 1, value: 2 } })
alice.append({ author: 'alice', sequence: 3, content: { sum: 3, value: 3 } })
alice.append({ author: 'alice', sequence: 4, content: { sum: 6, value: 4 } })
alice.append({ author: 'alice', sequence: 5, content: { sum: 10, value: 5 } })
alice.append({ author: 'alice', sequence: 6, content: { sum: 15, value: 6 } })
alice.append({ author: 'alice', sequence: 7, content: { sum: 21, value: 7 } })
bob.append({author: 'alice', sequence: 1, content: {sum: 0, value: 1}})
bob.append({author: 'alice', sequence: 2, content: {sum: 1, value: 3}})
// bob.append({author: 'alice', sequence: 3, content: {sum: 4, value: 1}})
bob.append({ author: 'alice', sequence: 1, content: { sum: 0, value: 1 } })
bob.append({ author: 'alice', sequence: 2, content: { sum: 1, value: 3 } })
// bob.append({author: 'alice', sequence: 3, content: {sum: 4, value: 1}})
alice.follow('alice')
bob.follow('alice')
// charles.follow('alice')
// charles.follow('alice')
alice.connect(bob)
// alice.connect(charles)
// alice.connect(charles)
while(tick(network)) ;
while (tick(network)) ;
//should have set up peer.replicatings to tx/rx alice
// should have set up peer.replicatings to tx/rx alice
t.deepEqual(bob.state.blocks, {alice: {alice: true}})
t.deepEqual(bob.state.blocks, { alice: { alice: true } })
var prog = progress(bob.state)
const prog = progress(bob.state)
t.equal(prog.current, prog.target)
// t.equal(bob.state.peers.alice.replicating.alice.tx, false, 'bob is not transmitting forked alice with alice')
// t.equal(bob.state.peers.alice.replicating.alice.tx, false, 'bob is not transmitting forked alice with alice')
t.equal(bob.state.peers.alice.replicating.alice.rx, false, 'bob is not receiving forked alice with alice')
if(log)
if (log) {
console.log(
tick.output.map(function (e) {
if(e.msg)
return e.from+'>'+e.to+':'+e.value.sequence
else
return e.from+'>'+e.to+':'+JSON.stringify(e.value)
if (e.msg) { return e.from + '>' + e.to + ':' + e.value.sequence } else { return e.from + '>' + e.to + ':' + JSON.stringify(e.value) }
}).join('\n')
)
}

@@ -72,5 +70,4 @@ t.end()

var seed = process.argv[2]
if(isNaN(seed)) for(var i = 0; i < 100; i++) createTest(i)
const seed = process.argv[2]
if (isNaN(seed)) for (let i = 0; i < 100; i++) createTest(i)
else createTest(+seed, true)

@@ -1,15 +0,13 @@

var test = require('tape')
const test = require('tape')
function isObject(o) {
return o && 'object' === typeof o
function isObject (o) {
return o && typeof o === 'object'
}
function isFunction (f) {
return 'function' === typeof f
return typeof f === 'function'
}
function is (t, actual, expected, path) {
if(isFunction(expected))
expected.call(actual)
else t.equal(expected, actual, 'expected '+path.join('.')+' to equal:'+actual)
if (isFunction(expected)) { expected.call(actual) } else t.equal(expected, actual, 'expected ' + path.join('.') + ' to equal:' + actual)
}

@@ -20,138 +18,135 @@

if(!(isObject(actual))) return is(t, actual, expected, path)
if (!(isObject(actual))) return is(t, actual, expected, path)
if(!isObject(expected))
return t.fail('expected object at path:'+path.join('.'))
if (!isObject(expected)) { return t.fail('expected object at path:' + path.join('.')) }
for(var k in expected)
has(t, actual[k], expected[k], path.concat(k))
for (const k in expected) { has(t, actual[k], expected[k], path.concat(k)) }
}
module.exports = function (events) {
const note = events.note
var note = events.note
test('initialize, connect to new peer', function (t) {
let state = events.initialize()
test('initialize, connect to new peer', function (t) {
state = events.connect(state, { id: 'alice', client: false })
state = events.peerClock(state, { id: 'alice', value: {} })
var state = events.initialize()
has(t, state, {
peers: {
alice: { clock: {}, msgs: [], notes: {}, replicating: {} }
}
})
state = events.connect(state, {id: 'alice', client: false})
state = events.peerClock(state, {id: 'alice', value: {}})
state = events.clock(state, {})
has(t, state, {
peers: {
alice: { clock: {}, msgs: [], notes: {}, replicating: {} },
}
})
state = events.follow(state, { id: 'alice', value: true })
state = events.clock(state, {})
t.deepEqual(state.follows, { alice: true })
console.log(state.peers.alice)
state = events.follow(state, {id: 'alice', value: true})
has(t, state.peers.alice, {
clock: {},
notes: { alice: note(0, true) },
replicating: { alice: { rx: true } }
}, ['state', 'peers', 'alice'])
t.deepEqual(state.follows, {alice: true})
console.log(state.peers.alice)
// lets say we send the note
has(t, state.peers.alice, {
clock: {},
notes: { alice: note(0, true) },
replicating: {alice: {rx: true}}
}, ['state', 'peers', 'alice'])
//lets say we send the note
state = events.notes(state, {id: 'alice', value: {alice: note(2, true)}})
has(t, state, {
clock: {},
follows: {alice: true},
peers: {
alice: {
clock: {alice: 2},
replicating: {
alice: {
rx: true, tx: true
state = events.notes(state, { id: 'alice', value: { alice: note(2, true) } })
has(t, state, {
clock: {},
follows: { alice: true },
peers: {
alice: {
clock: { alice: 2 },
replicating: {
alice: {
rx: true, tx: true
}
}
}
}
}
})
})
var msg = {author: 'alice', sequence: 1, content: {}}
state = events.receive(state, {id: 'alice', value:msg})
const msg = { author: 'alice', sequence: 1, content: {} }
state = events.receive(state, { id: 'alice', value: msg })
has(t, state, {
peers: {
alice: {
clock: {alice: 2},
replicating: {
alice: {
rx: true, tx: true
has(t, state, {
peers: {
alice: {
clock: { alice: 2 },
replicating: {
alice: {
rx: true, tx: true
}
}
}
}
},
receive: [{id: 'alice', value: msg}],
})
},
receive: [{ id: 'alice', value: msg }]
})
var ev = state.receive.shift()
const ev = state.receive.shift()
state = events.append(state, ev.value)
state = events.append(state, ev.value)
has(t, state, {
clock: {alice: 1}
})
has(t, state, {
clock: { alice: 1 }
})
var msg2 = {author: 'alice', sequence: 2, content: {}}
state = events.receive(state, {id: 'alice', value:msg2})
state = events.append(state, state.receive.shift().value)
const msg2 = { author: 'alice', sequence: 2, content: {} }
state = events.receive(state, { id: 'alice', value: msg2 })
state = events.append(state, state.receive.shift().value)
has(t, state, {
clock: {alice: 2}
})
has(t, state, {
clock: { alice: 2 }
})
var msg3 = {author: 'alice', sequence: 3, content: {}}
state = events.receive(state, {id: 'alice', value:msg3})
state = events.append(state, state.receive.shift().value)
const msg3 = { author: 'alice', sequence: 3, content: {} }
state = events.receive(state, { id: 'alice', value: msg3 })
state = events.append(state, state.receive.shift().value)
has(t, state, {
clock: {alice: 3}
has(t, state, {
clock: { alice: 3 }
})
t.end()
})
t.end()
test('initialize, but append before peerClock loads', function (t) {
let state = events.initialize()
state = events.clock(state, { alice: 1, bob: 2 })
})
state = events.connect(state, { id: 'alice', client: false })
state = events.append(state, { author: 'bob', sequence: 3, content: {} })
test('initialize, but append before peerClock loads', function (t) {
state = events.peerClock(state, { id: 'alice', value: {} })
// TODO > does this test anything?
t.end()
})
var state = events.initialize()
state = events.clock(state, {alice: 1, bob: 2})
state = events.connect(state, {id: 'alice', client: false})
state = events.append(state, {author: 'bob', sequence: 3, content: {}})
state = events.peerClock(state, {id: 'alice', value: {}})
t.end()
})
test('connect to two peers, append message one send, one note', function (t) {
var state = {
clock: { alice: 1 },
follows: { alice: true },
blocks: {},
peers: {
bob: {
clock: { alice: 1 },
msgs: [], retrive: [],
replicating: {
alice: {
rx: true, tx: true, sent: 1, retrive: false
test('connect to two peers, append message one send, one note', function (t) {
let state = {
clock: { alice: 1 },
follows: { alice: true },
blocks: {},
peers: {
bob: {
clock: { alice: 1 },
msgs: [],
retrive: [],
replicating: {
alice: {
rx: true, tx: true, sent: 1, retrive: false
}
}
}
},
charles: {
clock: {alice: 1},
msgs: [], retrive: [],
replicating: {
alice: {
rx: false, tx: false, sent: 1, retrive: false
},
charles: {
clock: { alice: 1 },
msgs: [],
retrive: [],
replicating: {
alice: {
rx: false, tx: false, sent: 1, retrive: false
}
}

@@ -161,151 +156,153 @@ }

}
}
var msg = {author: 'alice', sequence: 2, content: {}}
state = events.append(state, msg)
const msg = { author: 'alice', sequence: 2, content: {} }
state = events.append(state, msg)
has(t, state, {
clock: { alice: 2 },
peers: {
bob: {
clock: { alice: 1 },
msgs: [msg],
retrive: [],
replicating: {
alice: {
rx: true, tx: true, sent: 2, retrive: false
has(t, state, {
clock: { alice: 2 },
peers: {
bob: {
clock: { alice: 1 },
msgs: [msg],
retrive: [],
replicating: {
alice: {
rx: true, tx: true, sent: 2, retrive: false
}
}
}
},
charles: {
clock: { alice: 1 },
notes: { alice: note(2, false) },
retrive: [],
replicating: {
alice: {
rx: false, tx: false, sent: 1
},
charles: {
clock: { alice: 1 },
notes: { alice: note(2, false) },
retrive: [],
replicating: {
alice: {
rx: false, tx: false, sent: 1
}
}
}
}
}
})
t.end()
})
t.end()
test('replicate a hops=2 peer that my hops=1 friend still doesnt have', function (t) {
let state = events.initialize()
state = events.clock(state, {})
})
state = events.connect(state, { id: 'alice', client: false })
state = events.peerClock(state, { id: 'alice', value: { alice: 0, bob: 0 } })
test('replicate a hops=2 peer that my hops=1 friend still doesnt have', function (t) {
var state = events.initialize()
state = events.clock(state, {})
state = events.follow(state, { id: 'alice', value: true })
state = events.follow(state, { id: 'bob', value: true })
state = events.connect(state, {id: 'alice', client: false})
state = events.peerClock(state, {id: 'alice', value: {'alice': 0, 'bob': 0}})
t.ok(state.peers.alice.replicating.bob)
state = events.follow(state, {id: 'alice', value: true})
state = events.follow(state, {id: 'bob', value: true})
t.end()
})
t.ok(state.peers['alice'].replicating['bob'])
test('replicate a hops=2 peer that my hops=1 friend still doesnt have (2)', function (t) {
let state = events.initialize()
state = events.clock(state, {})
t.end()
})
state = events.follow(state, { id: 'alice', value: true })
state = events.follow(state, { id: 'bob', value: true })
test('replicate a hops=2 peer that my hops=1 friend still doesnt have (2)', function (t) {
var state = events.initialize()
state = events.clock(state, {})
state = events.connect(state, { id: 'alice', client: false })
state = events.peerClock(state, { id: 'alice', value: { alice: 0, bob: 0 } })
state = events.follow(state, {id: 'alice', value: true})
state = events.follow(state, {id: 'bob', value: true})
t.ok(state.peers.alice.replicating.bob)
state = events.connect(state, {id: 'alice', client: false})
state = events.peerClock(state, {id: 'alice', value: {'alice': 0, 'bob': 0}})
t.end()
})
t.ok(state.peers['alice'].replicating['bob'])
test('reply to any clock they send, 1', function (t) {
let state = {
clock: { alice: 3, bob: 2, charles: 3 },
follows: { alice: true, bob: true, charles: true, darlene: false },
blocks: {},
peers: {}
}
t.end()
})
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: 3, charles: 1 } })
t.deepEqual(state.peers.bob.notes, { bob: note(2, true), charles: note(3, true) })
test('reply to any clock they send, 1', function (t) {
var state = {
clock: { alice: 3, bob: 2, charles: 3 },
follows: { alice: true, bob: true, charles: true, darlene: false },
blocks: {},
peers: {}
}
state = events.notes(state, { id: 'bob', value: { alice: note(3, true), darlene: note(4, true) } })
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value:{alice: 3, charles: 1}})
t.deepEqual(state.peers.bob.notes, {bob: note(2, true), charles: note(3, true)})
// notes hasn't been sent, so this is merged with previous
t.deepEqual(state.peers.bob.notes, { alice: note(3, false), bob: note(2, true), charles: note(3, true), darlene: note(-1, true) })
state = events.notes(state, {id: 'bob', value: {alice: note(3, true), darlene: note(4, true)}})
t.end()
})
//notes hasn't been sent, so this is merged with previous
t.deepEqual(state.peers.bob.notes, {alice: note(3, false), bob: note(2, true), charles: note(3, true), darlene: note(-1, true)})
test('reply to any clock they send, 2', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: { alice: true, bob: true },
blocks: {},
peers: {}
}
t.end()
})
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: 3, charles: 1 } })
t.deepEqual(state.peers.bob.notes, { bob: note(2, true) })
test('reply to any clock they send, 2', function (t) {
var state = {
clock: { alice: 3, bob: 2},
follows: { alice: true, bob: true}, blocks: {},
peers: {},
}
state = events.notes(state, { id: 'bob', value: { alice: note(3, true) } })
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value:{alice: 3, charles: 1}})
t.deepEqual(state.peers.bob.notes, {bob: note(2, true)})
// notes hasn't been sent, so this is merged with previous
t.deepEqual(state.peers.bob.notes, { alice: note(3, false), bob: note(2, true) })
state = events.notes(state, {id: 'bob', value: {alice: note(3, true)}})
state = events.follow(state, { id: 'charles', value: true })
t.deepEqual(state.peers.bob.notes, { alice: note(3, false), bob: note(2, true), charles: note(0, true) })
//notes hasn't been sent, so this is merged with previous
t.deepEqual(state.peers.bob.notes, {alice: note(3, false), bob: note(2, true)})
t.end()
})
state = events.follow(state, {id: 'charles',value: true})
t.deepEqual(state.peers.bob.notes, {alice: note(3, false), bob: note(2, true), charles: note(0, true)})
test('append when not in TX mode', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: { alice: true, bob: true },
blocks: {},
peers: {}
}
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: 3, charles: 1 } })
t.deepEqual(state.peers.bob.notes, { bob: note(2, true) })
t.end()
})
state = events.notes(state, { id: 'bob', value: { alice: note(3, false) } })
let rep = state.peers.bob.replicating.alice
t.equal(rep.tx, false)
t.equal(rep.sent, 3)
test('append when not in TX mode', function (t) {
var state = {
clock: { alice: 3, bob: 2},
follows: { alice: true, bob: true}, blocks: {},
peers: {}
}
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value:{alice: 3, charles: 1}})
t.deepEqual(state.peers.bob.notes, {bob: note(2, true)})
console.log(state.peers.bob.replicating)
state = events.notes(state, {id: 'bob', value: {alice: note(3, false)}})
var rep = state.peers.bob.replicating.alice
t.equal(rep.tx, false)
t.equal(rep.sent, 3)
state = events.append(state, { author: 'alice', sequence: 4, content: {} })
t.deepEqual(state.peers.bob.notes, { bob: note(2, true), alice: note(4, false) })
rep = state.peers.bob.replicating.alice
t.equal(rep.tx, false)
t.equal(rep.sent, 3)
console.log(state.peers.bob.replicating)
state = events.notes(state, { id: 'bob', value: { alice: note(3, true) } })
t.deepEqual(state.peers.bob.retrive, ['alice'])
state = events.append(state, {author: 'alice', sequence: 4, content: {}})
t.deepEqual(state.peers.bob.notes, {bob: note(2, true), alice: note(4, false)})
rep = state.peers.bob.replicating.alice
t.equal(rep.tx, false)
t.equal(rep.sent, 3)
t.end()
})
state = events.notes(state, {id: 'bob', value: {alice: note(3, true)}})
t.deepEqual(state.peers.bob.retrive, ['alice'])
t.end()
})
test('note when not in RX mode', function (t) {
var state = {
clock: { alice: 3, bob: 2},
follows: { alice: true, bob: true}, blocks: {},
peers: {
bob: {
clock: {alice: 3, bob: 2},
retrive: [],
msgs: [],
notes: null,
replicating: {
alice: {
tx:false, rx: false, sent: 3
test('note when not in RX mode', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: { alice: true, bob: true },
blocks: {},
peers: {
bob: {
clock: { alice: 3, bob: 2 },
retrive: [],
msgs: [],
notes: null,
replicating: {
alice: {
tx: false, rx: false, sent: 3
}
}

@@ -315,198 +312,197 @@ }

}
}
state = events.notes(state, {id: 'bob', value: {alice: note(5, false)}})
var rep = state.peers.bob.replicating.alice
// t.equal(rep.tx, true)
t.equal(rep.rx, true)
t.equal(rep.sent, 5)
t.deepEqual(state.peers.bob.notes, {alice: note(3, true)})
state = events.notes(state, { id: 'bob', value: { alice: note(5, false) } })
const rep = state.peers.bob.replicating.alice
// t.equal(rep.tx, true)
t.equal(rep.rx, true)
t.equal(rep.sent, 5)
t.deepEqual(state.peers.bob.notes, { alice: note(3, true) })
console.log(state.peers.bob.replicating)
console.log(state.peers.bob.replicating)
// state = events.append(state, {author: 'alice', sequence: 4, content: {}})
// t.deepEqual(state.peers.bob.notes, {bob: note(2, true), alice: note(4, false)})
t.end()
// state = events.append(state, {author: 'alice', sequence: 4, content: {}})
// t.deepEqual(state.peers.bob.notes, {bob: note(2, true), alice: note(4, false)})
t.end()
})
})
test('note when value is not integer', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: { alice: true, bob: true },
blocks: {},
peers: {}
}
test('note when value is not integer', function (t) {
var state = {
clock: { alice: 3, bob: 2},
follows: { alice: true, bob: true}, blocks: {},
peers: {}
}
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: {} })
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value:{}})
t.deepEqual(state.peers.bob.clock, {})
state = events.notes(state, { id: 'bob', value: { alice: true } })
t.deepEqual(state.peers.bob.clock, {})
state = events.notes(state, {id: 'bob', value: {alice: true}})
t.deepEqual(state.peers.bob.clock, { alice: -1 })
t.deepEqual(state.peers.bob.notes, { alice: note(3, true), bob: note(2, true) })
t.deepEqual(state.peers.bob.clock, {alice: -1})
t.deepEqual(state.peers.bob.notes, {alice: note(3,true), bob: note(2, true)})
t.end()
})
t.end()
})
test('test sends empty clock if nothing needed', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: { alice: true, bob: true },
blocks: {},
peers: {}
}
test('test sends empty clock if nothing needed', function (t) {
var state = {
clock: { alice: 3, bob: 2},
follows: { alice: true, bob: true}, blocks: {},
peers: {}
}
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: 3, bob: 2 } })
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value:{alice: 3, bob: 2}})
t.deepEqual(state.peers.bob.clock, { alice: 3, bob: 2 })
t.deepEqual(state.peers.bob.notes, {})
t.deepEqual(state.peers.bob.clock, {alice: 3, bob: 2})
t.deepEqual(state.peers.bob.notes, {})
// receive empty clock
state = events.notes(state, { id: 'bob', value: {} })
t.deepEqual(state.peers.bob.replicating, {})
//receive empty clock
state = events.notes(state, {id: 'bob', value: {}})
t.deepEqual(state.peers.bob.replicating, {})
t.end()
})
t.end()
})
test('connects in sync then another message', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: { alice: true, bob: true },
blocks: {},
peers: {}
}
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: 3, bob: 2 } })
test('connects in sync then another message', function (t) {
var state = {
clock: { alice: 3, bob: 2},
follows: { alice: true, bob: true}, blocks: {},
peers: {}
}
t.deepEqual(state.peers.bob.clock, { alice: 3, bob: 2 })
t.deepEqual(state.peers.bob.notes, {})
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value:{alice: 3, bob: 2}})
// receive empty clock
state = events.notes(state, { id: 'bob', value: {} })
t.deepEqual(state.peers.bob.replicating, {})
t.deepEqual(state.peers.bob.clock, {alice: 3, bob: 2})
t.deepEqual(state.peers.bob.notes, {})
state = events.append(state, { author: 'alice', sequence: 4, content: {} })
t.deepEqual(state.peers.bob.notes, { alice: note(4, false) })
//receive empty clock
state = events.notes(state, {id: 'bob', value: {}})
t.deepEqual(state.peers.bob.replicating, {})
t.end()
})
state = events.append(state, {author: 'alice', sequence: 4, content: {}})
t.deepEqual(state.peers.bob.notes, {alice: note(4, false)})
test('unfollow', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: {},
blocks: {},
peers: {}
}
t.end()
})
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: {} })
test('unfollow', function (t) {
t.deepEqual(state.peers.bob.clock, {})
t.deepEqual(state.peers.bob.notes, { })
state = events.notes(state, { id: 'bob', value: { alice: note(3, true), bob: note(2, true) } })
t.deepEqual(state.peers.bob.notes, { alice: note(-1, true), bob: note(-1, true) })
var state = {
clock: { alice: 3, bob: 2},
follows: {}, blocks: {},
peers: {}
}
state.peers.bob.notes = null
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value:{}})
state = events.follow(state, { id: 'alice', value: false })
t.deepEqual(state.peers.bob.clock, {})
t.deepEqual(state.peers.bob.notes, { })
state = events.notes(state, {id: 'bob', value:{alice: note(3, true), bob: note(2, true)}})
t.deepEqual(state.peers.bob.notes, { alice: note(-1, true), bob: note(-1, true)})
t.deepEqual(state.peers.bob.notes, null)
state.peers.bob.notes = null
state = events.notes(state, { id: 'bob', value: { charles: note(-1, true) } })
t.deepEqual(state.peers.bob.notes, { charles: note(-1, true) })
state.peers.bob.notes = null
state = events.notes(state, { id: 'bob', value: { charles: note(-1, true) } })
t.deepEqual(state.peers.bob.notes, null)
state = events.follow(state, {id: 'alice', value: false})
t.end()
})
t.deepEqual(state.peers.bob.notes, null)
test('remember clock of unfollow', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: { alice: true },
blocks: {},
peers: {}
}
state = events.notes(state, {id: 'bob', value:{charles: note(-1, true)}})
t.deepEqual(state.peers.bob.notes, {charles: note(-1, true)})
state.peers.bob.notes = null
state = events.notes(state, {id: 'bob', value:{charles: note(-1, true)}})
t.deepEqual(state.peers.bob.notes, null)
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: -1 } })
t.end()
})
t.deepEqual(state.peers.bob.clock, { alice: -1 })
t.deepEqual(state.peers.bob.notes, {})
t.end()
})
test('remember clock of unfollow', function (t) {
test('notes can be passed inside {clock:{}} object', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: { alice: true },
blocks: {},
peers: {}
}
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: -1 } })
var state = {
clock: { alice: 3, bob: 2},
follows: {alice: true}, blocks: {},
peers: {}
}
state = events.notes(state, {
id: 'bob',
value: {
clock: { bob: note(4, true) }
}
})
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value:{alice: -1}})
t.equal(state.peers.bob.clock.bob, 4)
t.end()
})
t.deepEqual(state.peers.bob.clock, {alice: -1})
t.deepEqual(state.peers.bob.notes, {})
test('test if timeout happens while loading', function (t) {
let state = {
clock: { alice: 3, bob: 2 },
follows: { alice: true, bob: true },
blocks: {},
peers: {},
timeout: 1
}
t.end()
})
state = events.connect(state, { id: 'bob', ts: 1, client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: note(0, true), bob: note(0, true) } })
test('notes can be passed inside {clock:{}} object', function (t) {
var state = {
clock: { alice: 3, bob: 2},
follows: {alice: true}, blocks: {},
peers: {}
}
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value:{alice: -1}})
state = events.connect(state, { id: 'charles', ts: 2, client: false })
console.log(state)
state = events.timeout(state, { ts: 4 })
state = events.notes(state, {id: 'bob', value: {
clock: {bob: note(4, true)}
}})
t.end()
})
t.equal(state.peers.bob.clock.bob, 4)
t.end()
})
test('test blocks while connected', function (t) {
let state = {
id: 'alice', // we are alice
clock: { alice: 3, bob: 2 },
follows: { alice: true, bob: true },
blocks: {},
peers: {},
timeout: 1
}
test('test if timeout happens while loading', function (t) {
state = events.connect(state, { id: 'bob', ts: 1, client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: note(0, true), bob: note(0, true) } })
var state = {
clock: { alice: 3, bob: 2},
follows: {alice: true, bob: true}, blocks: {},
peers: {},
timeout: 1
}
// charles blocks bob
state = events.block(state, { id: 'charles', target: 'bob', value: true })
t.deepEqual(state.blocks, { charles: { bob: true } })
t.notOk(state.peers.bob.blocked)
state = events.block(state, { id: 'alice', target: 'bob', value: true })
t.deepEqual(state.blocks, { charles: { bob: true }, alice: { bob: true } })
t.equal(state.peers.bob.blocked, true)
state = events.connect(state, {id: 'bob', ts: 1, client: false})
state = events.peerClock(state, {id: 'bob', value:{alice: note(0, true), bob: note(0, true)}})
state = events.timeout(state, { ts: 4 })
state = events.connect(state, {id: 'charles', ts: 2, client: false})
console.log(state)
state = events.timeout(state, {ts: 4})
t.end()
})
test('test blocks while connected', function (t) {
var state = {
id: 'alice', //we are alice
clock: { alice: 3, bob: 2},
follows: {alice: true, bob: true}, blocks: {},
peers: {},
timeout: 1
}
state = events.connect(state, {id: 'bob', ts: 1, client: false})
state = events.peerClock(state, {id: 'bob', value:{alice: note(0, true), bob: note(0, true)}})
//charles blocks bob
state = events.block(state, {id: 'charles', target: 'bob', value: true})
t.deepEqual(state.blocks, {charles: {bob: true}})
t.notOk(state.peers.bob.blocked)
state = events.block(state, {id: 'alice', target: 'bob', value: true})
t.deepEqual(state.blocks, {charles: {bob: true}, alice: {bob: true}})
t.equal(state.peers.bob.blocked, true)
state = events.timeout(state, {ts: 4})
t.end()
})
t.end()
})
}
if(!module.parent)
module.exports(require('./options'))
if (!module.parent) { module.exports(require('./options')) }
var createSimulator = require('./simulator')
var _events = require('../events')(require('./options'))
var test = require('tape')
var progress = require('../progress')
var events = {}
for(var k in _events) (function (fn, k) {
events[k] = function (state, ev) {
if(state.stalled) return state
return fn(state, ev)
}
})(_events[k], k)
const createSimulator = require('./simulator')
const _events = require('../events')(require('./options'))
const test = require('tape')
const progress = require('../progress')
const events = {}
for (const k in _events) {
(function (fn, k) {
events[k] = function (state, ev) {
if (state.stalled) return state
return fn(state, ev)
}
})(_events[k], k)
}
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
var carl = network['carl'] = tick.createPeer('carl')
var dawn = network['dawn'] = tick.createPeer('dawn')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')
const carl = network.carl = tick.createPeer('carl')
const dawn = network.dawn = tick.createPeer('dawn')

@@ -31,6 +32,6 @@ alice.state.timeout = bob.state.timeout = dawn.state.timeout = 2

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
bob.append({author: 'bob', sequence: 1, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })
bob.append({ author: 'bob', sequence: 1, content: {} })

@@ -54,3 +55,3 @@ alice.follow('alice')

carl.state.stalled = true
alice.append({author: 'alice', sequence: 4, content: {}})
alice.append({ author: 'alice', sequence: 4, content: {} })

@@ -63,4 +64,4 @@ tick.run(network)

function isComplete (peer, name) {
var prog = progress(peer.state)
t.equal(prog.current, prog.target, name +' is complete')
const prog = progress(peer.state)
t.equal(prog.current, prog.target, name + ' is complete')
}

@@ -76,10 +77,3 @@

var seed = process.argv[2]
if(isNaN(seed))
for(var i = 0; i < 100; i++) createTest(i)
else createTest(+seed, true)
const seed = process.argv[2]
if (isNaN(seed)) { for (let i = 0; i < 100; i++) createTest(i) } else createTest(+seed, true)
var createSimulator = require('./simulator')
var options = require('./options')
const createSimulator = require('./simulator')
const options = require('./options')
var test = require('tape')
const test = require('tape')
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log, options)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
var charles = network['charles'] = tick.createPeer('charles')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')
const charles = network.charles = tick.createPeer('charles')

@@ -20,5 +20,5 @@ alice.init({})

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })

@@ -33,5 +33,5 @@ alice.follow('alice')

while(tick(network)) ;
while (tick(network)) ;
//should have set up peer.replicatings to tx/rx alice
// should have set up peer.replicatings to tx/rx alice

@@ -41,3 +41,3 @@ t.deepEqual(bob.store, alice.store, 'alice<->bob')

if(log) tick.log()
if (log) tick.log()

@@ -48,18 +48,5 @@ t.end()

var seed = process.argv[2]
if(isNaN(seed))
for(var i = 0; i < 100; i++)
createTest(i)
else
createTest(+seed, true)
const seed = process.argv[2]
if (isNaN(seed)) {
for (let i = 0; i < 100; i++) { createTest(i) }
} else { createTest(+seed, true) }

@@ -1,5 +0,5 @@

var createSimulator = require('./simulator')
var options = require('./options')
var progress = require('../progress')
var test = require('tape')
const createSimulator = require('./simulator')
const options = require('./options')
const progress = require('../progress')
const test = require('tape')

@@ -14,20 +14,19 @@ function count (output) {

return output.reduce(function (a, b) {
if(b.msg) return a
for(var k in b.value)
a[b.from][k] = options.getSequence(b.value[k])
if (b.msg) return a
for (const k in b.value) { a[b.from][k] = options.getSequence(b.value[k]) }
return a
}, {alice: {}, bob: {}})
}, { alice: {}, bob: {} })
}
function isComplete (peer, name, t) {
var prog = progress(peer.state)
t.equal(prog.current, prog.target, name +' is complete')
const prog = progress(peer.state)
t.equal(prog.current, prog.target, name + ' is complete')
}
test('loose local state', function (t) {
var tick = createSimulator(0, true, options)
const tick = createSimulator(0, true, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
const network = {}
const alice = network.alice = tick.createPeer('alice')
let bob = network.bob = tick.createPeer('bob')

@@ -37,7 +36,7 @@ alice.init({})

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
bob.append({author: 'bob', sequence: 1, content: {}})
bob.append({author: 'bob', sequence: 2, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })
bob.append({ author: 'bob', sequence: 1, content: {} })
bob.append({ author: 'bob', sequence: 2, content: {} })

@@ -51,8 +50,8 @@ alice.follow('bob')

while(tick(network)) ;
while (tick(network)) ;
alice.disconnect(bob)
//should have set up peer.replicatings to tx/rx alice
t.deepEqual(flatten(tick.output), {alice: {alice: 3, bob: 0}, bob: {alice: 0, bob: 2}})
// should have set up peer.replicatings to tx/rx alice
t.deepEqual(flatten(tick.output), { alice: { alice: 3, bob: 0 }, bob: { alice: 0, bob: 2 } })
t.equal(count(tick.output), 2)

@@ -65,6 +64,6 @@

console.log("===========START OVER===========")
console.log('===========START OVER===========')
// bob gets a brick in his head and forgets everything
bob = network['bob'] = tick.createPeer('bob')
bob = network.bob = tick.createPeer('bob')
bob.init({})

@@ -77,5 +76,5 @@ t.deepEqual(bob.store, {})

while(tick(network)) ;
while (tick(network)) ;
console.log("===========SECOND ROUND===========")
console.log('===========SECOND ROUND===========')

@@ -85,3 +84,3 @@ // simulate a contact message received in bobs feed

while(tick(network)) ;
while (tick(network)) ;

@@ -95,9 +94,9 @@ t.deepEqual(bob.store, alice.store)

console.log("===========START OVER 2===========")
console.log('===========START OVER 2===========')
// bob gets a brick in his head and restores from backup
bob = network['bob'] = tick.createPeer('bob')
bob = network.bob = tick.createPeer('bob')
bob.init({})
bob.append({author: 'bob', sequence: 1, content: {}})
bob.append({ author: 'bob', sequence: 1, content: {} })

@@ -108,5 +107,5 @@ bob.follow('bob')

while(tick(network)) ;
while (tick(network)) ;
console.log("===========SECOND ROUND===========")
console.log('===========SECOND ROUND===========')

@@ -116,3 +115,3 @@ // simulate a contact message received in bobs feed

while(tick(network)) ;
while (tick(network)) ;

@@ -119,0 +118,0 @@ t.deepEqual(bob.store, alice.store)

@@ -0,55 +1,56 @@

/* eslint-disable camelcase */
var test = require('tape')
const test = require('tape')
module.exports = function (events) {
const note = events.note
var note = events.note
test('if connects to multiple peers, should replicate a feed from only one', function (t) {
let state = events.initialize('alice')
state.follows = {
alice: true, bob: true, charles: true
}
state = events.clock(state, { alice: 3, bob: 2, charles: 5 })
test('if connects to multiple peers, should replicate a feed from only one', function (t) {
state = events.connect(state, { id: 'bob', client: false })
state = events.peerClock(state, { id: 'bob', value: { alice: 2, bob: 2, charles: 5 } })
state = events.connect(state, { id: 'charles', client: false })
state = events.peerClock(state, { id: 'charles', value: { alice: 2, bob: 2, charles: 5 } })
var state = events.initialize('alice')
state.follows = {
alice: true, bob: true, charles: true
}
state = events.clock(state, {alice: 3, bob: 2, charles: 5})
state = events.connect(state, {id: 'bob', client: false})
state = events.peerClock(state, {id: 'bob', value: {alice: 2, bob: 2, charles: 5}})
state = events.connect(state, {id: 'charles', client: false})
state = events.peerClock(state, {id: 'charles', value: {alice: 2, bob: 2, charles: 5}})
console.log(state.peers)
console.log(state.peers)
state = events.notes(state, {
id: 'bob',
value: {
alice: note(3, true), bob: note(5, true), charles: note(9, true)
}
})
state = events.notes(state, {
id: 'charles',
value: {
alice: note(3, true), bob: note(4, true), charles: note(9, true)
}
})
console.log(state.peers)
state = events.notes(state, {id: 'bob', value: {
alice: note(3, true), bob: note(5, true), charles: note(9, true)
}})
state = events.notes(state, {id: 'charles', value: {
alice: note(3, true), bob: note(4, true), charles: note(9, true)
}})
console.log(state.peers)
//we should only request transmissions from at most one peer.
var notes = {}
for(var peer_id in state.peers) {
var peer = state.peers[peer_id]
for(var feed_id in peer.notes) {
t.equal(events.getReceive(peer.notes[feed_id]), peer.replicating[feed_id].rx, 'implied rx state should be recorded, seq:'+peer.notes[feed_id]+', rx='+peer.replicating[feed_id].rx)
if(events.getReceive(peer.notes[feed_id])) {
notes[feed_id] = (notes[feed_id] || 0) + 1
// we should only request transmissions from at most one peer.
const notes = {}
for (const peer_id in state.peers) {
const peer = state.peers[peer_id]
for (const feed_id in peer.notes) {
t.equal(events.getReceive(peer.notes[feed_id]), peer.replicating[feed_id].rx, 'implied rx state should be recorded, seq:' + peer.notes[feed_id] + ', rx=' + peer.replicating[feed_id].rx)
if (events.getReceive(peer.notes[feed_id])) {
notes[feed_id] = (notes[feed_id] || 0) + 1
}
}
}
}
console.log(JSON.stringify(state.peers, null, 2))
console.log(JSON.stringify(state.peers, null, 2))
t.deepEqual(notes, {alice: 1, bob: 1, charles: 1})
t.deepEqual(notes, { alice: 1, bob: 1, charles: 1 })
t.end()
})
t.end()
})
}
if(!module.parent)
module.exports(require('./options'))
if (!module.parent) { module.exports(require('./options')) }

@@ -1,13 +0,13 @@

var createSimulator = require('./simulator')
var options = require('./options')
const createSimulator = require('./simulator')
const options = require('./options')
var test = require('tape')
const test = require('tape')
test('partial replication', function (t) {
var tick = createSimulator(0, true, options)
const tick = createSimulator(0, true, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
var charlie = network['charlie'] = tick.createPeer('charlie')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')
const charlie = network.charlie = tick.createPeer('charlie')

@@ -18,8 +18,8 @@ alice.init({})

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })
//alice.store['alice'] = alice.store['alice'].slice(1)
// alice.store['alice'] = alice.store['alice'].slice(1)
alice.follow('alice')

@@ -34,3 +34,3 @@ bob.follow('alice')

while(tick(network)) ;
while (tick(network)) ;

@@ -43,8 +43,8 @@ // alice sends her whole feed to bob

// lets assume that instead bob had done a partial replication with alice
bob.store['alice'] = bob.store['alice'].slice(1)
bob.store.alice = bob.store.alice.slice(1)
bob.connect(charlie)
while(tick(network)) ;
while (tick(network)) ;
// charlie is not able to get alices feed from bob

@@ -54,9 +54,9 @@ t.deepEqual({}, charlie.store)

charlie.connect(alice)
while(tick(network)) ;
while (tick(network)) ;
// charlie should now have alices feed
t.deepEqual(alice.store, charlie.store)
t.end()
})

@@ -1,5 +0,5 @@

var createSimulator = require('./simulator')
var options = require('./options')
var progress = require('../progress')
var test = require('tape')
const createSimulator = require('./simulator')
const options = require('./options')
const progress = require('../progress')
const test = require('tape')

@@ -14,16 +14,15 @@ function count (output) {

return output.reduce(function (a, b) {
if(b.msg) return a
for(var k in b.value)
a[b.from][k] = options.getSequence(b.value[k])
if (b.msg) return a
for (const k in b.value) { a[b.from][k] = options.getSequence(b.value[k]) }
return a
}, {alice: {}, bob: {}})
}, { alice: {}, bob: {} })
}
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log, options)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')

@@ -33,6 +32,6 @@ alice.init({})

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
bob.append({author: 'bob', sequence: 1, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })
bob.append({ author: 'bob', sequence: 1, content: {} })

@@ -46,13 +45,13 @@ alice.follow('alice')

while(tick(network)) ;
while (tick(network)) ;
alice.disconnect(bob)
//should have set up peer.replicatings to tx/rx alice
t.deepEqual(flatten(tick.output), {alice: {alice: 3, bob: 0}, bob: {alice: 0, bob: 1}})
// should have set up peer.replicatings to tx/rx alice
t.deepEqual(flatten(tick.output), { alice: { alice: 3, bob: 0 }, bob: { alice: 0, bob: 1 } })
t.equal(count(tick.output), 2)
bob.append({author: 'bob', sequence: 2, content: {}})
bob.append({ author: 'bob', sequence: 2, content: {} })
console.log('1', tick.output)
tick.output.splice(0, tick.output.length)
while(tick(network)) ;
while (tick(network)) ;

@@ -62,6 +61,6 @@ console.log('2', tick.output)

alice.connect(bob)
while(tick(network)) ;
while (tick(network)) ;
console.log('3', tick.output)
t.deepEqual(flatten(tick.output), {alice: {alice: 3, bob: 1}, bob: {alice: 3, bob: 2}})
t.deepEqual(flatten(tick.output), { alice: { alice: 3, bob: 1 }, bob: { alice: 3, bob: 2 } })
t.equal(count(tick.output), 3)

@@ -72,3 +71,3 @@ tick.output.splice(0, tick.output.length)

alice.connect(bob)
while(tick(network)) ;
while (tick(network)) ;

@@ -79,6 +78,5 @@ t.deepEqual(bob.store, alice.store)

function isComplete (peer, name) {
var prog = progress(peer.state)
t.equal(prog.current, prog.target, name +' is complete')
const prog = progress(peer.state)
t.equal(prog.current, prog.target, name + ' is complete')
}

@@ -93,8 +91,3 @@

var seed = process.argv[2]
if(isNaN(seed))
for(var i = 0; i < 100; i++) createTest(i)
else createTest(+seed, true)
const seed = process.argv[2]
if (isNaN(seed)) { for (let i = 0; i < 100; i++) createTest(i) } else createTest(+seed, true)

@@ -1,13 +0,13 @@

var createSimulator = require('./simulator')
var options = require('./options')
const createSimulator = require('./simulator')
const options = require('./options')
var test = require('tape')
const test = require('tape')
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log, options)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')

@@ -17,5 +17,5 @@ alice.init({})

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })

@@ -27,5 +27,5 @@ alice.follow('alice')

while(tick(network)) ;
while (tick(network)) ;
//should have set up peer.replicatings to tx/rx alice
// should have set up peer.replicatings to tx/rx alice

@@ -37,7 +37,5 @@ t.deepEqual(bob.store, alice.store)

var seed = process.argv[2]
if(isNaN(seed))
for(var i = 0; i < 100; i++)
createTest(i)
else
createTest(+seed, true)
const seed = process.argv[2]
if (isNaN(seed)) {
for (let i = 0; i < 100; i++) { createTest(i) }
} else { createTest(+seed, true) }

@@ -1,45 +0,49 @@

var RNG = require('rng')
/* eslint-disable camelcase */
const RNG = require('rng')
var log
let log
module.exports = function (seed, _log, _events) {
if(!_events) _events = require('../events')(require('../v3'))
if (!_events) _events = require('../events')(require('../v3'))
log = _log
var rng = new RNG.MT(seed || 0)
const rng = new RNG.MT(seed || 0)
var events = {}
const events = {}
for(var k in _events) (function (fn, k) {
events[k] = function (state, value) {
if(log) console.log(k.toUpperCase()+'('+state.id+')', value)
return fn(state, value)
}
})(_events[k],k)
for (const k in _events) {
(function (fn, k) {
events[k] = function (state, value) {
if (log) console.log(k.toUpperCase() + '(' + state.id + ')', value)
return fn(state, value)
}
})(_events[k], k)
}
var output = []
var ts = 0
const output = []
let ts = 0
function createPeer(id, validate) {
function createPeer (id, validate) {
validate = validate || function () {}
var store = {}, state = events.initialize(id), self
var ts = 0
var pClock = {}
return self = {
id: id,
let store = {}
let state = events.initialize(id)
let ts = 0
const pClock = {}
const self = {
id,
clocks: pClock,
store: store,
state: state,
store,
state,
retriving: [],
init: function (_store) {
self.store = store = _store
var clock = {}
for(var k in store)
clock[k] = store[k].length
const clock = {}
for (const k in store) { clock[k] = store[k].length }
state = events.clock(state, clock)
},
connect: function (other) {
state = events.connect(state, {id: other.id, ts: ++ts, client: true})
state = events.peerClock(state, {id: other.id, value: pClock[other.id] || {}, ts: ++ts})
other.state = events.connect(other.state, {id: this.id, ts: ++ts, client: false})
other.state = events.peerClock(other.state, {id: id, value: other.clocks[id] || {}, ts: ++ts})
state = events.connect(state, { id: other.id, ts: ++ts, client: true })
state = events.peerClock(state, { id: other.id, value: pClock[other.id] || {}, ts: ++ts })
other.state = events.connect(other.state, { id: this.id, ts: ++ts, client: false })
other.state = events.peerClock(other.state, { id, value: other.clocks[id] || {}, ts: ++ts })
},

@@ -50,12 +54,12 @@ disconnect: function (other) {

state = events.disconnect(state, {id: other.id, ts: ++ts})
other.state = events.disconnect(other.state, {id: this.id, ts: ++ts})
state = events.disconnect(state, { id: other.id, ts: ++ts })
other.state = events.disconnect(other.state, { id: this.id, ts: ++ts })
},
follow: function (peer, value) {
state = events.follow(state, {id: peer, value: value !== false, ts: ++ts})
state = events.follow(state, { id: peer, value: value !== false, ts: ++ts })
},
append: function (msg) {
var ary = store[msg.author] = store[msg.author] || []
if(msg.sequence === ary.length + 1) {
validate (store[msg.author], msg)
const ary = store[msg.author] = store[msg.author] || []
if (msg.sequence === ary.length + 1) {
validate(store[msg.author], msg)
ary.push(msg)

@@ -66,8 +70,10 @@ state = events.append(state, msg)

}
return self
}
function shuffle (ary) {
for(var i = 0; i < ary.length; i++) {
var j = ~~(rng.random()*ary.length)
var tmp = ary[i]
for (let i = 0; i < ary.length; i++) {
const j = ~~(rng.random() * ary.length)
const tmp = ary[i]
ary[i] = ary[j]

@@ -79,9 +85,8 @@ ary[j] = tmp

function randomFind(obj, iter) {
if(!iter) iter = function (key, fn) { return fn() }
if(!obj) throw new Error('obj not provided')
function randomFind (obj, iter) {
if (!iter) iter = function (key, fn) { return fn() }
if (!obj) throw new Error('obj not provided')
var keys = shuffle(Object.keys(obj))
for(var i = 0; i < keys.length; i++)
if(iter(keys[i], obj[keys[i]])) return true
const keys = shuffle(Object.keys(obj))
for (let i = 0; i < keys.length; i++) { if (iter(keys[i], obj[keys[i]])) return true }

@@ -93,10 +98,10 @@ return false

return randomFind(network, function (id, peer) {
//database ops
if(peer.state.stalled) return
// database ops
if (peer.state.stalled) return
return randomFind([function () {
//append(receive), retrive, retrive_cb
// append(receive), retrive, retrive_cb
return randomFind([function () {
return randomFind(peer.state.peers, function (key, p2p) {
if(!p2p.clock) {
peer.state = events.peerClock(peer.state, {id: key, value: {}, ts: ++ts})
if (!p2p.clock) {
peer.state = events.peerClock(peer.state, { id: key, value: {}, ts: ++ts })
return true

@@ -106,8 +111,9 @@ }

}, function () {
if(peer.state.receive.length) {
var ev = peer.state.receive.shift()
if (peer.state.receive.length) {
const ev = peer.state.receive.shift()
try {
peer.append(ev.value)
} catch (err) {
return peer.state = events.block(peer.state, {id: ev.value.author, target: ev.id, value: true})
peer.state = events.block(peer.state, { id: ev.value.author, target: ev.id, value: true })
return peer.state
}

@@ -118,13 +124,13 @@ return true

return randomFind(peer.state.peers, function (key, p2p) {
//randomly order, to simulate async
// randomly order, to simulate async
p2p.retrive = shuffle(p2p.retrive)
if(p2p.retrive.length) {
var peer_id = p2p.retrive.shift()
//it's possible that two peers need to retrive the same message at the same time
//this may mean that the retrival is queued twice.
var rep = p2p.replicating[peer_id]
if(rep.tx && rep.sent < peer.state.clock[peer_id]) {
var msg = peer.store[peer_id][rep.sent]
if(msg == null) {
throw new Error('null msg!, clock:'+peer.state.clock[peer_id]+ ', id:'+peer_id)
if (p2p.retrive.length) {
const peer_id = p2p.retrive.shift()
// it's possible that two peers need to retrive the same message at the same time
// this may mean that the retrival is queued twice.
const rep = p2p.replicating[peer_id]
if (rep.tx && rep.sent < peer.state.clock[peer_id]) {
const msg = peer.store[peer_id][rep.sent]
if (msg == null) {
throw new Error('null msg!, clock:' + peer.state.clock[peer_id] + ', id:' + peer_id)
}

@@ -137,3 +143,3 @@ peer.retriving.push(msg)

}, function () {
if(peer.retriving.length) {
if (peer.retriving.length) {
peer.retriving = shuffle(peer.retriving)

@@ -144,16 +150,15 @@ peer.state = events.retrive(peer.state, peer.retriving.shift())

}])
}, function () { //network ops
}, function () { // network ops
return randomFind(peer.state.peers, function (remote_id, remote) {
if(remote.notes) {
var notes = remote.notes
if (remote.notes) {
const notes = remote.notes
remote.notes = null
network[remote_id].state =
events.notes(network[remote_id].state, {id: id, value: notes, ts: ++ts})
output.push({from: id, to: remote_id, value: notes, msg: false})
events.notes(network[remote_id].state, { id, value: notes, ts: ++ts })
output.push({ from: id, to: remote_id, value: notes, msg: false })
return true
}
else if(remote.msgs.length) {
output.push({from: id, to: remote_id, value: remote.msgs[0], msg: true})
} else if (remote.msgs.length) {
output.push({ from: id, to: remote_id, value: remote.msgs[0], msg: true })
network[remote_id].state =
events.receive(network[remote_id].state, {id: id, value: remote.msgs.shift(), ts: ++ts})
events.receive(network[remote_id].state, { id, value: remote.msgs.shift(), ts: ++ts })
return true

@@ -164,3 +169,3 @@ }

})
//TODO: test random network connections.
// TODO: test random network connections.
}

@@ -174,6 +179,4 @@

tick.output.map(function (e) {
if(e.msg)
return e.from+'>'+e.to+':'+e.value.author[0]+e.value.sequence
else
return e.from+'>'+e.to+':'+JSON.stringify(e.value)
if (e.msg) return e.from + '>' + e.to + ':' + e.value.author[0] + e.value.sequence
else return e.from + '>' + e.to + ':' + JSON.stringify(e.value)
}).join('\n')

@@ -184,14 +187,14 @@ )

tick.ts = function (_ts) {
return ts += (_ts|0)
ts += (_ts | 0)
return ts
}
tick.run = function (network) {
var loop = 1, first = true
while(loop) {
let loop = 1; let first = true
while (loop) {
loop = 0
while(tick(network)) loop ++
if(loop || first) {
for(var k in network)
network[k].state = events.timeout(network[k].state, {ts: ts++})
if(first) loop = 1
while (tick(network)) loop++
if (loop || first) {
for (const k in network) { network[k].state = events.timeout(network[k].state, { ts: ts++ }) }
if (first) loop = 1
first = false

@@ -204,4 +207,1 @@ }

}
var createSimulator = require('./simulator')
var _events = require('../events')(require('./options'))
var test = require('tape')
const createSimulator = require('./simulator')
const _events = require('../events')(require('./options'))
const test = require('tape')
var events = {}
for(var k in _events) (function (fn, k) {
events[k] = function (state, ev) {
if(state.stalled) return state
return fn(state, ev)
}
})(_events[k], k)
const events = {}
for (const k in _events) {
(function (fn, k) {
events[k] = function (state, ev) {
if (state.stalled) return state
return fn(state, ev)
}
})(_events[k], k)
}
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log, events)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log, events)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
var carl = network['carl'] = tick.createPeer('carl')
var dawn = network['dawn'] = tick.createPeer('dawn')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')
const carl = network.carl = tick.createPeer('carl')
const dawn = network.dawn = tick.createPeer('dawn')

@@ -31,10 +32,10 @@ alice.state.timeout = bob.state.timeout = dawn.state.timeout = 1

alice.append({author: 'alice', sequence: 1, content: {}})
bob.append({author: 'alice', sequence: 1, content: {}})
carl.append({author: 'alice', sequence: 1, content: {}})
dawn.append({author: 'alice', sequence: 1, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
bob.append({ author: 'alice', sequence: 1, content: {} })
carl.append({ author: 'alice', sequence: 1, content: {} })
dawn.append({ author: 'alice', sequence: 1, content: {} })
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
bob.append({author: 'bob', sequence: 1, content: {}})
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })
bob.append({ author: 'bob', sequence: 1, content: {} })

@@ -57,20 +58,19 @@ alice.follow('alice')

while((
while ((
(!dawn.store.alice || dawn.store.alice.length < 2)
// &&
// (!bob.store.alice || bob.store.alice.length < 2)
// &&
// (!bob.store.alice || bob.store.alice.length < 2)
) && tick(network))
;
carl.state.stalled = true
// bob.state.peers.alice.replicating.alice.rx = false
// dawn.state.peers.bob.replicating.alice.rx = false
// bob.state.peers.carl.replicating.alice.rx = true
// dawn.state.peers.carl.replicating.alice.rx = true
// bob.state.peers.alice.replicating.alice.rx = false
// dawn.state.peers.bob.replicating.alice.rx = false
// bob.state.peers.carl.replicating.alice.rx = true
// dawn.state.peers.carl.replicating.alice.rx = true
// bob.state.peers.alice.notes = null
// dawn.state.peers.bob.notes = null
// bob.state.peers.alice.notes = null
// dawn.state.peers.bob.notes = null
//then continue running the simulation, including timeout
// then continue running the simulation, including timeout
tick.log()

@@ -80,12 +80,12 @@ tick.output.splice(0, tick.output.length)

console.log(JSON.stringify(dawn.state, null, 2))
// console.log(tick.ts())
// console.log("CONTINUE")
// return t.end()
// console.log(tick.ts())
// console.log("CONTINUE")
// return t.end()
tick.run(network)
// while(tick(network));
// while(tick(network));
tick.log()
// return t.end()
// return t.end()

@@ -99,10 +99,3 @@ t.deepEqual(dawn.store, alice.store, 'dawn matches alice')

var seed = process.argv[2]
if(isNaN(seed))
for(var i = 0; i < 100; i++) createTest(i)
else createTest(+seed, true)
const seed = process.argv[2]
if (isNaN(seed)) { for (let i = 0; i < 100; i++) createTest(i) } else createTest(+seed, true)

@@ -1,12 +0,10 @@

var createPeer = require('../')
var test = require('tape')
const createPeer = require('../')
const test = require('tape')
function create (id) {
var store = {}
const store = {}
function append (msg, cb) {
store[msg.author] = store[msg.author] || []
if(msg.sequence - 1 != store[msg.author].length)
cb(new Error('out of order'))
else {
if (msg.sequence - 1 !== store[msg.author].length) { cb(new Error('out of order')) } else {
store[msg.author].push(msg)

@@ -18,4 +16,4 @@ p.onAppend(msg)

var p = createPeer({
id: id,
const p = createPeer({
id,
getClock: function (id, cb) {

@@ -26,6 +24,6 @@ cb(null, {})

getAt: function (pair, cb) {
if(!store[pair.id] || !store[pair.id][pair.sequence]) cb(new Error('not found'))
if (!store[pair.id] || !store[pair.id][pair.sequence]) cb(new Error('not found'))
else cb(null, store[pair.id][pair.sequence])
},
append: append
append
})

@@ -38,6 +36,5 @@ p.store = store

test('a<->b', function (t) {
const alice = create('alice')
const bob = create('bob')
var alice = create('alice')
var bob = create('bob')
alice.request('alice', true)

@@ -48,30 +45,27 @@ alice.request('bob', true)

var as = alice.createStream('bob', 3, false)
var bs = bob.createStream('alice', 3, true)
const as = alice.createStream('bob', 3, false)
const bs = bob.createStream('alice', 3, true)
console.log('initial.alice:',alice.progress())
console.log('initial.bob :',bob.progress())
console.log('initial.alice:', alice.progress())
console.log('initial.bob :', bob.progress())
as.pipe(bs).pipe(as)
alice.append({ author: 'alice', sequence: 1, content: 'hello' }, function () {})
bob.append({ author: 'bob', sequence: 1, content: 'hello' }, function () {})
alice.append({author: 'alice', sequence: 1, content: 'hello'}, function () {})
bob.append({author: 'bob', sequence: 1, content: 'hello'}, function () {})
console.log(bob.store)
console.log(alice.store)
console.log('final.alice:',alice.progress())
console.log('final.bob :',bob.progress())
console.log('final.alice:', alice.progress())
console.log('final.bob :', bob.progress())
t.deepEqual(alice.store, bob.store)
t.end()
})
test('a<->b,b', function (t) {
const alice = create('alice')
const bob = create('bob')
var alice = create('alice')
var bob = create('bob')
alice.request('alice', true)

@@ -82,12 +76,12 @@ alice.request('bob', true)

var as = alice.createStream('bob', 3, true)
var bs = bob.createStream('alice', 3, false)
const as = alice.createStream('bob', 3, true)
const bs = bob.createStream('alice', 3, false)
console.log('initial.alice:',alice.progress())
console.log('initial.bob :',bob.progress())
console.log('initial.alice:', alice.progress())
console.log('initial.bob :', bob.progress())
as.pipe(bs).pipe(as)
alice.append({author: 'alice', sequence: 1, content: 'hello'}, function () {})
bob.append({author: 'bob', sequence: 1, content: 'hello'}, function () {})
alice.append({ author: 'alice', sequence: 1, content: 'hello' }, function () {})
bob.append({ author: 'bob', sequence: 1, content: 'hello' }, function () {})

@@ -97,4 +91,4 @@ console.log(bob.store)

console.log('final.alice:',alice.progress())
console.log('final.bob :',bob.progress())
console.log('final.alice:', alice.progress())
console.log('final.bob :', bob.progress())

@@ -106,9 +100,7 @@ t.deepEqual(alice.store, bob.store)

test('a3<->b3<->c2', function (t) {
const alice = create('alice')
const bob = create('bob')
const charles = create('charles')
var alice = create('alice')
var bob = create('bob')
var charles = create('charles')
alice.request('alice', true)

@@ -121,10 +113,10 @@ alice.request('bob', true)

var as3 = alice.createStream('bob', 3, true)
var bs3 = bob.createStream('alice', 3, false)
var bs2 = bob.createStream('charles', 3, false)
var cs2 = charles.createStream('bob', 3, true)
const as3 = alice.createStream('bob', 3, true)
const bs3 = bob.createStream('alice', 3, false)
const bs2 = bob.createStream('charles', 3, false)
const cs2 = charles.createStream('bob', 3, true)
console.log('initial.alice:',alice.progress())
console.log('initial.bob :',bob.progress())
console.log('initial.charles :',charles.progress())
console.log('initial.alice:', alice.progress())
console.log('initial.bob :', bob.progress())
console.log('initial.charles :', charles.progress())

@@ -134,11 +126,10 @@ as3.pipe(bs3).pipe(as3)

alice.append({ author: 'alice', sequence: 1, content: 'hello' }, function () {})
bob.append({ author: 'bob', sequence: 1, content: 'hello' }, function () {})
alice.append({author: 'alice', sequence: 1, content: 'hello'}, function () {})
bob.append({author: 'bob', sequence: 1, content: 'hello'}, function () {})
console.log(bob.store)
console.log(alice.store)
console.log('final.alice:',alice.progress())
console.log('final.bob :',bob.progress())
console.log('final.alice:', alice.progress())
console.log('final.bob :', bob.progress())

@@ -148,8 +139,7 @@ t.deepEqual(alice.store, bob.store)

t.end()
})
test('a<-!>b', function (t) {
var alice = create('alice')
var bob = create('bob')
const alice = create('alice')
const bob = create('bob')

@@ -162,4 +152,4 @@ alice.request('alice', true)

var as = alice.createStream('bob', 3, false)
var bs = bob.createStream('alice', 3, true)
const as = alice.createStream('bob', 3, false)
const bs = bob.createStream('alice', 3, true)

@@ -174,4 +164,4 @@ as.pipe(bs).pipe(as)

test('a<->b...!', function (t) {
var alice = create('alice')
var bob = create('bob')
const alice = create('alice')
const bob = create('bob')

@@ -183,4 +173,4 @@ alice.request('alice', true)

var as = alice.createStream('bob', 3, false)
var bs = bob.createStream('alice', 3, true)
const as = alice.createStream('bob', 3, false)
const bs = bob.createStream('alice', 3, true)

@@ -200,4 +190,4 @@ as.pipe(bs).pipe(as)

test('b<-!->a', function (t) {
var alice = create('alice')
var bob = create('bob')
const alice = create('alice')
const bob = create('bob')

@@ -210,4 +200,4 @@ alice.request('alice', true)

var as = alice.createStream('bob', 3, true)
var bs = bob.createStream('alice', 3, false)
const as = alice.createStream('bob', 3, true)
const bs = bob.createStream('alice', 3, false)

@@ -220,11 +210,1 @@ as.pipe(bs).pipe(as)

})
var createSimulator = require('./simulator')
var options = require('./options')
const createSimulator = require('./simulator')
const options = require('./options')
var test = require('tape')
const test = require('tape')
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log, options)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
var charles = network['charles'] = tick.createPeer('charles')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')
const charles = network.charles = tick.createPeer('charles')

@@ -20,13 +20,13 @@ alice.init({})

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })
bob.append({author: 'bob', sequence: 1, content: {}})
bob.append({author: 'bob', sequence: 2, content: {}})
bob.append({author: 'bob', sequence: 3, content: {}})
bob.append({ author: 'bob', sequence: 1, content: {} })
bob.append({ author: 'bob', sequence: 2, content: {} })
bob.append({ author: 'bob', sequence: 3, content: {} })
charles.append({author: 'charles', sequence: 1, content: {}})
charles.append({author: 'charles', sequence: 2, content: {}})
charles.append({author: 'charles', sequence: 3, content: {}})
charles.append({ author: 'charles', sequence: 1, content: {} })
charles.append({ author: 'charles', sequence: 2, content: {} })
charles.append({ author: 'charles', sequence: 3, content: {} })

@@ -48,5 +48,5 @@ alice.follow('alice')

while(tick(network)) ;
while (tick(network)) ;
//should have set up peer.replicatings to tx/rx alice
// should have set up peer.replicatings to tx/rx alice

@@ -58,6 +58,6 @@ t.deepEqual(bob.store, alice.store, 'alice<->bob')

alice.append({author: 'alice', sequence: 4, content: {}})
alice.append({author: 'alice', sequence: 5, content: {}})
alice.append({ author: 'alice', sequence: 4, content: {} })
alice.append({ author: 'alice', sequence: 5, content: {} })
while(tick(network)) ;
while (tick(network)) ;

@@ -69,5 +69,5 @@ t.deepEqual(bob.store, alice.store, 'alice<->bob')

alice.append({author: 'alice', sequence: 6, content: {}})
alice.append({ author: 'alice', sequence: 6, content: {} })
while(tick(network)) ;
while (tick(network)) ;

@@ -77,3 +77,3 @@ t.deepEqual(bob.store, alice.store, 'alice<->bob')

if(log) tick.log()
if (log) tick.log()

@@ -84,12 +84,4 @@ t.end()

var seed = process.argv[2]
if(isNaN(seed)) for(var i = 0; i < 100; i++) createTest(i)
const seed = process.argv[2]
if (isNaN(seed)) for (let i = 0; i < 100; i++) createTest(i)
else createTest(+seed, true)
var test = require('tape')
var events = require('../events')(require('./options'))
const test = require('tape')
const events = require('../events')(require('./options'))
test('switch peers if timeout exceeded', function (t) {
var state = {
let state = {
id: 'alice',
clock: {bob: 5, charles: 6, dawn: 3},
clock: { bob: 5, charles: 6, dawn: 3 },
retrive: [],
follows: {bob: true}, blocks: {},
follows: { bob: true },
blocks: {},
timeout: 1000,
peers: {
bob: {
clock: {bob: 7},
clock: { bob: 7 },
notes: null,
replicating: { bob: {rx: true, tx: false, sent: -1 }},
replicating: { bob: { rx: true, tx: false, sent: -1 } },
ts: 3000
},
charles: {
clock: {bob: 10},
clock: { bob: 10 },
notes: null,
replicating: { bob: {rx: false, tx: false, sent: -1 }}
replicating: { bob: { rx: false, tx: false, sent: -1 } }
},
dawn: {
clock: {bob: 9},
clock: { bob: 9 },
notes: null,
replicating: { bob: {rx: false, tx: false, sent: -1 }}
replicating: { bob: { rx: false, tx: false, sent: -1 } }
}

@@ -32,3 +33,3 @@ }

state = events.timeout(state, {ts: 5000})
state = events.timeout(state, { ts: 5000 })

@@ -40,3 +41,3 @@ t.equal(state.peers.bob.replicating.bob.rx, false)

state = events.timeout(state, {ts: 10000})
state = events.timeout(state, { ts: 10000 })

@@ -46,3 +47,3 @@ t.equal(state.peers.charles.replicating.bob.rx, false)

state = events.timeout(state, {ts: 15000})
state = events.timeout(state, { ts: 15000 })

@@ -53,11 +54,10 @@ t.equal(state.peers.dawn.replicating.bob.rx, false)

t.end()
})
test('if up to latest message by peer, swich if another peer claims newer', function (t) {
var state = {
let state = {
id: 'alice',
clock: {bob: 7, charles: 6, dawn: 3},
clock: { bob: 7, charles: 6, dawn: 3 },
retrive: [],
follows: {bob: true},
follows: { bob: true },
blocks: {},

@@ -67,16 +67,16 @@ timeout: 1000,

bob: {
clock: {bob: 7},
clock: { bob: 7 },
notes: null,
replicating: { bob: {rx: true, tx: false, sent: -1 }},
replicating: { bob: { rx: true, tx: false, sent: -1 } },
ts: 3000
},
charles: {
clock: {bob: 10},
clock: { bob: 10 },
notes: null,
replicating: { bob: {rx: false, tx: false, sent: -1 }}
replicating: { bob: { rx: false, tx: false, sent: -1 } }
},
dawn: {
clock: {bob: 9},
clock: { bob: 9 },
notes: null,
replicating: { bob: {rx: false, tx: false, sent: -1 }}
replicating: { bob: { rx: false, tx: false, sent: -1 } }
}

@@ -86,3 +86,3 @@ }

state = events.timeout(state, {ts: 5000})
state = events.timeout(state, { ts: 5000 })

@@ -92,9 +92,8 @@ t.equal(state.peers.bob.replicating.bob.rx, false)

state = events.timeout(state, { ts: 10000 })
state = events.timeout(state, {ts: 10000})
t.equal(state.peers.charles.replicating.bob.rx, false)
t.equal(state.peers.dawn.replicating.bob.rx, true)
state = events.timeout(state, {ts: 15000})
state = events.timeout(state, { ts: 15000 })

@@ -104,9 +103,6 @@ console.log(JSON.stringify(state, null, 2))

t.equal(state.peers.dawn.replicating.bob.rx, false)
// t.equal(state.peers.charles.replicating.bob.rx, true)
// t.equal(state.peers.charles.replicating.bob.rx, true)
t.equal(state.peers.bob.replicating.bob.rx, true)
t.end()
})

@@ -1,15 +0,15 @@

var createSimulator = require('./simulator')
var options = require('./options')
var progress = require('../progress')
const createSimulator = require('./simulator')
const options = require('./options')
const progress = require('../progress')
var test = require('tape')
const test = require('tape')
function createTest (seed, log) {
test('simple test with seed:'+seed, function (t) {
var tick = createSimulator(seed, log, options)
test('simple test with seed:' + seed, function (t) {
const tick = createSimulator(seed, log, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
var charles = network['charles'] = tick.createPeer('charles')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')
const charles = network.charles = tick.createPeer('charles')

@@ -20,5 +20,5 @@ alice.init({})

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })

@@ -32,5 +32,5 @@ alice.follow('alice')

while(tick(network)) ;
while (tick(network)) ;
//should have set up peer.replicatings to tx/rx alice
// should have set up peer.replicatings to tx/rx alice

@@ -42,6 +42,6 @@ t.deepEqual(bob.store, alice.store, 'alice<->bob')

alice.append({author: 'alice', sequence: 4, content: {}})
alice.append({author: 'alice', sequence: 5, content: {}})
alice.append({ author: 'alice', sequence: 4, content: {} })
alice.append({ author: 'alice', sequence: 5, content: {} })
while(tick(network)) ;
while (tick(network)) ;

@@ -53,5 +53,5 @@ t.deepEqual(bob.store, alice.store, 'alice<->bob')

alice.append({author: 'alice', sequence: 6, content: {}})
alice.append({ author: 'alice', sequence: 6, content: {} })
while(tick(network)) ;
while (tick(network)) ;

@@ -61,13 +61,13 @@ t.deepEqual(bob.store, alice.store, 'alice<->bob')

var totals = tick.output.reduce(function (a, b) {
if(!a) a = [0,0,0]; a[0] ++; a[1 + (+b.msg)] ++
const totals = tick.output.reduce(function (a, b) {
if (!a) a = [0, 0, 0]; a[0]++; a[1 + (+b.msg)]++
return a
}, null)
t.equal(totals[1], 3*2, 'number of handshakes sent is connections*2')
t.equal(totals[2], 6*(3-1), 'number of msgs sent is msgs*(peers-1)')
t.equal(totals[1], 3 * 2, 'number of handshakes sent is connections*2')
t.equal(totals[2], 6 * (3 - 1), 'number of msgs sent is msgs*(peers-1)')
var prog = progress(alice.state)
const prog = progress(alice.state)
t.equal(prog.current, prog.target)
var prog2 = progress(bob.state)
const prog2 = progress(bob.state)
t.equal(prog2.current, prog2.target)

@@ -77,11 +77,9 @@

if(log)
if (log) {
console.log(
tick.output.map(function (e) {
if(e.msg)
return e.from+'>'+e.to+':'+e.value.sequence
else
return e.from+'>'+e.to+':'+JSON.stringify(e.value)
if (e.msg) { return e.from + '>' + e.to + ':' + e.value.sequence } else { return e.from + '>' + e.to + ':' + JSON.stringify(e.value) }
}).join('\n')
)
}

@@ -92,8 +90,4 @@ t.end()

var seed = process.argv[2]
if(isNaN(seed)) for(var i = 0; i < 100; i++) createTest(i)
const seed = process.argv[2]
if (isNaN(seed)) for (let i = 0; i < 100; i++) createTest(i)
else createTest(+seed, true)

@@ -1,5 +0,5 @@

var createSimulator = require('./simulator')
var options = require('./options')
var progress = require('../progress')
var test = require('tape')
const createSimulator = require('./simulator')
const options = require('./options')
const progress = require('../progress')
const test = require('tape')

@@ -14,20 +14,19 @@ function count (output) {

return output.reduce(function (a, b) {
if(b.msg) return a
for(var k in b.value)
a[b.from][k] = options.getSequence(b.value[k])
if (b.msg) return a
for (const k in b.value) { a[b.from][k] = options.getSequence(b.value[k]) }
return a
}, {alice: {}, bob: {}})
}, { alice: {}, bob: {} })
}
function isComplete (peer, name, t) {
var prog = progress(peer.state)
t.equal(prog.current, prog.target, name +' is complete')
const prog = progress(peer.state)
t.equal(prog.current, prog.target, name + ' is complete')
}
test('write error', function (t) {
var tick = createSimulator(0, true, options)
const tick = createSimulator(0, true, options)
var network = {}
var alice = network['alice'] = tick.createPeer('alice')
var bob = network['bob'] = tick.createPeer('bob')
const network = {}
const alice = network.alice = tick.createPeer('alice')
const bob = network.bob = tick.createPeer('bob')

@@ -37,7 +36,7 @@ alice.init({})

alice.append({author: 'alice', sequence: 1, content: {}})
alice.append({author: 'alice', sequence: 2, content: {}})
alice.append({author: 'alice', sequence: 3, content: {}})
bob.append({author: 'bob', sequence: 1, content: {}})
bob.append({author: 'bob', sequence: 2, content: {}})
alice.append({ author: 'alice', sequence: 1, content: {} })
alice.append({ author: 'alice', sequence: 2, content: {} })
alice.append({ author: 'alice', sequence: 3, content: {} })
bob.append({ author: 'bob', sequence: 1, content: {} })
bob.append({ author: 'bob', sequence: 2, content: {} })

@@ -51,11 +50,11 @@ alice.follow('bob')

while(tick(network)) ;
while (tick(network)) ;
const bobPeerState = alice.state.peers.bob
console.log("bob peer state", bobPeerState)
console.log('bob peer state', bobPeerState)
alice.disconnect(bob)
//should have set up peer.replicatings to tx/rx alice
t.deepEqual(flatten(tick.output), {alice: {alice: 3, bob: 0}, bob: {alice: 0, bob: 2}})
// should have set up peer.replicatings to tx/rx alice
t.deepEqual(flatten(tick.output), { alice: { alice: 3, bob: 0 }, bob: { alice: 0, bob: 2 } })
t.equal(count(tick.output), 2)

@@ -65,4 +64,4 @@

console.log("alice store", alice.store)
console.log("bob store", bob.store)
console.log('alice store', alice.store)
console.log('bob store', bob.store)

@@ -72,11 +71,11 @@ isComplete(alice, 'alice', t)

console.log("===========START OVER===========")
console.log('===========START OVER===========')
// bob has a write error
bob.store.alice = bob.store.alice.slice(0,2)
bob.store.alice = bob.store.alice.slice(0, 2)
bob.clocks.alice.alice = 2
bob.state.clock.alice = 2
alice.append({author: 'alice', sequence: 4, content: {}})
alice.append({ author: 'alice', sequence: 4, content: {} })

@@ -87,8 +86,8 @@ alice.connect(bob)

alice.state.peers.bob.clock = { alice: 3, bob: 2 }
while(tick(network)) ;
t.equal(bob.store.alice.length, 4, "bob has all alices messages")
while (tick(network)) ;
t.equal(bob.store.alice.length, 4, 'bob has all alices messages')
t.end()
})

@@ -1,15 +0,15 @@

exports.note = function note(seq, rx) {
exports.note = function note (seq, rx) {
return seq === -1 ? -1 : seq << 1 | !rx
}
exports.getSequence = function getSequence(seq) {
exports.getSequence = function getSequence (seq) {
return !Number.isInteger(seq) ? -1 : seq >> 1
}
exports.getReplicate = function getReplicate(seq) {
exports.getReplicate = function getReplicate (seq) {
return seq !== -1
}
exports.getReceive = function getReceive(seq) {
exports.getReceive = function getReceive (seq) {
return !(seq & 1)
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc