Skip to content

Commit

Permalink
chore: add overlay params as configurable options
Browse files Browse the repository at this point in the history
  • Loading branch information
wemeetagain committed Jul 21, 2020
1 parent 97f8ef5 commit 1651261
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 22 deletions.
39 changes: 23 additions & 16 deletions ts/heartbeat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ export class Heartbeat {
* @returns {void}
*/
_heartbeat (): void {
const {
D,
Dlo,
Dhi,
Dscore,
Dout
} = this.gossipsub._options
this.gossipsub.heartbeatTicks++

// cache scores throught the heartbeat
Expand Down Expand Up @@ -154,9 +161,9 @@ export class Heartbeat {
})

// do we have enough peers?
if (peers.size < constants.GossipsubDlo) {
if (peers.size < Dlo) {
const backoff = this.gossipsub.backoff.get(topic)
const ineed = constants.GossipsubD - peers.size
const ineed = D - peers.size
const peersSet = getGossipPeers(this.gossipsub, topic, ineed, id => {
// filter out mesh peers, direct peers, peers we are backing off, peers with negative score
return !peers.has(id) && !this.gossipsub.direct.has(id) && (!backoff || !backoff.has(id)) && getScore(id) >= 0
Expand All @@ -166,26 +173,26 @@ export class Heartbeat {
}

// do we have to many peers?
if (peers.size > constants.GossipsubDhi) {
if (peers.size > Dhi) {
let peersArray = Array.from(peers)
// sort by score
peersArray.sort((a, b) => getScore(b) - getScore(a))
// We keep the first D_score peers by score and the remaining up to D randomly
// under the constraint that we keep D_out peers in the mesh (if we have that many)
peersArray = peersArray.slice(0, constants.GossipsubDscore).concat(
shuffle(peersArray.slice(constants.GossipsubDscore))
peersArray = peersArray.slice(0, Dscore).concat(
shuffle(peersArray.slice(Dscore))
)

// count the outbound peers we are keeping
let outbound = 0
peersArray.slice(0, constants.GossipsubD).forEach(p => {
peersArray.slice(0, D).forEach(p => {
if (this.gossipsub.outbound.get(p)) {
outbound++
}
})

// if it's less than D_out, bubble up some outbound peers from the random selection
if (outbound < constants.GossipsubDout) {
if (outbound < Dout) {
const rotate = (i: number): void => {
// rotate the peersArray to the right and put the ith peer in the front
const p = peersArray[i]
Expand All @@ -198,7 +205,7 @@ export class Heartbeat {
// first bubble up all outbound peers already in the selection to the front
if (outbound > 0) {
let ihave = outbound
for (let i = 1; i < constants.GossipsubD && ihave > 0; i++) {
for (let i = 1; i < D && ihave > 0; i++) {
if (this.gossipsub.outbound.get(peersArray[i])) {
rotate(i)
ihave--
Expand All @@ -207,8 +214,8 @@ export class Heartbeat {
}

// now bubble up enough outbound peers outside the selection to the front
let ineed = constants.GossipsubD - outbound
for (let i = constants.GossipsubD; i < peersArray.length && ineed > 0; i++) {
let ineed = D - outbound
for (let i = D; i < peersArray.length && ineed > 0; i++) {
if (this.gossipsub.outbound.get(peersArray[i])) {
rotate(i)
ineed--
Expand All @@ -217,11 +224,11 @@ export class Heartbeat {
}

// prune the excess peers
peersArray.slice(0, constants.GossipsubD).forEach(prunePeer)
peersArray.slice(0, D).forEach(prunePeer)
}

// do we have enough outbound peers?
if (peers.size >= constants.GossipsubDlo) {
if (peers.size >= Dlo) {
// count the outbound peers we have
let outbound = 0
peers.forEach(p => {
Expand All @@ -231,8 +238,8 @@ export class Heartbeat {
})

// if it's less than D_out, select some peers with outbound connections and graft them
if (outbound < constants.GossipsubDout) {
const ineed = constants.GossipsubDout - outbound
if (outbound < Dout) {
const ineed = Dout - outbound
const backoff = this.gossipsub.backoff.get(topic)
getGossipPeers(this.gossipsub, topic, ineed, (id: string): boolean => {
// filter our current mesh peers, direct peers, peers we are backing off, peers with negative score
Expand Down Expand Up @@ -301,8 +308,8 @@ export class Heartbeat {
})

// do we need more peers?
if (fanoutPeers.size < constants.GossipsubD) {
const ineed = constants.GossipsubD - fanoutPeers.size
if (fanoutPeers.size < D) {
const ineed = D - fanoutPeers.size
const peersSet = getGossipPeers(this.gossipsub, topic, ineed, (id: string): boolean => {
// filter out existing fanout peers, direct peers, and peers with score above the publish threshold
return !fanoutPeers.has(id) &&
Expand Down
42 changes: 36 additions & 6 deletions ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,30 @@ interface GossipInputOptions {
scoreParams: Partial<PeerScoreParams>
scoreThresholds: Partial<PeerScoreThresholds>
directPeers: AddrInfo[]
/**
* D sets the optimal degree for a Gossipsub topic mesh.
*/
D: number
/**
* Dlo sets the lower bound on the number of peers we keep in a Gossipsub topic mesh.
*/
Dlo: number
/**
* Dhi sets the upper bound on the number of peers we keep in a Gossipsub topic mesh.
*/
Dhi: number
/**
* Dscore affects how peers are selected when pruning a mesh due to over subscription.
*/
Dscore: number
/**
* Dout sets the quota for the number of outbound connections to maintain in a topic mesh.
*/
Dout: number
/**
* Dlazy affects how many peers we will emit gossip to at each heartbeat.
*/
Dlazy: number
}

interface GossipOptions extends GossipInputOptions {
Expand Down Expand Up @@ -83,6 +107,12 @@ class Gossipsub extends BasicPubsub {
fallbackToFloodsub: true,
floodPublish: true,
directPeers: [],
D: constants.GossipsubD,
Dlo: constants.GossipsubDlo,
Dhi: constants.GossipsubDhi,
Dscore: constants.GossipsubDscore,
Dout: constants.GossipsubDout,
Dlazy: constants.GossipsubDlazy,
...options,
scoreParams: createPeerScoreParams(options.scoreParams),
scoreThresholds: createPeerScoreThresholds(options.scoreThresholds)
Expand Down Expand Up @@ -611,7 +641,7 @@ class Gossipsub extends BasicPubsub {
// check the number of mesh peers; if it is at (or over) Dhi, we only accept grafts
// from peers with outbound connections; this is a defensive check to restrict potential
// mesh takeover attacks combined with love bombing
if (peersInMesh.size >= constants.GossipsubDhi && !this.outbound.get(id)) {
if (peersInMesh.size >= this._options.Dhi && !this.outbound.get(id)) {
prune.push(topicID)
this._addBackoff(id, topicID)
return
Expand Down Expand Up @@ -843,9 +873,9 @@ class Gossipsub extends BasicPubsub {
fanoutPeers.delete(id)
}
})
if (fanoutPeers.size < constants.GossipsubD) {
if (fanoutPeers.size < this._options.D) {
// we need more peers; eager, as this would get fixed in the next heartbeat
getGossipPeers(this, topic, constants.GossipsubD - fanoutPeers.size, (id: string): boolean => {
getGossipPeers(this, topic, this._options.D - fanoutPeers.size, (id: string): boolean => {
// filter our current peers, direct peers, and peers with negative scores
return !fanoutPeers.has(id) && !this.direct.has(id) && this.score.score(id) >= 0
}).forEach(id => fanoutPeers.add(id))
Expand All @@ -854,7 +884,7 @@ class Gossipsub extends BasicPubsub {
this.fanout.delete(topic)
this.lastpub.delete(topic)
} else {
const peers = getGossipPeers(this, topic, constants.GossipsubD, (id: string): boolean => {
const peers = getGossipPeers(this, topic, this._options.D, (id: string): boolean => {
// filter direct peers and peers with negative score
return !this.direct.has(id) && this.score.score(id) >= 0
})
Expand Down Expand Up @@ -959,7 +989,7 @@ class Gossipsub extends BasicPubsub {
meshPeers = this.fanout.get(topic)
if (!meshPeers) {
// If we are not in the fanout, then pick peers in topic above the publishThreshold
const peers = getGossipPeers(this, topic, constants.GossipsubD, id => {
const peers = getGossipPeers(this, topic, this._options.D, id => {
return this.score.score(id) >= this._options.scoreThresholds.publishThreshold
})

Expand Down Expand Up @@ -1144,7 +1174,7 @@ class Gossipsub extends BasicPubsub {
}
})

let target = constants.GossipsubDlazy
let target = this._options.Dlazy
const factor = constants.GossipsubGossipFactor * peersToGossip.length
if (factor > target) {
target = factor
Expand Down

0 comments on commit 1651261

Please sign in to comment.