diff --git a/src/main/java/org/bdware/server/trustedmodel/SelfAdaptiveShardingExecutor.java b/src/main/java/org/bdware/server/trustedmodel/SelfAdaptiveShardingExecutor.java index ca82728..d5a03bb 100644 --- a/src/main/java/org/bdware/server/trustedmodel/SelfAdaptiveShardingExecutor.java +++ b/src/main/java/org/bdware/server/trustedmodel/SelfAdaptiveShardingExecutor.java @@ -13,10 +13,7 @@ import org.bdware.sc.util.JsonUtil; import org.bdware.server.action.p2p.MasterServerRecoverMechAction; import org.bdware.server.action.p2p.MasterServerTCPAction; -import java.util.Arrays; -import java.util.Map; -import java.util.Queue; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ScheduledFuture; @@ -97,7 +94,9 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor { block.prevHash, block.requests.length, block.timestamp)); - if (!executedBlocks.contains(block.hash)) { + if (!toExecuted.containsKey(block.prevHash) && + !executedBlocks.contains(block.hash) && + block.isValid()) { toExecuted.put(block.prevHash, block); synchronized (flag) { flag.notify(); @@ -149,7 +148,7 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor { for (int i = 0; i < requests.length; ++i) { requests[i] = reqQueue.poll(); } - this.b.fillBlock(null, requests); + this.b.fillBlock(requests); return this.b; } @@ -157,6 +156,7 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor { String prevHash = "0"; String hash; String checkPoint; + String body; ContractRequest[] requests; long timestamp; @@ -167,14 +167,46 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor { this.prevHash = prev; } - public void fillBlock(String cp, ContractRequest[] requests) { - this.checkPoint = cp; + public void fillBlock(ContractRequest[] requests) { this.requests = requests; this.timestamp = System.currentTimeMillis(); - hash = HashUtil.sha3( - prevHash, - cp, - Arrays.stream(requests).map(ContractRequest::getRequestID).collect(Collectors.joining())); + this.body = merkle(requests); + this.hash = computeHash(); } + + public boolean isValid() { + return computeHash().equals(hash) && body.equals(merkle(this.requests)); + } + + private String computeHash() { + return HashUtil.sha3( + this.prevHash, + this.checkPoint, + this.body); + } + + + private String merkle(ContractRequest[] requests) { + if (requests.length == 0) { + return null; + } + if (requests.length == 1) { + return HashUtil.sha3(requests[0].getRequestID()); + } + Queue reqQueue = + Arrays.stream(requests).map(ContractRequest::getRequestID) + .collect(Collectors.toCollection(ArrayDeque::new)); + do { + int size; + for (size = reqQueue.size(); size > 1; size -= 2) { + reqQueue.add(HashUtil.sha3(reqQueue.poll(), reqQueue.poll())); + } + if (size == 1) { + reqQueue.add(reqQueue.poll()); + } + } while (1 != reqQueue.size()); + return reqQueue.poll(); + } + } }