mirror of
https://gitee.com/BDWare/agent-backend
synced 2025-01-10 01:44:14 +00:00
fix: fix bugs in SelfAdaptiveShardingExecutor
remove body check in SelfAdaptiveShardingExecutor.Block.isValid
This commit is contained in:
parent
78366fcb55
commit
ed507b14b4
@ -21,7 +21,9 @@ import org.bdware.server.GRPCPool;
|
|||||||
import org.bdware.server.GlobalConf;
|
import org.bdware.server.GlobalConf;
|
||||||
import org.bdware.server.action.p2p.MasterClientTCPAction;
|
import org.bdware.server.action.p2p.MasterClientTCPAction;
|
||||||
import org.bdware.server.trustedmodel.AgentManager;
|
import org.bdware.server.trustedmodel.AgentManager;
|
||||||
|
import org.bdware.server.trustedmodel.ContractExecutor;
|
||||||
import org.bdware.server.trustedmodel.KillUnitContractInfo;
|
import org.bdware.server.trustedmodel.KillUnitContractInfo;
|
||||||
|
import org.bdware.server.trustedmodel.SelfAdaptiveShardingExecutor;
|
||||||
import org.bdware.server.ws.ContractManagerFrameHandler;
|
import org.bdware.server.ws.ContractManagerFrameHandler;
|
||||||
import org.bdware.units.NetworkManager;
|
import org.bdware.units.NetworkManager;
|
||||||
import org.bdware.units.function.CommunicationManager;
|
import org.bdware.units.function.CommunicationManager;
|
||||||
@ -51,7 +53,6 @@ public class CMActions implements OnHashCallback {
|
|||||||
public static FuncInvokeInfo FUNCINVOKEINFO = new FuncInvokeInfo(); // 合约调用时参数和结果
|
public static FuncInvokeInfo FUNCINVOKEINFO = new FuncInvokeInfo(); // 合约调用时参数和结果
|
||||||
private static SecureRandom RANDOM;
|
private static SecureRandom RANDOM;
|
||||||
public ContractManagerFrameHandler handler;
|
public ContractManagerFrameHandler handler;
|
||||||
|
|
||||||
public CMActions() {
|
public CMActions() {
|
||||||
handler = null;
|
handler = null;
|
||||||
}
|
}
|
||||||
@ -532,6 +533,16 @@ public class CMActions implements OnHashCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Action(async = true, userPermission = 0)
|
||||||
|
public void checkBlocks(JsonObject args, final ResultCallback rcb) {
|
||||||
|
ContractExecutor executor = CMActions.manager.getExecutor(args.get("contractID").getAsString());
|
||||||
|
try {
|
||||||
|
ReplyUtil.simpleReply(rcb, "onCheckBlocks", ((SelfAdaptiveShardingExecutor) executor).checkCache());
|
||||||
|
} catch (Exception e) {
|
||||||
|
ReplyUtil.simpleReply(rcb, "onCheckBlocks", "error! " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 节点管理者
|
// 节点管理者
|
||||||
@Action(userPermission = 1L << 19)
|
@Action(userPermission = 1L << 19)
|
||||||
public void listAllContractProcess(JsonObject args, ResultCallback resultCallback) {
|
public void listAllContractProcess(JsonObject args, ResultCallback resultCallback) {
|
||||||
@ -1584,97 +1595,6 @@ public class CMActions implements OnHashCallback {
|
|||||||
// rc.onResult(peers);
|
// rc.onResult(peers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Action(userPermission = 1L << 26, async = true)
|
|
||||||
// public void queryContractInstanceInfoByDOI(JsonObject args, ResultCallback resultCallback)
|
|
||||||
// {
|
|
||||||
// long s = System.currentTimeMillis();
|
|
||||||
// String ret;
|
|
||||||
// try {
|
|
||||||
// String contractDOI = args.get("doi").getAsString();
|
|
||||||
// DigitalObject contractDO;
|
|
||||||
// DoipClient doipClient =
|
|
||||||
// DoipClient.createByRepoUrlAndMsgFmt(
|
|
||||||
// DOIPMainServer.repoUrl, DoipMessageFormat.PACKET.getName());
|
|
||||||
// DoMessage response = doipClient.retrieve(contractDOI, null, null);
|
|
||||||
// if (response.parameters.response == DoResponse.Success) {
|
|
||||||
// contractDO = DigitalObject.parse(response.body);
|
|
||||||
// } else {
|
|
||||||
// DoMessage resp = DOAClient.getGlobalInstance().retrieve(contractDOI, null,
|
|
||||||
// null);
|
|
||||||
// contractDO = DigitalObject.parse(resp.body);
|
|
||||||
// }
|
|
||||||
// ContractInstanceDO contractInstanceDO =
|
|
||||||
// (ContractInstanceDO)
|
|
||||||
// ContractManager.toObject(contractDO.elements.get(0).getData());
|
|
||||||
// // Dictionary<String, String> contractInfo = JsonUtil.fromJson(new
|
|
||||||
// // String(contractDO.getData()), new Hashtable<String, String>().getClass());
|
|
||||||
//
|
|
||||||
// ret =
|
|
||||||
// String.format(
|
|
||||||
// "Contract ID: %s\nContract PublicKey: %s",
|
|
||||||
// contractInstanceDO.id, contractInstanceDO.publicKey);
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
|
||||||
// e.printStackTrace(new PrintStream(bo));
|
|
||||||
// ret = bo.toString();
|
|
||||||
// }
|
|
||||||
// Map<String, Object> r = new HashMap<>();
|
|
||||||
// r.put("action", "onQueryContractInstanceInfoByDOI");
|
|
||||||
// r.put("data", ret);
|
|
||||||
// r.put("executeTime", System.currentTimeMillis() - s);
|
|
||||||
// resultCallback.onResult(JsonUtil.toJson(r));
|
|
||||||
// if (client != null && client.controller != null) {
|
|
||||||
// client.controller.updateContract();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @Action(userPermission = 1 << 19, async = true) public void
|
|
||||||
* staticVerify(JsonObject args, ResultCallback resultCallback) { Map<String,
|
|
||||||
* Object> r = new HashMap<>(); r.put("action", "onStaticVerifyResult");
|
|
||||||
*
|
|
||||||
* long start = System.currentTimeMillis(); Map<String, Object> ret = new
|
|
||||||
* HashMap<>(); Contract c = new Contract(); // c.setType(Type.Algorithm);
|
|
||||||
* c.setType(ContractType.Sole); ret.put("action", "onStartContract"); String path =
|
|
||||||
* null; if (args.has("path")) path = args.get("path").getAsString(); if (path
|
|
||||||
* != null && path.startsWith("/")) c.setScript(args.get("path").getAsString());
|
|
||||||
* else c.setScript(args.get("script").getAsString()); if
|
|
||||||
* (args.has("publicKey")) { c.setOwner(args.get("publicKey").getAsString());
|
|
||||||
* c.setSignature(args.get("signature").getAsString()); } else if
|
|
||||||
* (args.has("owner")) { c.setOwner(args.get("owner").getAsString());
|
|
||||||
* c.setSignature(args.get("signature").getAsString());
|
|
||||||
*
|
|
||||||
* } else { c.setOwner(GlobalConf.instance.keyPair.getPublicKeyStr());
|
|
||||||
* c.doSignature(GlobalConf.instance.keyPair); }
|
|
||||||
*
|
|
||||||
* if (!c.verifySignature()) { ret.put("data", "verify failed");
|
|
||||||
* resultCallback.onResult(gson.toJson(ret)); return; } if (path != null &&
|
|
||||||
* path.startsWith("/")) { String parPath; if (args.has("isPrivate") &&
|
|
||||||
* args.get("isPrivate").getAsBoolean()) { parPath =
|
|
||||||
* GlobalConf.instance.privateDir + "/" + handler.pubKey; } else { parPath =
|
|
||||||
* GlobalConf.instance.publicDir; } try { String[] pp = path.split("/"); String
|
|
||||||
* parentPath = path; for (int i = 0; i < pp.length && i < 2; i++) { parentPath
|
|
||||||
* += pp[i] + "/"; } System.out.println("[CMActions] pack Dir, from:" + path +
|
|
||||||
* " --> " + parentPath); byte[] bb = YJSPacker.pack(new File(parPath,
|
|
||||||
* parentPath).getAbsolutePath()); File temp = File.createTempFile(pp[pp.length
|
|
||||||
* - 1], ".zip"); FileOutputStream fout = new FileOutputStream(temp);
|
|
||||||
* fout.write(bb); fout.close(); System.out.println("StartContract, zipPath:" +
|
|
||||||
* temp.getAbsolutePath()); // TODO script should encoded!!
|
|
||||||
* c.setScript(temp.getAbsolutePath()); } catch (Exception e) {
|
|
||||||
* e.printStackTrace(); } }
|
|
||||||
*
|
|
||||||
* System.out.println("[CMActions] verifyContract: " + gson.toJson(c));
|
|
||||||
* r.put("data", manager.staticVerify(c)); r.put("cid", c.getID());
|
|
||||||
* r.put("executeTime", System.currentTimeMillis() - start); //
|
|
||||||
* GRPCPool.writeToChain(c.getOwner(), privKey, gson.toJson(r), //
|
|
||||||
* json.getString("requestID"));
|
|
||||||
*
|
|
||||||
* //addLocalContractLog("staticVerify", c.getID(), path.split("/")[1],
|
|
||||||
* c.getOwner(),null);
|
|
||||||
*
|
|
||||||
* resultCallback.onResult(gson.toJson(r)); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Action(async = true, userPermission = 0L)
|
@Action(async = true, userPermission = 0L)
|
||||||
public void updateNodeUnits(JsonObject args, ResultCallback rc) {
|
public void updateNodeUnits(JsonObject args, ResultCallback rc) {
|
||||||
LOGGER.debug("updateNodeUnits");
|
LOGGER.debug("updateNodeUnits");
|
||||||
@ -1842,6 +1762,97 @@ public class CMActions implements OnHashCallback {
|
|||||||
resultCallback.onResult(ret);
|
resultCallback.onResult(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Action(userPermission = 1L << 26, async = true)
|
||||||
|
// public void queryContractInstanceInfoByDOI(JsonObject args, ResultCallback resultCallback)
|
||||||
|
// {
|
||||||
|
// long s = System.currentTimeMillis();
|
||||||
|
// String ret;
|
||||||
|
// try {
|
||||||
|
// String contractDOI = args.get("doi").getAsString();
|
||||||
|
// DigitalObject contractDO;
|
||||||
|
// DoipClient doipClient =
|
||||||
|
// DoipClient.createByRepoUrlAndMsgFmt(
|
||||||
|
// DOIPMainServer.repoUrl, DoipMessageFormat.PACKET.getName());
|
||||||
|
// DoMessage response = doipClient.retrieve(contractDOI, null, null);
|
||||||
|
// if (response.parameters.response == DoResponse.Success) {
|
||||||
|
// contractDO = DigitalObject.parse(response.body);
|
||||||
|
// } else {
|
||||||
|
// DoMessage resp = DOAClient.getGlobalInstance().retrieve(contractDOI, null,
|
||||||
|
// null);
|
||||||
|
// contractDO = DigitalObject.parse(resp.body);
|
||||||
|
// }
|
||||||
|
// ContractInstanceDO contractInstanceDO =
|
||||||
|
// (ContractInstanceDO)
|
||||||
|
// ContractManager.toObject(contractDO.elements.get(0).getData());
|
||||||
|
// // Dictionary<String, String> contractInfo = JsonUtil.fromJson(new
|
||||||
|
// // String(contractDO.getData()), new Hashtable<String, String>().getClass());
|
||||||
|
//
|
||||||
|
// ret =
|
||||||
|
// String.format(
|
||||||
|
// "Contract ID: %s\nContract PublicKey: %s",
|
||||||
|
// contractInstanceDO.id, contractInstanceDO.publicKey);
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||||
|
// e.printStackTrace(new PrintStream(bo));
|
||||||
|
// ret = bo.toString();
|
||||||
|
// }
|
||||||
|
// Map<String, Object> r = new HashMap<>();
|
||||||
|
// r.put("action", "onQueryContractInstanceInfoByDOI");
|
||||||
|
// r.put("data", ret);
|
||||||
|
// r.put("executeTime", System.currentTimeMillis() - s);
|
||||||
|
// resultCallback.onResult(JsonUtil.toJson(r));
|
||||||
|
// if (client != null && client.controller != null) {
|
||||||
|
// client.controller.updateContract();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @Action(userPermission = 1 << 19, async = true) public void
|
||||||
|
* staticVerify(JsonObject args, ResultCallback resultCallback) { Map<String,
|
||||||
|
* Object> r = new HashMap<>(); r.put("action", "onStaticVerifyResult");
|
||||||
|
*
|
||||||
|
* long start = System.currentTimeMillis(); Map<String, Object> ret = new
|
||||||
|
* HashMap<>(); Contract c = new Contract(); // c.setType(Type.Algorithm);
|
||||||
|
* c.setType(ContractType.Sole); ret.put("action", "onStartContract"); String path =
|
||||||
|
* null; if (args.has("path")) path = args.get("path").getAsString(); if (path
|
||||||
|
* != null && path.startsWith("/")) c.setScript(args.get("path").getAsString());
|
||||||
|
* else c.setScript(args.get("script").getAsString()); if
|
||||||
|
* (args.has("publicKey")) { c.setOwner(args.get("publicKey").getAsString());
|
||||||
|
* c.setSignature(args.get("signature").getAsString()); } else if
|
||||||
|
* (args.has("owner")) { c.setOwner(args.get("owner").getAsString());
|
||||||
|
* c.setSignature(args.get("signature").getAsString());
|
||||||
|
*
|
||||||
|
* } else { c.setOwner(GlobalConf.instance.keyPair.getPublicKeyStr());
|
||||||
|
* c.doSignature(GlobalConf.instance.keyPair); }
|
||||||
|
*
|
||||||
|
* if (!c.verifySignature()) { ret.put("data", "verify failed");
|
||||||
|
* resultCallback.onResult(gson.toJson(ret)); return; } if (path != null &&
|
||||||
|
* path.startsWith("/")) { String parPath; if (args.has("isPrivate") &&
|
||||||
|
* args.get("isPrivate").getAsBoolean()) { parPath =
|
||||||
|
* GlobalConf.instance.privateDir + "/" + handler.pubKey; } else { parPath =
|
||||||
|
* GlobalConf.instance.publicDir; } try { String[] pp = path.split("/"); String
|
||||||
|
* parentPath = path; for (int i = 0; i < pp.length && i < 2; i++) { parentPath
|
||||||
|
* += pp[i] + "/"; } System.out.println("[CMActions] pack Dir, from:" + path +
|
||||||
|
* " --> " + parentPath); byte[] bb = YJSPacker.pack(new File(parPath,
|
||||||
|
* parentPath).getAbsolutePath()); File temp = File.createTempFile(pp[pp.length
|
||||||
|
* - 1], ".zip"); FileOutputStream fout = new FileOutputStream(temp);
|
||||||
|
* fout.write(bb); fout.close(); System.out.println("StartContract, zipPath:" +
|
||||||
|
* temp.getAbsolutePath()); // TODO script should encoded!!
|
||||||
|
* c.setScript(temp.getAbsolutePath()); } catch (Exception e) {
|
||||||
|
* e.printStackTrace(); } }
|
||||||
|
*
|
||||||
|
* System.out.println("[CMActions] verifyContract: " + gson.toJson(c));
|
||||||
|
* r.put("data", manager.staticVerify(c)); r.put("cid", c.getID());
|
||||||
|
* r.put("executeTime", System.currentTimeMillis() - start); //
|
||||||
|
* GRPCPool.writeToChain(c.getOwner(), privKey, gson.toJson(r), //
|
||||||
|
* json.getString("requestID"));
|
||||||
|
*
|
||||||
|
* //addLocalContractLog("staticVerify", c.getID(), path.split("/")[1],
|
||||||
|
* c.getOwner(),null);
|
||||||
|
*
|
||||||
|
* resultCallback.onResult(gson.toJson(r)); }
|
||||||
|
*/
|
||||||
|
|
||||||
@Action(async = true)
|
@Action(async = true)
|
||||||
public void askMasterElectTimeRecorder(JsonObject args, ResultCallback resultCallback) {
|
public void askMasterElectTimeRecorder(JsonObject args, ResultCallback resultCallback) {
|
||||||
String data = "null";
|
String data = "null";
|
||||||
@ -1953,6 +1964,4 @@ public class CMActions implements OnHashCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -186,8 +186,7 @@ public class MasterWSAction {
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
SM2KeyPair keyPair = GlobalConf.instance.keyPair;
|
String masterNode = GlobalConf.instance.keyPair.getPublicKeyStr();
|
||||||
String masterNode = keyPair.getPublicKeyStr();
|
|
||||||
nodeNames.add(masterNode);
|
nodeNames.add(masterNode);
|
||||||
int nodeSize = nodeNames.size();
|
int nodeSize = nodeNames.size();
|
||||||
|
|
||||||
@ -237,7 +236,7 @@ public class MasterWSAction {
|
|||||||
nodeSize);
|
nodeSize);
|
||||||
MasterServerTCPAction.sync.sleepWithTimeout(requestID, collector, 20);
|
MasterServerTCPAction.sync.sleepWithTimeout(requestID, collector, 20);
|
||||||
Map<String, Object> request = new HashMap<>();
|
Map<String, Object> request = new HashMap<>();
|
||||||
request.put("master", keyPair.getPublicKeyStr());
|
request.put("master", masterNode);
|
||||||
if (args.has("isPrivate")) {
|
if (args.has("isPrivate")) {
|
||||||
request.put("isPrivate", args.get("isPrivate").getAsString());
|
request.put("isPrivate", args.get("isPrivate").getAsString());
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,6 @@ import org.bdware.server.trustedmodel.KillUnitContractResultCollector;
|
|||||||
import org.bdware.server.trustedmodel.ResultCollector;
|
import org.bdware.server.trustedmodel.ResultCollector;
|
||||||
import org.bdware.units.NetworkManager;
|
import org.bdware.units.NetworkManager;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -132,15 +130,10 @@ public class MasterServerTCPAction {
|
|||||||
ContractMeta meta = CMActions.manager.statusRecorder.getContractMeta(contractID);
|
ContractMeta meta = CMActions.manager.statusRecorder.getContractMeta(contractID);
|
||||||
MultiContractMeta ret =
|
MultiContractMeta ret =
|
||||||
CMActions.manager.multiContractRecorder.getMultiContractMeta(contractID);
|
CMActions.manager.multiContractRecorder.getMultiContractMeta(contractID);
|
||||||
System.out.println(
|
LOGGER.debug(String.format("getCMInfo: %s %s %s",
|
||||||
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
meta.getName(),
|
||||||
.format(new Date(System.currentTimeMillis()))
|
meta.getID(),
|
||||||
+ " [MasterServerTCPAction] getCMInfo: "
|
meta.getStatus()));
|
||||||
+ meta.getName()
|
|
||||||
+ " "
|
|
||||||
+ meta.getID()
|
|
||||||
+ " "
|
|
||||||
+ meta.getStatus());
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +232,7 @@ public class MasterServerTCPAction {
|
|||||||
ContractMeta contractMeta =
|
ContractMeta contractMeta =
|
||||||
CMActions.manager.statusRecorder.getContractMeta(contractID);
|
CMActions.manager.statusRecorder.getContractMeta(contractID);
|
||||||
if (contractMeta == null || contractMeta.getStatus() == KILLED) {
|
if (contractMeta == null || contractMeta.getStatus() == KILLED) {
|
||||||
LOGGER.debug("send ReRoute response:" + cr.toString());
|
LOGGER.debug("send ReRoute response: " + cr);
|
||||||
JsonObject result = new JsonObject();
|
JsonObject result = new JsonObject();
|
||||||
result.addProperty("action", "reRouteContract");
|
result.addProperty("action", "reRouteContract");
|
||||||
result.addProperty("responseID", cr.get("requestID").getAsString());
|
result.addProperty("responseID", cr.get("requestID").getAsString());
|
||||||
@ -255,7 +248,9 @@ public class MasterServerTCPAction {
|
|||||||
// null") +
|
// null") +
|
||||||
// "\n");
|
// "\n");
|
||||||
|
|
||||||
if (info != null && contractMeta.contract.getType() != ContractExecType.Sharding) {
|
if (info != null &&
|
||||||
|
ContractExecType.Sharding != contractMeta.contract.getType()
|
||||||
|
&& !ContractExecType.SelfAdaptiveSharding.equals(contractMeta.contract.getType())) {
|
||||||
// 这个是个多节点的合约
|
// 这个是个多节点的合约
|
||||||
// Just forward it to the correct Node
|
// Just forward it to the correct Node
|
||||||
// Master节点直接发3个,聚合后返回结果。
|
// Master节点直接发3个,聚合后返回结果。
|
||||||
@ -296,7 +291,7 @@ public class MasterServerTCPAction {
|
|||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
} else {
|
} else {
|
||||||
LOGGER.debug("send ReRoute response:" + cr.toString());
|
LOGGER.debug("send ReRoute response:" + cr);
|
||||||
JsonObject result = new JsonObject();
|
JsonObject result = new JsonObject();
|
||||||
result.addProperty("action", "reRouteContract");
|
result.addProperty("action", "reRouteContract");
|
||||||
result.addProperty("responseID", cr.get("requestID").getAsString());
|
result.addProperty("responseID", cr.get("requestID").getAsString());
|
||||||
|
@ -209,8 +209,9 @@ public class NodeCenterClientController implements NodeCenterConn {
|
|||||||
public void updateNonMasters(JsonObject jo, ResultCallback cb) {
|
public void updateNonMasters(JsonObject jo, ResultCallback cb) {
|
||||||
String[] contracts = jo.get("contracts").getAsString().split(",");
|
String[] contracts = jo.get("contracts").getAsString().split(",");
|
||||||
for (String id : contracts) {
|
for (String id : contracts) {
|
||||||
LOGGER.info("旧的master设置合约 " + id + " 自己不再是master");
|
if (null != CMActions.manager.setContractIsMaster(id, String.valueOf(false))) {
|
||||||
CMActions.manager.setContractIsMaster(id, false + "");
|
LOGGER.warn("master of contract " + id + " changes");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,8 +332,8 @@ public class NodeCenterClientController implements NodeCenterConn {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String routeContract(String contractID) {
|
public String routeContract(String contractID) {
|
||||||
LOGGER.info("[CMClientController] routeContract : " + contractID);
|
LOGGER.debug("[CMClientController] routeContract : " + contractID);
|
||||||
LOGGER.info("contractID2Pubkey.contractsKey=" + contractID2PubKey.containsKey(contractID));
|
LOGGER.debug("contractID2Pubkey.contractsKey=" + contractID2PubKey.containsKey(contractID));
|
||||||
// TODO RouteContract是不是?IRP协议/DOIP协议?
|
// TODO RouteContract是不是?IRP协议/DOIP协议?
|
||||||
if (contractID2PubKey.containsKey(contractID)) {
|
if (contractID2PubKey.containsKey(contractID)) {
|
||||||
return contractID2PubKey.get(contractID);
|
return contractID2PubKey.get(contractID);
|
||||||
@ -519,93 +520,6 @@ public class NodeCenterClientController implements NodeCenterConn {
|
|||||||
queryNCRepoDOI(json, result);
|
queryNCRepoDOI(json, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ReceiveFileThread extends Thread {
|
|
||||||
private final Map<String, FileOutputStream> fileMap = new HashMap<>();
|
|
||||||
|
|
||||||
ReceiveFileThread() {
|
|
||||||
super();
|
|
||||||
this.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
for (; ; ) {
|
|
||||||
if (receiveQueue.size() > 0) {
|
|
||||||
try {
|
|
||||||
JsonObject jo = receiveQueue.poll();
|
|
||||||
receiveProject(jo);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (ReceiveFileThread.this) {
|
|
||||||
try {
|
|
||||||
this.wait();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void receiveProject(JsonObject args) {
|
|
||||||
|
|
||||||
String fileName = args.get("fileName").getAsString();
|
|
||||||
boolean isAppend = args.get("isAppend").getAsBoolean();
|
|
||||||
boolean isDone = args.get("isDone").getAsBoolean();
|
|
||||||
boolean isPrivate = args.get("isPrivate").getAsBoolean();
|
|
||||||
LOGGER.debug(
|
|
||||||
String.format("isAppend=%b isDone=%b isPrivate=%b", isAppend, isDone, isPrivate));
|
|
||||||
String path = GlobalConf.instance.publicCompiledDir;
|
|
||||||
if (isPrivate && args.has("pubKey")) {
|
|
||||||
path = GlobalConf.instance.privateCompiledDir + "/" + args.get("pubKey").getAsString();
|
|
||||||
}
|
|
||||||
File dir = new File(path);
|
|
||||||
if (!dir.exists()) {
|
|
||||||
LOGGER.debug("mkdir " + dir.getAbsoluteFile() + ": " + dir.mkdirs());
|
|
||||||
}
|
|
||||||
FileOutputStream fout = null;
|
|
||||||
if (!isAppend) {
|
|
||||||
try {
|
|
||||||
fout = new FileOutputStream(new File(dir, fileName));
|
|
||||||
fileMap.put(fileName, fout);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fout = fileMap.get(fileName);
|
|
||||||
}
|
|
||||||
if (isDone) {
|
|
||||||
if (fout != null)
|
|
||||||
try {
|
|
||||||
fout.close();
|
|
||||||
fileMap.remove(fileName);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
LOGGER.debug("receive finish.");
|
|
||||||
Map<String, String> req = new HashMap<>();
|
|
||||||
req.put("action", "onReceiveProject");
|
|
||||||
req.put("requestID", args.get("requestID").getAsString());
|
|
||||||
req.put("nodeID", nodeID);
|
|
||||||
req.put("progress", "100");
|
|
||||||
NetworkManager.instance.sendToNodeCenter(JsonUtil.toJson(req));
|
|
||||||
} else {
|
|
||||||
String data = args.get("data").getAsString();
|
|
||||||
byte[] byteData = ByteUtil.decodeBASE64(data);
|
|
||||||
try {
|
|
||||||
if (null != fout && null != byteData) {
|
|
||||||
fout.write(byteData);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Action(async = false)
|
@Action(async = false)
|
||||||
public synchronized void receiveProject(JsonObject args, final ResultCallback rc) {
|
public synchronized void receiveProject(JsonObject args, final ResultCallback rc) {
|
||||||
try {
|
try {
|
||||||
@ -758,6 +672,11 @@ public class NodeCenterClientController implements NodeCenterConn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Action(async = true)
|
||||||
|
public void onDistributeYPK(JsonObject json, ResultCallback rc) {
|
||||||
|
onDistribute(json, rc);
|
||||||
|
}
|
||||||
|
|
||||||
@Action(async = true)
|
@Action(async = true)
|
||||||
public void transferInstance(JsonObject jo, ResultCallback result) {
|
public void transferInstance(JsonObject jo, ResultCallback result) {
|
||||||
LOGGER.info("transferInstance");
|
LOGGER.info("transferInstance");
|
||||||
@ -831,4 +750,90 @@ public class NodeCenterClientController implements NodeCenterConn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ReceiveFileThread extends Thread {
|
||||||
|
private final Map<String, FileOutputStream> fileMap = new HashMap<>();
|
||||||
|
|
||||||
|
ReceiveFileThread() {
|
||||||
|
super();
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
for (; ; ) {
|
||||||
|
if (receiveQueue.size() > 0) {
|
||||||
|
try {
|
||||||
|
JsonObject jo = receiveQueue.poll();
|
||||||
|
receiveProject(jo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
synchronized (ReceiveFileThread.this) {
|
||||||
|
try {
|
||||||
|
this.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void receiveProject(JsonObject args) {
|
||||||
|
|
||||||
|
String fileName = args.get("fileName").getAsString();
|
||||||
|
boolean isAppend = args.get("isAppend").getAsBoolean();
|
||||||
|
boolean isDone = args.get("isDone").getAsBoolean();
|
||||||
|
boolean isPrivate = args.get("isPrivate").getAsBoolean();
|
||||||
|
LOGGER.debug(
|
||||||
|
String.format("isAppend=%b isDone=%b isPrivate=%b", isAppend, isDone, isPrivate));
|
||||||
|
String path = GlobalConf.instance.publicCompiledDir;
|
||||||
|
if (isPrivate && args.has("pubKey")) {
|
||||||
|
path = GlobalConf.instance.privateCompiledDir + "/" + args.get("pubKey").getAsString();
|
||||||
|
}
|
||||||
|
File dir = new File(path);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
LOGGER.debug("mkdir " + dir.getAbsoluteFile() + ": " + dir.mkdirs());
|
||||||
|
}
|
||||||
|
FileOutputStream fout = null;
|
||||||
|
if (!isAppend) {
|
||||||
|
try {
|
||||||
|
fout = new FileOutputStream(new File(dir, fileName));
|
||||||
|
fileMap.put(fileName, fout);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fout = fileMap.get(fileName);
|
||||||
|
}
|
||||||
|
if (isDone) {
|
||||||
|
if (fout != null)
|
||||||
|
try {
|
||||||
|
fout.close();
|
||||||
|
fileMap.remove(fileName);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
LOGGER.debug("receive finish.");
|
||||||
|
Map<String, String> req = new HashMap<>();
|
||||||
|
req.put("action", "onReceiveProject");
|
||||||
|
req.put("requestID", args.get("requestID").getAsString());
|
||||||
|
req.put("nodeID", nodeID);
|
||||||
|
req.put("progress", "100");
|
||||||
|
NetworkManager.instance.sendToNodeCenter(JsonUtil.toJson(req));
|
||||||
|
} else {
|
||||||
|
String data = args.get("data").getAsString();
|
||||||
|
byte[] byteData = ByteUtil.decodeBASE64(data);
|
||||||
|
try {
|
||||||
|
if (null != fout && null != byteData) {
|
||||||
|
fout.write(byteData);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ public class AgentManager implements AgentPeerManagerIntf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeByOtherNodeAsync(String pubKey, ContractRequest c, ResultCallback cb) {
|
public void executeByOtherNodeAsync(String pubKey, ContractRequest c, ResultCallback cb) {
|
||||||
LOGGER.error(pubKey + " " + c.getRequestID() + " " + c.getContractID() + " cb:" + cb);
|
LOGGER.debug(pubKey + " " + c.getRequestID() + " " + c.getContractID() + " cb:" + cb);
|
||||||
int maxMasterProxyLoad = CongestionControl.masterProxyLoad.incrementAndGet();
|
int maxMasterProxyLoad = CongestionControl.masterProxyLoad.incrementAndGet();
|
||||||
if (maxMasterProxyLoad > CongestionControl.maxMasterProxyLoad)
|
if (maxMasterProxyLoad > CongestionControl.maxMasterProxyLoad)
|
||||||
CongestionControl.maxMasterProxyLoad = maxMasterProxyLoad;
|
CongestionControl.maxMasterProxyLoad = maxMasterProxyLoad;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.bdware.server.trustedmodel;
|
package org.bdware.server.trustedmodel;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@ -13,15 +14,16 @@ import org.bdware.sc.bean.SM2Verifiable;
|
|||||||
import org.bdware.sc.conn.OnHashCallback;
|
import org.bdware.sc.conn.OnHashCallback;
|
||||||
import org.bdware.sc.conn.ResultCallback;
|
import org.bdware.sc.conn.ResultCallback;
|
||||||
import org.bdware.sc.units.MultiContractMeta;
|
import org.bdware.sc.units.MultiContractMeta;
|
||||||
import org.bdware.sc.units.RecoverFlag;
|
|
||||||
import org.bdware.sc.util.HashUtil;
|
import org.bdware.sc.util.HashUtil;
|
||||||
import org.bdware.sc.util.JsonUtil;
|
import org.bdware.sc.util.JsonUtil;
|
||||||
import org.bdware.server.action.CMActions;
|
import org.bdware.server.action.CMActions;
|
||||||
import org.bdware.server.action.p2p.MasterServerRecoverMechAction;
|
|
||||||
import org.bdware.units.NetworkManager;
|
import org.bdware.units.NetworkManager;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,66 +31,76 @@ import java.util.stream.Collectors;
|
|||||||
*/
|
*/
|
||||||
public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
||||||
private static final Logger LOGGER = LogManager.getLogger(SelfAdaptiveShardingExecutor.class);
|
private static final Logger LOGGER = LogManager.getLogger(SelfAdaptiveShardingExecutor.class);
|
||||||
private static final int SUBMIT_LIMIT = 1024;
|
private static final int SUBMIT_LIMIT = 5120;
|
||||||
private static final int DELAY = 1;
|
private static final int DELAY = 1;
|
||||||
private final Queue<ContractRequest> reqQueue = new ConcurrentLinkedQueue<>();
|
private final Queue<ContractRequest> reqQueue = new ConcurrentLinkedQueue<>();
|
||||||
private final MultiContractMeta meta;
|
private final MultiContractMeta meta;
|
||||||
private final Map<String, Block> toExecuted = new ConcurrentHashMap<>();
|
private final Map<String, Block> toExecuted = new ConcurrentHashMap<>();
|
||||||
private final Set<String> executedBlocks = ConcurrentHashMap.newKeySet();
|
private final Set<String> executedBlocks = ConcurrentHashMap.newKeySet();
|
||||||
private final Map<String, Boolean> executedTxs = new ConcurrentHashMap<>();
|
private final Map<String, Boolean> executedTxs = new ConcurrentHashMap<>();
|
||||||
private final Object flag = new Object();
|
private final Object executorFlag = new Object();
|
||||||
private final ScheduledFuture<?> future;
|
private final ScheduledFuture<?> future;
|
||||||
private boolean running = true;
|
private boolean running = true;
|
||||||
|
// the pointer to the latest executed block
|
||||||
|
private String executorPointer = "0";
|
||||||
|
// the block to be submitted
|
||||||
private Block b = new Block();
|
private Block b = new Block();
|
||||||
|
|
||||||
public SelfAdaptiveShardingExecutor(String contractID) {
|
public SelfAdaptiveShardingExecutor(String contractID) {
|
||||||
this.meta =
|
this.meta = CMActions.manager.multiContractRecorder.getMultiContractMeta(contractID);
|
||||||
CMActions.manager.multiContractRecorder.getMultiContractMeta(contractID);
|
|
||||||
this.future = ContractManager.scheduledThreadPool.scheduleWithFixedDelay(
|
this.future = ContractManager.scheduledThreadPool.scheduleWithFixedDelay(
|
||||||
this::submitBlock,
|
this::submitBlock,
|
||||||
DELAY,
|
DELAY,
|
||||||
DELAY,
|
DELAY,
|
||||||
TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
LOGGER.debug(String.format("ContractManager.threadPool=%d/%d",
|
|
||||||
((ThreadPoolExecutor) ContractManager.threadPool).getActiveCount(),
|
|
||||||
((ThreadPoolExecutor) ContractManager.threadPool).getPoolSize()));
|
|
||||||
ContractManager.threadPool.execute(() -> {
|
ContractManager.threadPool.execute(() -> {
|
||||||
LOGGER.info(
|
LOGGER.info(String.format(
|
||||||
"[SelfAdaptiveShardingExecutor " + meta.getContractID() + "] starting service..." + running);
|
"[Executor %s] starting executing service... %b",
|
||||||
|
meta.getContractID(), meta.isMaster()));
|
||||||
while (running) {
|
while (running) {
|
||||||
LOGGER.info("checking blocks to be executed, latest block=" +
|
LOGGER.info(String.format(
|
||||||
this.b.prevHash + ", to be executed size=" + toExecuted.size());
|
"[Executor %s] checking blocks to be executed, latest block=%s, to be executed size=%d",
|
||||||
|
meta.getContractID(), executorPointer, toExecuted.size()));
|
||||||
LOGGER.debug("executed: " + JsonUtil.toJson(executedBlocks) + "\n\t" + JsonUtil.toJson(executedTxs));
|
LOGGER.debug("executed: " + JsonUtil.toJson(executedBlocks) + "\n\t" + JsonUtil.toJson(executedTxs));
|
||||||
while (!toExecuted.isEmpty()) {
|
while (!toExecuted.isEmpty()) {
|
||||||
String key = this.b.prevHash;
|
Block block = toExecuted.get(executorPointer);
|
||||||
Block block = toExecuted.get(key);
|
// check if the execution ends
|
||||||
if (null != block) {
|
if (null == block) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
executeBlock(block);
|
executeBlock(block);
|
||||||
|
toExecuted.remove(executorPointer);
|
||||||
|
executorPointer = block.hash;
|
||||||
}
|
}
|
||||||
toExecuted.remove(key);
|
|
||||||
}
|
|
||||||
synchronized (flag) {
|
|
||||||
try {
|
try {
|
||||||
flag.wait();
|
synchronized (executorFlag) {
|
||||||
|
executorFlag.wait();
|
||||||
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.warn(String.format(
|
LOGGER.warn(String.format(
|
||||||
"[SelfAdaptiveShardingExecutor %s] waiting is interrupted: %s",
|
"[Executor %s] waiting is interrupted: %s",
|
||||||
meta.getContractID(),
|
meta.getContractID(), e.getMessage()));
|
||||||
e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JsonArray checkCache() {
|
||||||
|
JsonArray ret = new JsonArray();
|
||||||
|
ret.add(executorPointer);
|
||||||
|
for (Map.Entry<String, Block> entry : toExecuted.entrySet()) {
|
||||||
|
ret.add(String.format("%s,%s,%d", entry.getKey(), entry.getValue().hash, entry.getValue().height));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String requestID, ContractRequest req, ResultCallback rcb, OnHashCallback hcb) {
|
public void execute(String requestID, ContractRequest req, ResultCallback rcb, OnHashCallback hcb) {
|
||||||
// check client
|
// check client
|
||||||
ContractClient client = CMActions.manager.getClient(meta.getContractID());
|
ContractClient client = CMActions.manager.getClient(meta.getContractID());
|
||||||
if (null == client) {
|
if (null == client) {
|
||||||
LOGGER.error("contract " + meta.getContractID() + " not found!");
|
LOGGER.error("contract " + meta.getContractID() + " not found!");
|
||||||
rcb.onResult(JsonUtil.toJson(new ContractResult(
|
rcb.onResult(JsonUtil.toJson(new ContractResult(ContractResult.Status.Error,
|
||||||
ContractResult.Status.Error,
|
|
||||||
new JsonPrimitive("contract " + meta.getContractID() + " not found!"))));
|
new JsonPrimitive("contract " + meta.getContractID() + " not found!"))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -96,12 +108,10 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
|||||||
FunctionDesp funDesp = client.contractMeta.getExportedFunction(req.getAction());
|
FunctionDesp funDesp = client.contractMeta.getExportedFunction(req.getAction());
|
||||||
if (null == funDesp) {
|
if (null == funDesp) {
|
||||||
LOGGER.warn("action " + req.getAction() + " of contract " + meta.getContractID() + " not found!");
|
LOGGER.warn("action " + req.getAction() + " of contract " + meta.getContractID() + " not found!");
|
||||||
rcb.onResult(JsonUtil.toJson(new ContractResult(
|
rcb.onResult(JsonUtil.toJson(new ContractResult(ContractResult.Status.Error,
|
||||||
ContractResult.Status.Error,
|
new JsonPrimitive(String.format(
|
||||||
new JsonPrimitive(
|
"action %s of contract %s not found!",
|
||||||
String.format("action %s of contract %s not found!",
|
req.getAction(), meta.getContractID())))));
|
||||||
req.getAction(),
|
|
||||||
meta.getContractID())))));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// for view function, execute it
|
// for view function, execute it
|
||||||
@ -111,18 +121,21 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
|||||||
}
|
}
|
||||||
// normal function, check if it is in blocks
|
// normal function, check if it is in blocks
|
||||||
if (executedTxs.containsKey(requestID)) {
|
if (executedTxs.containsKey(requestID)) {
|
||||||
rcb.onResult(JsonUtil.toJson(new ContractResult(
|
rcb.onResult(JsonUtil.toJson(new ContractResult(ContractResult.Status.Error,
|
||||||
ContractResult.Status.Error,
|
|
||||||
new JsonPrimitive("this request has been packed!"))));
|
new JsonPrimitive("this request has been packed!"))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// forward to master
|
||||||
|
if (!meta.isMaster()) {
|
||||||
|
CMActions.manager.executeContractOnOtherNodes(req, rcb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// add blocks into request cache
|
// add blocks into request cache
|
||||||
LOGGER.debug("receive contract request " + requestID);
|
LOGGER.debug("receive contract request " + requestID);
|
||||||
executedTxs.put(requestID, false);
|
executedTxs.put(requestID, false);
|
||||||
reqQueue.add(req);
|
reqQueue.add(req);
|
||||||
rcb.onResult(JsonUtil.toJson(new ContractResult(
|
rcb.onResult(JsonUtil.toJson(new ContractResult(ContractResult.Status.Executing,
|
||||||
ContractResult.Status.Executing,
|
new JsonPrimitive("this request is added into blocks"))));
|
||||||
new JsonPrimitive("this request is adding into blocks"))));
|
|
||||||
// if cache is full, submit
|
// if cache is full, submit
|
||||||
if (reqQueue.size() >= SUBMIT_LIMIT) {
|
if (reqQueue.size() >= SUBMIT_LIMIT) {
|
||||||
ContractManager.threadPool.execute(this::submitBlock);
|
ContractManager.threadPool.execute(this::submitBlock);
|
||||||
@ -137,17 +150,18 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
|||||||
LOGGER.info("destruct executor of contract " + meta.getContractID());
|
LOGGER.info("destruct executor of contract " + meta.getContractID());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(String blockStr) {
|
public void receiveBlock(String blockStr) {
|
||||||
Block block = JsonUtil.fromJson(blockStr, Block.class);
|
Block block = JsonUtil.fromJson(blockStr, Block.class);
|
||||||
// the block must have not been cached or executed, and must be valid
|
// the block must have not been cached or executed, and must be valid
|
||||||
|
boolean valid = block.isValid();
|
||||||
if (!toExecuted.containsKey(block.prevHash) &&
|
if (!toExecuted.containsKey(block.prevHash) &&
|
||||||
!executedBlocks.contains(block.hash) &&
|
!executedBlocks.contains(block.hash) &&
|
||||||
block.isValid()) {
|
valid) {
|
||||||
// add block into block cache
|
// add block into block cache
|
||||||
LOGGER.info(String.format(
|
LOGGER.info(String.format(
|
||||||
"[SelfAdaptiveShardingExecutor %s] receive block %s -> %s," +
|
"[Executor %s] receive block [%d] %s -> %s, %d transactions, timestamp=%d, size=%d",
|
||||||
" %d transactions, timestamp=%d, size=%d",
|
|
||||||
meta.getContractID(),
|
meta.getContractID(),
|
||||||
|
block.height,
|
||||||
block.hash,
|
block.hash,
|
||||||
block.prevHash,
|
block.prevHash,
|
||||||
block.requests.length,
|
block.requests.length,
|
||||||
@ -155,9 +169,16 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
|||||||
blockStr.length()));
|
blockStr.length()));
|
||||||
toExecuted.put(block.prevHash, block);
|
toExecuted.put(block.prevHash, block);
|
||||||
// notify thread to execute blocks
|
// notify thread to execute blocks
|
||||||
synchronized (flag) {
|
synchronized (executorFlag) {
|
||||||
flag.notify();
|
executorFlag.notify();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LOGGER.warn(String.format("receive block [%d] %s failed! checking: cached %b executed %b valid %b",
|
||||||
|
block.height,
|
||||||
|
block.hash,
|
||||||
|
toExecuted.containsKey(block.prevHash),
|
||||||
|
executedBlocks.contains(block.hash),
|
||||||
|
valid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,41 +197,48 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
|||||||
for (ContractRequest request : block.requests) {
|
for (ContractRequest request : block.requests) {
|
||||||
String ret = CMActions.manager.executeLocally(request, null);
|
String ret = CMActions.manager.executeLocally(request, null);
|
||||||
LOGGER.debug(String.format(
|
LOGGER.debug(String.format(
|
||||||
"[SelfAdaptiveShardingExecutor %s] result of request %s: %s",
|
"[Executor %s] result of request %s: %s",
|
||||||
meta.getContractID(),
|
meta.getContractID(), request.getRequestID(), ret));
|
||||||
request.getRequestID(),
|
|
||||||
ret));
|
|
||||||
executedTxs.put(request.getRequestID(), true);
|
executedTxs.put(request.getRequestID(), true);
|
||||||
}
|
}
|
||||||
LOGGER.info(String.format(
|
LOGGER.info(String.format(
|
||||||
"[SelfAdaptiveShardingExecutor %s] execute %d transactions of block %s",
|
"[Executor %s] execute %d transactions of block [%d] %s",
|
||||||
meta.getContractID(),
|
meta.getContractID(), block.requests.length, block.height, block.hash));
|
||||||
block.requests.length,
|
|
||||||
block.hash));
|
|
||||||
// TODO create check point
|
// TODO create check point
|
||||||
this.b = new Block(block.hash, this.b.height + 1);
|
// this.b = new Block(block.hash, this.b.height + 1);
|
||||||
executedBlocks.add(block.hash);
|
executedBlocks.add(block.hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void submitBlock() {
|
private void submitBlock() {
|
||||||
Block block = fillBlock();
|
Block block = fillBlock();
|
||||||
if (null != block) {
|
if (null != block) {
|
||||||
LOGGER.info("deliver block " + block.hash + "...");
|
|
||||||
LOGGER.debug(JsonUtil.toPrettyJson(block));
|
LOGGER.debug(JsonUtil.toPrettyJson(block));
|
||||||
String[] nodes = this.meta.getMembers();
|
String[] nodes = this.meta.getMembers();
|
||||||
|
LOGGER.debug(JsonUtil.toJson(nodes));
|
||||||
JsonObject req = new JsonObject();
|
JsonObject req = new JsonObject();
|
||||||
|
String blockStr = JsonUtil.toJson(block);
|
||||||
req.addProperty("action", "deliverBlock");
|
req.addProperty("action", "deliverBlock");
|
||||||
req.addProperty("data", JsonUtil.toJson(block));
|
req.addProperty("data", blockStr);
|
||||||
req.addProperty("contractID", this.meta.getContractID());
|
req.addProperty("contractID", this.meta.getContractID());
|
||||||
String reqStr = req.toString();
|
String reqStr = req.toString();
|
||||||
// deliver blocks
|
// deliver blocks
|
||||||
|
LOGGER.info("deliver block " + block.hash + "...");
|
||||||
|
String myself = CMActions.manager.nodeCenterConn.getNodeId();
|
||||||
for (String node : nodes) {
|
for (String node : nodes) {
|
||||||
if (MasterServerRecoverMechAction.recoverStatus.get(node).get(this.meta.getContractID())
|
// TODO: find dead lock here
|
||||||
== RecoverFlag.Fine) {
|
// if (MasterServerRecoverMechAction.recoverStatus.get(node).get(this.meta.getContractID())
|
||||||
|
// == RecoverFlag.Fine) {
|
||||||
|
// LOGGER.info("deliver block " + block.hash + " to node " + node);
|
||||||
|
// NetworkManager.instance.sendToAgent(node, reqStr);
|
||||||
|
// }
|
||||||
|
if (!Objects.equals(myself, node)) {
|
||||||
NetworkManager.instance.sendToAgent(node, reqStr);
|
NetworkManager.instance.sendToAgent(node, reqStr);
|
||||||
}
|
}
|
||||||
|
// LOGGER.info("delivering done: " + node);
|
||||||
}
|
}
|
||||||
|
this.receiveBlock(blockStr);
|
||||||
}
|
}
|
||||||
|
// LOGGER.info("end " + (null != block));
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized Block fillBlock() {
|
private synchronized Block fillBlock() {
|
||||||
@ -222,8 +250,10 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
|||||||
for (int i = 0; i < requests.length; ++i) {
|
for (int i = 0; i < requests.length; ++i) {
|
||||||
requests[i] = reqQueue.poll();
|
requests[i] = reqQueue.poll();
|
||||||
}
|
}
|
||||||
this.b.fillBlock(requests);
|
Block block = this.b;
|
||||||
return this.b;
|
block.fillBlock(requests);
|
||||||
|
this.b = new Block(block.hash, block.height + 1);
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Block extends SM2Verifiable {
|
static class Block extends SM2Verifiable {
|
||||||
@ -254,15 +284,19 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return computeHash().equals(hash) && body.equals(merkle(this.requests)) && verifySignature();
|
boolean hashValid = computeHash().equals(hash),
|
||||||
|
// bodyValid = body.equals(merkle(this.requests)),
|
||||||
|
bodyValid = true,
|
||||||
|
signValid = verifySignature();
|
||||||
|
boolean ret = hashValid & bodyValid & signValid;
|
||||||
|
if (!ret) {
|
||||||
|
LOGGER.warn(String.format("hash %b body %b sign %b", hashValid, bodyValid, signValid));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String computeHash() {
|
private String computeHash() {
|
||||||
return HashUtil.sha3(
|
return HashUtil.sha3(String.valueOf(this.height), this.prevHash, this.checkPoint, this.body);
|
||||||
String.valueOf(this.height),
|
|
||||||
this.prevHash,
|
|
||||||
this.checkPoint,
|
|
||||||
this.body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String merkle(ContractRequest[] requests) {
|
private String merkle(ContractRequest[] requests) {
|
||||||
@ -273,19 +307,19 @@ public class SelfAdaptiveShardingExecutor implements ContractExecutor {
|
|||||||
if (requests.length == 1) {
|
if (requests.length == 1) {
|
||||||
return HashUtil.sha3(requests[0].getRequestID());
|
return HashUtil.sha3(requests[0].getRequestID());
|
||||||
}
|
}
|
||||||
Queue<String> reqQueue =
|
Queue<String> merkleQueue =
|
||||||
Arrays.stream(requests).map(ContractRequest::getRequestID)
|
Arrays.stream(requests).map(ContractRequest::getRequestID)
|
||||||
.collect(Collectors.toCollection(ArrayDeque::new));
|
.collect(Collectors.toCollection(ArrayDeque::new));
|
||||||
do {
|
do {
|
||||||
int size;
|
int size;
|
||||||
for (size = reqQueue.size(); size > 1; size -= 2) {
|
for (size = merkleQueue.size(); size > 1; size -= 2) {
|
||||||
reqQueue.add(HashUtil.sha3(reqQueue.poll(), reqQueue.poll()));
|
merkleQueue.add(HashUtil.sha3(merkleQueue.poll(), merkleQueue.poll()));
|
||||||
}
|
}
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
reqQueue.add(reqQueue.poll());
|
merkleQueue.add(merkleQueue.poll());
|
||||||
}
|
}
|
||||||
} while (1 != reqQueue.size());
|
} while (1 != merkleQueue.size());
|
||||||
return reqQueue.poll();
|
return merkleQueue.poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user