From 1e2b04a75cff2e98c36066f678650a3ddb877b31 Mon Sep 17 00:00:00 2001 From: armin Date: Fri, 27 Apr 2018 23:38:52 +0200 Subject: [PATCH] Marking fraction of already checked keys as searched --- bfclient/src/bfclient.cpp | 2 +- cnc/src/main/java/org/btcollider/cnc/CnC.java | 6 +-- .../org/btcollider/cnc/keysrv/KSFactory.java | 23 ++++++++++- .../keysrv/impl/keytree/KeyTreeServer.java | 38 ++++++++++++++++++- .../impl/multistage/MultiStagedServer.java | 9 +++-- 5 files changed, 67 insertions(+), 11 deletions(-) diff --git a/bfclient/src/bfclient.cpp b/bfclient/src/bfclient.cpp index e50200f..7a0e7a8 100644 --- a/bfclient/src/bfclient.cpp +++ b/bfclient/src/bfclient.cpp @@ -35,7 +35,7 @@ int main() { thread* threads = new thread[numThreads]; cout << "Starting " << numThreads << " threads" << endl; - numThreads = 1; + //numThreads = 1; for (unsigned int i = 0; i < numThreads; i++) { threads[i] = thread{bf::Brainflyer(i, "127.0.0.1", 26765, key)}; } diff --git a/cnc/src/main/java/org/btcollider/cnc/CnC.java b/cnc/src/main/java/org/btcollider/cnc/CnC.java index fd51b11..d704157 100644 --- a/cnc/src/main/java/org/btcollider/cnc/CnC.java +++ b/cnc/src/main/java/org/btcollider/cnc/CnC.java @@ -15,19 +15,19 @@ import org.slf4j.LoggerFactory; * */ public class CnC { - final static Logger log = LoggerFactory.getLogger(CnC.class); + static final Logger log = LoggerFactory.getLogger(CnC.class); public static final int PORT = 26765; // Invariant: positive long (2^63-1) must be able to hold all bits handled here public static final int MAX_BITS = 62; public static void main(String[] args) { - KeyServer kts = KSFactory.build(54, 30, 90, TimeUnit.MINUTES); + KeyServer kts = KSFactory.build(54, 30, 90, TimeUnit.MINUTES, 0.62f); CommServer server = new CommServer(PORT, kts); try { server.listen(); } catch (CommException e) { - log.error("CommServer couldn't be started"); + log.error("CommServer couldn't be started", e); } finally { server.stop(); } diff --git a/cnc/src/main/java/org/btcollider/cnc/keysrv/KSFactory.java b/cnc/src/main/java/org/btcollider/cnc/keysrv/KSFactory.java index bb7fc4d..e8f3d28 100644 --- a/cnc/src/main/java/org/btcollider/cnc/keysrv/KSFactory.java +++ b/cnc/src/main/java/org/btcollider/cnc/keysrv/KSFactory.java @@ -6,11 +6,30 @@ import org.btcollider.cnc.keysrv.impl.keytree.KeyTreeServer; import org.btcollider.cnc.keysrv.impl.multistage.MultiStagedServer; public class KSFactory { + + public static KeyServer build(int index, int depth, long maxWorkSpan) { + return build(index, depth, maxWorkSpan, TimeUnit.MILLISECONDS); + } + public static KeyServer build(int index, int depth, long maxWorkSpan, TimeUnit timeUnit) { + return build(index, depth, maxWorkSpan, timeUnit, 0); + } + + public static KeyServer build(int index, int depth, long maxWorkSpan, TimeUnit timeUnit, float pruneFraction) { + assert (pruneFraction >= 0.0 && pruneFraction <= 1.0); + + long maxKey = ((long) 1 << index) | (( (long) 1 << index) - 1); + long pruneKey = (long) Math.floor(maxKey * pruneFraction); + + return build(index, depth, maxWorkSpan, timeUnit, pruneKey); + } + + public static KeyServer build(int index, int depth, long maxWorkSpan, TimeUnit timeUnit, long pruneKey) { if (depth == 25) { - return new KeyTreeServer(index, depth, timeUnit.toMillis(maxWorkSpan)); + return new KeyTreeServer(index, depth, timeUnit.toMillis(maxWorkSpan), pruneKey); } else { - return new MultiStagedServer(index, depth, timeUnit.toMillis(maxWorkSpan)); + return new MultiStagedServer(index, depth, timeUnit.toMillis(maxWorkSpan), pruneKey); } + } } diff --git a/cnc/src/main/java/org/btcollider/cnc/keysrv/impl/keytree/KeyTreeServer.java b/cnc/src/main/java/org/btcollider/cnc/keysrv/impl/keytree/KeyTreeServer.java index 88ed3ba..dc874d1 100644 --- a/cnc/src/main/java/org/btcollider/cnc/keysrv/impl/keytree/KeyTreeServer.java +++ b/cnc/src/main/java/org/btcollider/cnc/keysrv/impl/keytree/KeyTreeServer.java @@ -21,13 +21,15 @@ public class KeyTreeServer implements KeyServer { private int index; private int depth; - public KeyTreeServer(int index, int depth, long maxWorkSpan) { + public KeyTreeServer(int index, int depth, long maxWorkSpan, long pruneKey) { assert Math.pow(2, CnC.MAX_BITS) <= Long.MAX_VALUE; assert index < CnC.MAX_BITS && depth <= CnC.MAX_BITS; this.depth = depth; this.index = index; this.root = generateKeyTree(depth); + + if (pruneKey > 0) prune(pruneKey); if (maxWorkSpan > 0) { log.info("Starting KeyTree concierge"); @@ -113,6 +115,40 @@ public class KeyTreeServer implements KeyServer { return nodeName; } + /** + * Prunes every branch strictly smaller than pruneKey + * + * @param prune + * The smallest valid key in the keyspace Must be at least as large + * as the smallest key in the tree Must be at most as large as the + * largest key in the tree + */ + private void prune(Long pruneKey) { + BitSet pkBS = BitSet.valueOf(new long[] { pruneKey }); + int curIdx = pkBS.length() - 1; + assert (curIdx == this.index); // at least the smallest, at most the largest key in the tree + // -> pos of highest bits is equal + + recPrune(pkBS, this.root, curIdx); + } + + private void recPrune(BitSet pruneKey, KeyTree node, int curIdx) { + if (node.getValue() && !pruneKey.get(curIdx)) { // node[ix] = 0 and pruneK[ix] = 1 -> path smaller + node.setSearched(true); + return; + } else if (!node.getValue() && pruneKey.get(curIdx)) { // node[ix] = 1 and pruneK[ix] = 0 -> path + return; + } + + if (node.isLeaf()) { // end reached + assert (curIdx == 0); + return; + } + + recPrune(pruneKey, node.getLeft(), curIdx-1); + recPrune(pruneKey, node.getRight(), curIdx-1); + } + private void markInWork(BitSet key) { KeyTree keyTreePointer = root; diff --git a/cnc/src/main/java/org/btcollider/cnc/keysrv/impl/multistage/MultiStagedServer.java b/cnc/src/main/java/org/btcollider/cnc/keysrv/impl/multistage/MultiStagedServer.java index 8f19492..9a60446 100644 --- a/cnc/src/main/java/org/btcollider/cnc/keysrv/impl/multistage/MultiStagedServer.java +++ b/cnc/src/main/java/org/btcollider/cnc/keysrv/impl/multistage/MultiStagedServer.java @@ -25,21 +25,22 @@ public class MultiStagedServer implements KeyServer { private int subIndex; private long maxWorkSpan; - public MultiStagedServer(int index, int depth, long maxWorkSpan) { + public MultiStagedServer(int index, int depth, long maxWorkSpan, long pruneKey) { this.remainingDepth = depth - PARTITION_DEPTH; this.subIndex = index - PARTITION_DEPTH; this.maxWorkSpan = maxWorkSpan; // Build a reasonably sized KeyTreeServer with disabled KTConcierge service // This represents the first partitioning of the key space - this.primKTS = new KeyTreeServer(index, PARTITION_DEPTH, 0); + this.primKTS = new KeyTreeServer(index, PARTITION_DEPTH, 0, pruneKey); // Get a random starting range from the primary KTS, this range is still too huge this.partition = primKTS.getRange(); // Start a secondary KTS to partition remaining key space in currentRange // This represents the actual work-horse KeyTreeServer for the current partition with // enabled KTConcierge service. // Needs subindex+1 because starting bit always set to 1 - this.secKTS = new KeyTreeServer(subIndex+1, remainingDepth, maxWorkSpan); + long subPrune = ((long) 1 << subIndex+1) | ( (((long) 1 << subIndex+1) - 1) & pruneKey ); + this.secKTS = new KeyTreeServer(subIndex+1, remainingDepth, maxWorkSpan, subPrune); this.keyRangeBuffer = new KeyRangeBuffer(maxWorkSpan); } @@ -58,7 +59,7 @@ public class MultiStagedServer implements KeyServer { log.info("Subrange {} finished. Opening new partition.", partition); primKTS.setSearched(partition); partition = primKTS.getRange(); - secKTS = new KeyTreeServer(subIndex+1, remainingDepth, maxWorkSpan); + secKTS = new KeyTreeServer(subIndex+1, remainingDepth, maxWorkSpan, 0); return getRange(); }