diff --git a/README.md b/README.md
index febd3ffb..336915e8 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
**GUN** is an _ecosystem_ of tools that let you build tomorrow's dApps, today.
-Decentralized alternatives to [Reddit](https://notabug.io/), [YouTube](https://d.tube/), [Wikipedia](https://news.ycombinator.com/item?id=17685682), etc. are already pushing terabytes of daily P2P traffic on GUN. We are a [friendly community](https://gitter.im/amark/gun) creating a free fun future for freedom:
+Decentralized alternatives to [Reddit](https://notabug.io/t/whatever/comments/36588a16b9008da4e3f15663c2225e949eca4a15/gpu-bot-test), [YouTube](https://d.tube/), [Wikipedia](https://news.ycombinator.com/item?id=17685682), etc. are already pushing terabytes of daily P2P traffic on GUN. We are a [friendly community](https://gitter.im/amark/gun) creating a free fun future for freedom:
diff --git a/lib/les.js b/lib/les.js
new file mode 100644
index 00000000..e6f3cb16
--- /dev/null
+++ b/lib/les.js
@@ -0,0 +1,121 @@
+;
+(function() {
+
+ // _ _____ ____ _
+ // | | | ____/ ___| (_)___
+ // | | | _| \___ \ | / __|
+ // | |___| |___ ___) | | \__ \
+ // |_____|_____|____(_)/ |___/
+ // ----------------------------
+ // LES.js (Last rEcently uSed)
+ // ----------------------------
+ // A Small, lightweight, queue-based
+ // Garbage Collector for Gun
+ // Originally By: Collin Conrad (@masterex1000)
+
+ //NOTE: set to false is running from file in YOUR code
+ var USELOCALGUN = true;
+
+ //NOTE: adds some debug messages
+ var DEBUG = false;
+
+
+ var Gun = (typeof window !== "undefined") ? window.Gun : (USELOCALGUN ? require('../gun') : require("gun"));
+ var ev = {};
+ var empty = {};
+
+ Gun.on('opt', function(root) {
+ this.to.next(root);
+ if (root.once)
+ return;
+ if (typeof process == 'undefined')
+ return
+ var mem = process.memoryUsage;
+
+ if (!mem) //exit because we are in the browser
+ return;
+
+ //Figure out the most amount of memory we can use. TODO: make configurable?
+ ev.max = parseFloat(root.opt.memory || process.env.WEB_MEMORY || 512) * 0.8;
+
+ var nodes = {}; //checks if the node already exists
+ var nodesArray = []; //used to easily sort everything and store info about the nodes
+ var memoryUpdate = 0; // last time we printed the current memory stats
+
+ var check = function() {
+ ev.used = mem().rss / 1024 / 1024; //Contains the amt. of used ram in MB
+ setTimeout(function() { // So we can handle requests etc. before we start collecting
+ GC(ev.used / ev.max); // Calculate the memory ratio, and execute the garbage collector
+ }, 1);
+ }
+
+ setInterval(check, 1000); // set the garbage collector to run every second, TODO: make configurable
+
+ //Executed every time a node gets modifyed
+ root.on("put", function(e) {
+ var ctime = Date.now();
+ var souls = Object.keys(e.put || empty);
+ for (var i = 0; i < souls.length; i++) {
+ enqueueNode(souls[i], ctime);
+ }
+ });
+
+ //Adds a soul the garbage collectors "freeing" queue
+ function enqueueNode(soul, ctime) {
+ if (nodes[soul] == true) { //The node already exists in the queue
+ var index = nodesArray.findIndex(function(e) {
+ return e[0] === soul;
+ });
+ if (index == -1) {
+ console.err("Something happened and the node '" + soul + "' won't get garbage collection unless the value is updated agian");
+ return;
+ } else {
+ nodesArray.splice(index, 1); // remove the existing ref.
+ nodesArray.push([soul, ctime]); // push the new instance
+ }
+ } else {
+ nodesArray.push([soul, ctime]);
+ nodes[soul] = true;
+ }
+ }
+
+ //The main garbage collecting routine
+ function GC(memRatio) {
+ var curTime = Date.now(); // get the current time
+
+ if (curTime - memoryUpdate >= 5000) {
+ console.log("|GC| %s | Current Memory Ratio: %d | Current Ram Usage %sMB | Nodes in Memory %s", new Date().toLocaleString(), round(memRatio, 2), round(ev.used, 2), Object.keys(root.graph || empty).length);
+ memoryUpdate = curTime;
+ }
+
+ var freed = 0;
+
+ while (nodesArray.length > 0) {
+ var soul = nodesArray[0][0];
+ var nts = nodesArray[0][1];
+ if (DEBUG)
+ console.log("Soul: " + soul + " | Remove Importance: " + calcRemoveImportance(nts, curTime, memRatio) +
+ " | Memory Ratio: " + memRatio + " | Time Existed: " + (curTime - nts) / 1000);
+ if (calcRemoveImportance(nodesArray[0][1], curTime, memRatio) >= 100) {
+ root.gun.get(nodesArray[0][0]).off(); //Remove the node
+ delete nodes[nodesArray[0][0]]; // remove the lookup value
+ nodesArray.splice(0, 1);
+ freed++;
+ } else
+ break;
+ }
+ if (freed > 0)
+ console.log("|GC| Removed %s nodes in %s seconds-----------------------------------------------------------------", freed, (Date.now() - curTime) * 0.001);
+ }
+
+ //Generates a number that, after it hits a threshold, the node gets removed
+ function calcRemoveImportance(timestamp, ctime, memoryUsageRatio) {
+ var time = (ctime - timestamp) * 0.001;
+ return time * 10 * (memoryUsageRatio * memoryUsageRatio)
+ }
+
+ function round(value, decimals) { //a basic rounding function
+ return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
+ }
+ });
+}());
\ No newline at end of file
diff --git a/nts.js b/nts.js
index 91f9d63d..e8a491c7 100644
--- a/nts.js
+++ b/nts.js
@@ -37,8 +37,8 @@
NTS.end = Gun.state();
Gun.obj.del(ask, ack);
NTS.latency = (NTS.end - NTS.start)/2;
- if(!at.NTS){ return }
- NTS.calc = NTS.latency + at.NTS;
+ if(!at.nts && !at.NTS){ return }
+ NTS.calc = NTS.latency + (at.NTS || at.nts);
Gun.state.drift -= (NTS.end - NTS.calc)/2;
setTimeout(ping, 1000);
}
diff --git a/sea.js b/sea.js
index d3b58f82..7c08fc81 100644
--- a/sea.js
+++ b/sea.js
@@ -267,7 +267,7 @@
// This internal func returns SHA-1 hashed data for KeyID generation
const __shim = USE('./shim')
const subtle = __shim.subtle
- const ossl = __shim.ossl ? __shim.__ossl : subtle
+ const ossl = __shim.ossl ? __shim.ossl : subtle
const sha1hash = (b) => ossl.digest({name: 'SHA-1'}, new ArrayBuffer(b))
module.exports = sha1hash
})(USE, './sha1');
@@ -625,7 +625,7 @@
try {
// base64('base64(x):base64(y)') => Buffer(xy)
const pb = Buffer.concat(
- Buffer.from(pub, 'base64').toString('utf8').split(':')
+ pub.replace(/-/g, '+').replace(/_/g, '/').split('.')
.map((t) => Buffer.from(t, 'base64'))
)
// id is PGPv4 compliant raw key
diff --git a/sea/index.js b/sea/index.js
index 52ec5f38..80a5d26f 100644
--- a/sea/index.js
+++ b/sea/index.js
@@ -62,7 +62,7 @@
// if there is a request to read data from us, then...
var soul = msg.get['#'];
if(soul){ // for now, only allow direct IDs to be read.
- if(soul !== 'string'){ return to.next(msg) } // do not handle lexical cursors.
+ if(typeof soul !== 'string'){ return to.next(msg) } // do not handle lexical cursors.
if('alias' === soul){ // Allow reading the list of usernames/aliases in the system?
return to.next(msg); // yes.
} else
@@ -226,4 +226,4 @@
to.next(msg); // pass forward any data we do not know how to handle or process (this allows custom security protocols).
}
-
\ No newline at end of file
+
diff --git a/sea/sea.js b/sea/sea.js
index f85b9a3b..77032638 100644
--- a/sea/sea.js
+++ b/sea/sea.js
@@ -49,7 +49,7 @@
try {
// base64('base64(x):base64(y)') => Buffer(xy)
const pb = Buffer.concat(
- Buffer.from(pub, 'base64').toString('utf8').split(':')
+ pub.replace(/-/g, '+').replace(/_/g, '/').split('.')
.map((t) => Buffer.from(t, 'base64'))
)
// id is PGPv4 compliant raw key
diff --git a/sea/sha1.js b/sea/sha1.js
index c18ba691..9272cffc 100644
--- a/sea/sha1.js
+++ b/sea/sha1.js
@@ -2,7 +2,7 @@
// This internal func returns SHA-1 hashed data for KeyID generation
const __shim = require('./shim')
const subtle = __shim.subtle
- const ossl = __shim.ossl ? __shim.__ossl : subtle
+ const ossl = __shim.ossl ? __shim.ossl : subtle
const sha1hash = (b) => ossl.digest({name: 'SHA-1'}, new ArrayBuffer(b))
module.exports = sha1hash
\ No newline at end of file
diff --git a/test/sea/sea.html b/test/sea/sea.html
index 82c16de7..72aaea9e 100644
--- a/test/sea/sea.html
+++ b/test/sea/sea.html
@@ -1,6 +1,6 @@
-
-
-
+
+
+