mirror of
				https://gitee.com/BDWare/cm
				synced 2025-11-04 02:22:14 +00:00 
			
		
		
		
	build: config spotless plugin and reformat code
This commit is contained in:
		
							parent
							
								
									6cd99cf17a
								
							
						
					
					
						commit
						fc453d56fc
					
				@ -2,6 +2,9 @@ plugins {
 | 
			
		||||
    id 'java'
 | 
			
		||||
    id 'java-library'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
apply from: '../spotless.gradle'
 | 
			
		||||
 | 
			
		||||
repositories {
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -9,28 +9,14 @@ public interface ChainOpener {
 | 
			
		||||
 | 
			
		||||
    String register(String arg);
 | 
			
		||||
 | 
			
		||||
    void writeContractResultToLocalAndLedger(
 | 
			
		||||
            String result,
 | 
			
		||||
            ContractClient client,
 | 
			
		||||
            ContractRequest contractRequest,
 | 
			
		||||
            OnHashCallback cb, long start, long l);
 | 
			
		||||
    void writeContractResultToLocalAndLedger(String result, ContractClient client,
 | 
			
		||||
            ContractRequest contractRequest, OnHashCallback cb, long start, long l);
 | 
			
		||||
 | 
			
		||||
    void writeToChain(
 | 
			
		||||
            OnHashCallback cb,
 | 
			
		||||
            String from,
 | 
			
		||||
            String to,
 | 
			
		||||
            String data,
 | 
			
		||||
            String requestID,
 | 
			
		||||
    void writeToChain(OnHashCallback cb, String from, String to, String data, String requestID,
 | 
			
		||||
            String namedLedger);
 | 
			
		||||
 | 
			
		||||
    void writeToChainWithContract(
 | 
			
		||||
            OnHashCallback cb,
 | 
			
		||||
            String from,
 | 
			
		||||
            String to,
 | 
			
		||||
            String data,
 | 
			
		||||
            String requestID,
 | 
			
		||||
            String contractID,
 | 
			
		||||
            String namedLedger);
 | 
			
		||||
    void writeToChainWithContract(OnHashCallback cb, String from, String to, String data,
 | 
			
		||||
            String requestID, String contractID, String namedLedger);
 | 
			
		||||
 | 
			
		||||
    JsonElement getLedgerParams();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -138,21 +138,16 @@ public class ContractClient {
 | 
			
		||||
        // LOGGER.info("initProps ---- position-----2");
 | 
			
		||||
        String strEvent = get.syncGet("", "getDeclaredEvents", "");
 | 
			
		||||
        LOGGER.debug("event: " + strEvent);
 | 
			
		||||
        contractMeta.declaredEvents =
 | 
			
		||||
                JsonUtil.fromJson(
 | 
			
		||||
                        strEvent, new TypeToken<Map<String, REventSemantics>>() {
 | 
			
		||||
                        }.getType());
 | 
			
		||||
        contractMeta.declaredEvents = JsonUtil.fromJson(strEvent,
 | 
			
		||||
                new TypeToken<Map<String, REventSemantics>>() {}.getType());
 | 
			
		||||
        // LOGGER.info("initProps ---- position-----3");
 | 
			
		||||
        contractMeta.dependentContracts = JsonUtil.fromJson(
 | 
			
		||||
                get.syncGet("", "getDependentContracts", ""),
 | 
			
		||||
                new TypeToken<Set<String>>() {
 | 
			
		||||
                }.getType());
 | 
			
		||||
        contractMeta.dependentContracts =
 | 
			
		||||
                JsonUtil.fromJson(get.syncGet("", "getDependentContracts", ""),
 | 
			
		||||
                        new TypeToken<Set<String>>() {}.getType());
 | 
			
		||||
        // LOGGER.info("initProps ---- position-----4");
 | 
			
		||||
        contractMeta.exportedFunctions =
 | 
			
		||||
                JsonUtil.fromJson(
 | 
			
		||||
                        get.syncGet("", "getExportedFunctions", ""),
 | 
			
		||||
                        new TypeToken<List<FunctionDesp>>() {
 | 
			
		||||
                        }.getType());
 | 
			
		||||
                JsonUtil.fromJson(get.syncGet("", "getExportedFunctions", ""),
 | 
			
		||||
                        new TypeToken<List<FunctionDesp>>() {}.getType());
 | 
			
		||||
        contractMeta.logDetail = new HashMap<>();
 | 
			
		||||
        for (FunctionDesp func : contractMeta.exportedFunctions) {
 | 
			
		||||
            StringBuilder str = new StringBuilder();
 | 
			
		||||
@ -164,8 +159,7 @@ public class ContractClient {
 | 
			
		||||
                }
 | 
			
		||||
                if (anno.getType().equals("LogLocation")) {
 | 
			
		||||
                    for (String logLoc : anno.getArgs()) {
 | 
			
		||||
                        if (logLoc.equals("\"dataware\"")
 | 
			
		||||
                                || logLoc.equals("\"bdledger\"")
 | 
			
		||||
                        if (logLoc.equals("\"dataware\"") || logLoc.equals("\"bdledger\"")
 | 
			
		||||
                                || logLoc.equals("\"bdledger:\"")) {
 | 
			
		||||
                            str.append("bdcontract;");
 | 
			
		||||
                        } else if (logLoc.startsWith("\"bdledger:") && logLoc.length() > 11) {
 | 
			
		||||
@ -183,8 +177,7 @@ public class ContractClient {
 | 
			
		||||
 | 
			
		||||
            String anno = get.syncGet("", "getAnnotations", "");
 | 
			
		||||
            contractMeta.annotations =
 | 
			
		||||
                    JsonUtil.fromJson(anno, new TypeToken<List<AnnotationNode>>() {
 | 
			
		||||
                    }.getType());
 | 
			
		||||
                    JsonUtil.fromJson(anno, new TypeToken<List<AnnotationNode>>() {}.getType());
 | 
			
		||||
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            // supoort contract process before version 0.70
 | 
			
		||||
@ -201,14 +194,12 @@ public class ContractClient {
 | 
			
		||||
        contractMeta.contract =
 | 
			
		||||
                JsonUtil.fromJson(get.syncGet("", "getContract", ""), Contract.class);
 | 
			
		||||
        contractMeta.id = contractMeta.contract.getID();
 | 
			
		||||
        get.setOfflineExceptionHandler(
 | 
			
		||||
                new SocketGet.OfflineHandler() {
 | 
			
		||||
        get.setOfflineExceptionHandler(new SocketGet.OfflineHandler() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onException(SocketGet socketGet, Exception e) {
 | 
			
		||||
                if (e.getMessage().contains("Connection refused")) {
 | 
			
		||||
                    contractMeta.status = ContractStatusEnum.HANGED;
 | 
			
		||||
                            ContractManager.instance.statusRecorder.resumeContractProcess(
 | 
			
		||||
                                    contractMeta.id);
 | 
			
		||||
                    ContractManager.instance.statusRecorder.resumeContractProcess(contractMeta.id);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
@ -233,15 +224,12 @@ public class ContractClient {
 | 
			
		||||
        String osJni = ((HardwareInfo.type == OSType.linux) ? "/jni/linux" : "/jni/mac");
 | 
			
		||||
        darg += jniPath.getAbsolutePath() + osJni;
 | 
			
		||||
        if (!new File(classpath).exists()) {
 | 
			
		||||
            ContractResult r =
 | 
			
		||||
                    new ContractResult(
 | 
			
		||||
                            Status.Exception, new JsonPrimitive("incorrect path: yjs.jar"));
 | 
			
		||||
            ContractResult r = new ContractResult(Status.Exception,
 | 
			
		||||
                    new JsonPrimitive("incorrect path: yjs.jar"));
 | 
			
		||||
            return JsonUtil.toJson(r);
 | 
			
		||||
        }
 | 
			
		||||
        if (!new File(jniPath, "libs").exists()) {
 | 
			
		||||
            ContractResult r =
 | 
			
		||||
                    new ContractResult(
 | 
			
		||||
                            Status.Exception,
 | 
			
		||||
            ContractResult r = new ContractResult(Status.Exception,
 | 
			
		||||
                    new JsonPrimitive("incorrect path: yjs.jar, missing libs"));
 | 
			
		||||
            return JsonUtil.toJson(r);
 | 
			
		||||
        }
 | 
			
		||||
@ -251,13 +239,17 @@ public class ContractClient {
 | 
			
		||||
        pbParameters.add("-Dfile.encoding=UTF-8");
 | 
			
		||||
        pbParameters.add(darg);
 | 
			
		||||
        if (contractMeta.contract.getRemoteDebugPort() != 0) {
 | 
			
		||||
            pbParameters.add(String.format("-agentlib:jdwp=transport=dt_socket,address=%d,server=y,suspend=n", contractMeta.contract.getRemoteDebugPort()));
 | 
			
		||||
            pbParameters.add(String.format(
 | 
			
		||||
                    "-agentlib:jdwp=transport=dt_socket,address=%d,server=y,suspend=n",
 | 
			
		||||
                    contractMeta.contract.getRemoteDebugPort()));
 | 
			
		||||
        }
 | 
			
		||||
        File classParent = new File(classpath).getParentFile();
 | 
			
		||||
        if (contractMeta.contract.isDebug()) {
 | 
			
		||||
            pbParameters.add("-Dlog4j.configurationFile=" + new File(classParent, "log4j2.debug.properties").getAbsolutePath());
 | 
			
		||||
            pbParameters.add("-Dlog4j.configurationFile="
 | 
			
		||||
                    + new File(classParent, "log4j2.debug.properties").getAbsolutePath());
 | 
			
		||||
        } else {
 | 
			
		||||
            pbParameters.add("-Dlog4j.configurationFile=" + new File(classParent, "log4j2.properties").getAbsolutePath());
 | 
			
		||||
            pbParameters.add("-Dlog4j.configurationFile="
 | 
			
		||||
                    + new File(classParent, "log4j2.properties").getAbsolutePath());
 | 
			
		||||
        }
 | 
			
		||||
        pbParameters.add("-jar");
 | 
			
		||||
        pbParameters.add(classpath);
 | 
			
		||||
@ -268,7 +260,8 @@ public class ContractClient {
 | 
			
		||||
        ProcessBuilder builder;
 | 
			
		||||
        String[] result = new String[pbParameters.size()];
 | 
			
		||||
        pbParameters.toArray(result);
 | 
			
		||||
        Constructor<ProcessBuilder> pbc = ProcessBuilder.class.getDeclaredConstructor(String[].class);
 | 
			
		||||
        Constructor<ProcessBuilder> pbc =
 | 
			
		||||
                ProcessBuilder.class.getDeclaredConstructor(String[].class);
 | 
			
		||||
        builder = pbc.newInstance(new Object[] {result});
 | 
			
		||||
 | 
			
		||||
        File directory = new File("./");
 | 
			
		||||
@ -294,10 +287,8 @@ public class ContractClient {
 | 
			
		||||
                try {
 | 
			
		||||
                    // Set contractPort to max(mainPort, contractPort)
 | 
			
		||||
                    int portIndex = status.indexOf("mainPort");
 | 
			
		||||
                    int port =
 | 
			
		||||
                            Integer.parseInt(
 | 
			
		||||
                                    status.substring(portIndex + 9, portIndex + 14)
 | 
			
		||||
                                            .replaceAll("\\s+", ""));
 | 
			
		||||
                    int port = Integer.parseInt(
 | 
			
		||||
                            status.substring(portIndex + 9, portIndex + 14).replaceAll("\\s+", ""));
 | 
			
		||||
                    if (port != startPort) {
 | 
			
		||||
                        ContractManager.cPort.reSetPort(port + 1);
 | 
			
		||||
                    }
 | 
			
		||||
@ -327,20 +318,20 @@ public class ContractClient {
 | 
			
		||||
        }
 | 
			
		||||
        get.syncGet("", "registerMangerPort", String.valueOf(ContractManager.cPort.getCMPort()));
 | 
			
		||||
 | 
			
		||||
        MultiContractMeta multiContractMeta =
 | 
			
		||||
                ContractManager.instance.multiContractRecorder.getMultiContractMeta(contractMeta.getID());
 | 
			
		||||
        MultiContractMeta multiContractMeta = ContractManager.instance.multiContractRecorder
 | 
			
		||||
                .getMultiContractMeta(contractMeta.getID());
 | 
			
		||||
        if (multiContractMeta != null && multiContractMeta.getMembers() != null) {
 | 
			
		||||
            String setMemberResult = get.syncGet(
 | 
			
		||||
                    "", "setMembers", JsonUtil.toJson(multiContractMeta.getMembers()));
 | 
			
		||||
            String setMemberResult =
 | 
			
		||||
                    get.syncGet("", "setMembers", JsonUtil.toJson(multiContractMeta.getMembers()));
 | 
			
		||||
            LOGGER.info("setMember:" + setMemberResult);
 | 
			
		||||
        } else {
 | 
			
		||||
            LOGGER.info("setMember ignore, meta:" + (multiContractMeta == null) + (multiContractMeta == null ? "NULL" : " members:" + multiContractMeta.getMembers()));
 | 
			
		||||
            LOGGER.info("setMember ignore, meta:" + (multiContractMeta == null)
 | 
			
		||||
                    + (multiContractMeta == null ? "NULL"
 | 
			
		||||
                            : " members:" + multiContractMeta.getMembers()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isBundlePath(contractMeta.contract.getScriptStr())) {
 | 
			
		||||
            status =
 | 
			
		||||
                    get.syncGet(
 | 
			
		||||
                            "", "setContractBundle", JsonUtil.toJson(contractMeta.contract));
 | 
			
		||||
            status = get.syncGet("", "setContractBundle", JsonUtil.toJson(contractMeta.contract));
 | 
			
		||||
        } else {
 | 
			
		||||
            status = get.syncGet("", "setContract", JsonUtil.toJson(contractMeta.contract));
 | 
			
		||||
        }
 | 
			
		||||
@ -369,11 +360,7 @@ public class ContractClient {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            lastUpdate = System.currentTimeMillis();
 | 
			
		||||
            get.asyncGet(
 | 
			
		||||
                    "",
 | 
			
		||||
                    ".UsedMemory",
 | 
			
		||||
                    "",
 | 
			
		||||
                    new ResultCallback() {
 | 
			
		||||
            get.asyncGet("", ".UsedMemory", "", new ResultCallback() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onResult(String str) {
 | 
			
		||||
                    memory = Long.parseLong(str);
 | 
			
		||||
@ -457,12 +444,10 @@ public class ContractClient {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void loadTimesAndTraffic() {
 | 
			
		||||
        String tempTime2 =
 | 
			
		||||
                KeyValueDBUtil.instance.getValue(
 | 
			
		||||
                        CMTables.ContractInfo.toString(), contractMeta.name + "-Times");
 | 
			
		||||
        String tempTraffic2 =
 | 
			
		||||
                KeyValueDBUtil.instance.getValue(
 | 
			
		||||
                        CMTables.ContractInfo.toString(), contractMeta.name + "-Traffic");
 | 
			
		||||
        String tempTime2 = KeyValueDBUtil.instance.getValue(CMTables.ContractInfo.toString(),
 | 
			
		||||
                contractMeta.name + "-Times");
 | 
			
		||||
        String tempTraffic2 = KeyValueDBUtil.instance.getValue(CMTables.ContractInfo.toString(),
 | 
			
		||||
                contractMeta.name + "-Traffic");
 | 
			
		||||
        if (tempTime2 != null && !tempTime2.equals("")) {
 | 
			
		||||
            times = Long.parseLong(tempTime2);
 | 
			
		||||
        }
 | 
			
		||||
@ -472,10 +457,10 @@ public class ContractClient {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void saveTimesAndTraffic() {
 | 
			
		||||
        KeyValueDBUtil.instance.setValue(
 | 
			
		||||
                CMTables.ContractInfo.toString(), contractMeta.name + "-Times", times + "");
 | 
			
		||||
        KeyValueDBUtil.instance.setValue(
 | 
			
		||||
                CMTables.ContractInfo.toString(), contractMeta.name + "-Traffic", traffic + "");
 | 
			
		||||
        KeyValueDBUtil.instance.setValue(CMTables.ContractInfo.toString(),
 | 
			
		||||
                contractMeta.name + "-Times", times + "");
 | 
			
		||||
        KeyValueDBUtil.instance.setValue(CMTables.ContractInfo.toString(),
 | 
			
		||||
                contractMeta.name + "-Traffic", traffic + "");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setMask(JsonObject args) {
 | 
			
		||||
 | 
			
		||||
@ -38,22 +38,13 @@ import java.util.concurrent.*;
 | 
			
		||||
 | 
			
		||||
public class ContractManager {
 | 
			
		||||
    public static final Object checkAndStartLock = new Object();
 | 
			
		||||
    static final Counter contractCounter =
 | 
			
		||||
            Counter.build()
 | 
			
		||||
                    .name("execute_contract_counter")
 | 
			
		||||
                    .help("contract execution status")
 | 
			
		||||
                    .register();
 | 
			
		||||
    static final Counter oracleCounter =
 | 
			
		||||
            Counter.build()
 | 
			
		||||
                    .name("execute_oracle_counter")
 | 
			
		||||
                    .help("oracle execution status")
 | 
			
		||||
                    .register();
 | 
			
		||||
    static final Counter contractCounter = Counter.build().name("execute_contract_counter")
 | 
			
		||||
            .help("contract execution status").register();
 | 
			
		||||
    static final Counter oracleCounter = Counter.build().name("execute_oracle_counter")
 | 
			
		||||
            .help("oracle execution status").register();
 | 
			
		||||
 | 
			
		||||
    static final Counter totalCounter =
 | 
			
		||||
            Counter.build()
 | 
			
		||||
                    .name("execute_counter")
 | 
			
		||||
                    .help("contract and oracle execution status")
 | 
			
		||||
                    .register();
 | 
			
		||||
    static final Counter totalCounter = Counter.build().name("execute_counter")
 | 
			
		||||
            .help("contract and oracle execution status").register();
 | 
			
		||||
 | 
			
		||||
    static final long memoryLimit = 100L * 1024L * 1024L;
 | 
			
		||||
    private static final Logger LOGGER = LogManager.getLogger(ContractManager.class);
 | 
			
		||||
@ -66,12 +57,7 @@ public class ContractManager {
 | 
			
		||||
    public static ContractPort cPort;
 | 
			
		||||
    public static boolean eventPersistenceEnabled = false;
 | 
			
		||||
    public static ExecutorService threadPool =
 | 
			
		||||
            new ThreadPoolExecutor(
 | 
			
		||||
                    8,
 | 
			
		||||
                    15,
 | 
			
		||||
                    60,
 | 
			
		||||
                    TimeUnit.SECONDS,
 | 
			
		||||
                    new SynchronousQueue<>());
 | 
			
		||||
            new ThreadPoolExecutor(8, 15, 60, TimeUnit.SECONDS, new SynchronousQueue<>());
 | 
			
		||||
    public static ScheduledExecutorService scheduledThreadPool =
 | 
			
		||||
            Executors.newScheduledThreadPool(10);
 | 
			
		||||
 | 
			
		||||
@ -83,9 +69,8 @@ public class ContractManager {
 | 
			
		||||
        KeyValueDBUtil.setupCM();
 | 
			
		||||
        KeyValueRocksDBUtil.setupCM();
 | 
			
		||||
        TimeDBUtil.setupCM();
 | 
			
		||||
        logsDB =
 | 
			
		||||
                new MultiIndexTimeRocksDBUtil(
 | 
			
		||||
                        "./ContractManagerDB", CMTables.LocalContractLogDB.toString());
 | 
			
		||||
        logsDB = new MultiIndexTimeRocksDBUtil("./ContractManagerDB",
 | 
			
		||||
                CMTables.LocalContractLogDB.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected final EventBroker eventBroker;
 | 
			
		||||
@ -361,12 +346,8 @@ public class ContractManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void fillContractResourceInfo(
 | 
			
		||||
            Map<String, Map<String, String>> contractResourceInfo,
 | 
			
		||||
            String pid,
 | 
			
		||||
            String res,
 | 
			
		||||
            String cpu,
 | 
			
		||||
            String mem,
 | 
			
		||||
            Scanner sc2) {
 | 
			
		||||
            Map<String, Map<String, String>> contractResourceInfo, String pid, String res,
 | 
			
		||||
            String cpu, String mem, Scanner sc2) {
 | 
			
		||||
        sc2.close();
 | 
			
		||||
 | 
			
		||||
        Map<String, String> tmp = new HashMap<>();
 | 
			
		||||
@ -386,8 +367,8 @@ public class ContractManager {
 | 
			
		||||
        return isNodeManager;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void checkPointToLedger(
 | 
			
		||||
            OnHashCallback cb, String contractID, String data, String requestID) {
 | 
			
		||||
    public static void checkPointToLedger(OnHashCallback cb, String contractID, String data,
 | 
			
		||||
            String requestID) {
 | 
			
		||||
        boolean isMaster = instance.getContractIsMaster(contractID);
 | 
			
		||||
        if (!isMaster) {
 | 
			
		||||
            LOGGER.info("非合约 " + contractID + "的master,无需承担checkPoint上链任务!");
 | 
			
		||||
@ -408,7 +389,8 @@ public class ContractManager {
 | 
			
		||||
                return "bundle_" + md5;
 | 
			
		||||
            } else {
 | 
			
		||||
                String md5 = DigestUtils.md5Hex(c.getScriptStr());
 | 
			
		||||
                if (c.getOwner() != null) md5 = DigestUtils.md5Hex(md5 + c.getOwner());
 | 
			
		||||
                if (c.getOwner() != null)
 | 
			
		||||
                    md5 = DigestUtils.md5Hex(md5 + c.getOwner());
 | 
			
		||||
                return "script_" + md5;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
@ -433,13 +415,15 @@ public class ContractManager {
 | 
			
		||||
 | 
			
		||||
    public String getContractIDByName(String name) {
 | 
			
		||||
        ContractMeta meta = statusRecorder.getContractMeta(name);
 | 
			
		||||
        if (meta != null) return meta.id;
 | 
			
		||||
        if (meta != null)
 | 
			
		||||
            return meta.id;
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getContractNameByID(String id) {
 | 
			
		||||
        ContractMeta meta = statusRecorder.getContractMeta(id);
 | 
			
		||||
        if (meta != null) return meta.name;
 | 
			
		||||
        if (meta != null)
 | 
			
		||||
            return meta.name;
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -481,8 +465,8 @@ public class ContractManager {
 | 
			
		||||
        }
 | 
			
		||||
        String result = client.get.syncGet("", "getDumpPeriod", "a");
 | 
			
		||||
        ContractMeta meta = client.contractMeta;
 | 
			
		||||
        addLocalContractLog(
 | 
			
		||||
                "getDumpPeriod", meta.contract.getID(), meta.name, meta.contract.getOwner());
 | 
			
		||||
        addLocalContractLog("getDumpPeriod", meta.contract.getID(), meta.name,
 | 
			
		||||
                meta.contract.getOwner());
 | 
			
		||||
 | 
			
		||||
        if (!"failed".equals(result)) {
 | 
			
		||||
            return result;
 | 
			
		||||
@ -529,7 +513,8 @@ public class ContractManager {
 | 
			
		||||
        if (f.exists() && f.isDirectory()) {
 | 
			
		||||
            String path = null;
 | 
			
		||||
            for (File subFile : Objects.requireNonNull(f.listFiles())) {
 | 
			
		||||
                if (path == null) path = subFile.getName();
 | 
			
		||||
                if (path == null)
 | 
			
		||||
                    path = subFile.getName();
 | 
			
		||||
                else if (path.compareTo(subFile.getName()) < 0) {
 | 
			
		||||
                    path = subFile.getName();
 | 
			
		||||
                }
 | 
			
		||||
@ -556,8 +541,8 @@ public class ContractManager {
 | 
			
		||||
        loadProjectConfig(client);
 | 
			
		||||
 | 
			
		||||
        ContractMeta meta = client.contractMeta;
 | 
			
		||||
        addLocalContractLog(
 | 
			
		||||
                "changeDumpPeriod", meta.contract.getID(), meta.name, meta.contract.getOwner());
 | 
			
		||||
        addLocalContractLog("changeDumpPeriod", meta.contract.getID(), meta.name,
 | 
			
		||||
                meta.contract.getOwner());
 | 
			
		||||
        r = new ContractResult(Status.Success, new JsonPrimitive("change dump period finished"));
 | 
			
		||||
 | 
			
		||||
        return JsonUtil.toJson(r);
 | 
			
		||||
@ -889,11 +874,10 @@ public class ContractManager {
 | 
			
		||||
        ProjectConfig config = projectRecoder.getProjectConfig(client.getContractID());
 | 
			
		||||
        LOGGER.debug("zz");
 | 
			
		||||
        String str = client.contractMeta.contract.getScriptStr();
 | 
			
		||||
        /*if(config!=null){
 | 
			
		||||
            System.out.println("not NULL");
 | 
			
		||||
            client.setProjectConfig(JsonUtil.toJson(config));
 | 
			
		||||
            return;
 | 
			
		||||
        }*/
 | 
			
		||||
        /*
 | 
			
		||||
         * if(config!=null){ System.out.println("not NULL");
 | 
			
		||||
         * client.setProjectConfig(JsonUtil.toJson(config)); return; }
 | 
			
		||||
         */
 | 
			
		||||
        // TODO
 | 
			
		||||
        loadMaskConfig(config, str);
 | 
			
		||||
        loadMockConfig(config, str);
 | 
			
		||||
@ -951,8 +935,8 @@ public class ContractManager {
 | 
			
		||||
                    KeyValueDBUtil.instance.getValue(CMTables.ContractInfo.toString(), key);
 | 
			
		||||
            if (privateKeyStr == null || privateKeyStr.length() == 0) {
 | 
			
		||||
                privateKeyStr = SM2Util.generateSM2KeyPair().toJson();
 | 
			
		||||
                KeyValueDBUtil.instance.setValue(
 | 
			
		||||
                        CMTables.ContractInfo.toString(), key, privateKeyStr);
 | 
			
		||||
                KeyValueDBUtil.instance.setValue(CMTables.ContractInfo.toString(), key,
 | 
			
		||||
                        privateKeyStr);
 | 
			
		||||
            }
 | 
			
		||||
            SM2KeyPair sm2Key = SM2KeyPair.fromJson(privateKeyStr);
 | 
			
		||||
            c.setKey(sm2Key.getPrivateKey().toString(16));
 | 
			
		||||
@ -965,9 +949,8 @@ public class ContractManager {
 | 
			
		||||
        if (JsonUtil.fromJson(ret, ContractResult.class).status == Status.Success) {
 | 
			
		||||
            if (findConflictOfName(client.getContractName())) {
 | 
			
		||||
                invokeContractSuicide(client);
 | 
			
		||||
                ContractResult r =
 | 
			
		||||
                        new ContractResult(
 | 
			
		||||
                                Status.Error, new JsonPrimitive("Duplicate contract name."));
 | 
			
		||||
                ContractResult r = new ContractResult(Status.Error,
 | 
			
		||||
                        new JsonPrimitive("Duplicate contract name."));
 | 
			
		||||
                return JsonUtil.toJson(r);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -1024,15 +1007,10 @@ public class ContractManager {
 | 
			
		||||
    public void clearCache() {
 | 
			
		||||
        final long time = System.currentTimeMillis() - 30000L;
 | 
			
		||||
        // LOGGER.info("try to clear cache, clear 0");
 | 
			
		||||
        /* reqCache.entrySet()
 | 
			
		||||
                .removeIf(
 | 
			
		||||
                        entry -> {
 | 
			
		||||
                            RespCache cache = entry.getValue();
 | 
			
		||||
                            if (cache == null) return true;
 | 
			
		||||
                            if (cache.count < 0) return true;
 | 
			
		||||
                            return cache.time < time;
 | 
			
		||||
                        });
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * reqCache.entrySet() .removeIf( entry -> { RespCache cache = entry.getValue(); if (cache
 | 
			
		||||
         * == null) return true; if (cache.count < 0) return true; return cache.time < time; });
 | 
			
		||||
         * 
 | 
			
		||||
         */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1045,11 +1023,8 @@ public class ContractManager {
 | 
			
		||||
                LOGGER.debug("create cache:" + requestID);
 | 
			
		||||
                RespCache resp = new RespCache();
 | 
			
		||||
                try {
 | 
			
		||||
                    resp.count =
 | 
			
		||||
                            Integer.parseInt(
 | 
			
		||||
                                    requestID
 | 
			
		||||
                                            .replaceFirst("[^_]*_", "")
 | 
			
		||||
                                            .replaceAll("_.*$", ""));
 | 
			
		||||
                    resp.count = Integer
 | 
			
		||||
                            .parseInt(requestID.replaceFirst("[^_]*_", "").replaceAll("_.*$", ""));
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    resp.count = 2;
 | 
			
		||||
                }
 | 
			
		||||
@ -1071,11 +1046,8 @@ public class ContractManager {
 | 
			
		||||
 | 
			
		||||
        if (null == c.getContractID()) {
 | 
			
		||||
            LOGGER.info("合约Name转为ID error!");
 | 
			
		||||
            cr =
 | 
			
		||||
                    new ContractResult(
 | 
			
		||||
                            Status.Error,
 | 
			
		||||
                            new JsonPrimitive(
 | 
			
		||||
                                    c.getContractID() + " Contract not Exists, CMLocallyAsync!"));
 | 
			
		||||
            cr = new ContractResult(Status.Error,
 | 
			
		||||
                    new JsonPrimitive(c.getContractID() + " Contract not Exists, CMLocallyAsync!"));
 | 
			
		||||
            r.onResult(JsonUtil.toJson(cr));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@ -1084,11 +1056,8 @@ public class ContractManager {
 | 
			
		||||
 | 
			
		||||
        final ContractClient client = getClient(c.getContractID());
 | 
			
		||||
        if (null == client) {
 | 
			
		||||
            cr =
 | 
			
		||||
                    new ContractResult(
 | 
			
		||||
                            Status.Error,
 | 
			
		||||
                            new JsonPrimitive(
 | 
			
		||||
                                    c.getContractID() + " Contract not Exists, CMLocallyAsync!"));
 | 
			
		||||
            cr = new ContractResult(Status.Error,
 | 
			
		||||
                    new JsonPrimitive(c.getContractID() + " Contract not Exists, CMLocallyAsync!"));
 | 
			
		||||
            r.onResult(JsonUtil.toJson(cr));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@ -1107,10 +1076,7 @@ public class ContractManager {
 | 
			
		||||
                        LOGGER.info("[Hit Cache] " + requestID);
 | 
			
		||||
                        r.onResult(cache.val);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        executeInternalAsync(
 | 
			
		||||
                                client,
 | 
			
		||||
                                c,
 | 
			
		||||
                                new ResultCallback() {
 | 
			
		||||
                        executeInternalAsync(client, c, new ResultCallback() {
 | 
			
		||||
                            @Override
 | 
			
		||||
                            public void onResult(String str) {
 | 
			
		||||
                                cache.time = start;
 | 
			
		||||
@ -1118,16 +1084,13 @@ public class ContractManager {
 | 
			
		||||
                                r.onResult(cache.val);
 | 
			
		||||
                                cache.notifyAllWaiter();
 | 
			
		||||
                            }
 | 
			
		||||
                                },
 | 
			
		||||
                                cb);
 | 
			
		||||
                        }, cb);
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                ContractResult re =
 | 
			
		||||
                        new ContractResult(
 | 
			
		||||
                                Status.Error,
 | 
			
		||||
                ContractResult re = new ContractResult(Status.Error,
 | 
			
		||||
                        new JsonPrimitive("Timeout due to insufficient requester"));
 | 
			
		||||
                r.onResult(JsonUtil.toJson(re));
 | 
			
		||||
                return;
 | 
			
		||||
@ -1156,7 +1119,8 @@ public class ContractManager {
 | 
			
		||||
        request.setAction("getGlobal");
 | 
			
		||||
        request.setPublicKey(client.contractMeta.getPubkey());
 | 
			
		||||
        request.doSignature(client.contractMeta.contract.key);
 | 
			
		||||
        ContractResult result = JsonUtil.fromJson(executeLocally(request, null), ContractResult.class);
 | 
			
		||||
        ContractResult result =
 | 
			
		||||
                JsonUtil.fromJson(executeLocally(request, null), ContractResult.class);
 | 
			
		||||
        return JsonUtil.toJson(result.result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1171,11 +1135,8 @@ public class ContractManager {
 | 
			
		||||
        String requestID = c.getRequestID();
 | 
			
		||||
        if (c.getContractID() == null) {
 | 
			
		||||
            LOGGER.error("合约Name转为ID error!");
 | 
			
		||||
            ContractResult cr =
 | 
			
		||||
                    new ContractResult(
 | 
			
		||||
                            Status.Error,
 | 
			
		||||
                            new JsonPrimitive(
 | 
			
		||||
                                    c.getContractID() + " Contract not Exists, CMLocally!"));
 | 
			
		||||
            ContractResult cr = new ContractResult(Status.Error,
 | 
			
		||||
                    new JsonPrimitive(c.getContractID() + " Contract not Exists, CMLocally!"));
 | 
			
		||||
            return JsonUtil.toJson(cr);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -1183,11 +1144,8 @@ public class ContractManager {
 | 
			
		||||
        ContractResult cr2;
 | 
			
		||||
        ContractClient client = getClient(c.getContractID());
 | 
			
		||||
        if (client == null) {
 | 
			
		||||
            cr2 =
 | 
			
		||||
                    new ContractResult(
 | 
			
		||||
                            Status.Error,
 | 
			
		||||
                            new JsonPrimitive(
 | 
			
		||||
                                    c.getContractID() + " Contract not Exists, CMLocally!"));
 | 
			
		||||
            cr2 = new ContractResult(Status.Error,
 | 
			
		||||
                    new JsonPrimitive(c.getContractID() + " Contract not Exists, CMLocally!"));
 | 
			
		||||
            return JsonUtil.toJson(cr2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -1211,9 +1169,7 @@ public class ContractManager {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                ContractResult re =
 | 
			
		||||
                        new ContractResult(
 | 
			
		||||
                                Status.Error,
 | 
			
		||||
                ContractResult re = new ContractResult(Status.Error,
 | 
			
		||||
                        new JsonPrimitive("Timeout due to insufficient requester"));
 | 
			
		||||
                return JsonUtil.toJson(re);
 | 
			
		||||
            }
 | 
			
		||||
@ -1224,8 +1180,8 @@ public class ContractManager {
 | 
			
		||||
        return executeInternal(client, c, cb);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void executeInternalAsync(
 | 
			
		||||
            ContractClient client, ContractRequest request, ResultCallback rcb, OnHashCallback cb) {
 | 
			
		||||
    private void executeInternalAsync(ContractClient client, ContractRequest request,
 | 
			
		||||
            ResultCallback rcb, OnHashCallback cb) {
 | 
			
		||||
        ContractResult cr;
 | 
			
		||||
 | 
			
		||||
        long start = System.currentTimeMillis();
 | 
			
		||||
@ -1233,8 +1189,7 @@ public class ContractManager {
 | 
			
		||||
        client.contractStatus = ContractStatus.Executing;
 | 
			
		||||
        ResultCallback acb;
 | 
			
		||||
        // use to write to chian
 | 
			
		||||
        acb =
 | 
			
		||||
                new ResultCallback() {
 | 
			
		||||
        acb = new ResultCallback() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onResult(String result) {
 | 
			
		||||
                client.traffic += result.length();
 | 
			
		||||
@ -1243,13 +1198,8 @@ public class ContractManager {
 | 
			
		||||
                JsonObject finalRet = JsonUtil.parseStringAsJsonObject(result);
 | 
			
		||||
 | 
			
		||||
                rcb.onResult(finalRet);
 | 
			
		||||
                        chainOpener.writeContractResultToLocalAndLedger(
 | 
			
		||||
                                finalRet.toString(),
 | 
			
		||||
                                client,
 | 
			
		||||
                                request,
 | 
			
		||||
                                cb,
 | 
			
		||||
                                start,
 | 
			
		||||
                                System.currentTimeMillis() - start);
 | 
			
		||||
                chainOpener.writeContractResultToLocalAndLedger(finalRet.toString(), client,
 | 
			
		||||
                        request, cb, start, System.currentTimeMillis() - start);
 | 
			
		||||
                if (client.contractMeta.getYjsType() == YjsType.Oracle) {
 | 
			
		||||
                    oracleCounter.inc();
 | 
			
		||||
                } else {
 | 
			
		||||
@ -1271,8 +1221,8 @@ public class ContractManager {
 | 
			
		||||
        client.get.asyncGet("", "executeContract", JsonUtil.toJson(request), acb);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String executeInternal(
 | 
			
		||||
            ContractClient client, ContractRequest request, OnHashCallback ocb) {
 | 
			
		||||
    private String executeInternal(ContractClient client, ContractRequest request,
 | 
			
		||||
            OnHashCallback ocb) {
 | 
			
		||||
        // LOGGER.info("ContractManager executeInternal : ");
 | 
			
		||||
 | 
			
		||||
        ContractResult cr;
 | 
			
		||||
@ -1288,10 +1238,11 @@ public class ContractManager {
 | 
			
		||||
        client.traffic += result.length();
 | 
			
		||||
 | 
			
		||||
        if (client.getContractCopies() == 1) {
 | 
			
		||||
            extractEventsFromContractResult(ocb, JsonUtil.parseStringAsJsonObject(result), client, request, start);
 | 
			
		||||
            extractEventsFromContractResult(ocb, JsonUtil.parseStringAsJsonObject(result), client,
 | 
			
		||||
                    request, start);
 | 
			
		||||
        }
 | 
			
		||||
        chainOpener.writeContractResultToLocalAndLedger(
 | 
			
		||||
                result, client, request, ocb, start, System.currentTimeMillis() - start);
 | 
			
		||||
        chainOpener.writeContractResultToLocalAndLedger(result, client, request, ocb, start,
 | 
			
		||||
                System.currentTimeMillis() - start);
 | 
			
		||||
        contractCounter.inc();
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
@ -1301,45 +1252,29 @@ public class ContractManager {
 | 
			
		||||
     *
 | 
			
		||||
     * @author Kaidong Wu
 | 
			
		||||
     */
 | 
			
		||||
    public void extractEventsFromContractResult(
 | 
			
		||||
            OnHashCallback ocb,
 | 
			
		||||
            JsonObject result,
 | 
			
		||||
            ContractClient client,
 | 
			
		||||
            ContractRequest request,
 | 
			
		||||
            long startTime) {
 | 
			
		||||
    public void extractEventsFromContractResult(OnHashCallback ocb, JsonObject result,
 | 
			
		||||
            ContractClient client, ContractRequest request, long startTime) {
 | 
			
		||||
        try {
 | 
			
		||||
            ContractResult cr = JsonUtil.fromJson(result, ContractResult.class);
 | 
			
		||||
            if (null != cr.events && !cr.events.isEmpty()) {
 | 
			
		||||
                List<REvent> msgList = cr.events;
 | 
			
		||||
                cr.events = null;
 | 
			
		||||
                chainOpener.writeContractResultToLocalAndLedger(
 | 
			
		||||
                        result.toString(),
 | 
			
		||||
                        client,
 | 
			
		||||
                        request,
 | 
			
		||||
                chainOpener.writeContractResultToLocalAndLedger(result.toString(), client, request,
 | 
			
		||||
                        (reqID, hashStr) -> {
 | 
			
		||||
                            if (eventPersistenceEnabled) {
 | 
			
		||||
                                msgList.forEach(
 | 
			
		||||
                                        msg -> {
 | 
			
		||||
                                msgList.forEach(msg -> {
 | 
			
		||||
                                    msg.setTxHash(hashStr);
 | 
			
		||||
                                            msg.doSignature(
 | 
			
		||||
                                                    client.getPubkey(), client.getContractKey());
 | 
			
		||||
                                    msg.doSignature(client.getPubkey(), client.getContractKey());
 | 
			
		||||
                                    eventBroker.handle(msg);
 | 
			
		||||
                                });
 | 
			
		||||
                            }
 | 
			
		||||
                            if (null != ocb) {
 | 
			
		||||
                                ocb.publishHash(reqID, hashStr);
 | 
			
		||||
                            }
 | 
			
		||||
                        },
 | 
			
		||||
                        startTime,
 | 
			
		||||
                        System.currentTimeMillis() - startTime);
 | 
			
		||||
                        }, startTime, System.currentTimeMillis() - startTime);
 | 
			
		||||
                if (!eventPersistenceEnabled) {
 | 
			
		||||
                    threadPool.submit(
 | 
			
		||||
                            () ->
 | 
			
		||||
                                    msgList.forEach(
 | 
			
		||||
                                            e -> {
 | 
			
		||||
                                                e.doSignature(
 | 
			
		||||
                                                        client.getPubkey(),
 | 
			
		||||
                                                        client.contractMeta.contract.getKey());
 | 
			
		||||
                    threadPool.submit(() -> msgList.forEach(e -> {
 | 
			
		||||
                        e.doSignature(client.getPubkey(), client.contractMeta.contract.getKey());
 | 
			
		||||
                        eventBroker.handle(e);
 | 
			
		||||
                    }));
 | 
			
		||||
                }
 | 
			
		||||
@ -1368,8 +1303,8 @@ public class ContractManager {
 | 
			
		||||
        return resultCallback.strRet;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void executeContractInternal(
 | 
			
		||||
            ContractRequest cr, final ResultCallback rcb, final OnHashCallback hcb) {
 | 
			
		||||
    public void executeContractInternal(ContractRequest cr, final ResultCallback rcb,
 | 
			
		||||
            final OnHashCallback hcb) {
 | 
			
		||||
        LOGGER.debug(JsonUtil.toJson(cr));
 | 
			
		||||
        ContractMeta meta = statusRecorder.getContractMeta(cr.getContractID());
 | 
			
		||||
        MultiContractMeta multiMeta =
 | 
			
		||||
@ -1389,14 +1324,11 @@ public class ContractManager {
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onResult(JsonObject result) {
 | 
			
		||||
                    ContractManager.instance.extractEventsFromContractResult(
 | 
			
		||||
                            null, result, client, cr, start);
 | 
			
		||||
                    LOGGER.debug(
 | 
			
		||||
                            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
 | 
			
		||||
                                    .format(new Date(System.currentTimeMillis()))
 | 
			
		||||
                                    + meta.contractExecutor + " result="
 | 
			
		||||
                                    + result.toString()
 | 
			
		||||
                                    + "\n");
 | 
			
		||||
                    ContractManager.instance.extractEventsFromContractResult(null, result, client,
 | 
			
		||||
                            cr, start);
 | 
			
		||||
                    LOGGER.debug(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
 | 
			
		||||
                            .format(new Date(System.currentTimeMillis())) + meta.contractExecutor
 | 
			
		||||
                            + " result=" + result.toString() + "\n");
 | 
			
		||||
                    rcb.onResult(result);
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
@ -1439,17 +1371,12 @@ public class ContractManager {
 | 
			
		||||
                return;
 | 
			
		||||
                // result = masterStub.executeByOtherNode(pubKey, cr);
 | 
			
		||||
            } else {
 | 
			
		||||
                result =
 | 
			
		||||
                        new ContractResult(
 | 
			
		||||
                                Status.Error,
 | 
			
		||||
                                new JsonPrimitive(
 | 
			
		||||
                                        "Contract "
 | 
			
		||||
                                                + cr.getContractID()
 | 
			
		||||
                                                + "can't be located in router"));
 | 
			
		||||
                result = new ContractResult(Status.Error, new JsonPrimitive(
 | 
			
		||||
                        "Contract " + cr.getContractID() + "can't be located in router"));
 | 
			
		||||
                // 告知NC重选
 | 
			
		||||
                /*
 | 
			
		||||
                好像有点问题,之前这么写是觉得找不到的话,是因为master出问题了,需要重选,但是没考虑到这个合约确实不存在
 | 
			
		||||
                但是可能也不影响,如果这个合约确实不存在,那么即使NC发起了选举也不会真的进行选举
 | 
			
		||||
                 * 好像有点问题,之前这么写是觉得找不到的话,是因为master出问题了,需要重选,但是没考虑到这个合约确实不存在
 | 
			
		||||
                 * 但是可能也不影响,如果这个合约确实不存在,那么即使NC发起了选举也不会真的进行选举
 | 
			
		||||
                 */
 | 
			
		||||
                // JsonObject jo = new JsonObject();
 | 
			
		||||
                // jo.addProperty("action", "NCStartElect");
 | 
			
		||||
@ -1459,11 +1386,8 @@ public class ContractManager {
 | 
			
		||||
                // master为null,发请求给master令其发启选举");
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            result =
 | 
			
		||||
                    new ContractResult(
 | 
			
		||||
                            Status.Error,
 | 
			
		||||
                            new JsonPrimitive(
 | 
			
		||||
                                    "Contract " + cr.getContractID() + " doesn't exists!!"));
 | 
			
		||||
            result = new ContractResult(Status.Error,
 | 
			
		||||
                    new JsonPrimitive("Contract " + cr.getContractID() + " doesn't exists!!"));
 | 
			
		||||
        }
 | 
			
		||||
        rcb.onResult(JsonUtil.parseObjectAsJsonObject(result));
 | 
			
		||||
    }
 | 
			
		||||
@ -1575,7 +1499,8 @@ public class ContractManager {
 | 
			
		||||
        boolean isNodeManager = checkNodeManager(owner);
 | 
			
		||||
        List<ContractInfo> ret = new ArrayList<>();
 | 
			
		||||
        for (ContractMeta client : statusRecorder.getStatus().values()) {
 | 
			
		||||
            if (client.contract == null) continue;
 | 
			
		||||
            if (client.contract == null)
 | 
			
		||||
                continue;
 | 
			
		||||
            if (!client.contract.getOwner().equals(owner) && !isNodeManager) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
@ -1592,8 +1517,7 @@ public class ContractManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void sortContractInfoList(List<ContractInfo> infoList, String firstID) {
 | 
			
		||||
        infoList.sort(
 | 
			
		||||
                (o1, o2) -> {
 | 
			
		||||
        infoList.sort((o1, o2) -> {
 | 
			
		||||
            if (o1.id.equals(firstID)) {
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
@ -1617,8 +1541,10 @@ public class ContractManager {
 | 
			
		||||
        for (ContractMeta client : statusRecorder.getStatus().values()) {
 | 
			
		||||
            ContractInfo contractInfo = fillContractInfo(client);
 | 
			
		||||
            ContractClient contractClient = statusRecorder.getContractClient(contractInfo.id);
 | 
			
		||||
            if (contractClient != null) contractInfo.pid = contractClient.getPID();
 | 
			
		||||
            else contractInfo.pid = "-1";
 | 
			
		||||
            if (contractClient != null)
 | 
			
		||||
                contractInfo.pid = contractClient.getPID();
 | 
			
		||||
            else
 | 
			
		||||
                contractInfo.pid = "-1";
 | 
			
		||||
            if (!contractInfo.pid.equals("-1") && !contractInfo.pid.equals("0")) {
 | 
			
		||||
                try {
 | 
			
		||||
                    assert cris != null;
 | 
			
		||||
@ -1651,24 +1577,39 @@ public class ContractManager {
 | 
			
		||||
                // System.out.println(line);
 | 
			
		||||
                if (line.contains("%Cpu(s):")) {
 | 
			
		||||
                    Scanner sc2 = new Scanner(new ByteArrayInputStream(line.getBytes()));
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNextFloat()) freeCPU = sc2.nextFloat() + "%";
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNextFloat())
 | 
			
		||||
                        freeCPU = sc2.nextFloat() + "%";
 | 
			
		||||
                    sc2.close();
 | 
			
		||||
                } else if (line.contains("MiB Mem :")) {
 | 
			
		||||
                    Scanner sc2 = new Scanner(new ByteArrayInputStream(line.getBytes()));
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNextFloat()) totalMEM = sc2.nextFloat();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext()) sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNextFloat())
 | 
			
		||||
                        totalMEM = sc2.nextFloat();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNext())
 | 
			
		||||
                        sc2.next();
 | 
			
		||||
                    if (sc2.hasNextFloat())
 | 
			
		||||
                        freeMEM = String.format("%.1f", totalMEM - sc2.nextFloat()) + " MiB";
 | 
			
		||||
                    sc2.close();
 | 
			
		||||
@ -1712,23 +1653,15 @@ public class ContractManager {
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    {
 | 
			
		||||
       "name": "dx_substr",
 | 
			
		||||
       "parameter":
 | 
			
		||||
       {
 | 
			
		||||
           "columnIndex":5,
 | 
			
		||||
           "paras":["1","3"]
 | 
			
		||||
        }
 | 
			
		||||
     },
 | 
			
		||||
     * { "name": "dx_substr", "parameter": { "columnIndex":5, "paras":["1","3"] } },
 | 
			
		||||
     */
 | 
			
		||||
    /*
 | 
			
		||||
     * public String resetMask(String contractName, JsonObject MaskObject) { ContractClient client =
 | 
			
		||||
     * getByName(contractName); System.out.println("contractName"+client.getContractName());
 | 
			
		||||
     * 
 | 
			
		||||
     * //String result = client.get.syncGet("", "changeDebugFlag", String.valueOf(isDebug));
 | 
			
		||||
     * //設置clinet當中的mask client.contractMeta.isDebug = isDebug; return "resetMask"; }
 | 
			
		||||
     */
 | 
			
		||||
    /*public String resetMask(String contractName, JsonObject MaskObject) {
 | 
			
		||||
        ContractClient client = getByName(contractName);
 | 
			
		||||
        System.out.println("contractName"+client.getContractName());
 | 
			
		||||
 | 
			
		||||
        //String result = client.get.syncGet("", "changeDebugFlag", String.valueOf(isDebug));
 | 
			
		||||
        //設置clinet當中的mask client.contractMeta.isDebug = isDebug;
 | 
			
		||||
        return "resetMask";
 | 
			
		||||
    }*/
 | 
			
		||||
 | 
			
		||||
    public String dumpContract(String contractID, String path) {
 | 
			
		||||
        // LOGGER.info(contractID);
 | 
			
		||||
@ -1770,8 +1703,10 @@ public class ContractManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String loadMemory(ContractClient client, String path) {
 | 
			
		||||
        if (client == null) return "no such contract client";
 | 
			
		||||
        if (path == null || path.length() == 0) return "no such memory file";
 | 
			
		||||
        if (client == null)
 | 
			
		||||
            return "no such contract client";
 | 
			
		||||
        if (path == null || path.length() == 0)
 | 
			
		||||
            return "no such memory file";
 | 
			
		||||
        addLocalContractLog("loadMemory", client.contractMeta);
 | 
			
		||||
        return client.get.syncGet("", "loadMemory", path);
 | 
			
		||||
    }
 | 
			
		||||
@ -1810,13 +1745,12 @@ public class ContractManager {
 | 
			
		||||
        try {
 | 
			
		||||
            ContractClient client = getClient(contractID);
 | 
			
		||||
            if (client != null) {
 | 
			
		||||
                return new ContractResult(
 | 
			
		||||
                        Status.Success,
 | 
			
		||||
                return new ContractResult(Status.Success,
 | 
			
		||||
                        new JsonPrimitive(client.get.syncGet("", "getLogSize", "")));
 | 
			
		||||
            }
 | 
			
		||||
            // return new ContractResult(Status.Error, "cannot find contractID: " + contractID);
 | 
			
		||||
            return new ContractResult(
 | 
			
		||||
                    Status.Error, new JsonPrimitive("cannot find contractID: " + contractID));
 | 
			
		||||
            return new ContractResult(Status.Error,
 | 
			
		||||
                    new JsonPrimitive("cannot find contractID: " + contractID));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
            return new ContractResult(Status.Exception, new JsonPrimitive(e.getMessage()));
 | 
			
		||||
@ -1827,13 +1761,11 @@ public class ContractManager {
 | 
			
		||||
        try {
 | 
			
		||||
            ContractClient client = getClient(contractID);
 | 
			
		||||
            if (client != null) {
 | 
			
		||||
                return new ContractResult(
 | 
			
		||||
                        Status.Success,
 | 
			
		||||
                        new JsonPrimitive(
 | 
			
		||||
                return new ContractResult(Status.Success, new JsonPrimitive(
 | 
			
		||||
                        client.get.syncGet("", "requestLog", offset + "," + count)));
 | 
			
		||||
            }
 | 
			
		||||
            return new ContractResult(
 | 
			
		||||
                    Status.Error, new JsonPrimitive("cannot find contractID: " + contractID));
 | 
			
		||||
            return new ContractResult(Status.Error,
 | 
			
		||||
                    new JsonPrimitive("cannot find contractID: " + contractID));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
            return new ContractResult(Status.Exception, new JsonPrimitive(e.getMessage()));
 | 
			
		||||
@ -1844,13 +1776,11 @@ public class ContractManager {
 | 
			
		||||
        try {
 | 
			
		||||
            ContractClient client = getClient(contractID);
 | 
			
		||||
            if (client != null) {
 | 
			
		||||
                return new ContractResult(
 | 
			
		||||
                        Status.Success,
 | 
			
		||||
                        new JsonPrimitive(
 | 
			
		||||
                return new ContractResult(Status.Success, new JsonPrimitive(
 | 
			
		||||
                        client.get.syncGet("", "requestLastLog", String.valueOf(count))));
 | 
			
		||||
            }
 | 
			
		||||
            return new ContractResult(
 | 
			
		||||
                    Status.Error, new JsonPrimitive("cannot find contractID: " + contractID));
 | 
			
		||||
            return new ContractResult(Status.Error,
 | 
			
		||||
                    new JsonPrimitive("cannot find contractID: " + contractID));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
            return new ContractResult(Status.Exception, new JsonPrimitive(e.getMessage()));
 | 
			
		||||
@ -1858,39 +1788,20 @@ public class ContractManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
    public void addContractInfo(String name, String owner, String traffic, String times) {
 | 
			
		||||
        KeyValueDBUtil.instance.setValue(
 | 
			
		||||
                CMTables.ContractInfo.toString(),
 | 
			
		||||
                name,
 | 
			
		||||
                "{\"owner\":\""
 | 
			
		||||
                        + owner
 | 
			
		||||
                        + "\",\"traffic\":\""
 | 
			
		||||
                        + traffic
 | 
			
		||||
                        + "\",\"times\":\""
 | 
			
		||||
                        + times
 | 
			
		||||
                        + "\"}");
 | 
			
		||||
    }
 | 
			
		||||
     * public void addContractInfo(String name, String owner, String traffic, String times) {
 | 
			
		||||
     * KeyValueDBUtil.instance.setValue( CMTables.ContractInfo.toString(), name, "{\"owner\":\"" +
 | 
			
		||||
     * owner + "\",\"traffic\":\"" + traffic + "\",\"times\":\"" + times + "\"}"); }
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    public void addLocalContractLog(
 | 
			
		||||
            String action, String contractId, String contractName, String pubKey) {
 | 
			
		||||
        String sb =
 | 
			
		||||
                "{\"action\":\""
 | 
			
		||||
                        + action
 | 
			
		||||
                        + "\",\"pubKey\":\""
 | 
			
		||||
                        + pubKey
 | 
			
		||||
                        + "\",\"contractID\":\""
 | 
			
		||||
                        + contractId
 | 
			
		||||
                        + "\",\"contractName\":\""
 | 
			
		||||
                        + contractName
 | 
			
		||||
                        + "\",\"date\":"
 | 
			
		||||
                        + System.currentTimeMillis()
 | 
			
		||||
                        + "}";
 | 
			
		||||
    public void addLocalContractLog(String action, String contractId, String contractName,
 | 
			
		||||
            String pubKey) {
 | 
			
		||||
        String sb = "{\"action\":\"" + action + "\",\"pubKey\":\"" + pubKey + "\",\"contractID\":\""
 | 
			
		||||
                + contractId + "\",\"contractName\":\"" + contractName + "\",\"date\":"
 | 
			
		||||
                + System.currentTimeMillis() + "}";
 | 
			
		||||
        logsDB.put(contractName, sb);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void changePermission(String contractFileName, String pmList) {
 | 
			
		||||
    }
 | 
			
		||||
    public void changePermission(String contractFileName, String pmList) {}
 | 
			
		||||
 | 
			
		||||
    // public String getSyncType(String contractName) {
 | 
			
		||||
    // ContractClient client = getByName(contractName);
 | 
			
		||||
@ -1940,58 +1851,28 @@ public class ContractManager {
 | 
			
		||||
    // return result;
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    public void addLocalContractLog(
 | 
			
		||||
            String action,
 | 
			
		||||
            String contractId,
 | 
			
		||||
            String contractName,
 | 
			
		||||
            String pubKey,
 | 
			
		||||
            String function,
 | 
			
		||||
            String costTime,
 | 
			
		||||
            long totalGas,
 | 
			
		||||
            long executionGas,
 | 
			
		||||
            long extraGas,
 | 
			
		||||
            Map<String, String> logType) {
 | 
			
		||||
    public void addLocalContractLog(String action, String contractId, String contractName,
 | 
			
		||||
            String pubKey, String function, String costTime, long totalGas, long executionGas,
 | 
			
		||||
            long extraGas, Map<String, String> logType) {
 | 
			
		||||
        contractCounter.inc();
 | 
			
		||||
        if (logType == null || logType.isEmpty()) {
 | 
			
		||||
            logsDB.put(
 | 
			
		||||
                    contractName,
 | 
			
		||||
            logsDB.put(contractName,
 | 
			
		||||
                    String.format(
 | 
			
		||||
                            "{\"action\":\"%s\",\"pubKey\":\"%s\","
 | 
			
		||||
                                    + "\"contractID\":\"%s\",\"contractName\":\"%s\","
 | 
			
		||||
                                    + "\"function\":\"%s\",\"costTime\":\"%s\","
 | 
			
		||||
                                    + "\"totalGas\":\"%d\",\"executionGas\":\"%d\","
 | 
			
		||||
                                    + "\"extraGas\":\"%d\",\"date\":\"%d\"}",
 | 
			
		||||
                            action,
 | 
			
		||||
                            pubKey,
 | 
			
		||||
                            contractId,
 | 
			
		||||
                            contractName,
 | 
			
		||||
                            function,
 | 
			
		||||
                            costTime,
 | 
			
		||||
                            totalGas,
 | 
			
		||||
                            executionGas,
 | 
			
		||||
                            extraGas,
 | 
			
		||||
                            System.currentTimeMillis()));
 | 
			
		||||
                            action, pubKey, contractId, contractName, function, costTime, totalGas,
 | 
			
		||||
                            executionGas, extraGas, System.currentTimeMillis()));
 | 
			
		||||
        } else {
 | 
			
		||||
            StringBuilder str =
 | 
			
		||||
                    new StringBuilder()
 | 
			
		||||
                            .append("{\"action\":\"")
 | 
			
		||||
                            .append(action)
 | 
			
		||||
                            .append("\",\"pubKey\":\"")
 | 
			
		||||
                            .append(pubKey)
 | 
			
		||||
                            .append("\",\"contractID\":\"")
 | 
			
		||||
                            .append(contractId)
 | 
			
		||||
                            .append("\",\"contractName\":\"")
 | 
			
		||||
                            .append(contractName)
 | 
			
		||||
                            .append("\",\"function\":\"")
 | 
			
		||||
                            .append(function)
 | 
			
		||||
                            .append("\",\"costTime\":\"")
 | 
			
		||||
                            .append(costTime)
 | 
			
		||||
                            .append("\",\"totalGas\":\"")
 | 
			
		||||
                            .append(totalGas)
 | 
			
		||||
                            .append("\",\"executionGas\":\"")
 | 
			
		||||
                            .append(executionGas)
 | 
			
		||||
                            .append("\",\"extraGas\":\"")
 | 
			
		||||
                            .append(extraGas);
 | 
			
		||||
            StringBuilder str = new StringBuilder().append("{\"action\":\"").append(action)
 | 
			
		||||
                    .append("\",\"pubKey\":\"").append(pubKey).append("\",\"contractID\":\"")
 | 
			
		||||
                    .append(contractId).append("\",\"contractName\":\"").append(contractName)
 | 
			
		||||
                    .append("\",\"function\":\"").append(function).append("\",\"costTime\":\"")
 | 
			
		||||
                    .append(costTime).append("\",\"totalGas\":\"").append(totalGas)
 | 
			
		||||
                    .append("\",\"executionGas\":\"").append(executionGas)
 | 
			
		||||
                    .append("\",\"extraGas\":\"").append(extraGas);
 | 
			
		||||
 | 
			
		||||
            for (String key : logType.keySet()) {
 | 
			
		||||
                str.append("\",\"").append(key).append("\":\"").append(logType.get(key));
 | 
			
		||||
@ -2002,13 +1883,12 @@ public class ContractManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getTimesOfExecution(String contractName) {
 | 
			
		||||
        return KeyValueDBUtil.instance.getValue(
 | 
			
		||||
                CMTables.ContractInfo.toString(), contractName + "-Times");
 | 
			
		||||
        return KeyValueDBUtil.instance.getValue(CMTables.ContractInfo.toString(),
 | 
			
		||||
                contractName + "-Times");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getControlFlow(Contract c) {
 | 
			
		||||
        if (null == analysisClient
 | 
			
		||||
                || null == analysisClient.process
 | 
			
		||||
        if (null == analysisClient || null == analysisClient.process
 | 
			
		||||
                || !analysisClient.process.isAlive()) {
 | 
			
		||||
            initAnalysisClient();
 | 
			
		||||
        }
 | 
			
		||||
@ -2089,12 +1969,8 @@ public class ContractManager {
 | 
			
		||||
                String ret = client.get.syncGet("", "suicide", "");
 | 
			
		||||
                JsonObject jo = JsonUtil.parseStringAsJsonObject(ret);
 | 
			
		||||
                if (jo.has("cleanSub")) {
 | 
			
		||||
                    REvent msg =
 | 
			
		||||
                            new REvent(
 | 
			
		||||
                                    null,
 | 
			
		||||
                                    REvent.REventType.UNSUBSCRIBE,
 | 
			
		||||
                                    "{\"subscriber\":\"" + client.getContractName() + "\"}",
 | 
			
		||||
                                    "");
 | 
			
		||||
                    REvent msg = new REvent(null, REvent.REventType.UNSUBSCRIBE,
 | 
			
		||||
                            "{\"subscriber\":\"" + client.getContractName() + "\"}", "");
 | 
			
		||||
                    msg.doSignature(client.getPubkey(), client.getContractKey());
 | 
			
		||||
                    eventBroker.handle(msg);
 | 
			
		||||
                }
 | 
			
		||||
@ -2104,8 +1980,7 @@ public class ContractManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String parseYpkPermissions(String ypkPath) {
 | 
			
		||||
        if (null == analysisClient
 | 
			
		||||
                || null == analysisClient.process
 | 
			
		||||
        if (null == analysisClient || null == analysisClient.process
 | 
			
		||||
                || !analysisClient.process.isAlive()) {
 | 
			
		||||
            initAnalysisClient();
 | 
			
		||||
        }
 | 
			
		||||
@ -2113,8 +1988,7 @@ public class ContractManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String staticVerify(Contract c) {
 | 
			
		||||
        if (null == analysisClient
 | 
			
		||||
                || null == analysisClient.process
 | 
			
		||||
        if (null == analysisClient || null == analysisClient.process
 | 
			
		||||
                || !analysisClient.process.isAlive()) {
 | 
			
		||||
            initAnalysisClient();
 | 
			
		||||
        }
 | 
			
		||||
@ -2183,7 +2057,8 @@ public class ContractManager {
 | 
			
		||||
            this.sc = sc;
 | 
			
		||||
            this.TAG = tag;
 | 
			
		||||
            psList = new ArrayList<>();
 | 
			
		||||
            if (printStream != null) psList.add(printStream);
 | 
			
		||||
            if (printStream != null)
 | 
			
		||||
                psList.add(printStream);
 | 
			
		||||
            toRemove = new HashSet<>();
 | 
			
		||||
            start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -31,14 +31,7 @@ public class ContractMeta implements IDSerializable {
 | 
			
		||||
    boolean sigRequired;
 | 
			
		||||
    String thisPermission; // 合约当前权限
 | 
			
		||||
    /*
 | 
			
		||||
    {
 | 
			
		||||
       "name": "dx_substr",
 | 
			
		||||
       "parameter":
 | 
			
		||||
       {
 | 
			
		||||
           "columnIndex":5,
 | 
			
		||||
           "paras":["1","3"]
 | 
			
		||||
       }
 | 
			
		||||
    },
 | 
			
		||||
     * { "name": "dx_substr", "parameter": { "columnIndex":5, "paras":["1","3"] } },
 | 
			
		||||
     */
 | 
			
		||||
    // Map<Object,Object>MaskInfo;
 | 
			
		||||
 | 
			
		||||
@ -116,7 +109,8 @@ public class ContractMeta implements IDSerializable {
 | 
			
		||||
 | 
			
		||||
    private FunctionDesp seekFunction(String action) {
 | 
			
		||||
        for (FunctionDesp desp : exportedFunctions) {
 | 
			
		||||
            if (desp != null && desp.functionName.equals(action)) return desp;
 | 
			
		||||
            if (desp != null && desp.functionName.equals(action))
 | 
			
		||||
                return desp;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,8 @@
 | 
			
		||||
package org.bdware.sc;
 | 
			
		||||
 | 
			
		||||
public enum ContractStatusEnum {
 | 
			
		||||
    INIT(0, "初始化"),
 | 
			
		||||
    RUNNING(1, "内存运行中"),
 | 
			
		||||
    HANGED(2, "硬盘运行中"),
 | 
			
		||||
    KILLED(3, "已停止");
 | 
			
		||||
    INIT(0, "初始化"), RUNNING(1, "内存运行中"), HANGED(2, "硬盘运行中"), KILLED(3, "已停止");
 | 
			
		||||
 | 
			
		||||
    private Integer code;
 | 
			
		||||
    private String desc;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -33,8 +33,7 @@ public class ContractStatusRecorder extends StatusRecorder<ContractMeta> {
 | 
			
		||||
    static {
 | 
			
		||||
        final Object flag = new Object();
 | 
			
		||||
        // 调度一个task,在delay(ms)后开始调度,每次调度完后,最少等待period(ms)后才开始调
 | 
			
		||||
        ContractManager.scheduledThreadPool.scheduleWithFixedDelay(
 | 
			
		||||
                () -> {
 | 
			
		||||
        ContractManager.scheduledThreadPool.scheduleWithFixedDelay(() -> {
 | 
			
		||||
            boolean cleared = dealTimerContractProcess();
 | 
			
		||||
            if (cleared) {
 | 
			
		||||
                synchronized (flag) {
 | 
			
		||||
@ -45,10 +44,7 @@ public class ContractStatusRecorder extends StatusRecorder<ContractMeta> {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
                },
 | 
			
		||||
                0,
 | 
			
		||||
                1,
 | 
			
		||||
                TimeUnit.SECONDS);
 | 
			
		||||
        }, 0, 1, TimeUnit.SECONDS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // contract id to client, changes when some contract is started/stopped/resumed
 | 
			
		||||
@ -102,7 +98,8 @@ public class ContractStatusRecorder extends StatusRecorder<ContractMeta> {
 | 
			
		||||
        // TODO 是不是还有别的?这只是在内存里的哦。
 | 
			
		||||
        try {
 | 
			
		||||
            for (ContractClient c : id2ContractClient.values()) {
 | 
			
		||||
                if (Integer.parseInt(c.getPID()) == pid) return true;
 | 
			
		||||
                if (Integer.parseInt(c.getPID()) == pid)
 | 
			
		||||
                    return true;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            // e.printStackTrace();
 | 
			
		||||
@ -174,9 +171,11 @@ public class ContractStatusRecorder extends StatusRecorder<ContractMeta> {
 | 
			
		||||
 | 
			
		||||
    // TODO index name to contract
 | 
			
		||||
    public ContractMeta getContractMeta(String idOrNameOrDOI) {
 | 
			
		||||
        if (idOrNameOrDOI == null) return null;
 | 
			
		||||
        if (idOrNameOrDOI == null)
 | 
			
		||||
            return null;
 | 
			
		||||
        ContractMeta meta = getStatus().get(idOrNameOrDOI);
 | 
			
		||||
        if (meta != null) return meta;
 | 
			
		||||
        if (meta != null)
 | 
			
		||||
            return meta;
 | 
			
		||||
        for (ContractMeta cc : getStatus().values()) {
 | 
			
		||||
            if (cc.status == ContractStatusEnum.RUNNING || cc.status == ContractStatusEnum.HANGED)
 | 
			
		||||
                if (idOrNameOrDOI.equals(cc.name)) {
 | 
			
		||||
@ -184,8 +183,10 @@ public class ContractStatusRecorder extends StatusRecorder<ContractMeta> {
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
        for (ContractMeta cc : getStatus().values()) {
 | 
			
		||||
            if (cc.name == null) continue;
 | 
			
		||||
            if (cc.contract == null) continue;
 | 
			
		||||
            if (cc.name == null)
 | 
			
		||||
                continue;
 | 
			
		||||
            if (cc.contract == null)
 | 
			
		||||
                continue;
 | 
			
		||||
            if (idOrNameOrDOI.equals(cc.name)) {
 | 
			
		||||
                return cc;
 | 
			
		||||
            }
 | 
			
		||||
@ -224,9 +225,7 @@ public class ContractStatusRecorder extends StatusRecorder<ContractMeta> {
 | 
			
		||||
                LOGGER.info("need dump when stop");
 | 
			
		||||
                String contractName = client.getContractName();
 | 
			
		||||
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd.HH:mm:ss");
 | 
			
		||||
                File f =
 | 
			
		||||
                        new File(
 | 
			
		||||
                                ContractManager.dir + "/memory/" + contractName,
 | 
			
		||||
                File f = new File(ContractManager.dir + "/memory/" + contractName,
 | 
			
		||||
                        df.format(new Date()));
 | 
			
		||||
                client.get.syncGet("", "getMemoryDump", f.getAbsolutePath());
 | 
			
		||||
                ContractManager.instance.addLocalContractLog("dumpContract", meta);
 | 
			
		||||
@ -313,13 +312,12 @@ public class ContractStatusRecorder extends StatusRecorder<ContractMeta> {
 | 
			
		||||
                client.saveTimesAndTraffic();
 | 
			
		||||
 | 
			
		||||
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd.HH_mm_ss"); // 设置日期格式
 | 
			
		||||
                File f =
 | 
			
		||||
                        new File(
 | 
			
		||||
                                ContractManager.dir + "/memory/" + contractMeta.name,
 | 
			
		||||
                File f = new File(ContractManager.dir + "/memory/" + contractMeta.name,
 | 
			
		||||
                        df.format(new Date()));
 | 
			
		||||
                File parent = f.getParentFile();
 | 
			
		||||
                if (!parent.exists()) {
 | 
			
		||||
                    LOGGER.trace("make directory " + parent.getAbsolutePath() + ":" + parent.mkdirs());
 | 
			
		||||
                    LOGGER.trace(
 | 
			
		||||
                            "make directory " + parent.getAbsolutePath() + ":" + parent.mkdirs());
 | 
			
		||||
                }
 | 
			
		||||
                ContractManager.instance.dumpContract(contract.getID(), f.getAbsolutePath());
 | 
			
		||||
                ContractManager.instance.invokeContractSuicide(client);
 | 
			
		||||
@ -344,17 +342,11 @@ public class ContractStatusRecorder extends StatusRecorder<ContractMeta> {
 | 
			
		||||
                    JsonUtil.fromJson(startContractResult, ContractResult.class);
 | 
			
		||||
            if (contractResult.status == ContractResult.Status.Error) {
 | 
			
		||||
                // 记录错误日志
 | 
			
		||||
                ContractManager.instance.addLocalContractLog(
 | 
			
		||||
                        "resumeContract error",
 | 
			
		||||
                        meta.contract.getID(),
 | 
			
		||||
                        meta.name,
 | 
			
		||||
                        meta.contract.getOwner());
 | 
			
		||||
                ContractManager.instance.addLocalContractLog("resumeContract error",
 | 
			
		||||
                        meta.contract.getID(), meta.name, meta.contract.getOwner());
 | 
			
		||||
            } else {
 | 
			
		||||
                ContractManager.instance.addLocalContractLog(
 | 
			
		||||
                        "resumeContract success",
 | 
			
		||||
                        meta.contract.getID(),
 | 
			
		||||
                        meta.name,
 | 
			
		||||
                        meta.contract.getOwner());
 | 
			
		||||
                ContractManager.instance.addLocalContractLog("resumeContract success",
 | 
			
		||||
                        meta.contract.getID(), meta.name, meta.contract.getOwner());
 | 
			
		||||
                // TODO 可能会重复load相同的镜像?
 | 
			
		||||
                // 如果是killed 只根据manifest去判断是否加载memory
 | 
			
		||||
                // 可增加一个判断,如果hanged朋manifest里是加载memory,这里就不再加载了。
 | 
			
		||||
@ -416,26 +408,19 @@ public class ContractStatusRecorder extends StatusRecorder<ContractMeta> {
 | 
			
		||||
                        ContractManager.instance.invokeContractSuicide(client);
 | 
			
		||||
                        return false;
 | 
			
		||||
                    }
 | 
			
		||||
                    LOGGER.debug(
 | 
			
		||||
                            String.format(
 | 
			
		||||
                    LOGGER.debug(String.format(
 | 
			
		||||
                            "CP listened to port %d:\n\tID=%s\n\tName=%s\n\tType=%s\n"
 | 
			
		||||
                                    + "\tKey=%s\n\tPubKey=%s\n\tCopies=%d\n\t%s",
 | 
			
		||||
                                    i,
 | 
			
		||||
                                    client.getContractID(),
 | 
			
		||||
                                    client.contractMeta.name,
 | 
			
		||||
                                    client.getContractType(),
 | 
			
		||||
                                    client.getContractKey(),
 | 
			
		||||
                                    client.getPubkey(),
 | 
			
		||||
                                    client.getContractCopies(),
 | 
			
		||||
                                    client.contractMeta.contract.startInfo));
 | 
			
		||||
                            i, client.getContractID(), client.contractMeta.name,
 | 
			
		||||
                            client.getContractType(), client.getContractKey(), client.getPubkey(),
 | 
			
		||||
                            client.getContractCopies(), client.contractMeta.contract.startInfo));
 | 
			
		||||
                    client.get.syncGet("", "setDir", ContractManager.dir);
 | 
			
		||||
                    // String str = client.getIdentifier();
 | 
			
		||||
                    client.get.syncGet("", "getDumpPeriod", "a");
 | 
			
		||||
                    client.get.syncGet("", "startAutoDump", "a");
 | 
			
		||||
                    createContract(client);
 | 
			
		||||
                    LOGGER.info(
 | 
			
		||||
                            String.format("reconnect to port %d: contract %s",
 | 
			
		||||
                                    i, client.contractMeta.name));
 | 
			
		||||
                    LOGGER.info(String.format("reconnect to port %d: contract %s", i,
 | 
			
		||||
                            client.contractMeta.name));
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,5 @@
 | 
			
		||||
package org.bdware.sc;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Node
 | 
			
		||||
 | 
			
		||||
@ -20,10 +20,8 @@ public class MultiContractRecorder extends StatusRecorder<MultiContractMeta> {
 | 
			
		||||
        for (MultiContractMeta meta : getStatus().values()) {
 | 
			
		||||
            try {
 | 
			
		||||
                meta.initQueue();
 | 
			
		||||
                int lastExeSeq =
 | 
			
		||||
                        Integer.parseInt(
 | 
			
		||||
                                KeyValueDBUtil.instance.getValue(
 | 
			
		||||
                                        CMTables.LastExeSeq.toString(), meta.getContractID()));
 | 
			
		||||
                int lastExeSeq = Integer.parseInt(KeyValueDBUtil.instance
 | 
			
		||||
                        .getValue(CMTables.LastExeSeq.toString(), meta.getContractID()));
 | 
			
		||||
                meta.setLastExeSeq(lastExeSeq);
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                LOGGER.error(e);
 | 
			
		||||
@ -32,13 +30,15 @@ public class MultiContractRecorder extends StatusRecorder<MultiContractMeta> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public MultiContractMeta getMultiContractMeta(String idOrNameOrDOI) {
 | 
			
		||||
        if (idOrNameOrDOI == null) return null;
 | 
			
		||||
        if (idOrNameOrDOI == null)
 | 
			
		||||
            return null;
 | 
			
		||||
        ContractMeta meta = ContractManager.instance.statusRecorder.getContractMeta(idOrNameOrDOI);
 | 
			
		||||
        return getMultiContractMeta(meta);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public MultiContractMeta getMultiContractMeta(ContractMeta meta) {
 | 
			
		||||
        if (meta == null) return null;
 | 
			
		||||
        if (meta == null)
 | 
			
		||||
            return null;
 | 
			
		||||
        return getStatus().get(meta.id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,8 @@ public class PBFTAlgorithm implements CommitAlgorithm {
 | 
			
		||||
                    prepareMsg = new PBFTMessage();
 | 
			
		||||
                    prepareMsg.order = allocatedID.incrementAndGet();
 | 
			
		||||
                    prepareMsg.type = PBFTType.PrePrepare;
 | 
			
		||||
                    prepareMsg.content = (java.util.Arrays.hashCode(pbftMessage.content) + "").getBytes();
 | 
			
		||||
                    prepareMsg.content =
 | 
			
		||||
                            (java.util.Arrays.hashCode(pbftMessage.content) + "").getBytes();
 | 
			
		||||
 | 
			
		||||
                    temp = new PCInfo();
 | 
			
		||||
                    temp.request = pbftMessage;
 | 
			
		||||
@ -108,7 +109,8 @@ public class PBFTAlgorithm implements CommitAlgorithm {
 | 
			
		||||
                break;
 | 
			
		||||
            case Prepare:
 | 
			
		||||
                temp = info.get(pbftMessage.order);
 | 
			
		||||
                LOGGER.info("receive Prepare from:" + pbftMessage.sendID + " -> " + pbftMessage.order);
 | 
			
		||||
                LOGGER.info(
 | 
			
		||||
                        "receive Prepare from:" + pbftMessage.sendID + " -> " + pbftMessage.order);
 | 
			
		||||
                if (temp == null) {
 | 
			
		||||
                    PCInfo pcInfo = new PCInfo();
 | 
			
		||||
                    pcInfo.buff.add(pbftMessage);
 | 
			
		||||
@ -155,7 +157,8 @@ public class PBFTAlgorithm implements CommitAlgorithm {
 | 
			
		||||
                    prepareMsg.order = pbftMessage.order;
 | 
			
		||||
                    prepareMsg.type = PBFTType.PrePrepare;
 | 
			
		||||
                    temp = info.get(prepareMsg.order);
 | 
			
		||||
                    prepareMsg.content = (java.util.Arrays.hashCode(temp.request.content) + "").getBytes();
 | 
			
		||||
                    prepareMsg.content =
 | 
			
		||||
                            (java.util.Arrays.hashCode(temp.request.content) + "").getBytes();
 | 
			
		||||
                    broadcast(pbftMessage);
 | 
			
		||||
                }
 | 
			
		||||
            default:
 | 
			
		||||
@ -207,7 +210,8 @@ public class PBFTAlgorithm implements CommitAlgorithm {
 | 
			
		||||
    private void matchPrePrepareFromOriginReqeust(int hash, PBFTMessage pbftMessage) {
 | 
			
		||||
        for (PCInfo pcInfo : info.values()) {
 | 
			
		||||
            for (PBFTMessage msg : pcInfo.buff) {
 | 
			
		||||
                if (msg.type == PBFTType.PrePrepare && Integer.parseInt(new String(msg.content)) == hash) {
 | 
			
		||||
                if (msg.type == PBFTType.PrePrepare
 | 
			
		||||
                        && Integer.parseInt(new String(msg.content)) == hash) {
 | 
			
		||||
                    handlePrePrepare(msg, original.get(hash).second);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
@ -220,10 +224,8 @@ public class PBFTAlgorithm implements CommitAlgorithm {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void retryLater(int delay, final Node sender, final PBFTMessage pbftMessage) {
 | 
			
		||||
        ContractManager.scheduledThreadPool.schedule(
 | 
			
		||||
                () -> onPBFTMessage(sender, pbftMessage),
 | 
			
		||||
                delay,
 | 
			
		||||
                TimeUnit.MILLISECONDS);
 | 
			
		||||
        ContractManager.scheduledThreadPool.schedule(() -> onPBFTMessage(sender, pbftMessage),
 | 
			
		||||
                delay, TimeUnit.MILLISECONDS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void handlePrePrepare(PBFTMessage pbftMessage, PBFTMessage req) {
 | 
			
		||||
@ -399,8 +401,8 @@ public class PBFTAlgorithm implements CommitAlgorithm {
 | 
			
		||||
 | 
			
		||||
        public String getDisplayStr() {
 | 
			
		||||
            return "pSize:" + (prepare == null ? "null" : prepare.size()) + " cSize:"
 | 
			
		||||
                    + (commit == null ? "null" : commit.size()) + " isSendCommit:" + isSendCommit + " isSendReply:"
 | 
			
		||||
                    + isSendReply + " buffSize:" + buff.size();
 | 
			
		||||
                    + (commit == null ? "null" : commit.size()) + " isSendCommit:" + isSendCommit
 | 
			
		||||
                    + " isSendReply:" + isSendReply + " buffSize:" + buff.size();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@ package org.bdware.sc.consistency.pbft;
 | 
			
		||||
 | 
			
		||||
public enum PBFTType {
 | 
			
		||||
    Request(0), PrePrepare(1), Prepare(2), Commit(3), Reply(4), Unknown(5), ReSend(6), AddMember(7);
 | 
			
		||||
 | 
			
		||||
    private int type;
 | 
			
		||||
 | 
			
		||||
    PBFTType(int i) {
 | 
			
		||||
 | 
			
		||||
@ -4,8 +4,6 @@ import org.bdware.sc.bean.ContractRequest;
 | 
			
		||||
import org.bdware.sc.conn.Node;
 | 
			
		||||
import org.bdware.sc.consistency.CommitAlgorithm;
 | 
			
		||||
import org.bdware.sc.consistency.Committer;
 | 
			
		||||
import org.bdware.sc.consistency.pbft.PBFTMessage;
 | 
			
		||||
import org.bdware.sc.consistency.pbft.PBFTType;
 | 
			
		||||
import org.bdware.sc.units.TrustfulExecutorConnection;
 | 
			
		||||
 | 
			
		||||
public class ViewAlgorithm implements CommitAlgorithm {
 | 
			
		||||
@ -13,8 +11,7 @@ public class ViewAlgorithm implements CommitAlgorithm {
 | 
			
		||||
    private Committer committer;
 | 
			
		||||
    private TrustfulExecutorConnection connection;
 | 
			
		||||
 | 
			
		||||
    public ViewAlgorithm(boolean isMaster) {
 | 
			
		||||
    }
 | 
			
		||||
    public ViewAlgorithm(boolean isMaster) {}
 | 
			
		||||
 | 
			
		||||
    public void setCommitter(Committer c) {
 | 
			
		||||
        committer = c;
 | 
			
		||||
 | 
			
		||||
@ -49,22 +49,16 @@ public class EventBroker {
 | 
			
		||||
        tempTopics = recorder.recoverTempTopicsFromDb();
 | 
			
		||||
 | 
			
		||||
        // regularly check temporary topics and clean them
 | 
			
		||||
        ContractManager.scheduledThreadPool.scheduleWithFixedDelay(
 | 
			
		||||
                () -> {
 | 
			
		||||
        ContractManager.scheduledThreadPool.scheduleWithFixedDelay(() -> {
 | 
			
		||||
            long current = System.currentTimeMillis();
 | 
			
		||||
            int oldSize = tempTopics.size();
 | 
			
		||||
            tempTopics.keySet().forEach(topic -> {
 | 
			
		||||
                if (tempTopics.get(topic) + EXPIRED_TIME > current) {
 | 
			
		||||
                            String reqID =
 | 
			
		||||
                                    ContractManager.instance.nodeCenterConn.getNodeId() +
 | 
			
		||||
                                            "_" + System.currentTimeMillis();
 | 
			
		||||
                            REvent cleanEvent =
 | 
			
		||||
                                    new REvent(
 | 
			
		||||
                                            topic,
 | 
			
		||||
                                            UNSUBSCRIBE,
 | 
			
		||||
                                            null,
 | 
			
		||||
                                            reqID);
 | 
			
		||||
                            cleanEvent.doSignature(ContractManager.instance.nodeCenterConn.getNodeKeyPair());
 | 
			
		||||
                    String reqID = ContractManager.instance.nodeCenterConn.getNodeId() + "_"
 | 
			
		||||
                            + System.currentTimeMillis();
 | 
			
		||||
                    REvent cleanEvent = new REvent(topic, UNSUBSCRIBE, null, reqID);
 | 
			
		||||
                    cleanEvent
 | 
			
		||||
                            .doSignature(ContractManager.instance.nodeCenterConn.getNodeKeyPair());
 | 
			
		||||
                    handle(cleanEvent);
 | 
			
		||||
                    tempTopics.remove(topic);
 | 
			
		||||
                }
 | 
			
		||||
@ -72,16 +66,11 @@ public class EventBroker {
 | 
			
		||||
            if (oldSize != tempTopics.size()) {
 | 
			
		||||
                recorder.saveTempTopics(tempTopics);
 | 
			
		||||
            }
 | 
			
		||||
                },
 | 
			
		||||
                0L,
 | 
			
		||||
                EXPIRED_TIME,
 | 
			
		||||
                TimeUnit.MILLISECONDS);
 | 
			
		||||
        }, 0L, EXPIRED_TIME, TimeUnit.MILLISECONDS);
 | 
			
		||||
        // regularly create check point in database
 | 
			
		||||
        ContractManager.scheduledThreadPool.scheduleAtFixedRate(
 | 
			
		||||
                () -> recorder.createCheckPoint(topic2cIds, id2Consumers),
 | 
			
		||||
                EXPIRED_TIME,
 | 
			
		||||
                EXPIRED_TIME,
 | 
			
		||||
                TimeUnit.MILLISECONDS);
 | 
			
		||||
                () -> recorder.createCheckPoint(topic2cIds, id2Consumers), EXPIRED_TIME,
 | 
			
		||||
                EXPIRED_TIME, TimeUnit.MILLISECONDS);
 | 
			
		||||
 | 
			
		||||
        NodeConsumer.setCenter(center);
 | 
			
		||||
 | 
			
		||||
@ -106,7 +95,8 @@ public class EventBroker {
 | 
			
		||||
                    IEventConsumer consumer = doSubscribe(event);
 | 
			
		||||
                    // save & try to sub in center
 | 
			
		||||
                    recorder.appendEvent(event);
 | 
			
		||||
                    center.subInCenter(event.getTopic(), event.getSemantics(), event.getCenter(), consumer, event);
 | 
			
		||||
                    center.subInCenter(event.getTopic(), event.getSemantics(), event.getCenter(),
 | 
			
		||||
                            consumer, event);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case UNSUBSCRIBE:
 | 
			
		||||
@ -116,9 +106,10 @@ public class EventBroker {
 | 
			
		||||
            case PUBLISH:
 | 
			
		||||
            case PREPUB:
 | 
			
		||||
            case PRESUB:
 | 
			
		||||
                LOGGER.info(String.format("Receive %s event from topic %s", event.getSemantics(), topic));
 | 
			
		||||
                LOGGER.debug(String.format("Receive %s event %s: %s",
 | 
			
		||||
                        event.getSemantics(), topic, event.getContent()));
 | 
			
		||||
                LOGGER.info(String.format("Receive %s event from topic %s", event.getSemantics(),
 | 
			
		||||
                        topic));
 | 
			
		||||
                LOGGER.debug(String.format("Receive %s event %s: %s", event.getSemantics(), topic,
 | 
			
		||||
                        event.getContent()));
 | 
			
		||||
                if (event.isForward()) {
 | 
			
		||||
                    // send event to the event center
 | 
			
		||||
                    event.setForward(center.deliverEvent(topic, event));
 | 
			
		||||
@ -159,11 +150,8 @@ public class EventBroker {
 | 
			
		||||
     * @param id2Consumers consumer registry of broker or a check point in event recorder
 | 
			
		||||
     * @return if the subscribing succeeds
 | 
			
		||||
     */
 | 
			
		||||
    public boolean subInReg(
 | 
			
		||||
            String topic,
 | 
			
		||||
            IEventConsumer consumer,
 | 
			
		||||
            Map<String, Set<String>> topic2cIds,
 | 
			
		||||
            Map<String, IEventConsumer> id2Consumers) {
 | 
			
		||||
    public boolean subInReg(String topic, IEventConsumer consumer,
 | 
			
		||||
            Map<String, Set<String>> topic2cIds, Map<String, IEventConsumer> id2Consumers) {
 | 
			
		||||
        if (null == consumer) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
@ -177,8 +165,8 @@ public class EventBroker {
 | 
			
		||||
        topic2cIds.get(topic).add(cId);
 | 
			
		||||
        switch (consumer.getType()) {
 | 
			
		||||
            case Contract:
 | 
			
		||||
                LOGGER.info("contract " + ((ContractConsumer) consumer).getContract() +
 | 
			
		||||
                        " subscribes topic " + topic);
 | 
			
		||||
                LOGGER.info("contract " + ((ContractConsumer) consumer).getContract()
 | 
			
		||||
                        + " subscribes topic " + topic);
 | 
			
		||||
                break;
 | 
			
		||||
            case Node:
 | 
			
		||||
                LOGGER.info("node " + consumer.getId() + " subscribes topic " + topic);
 | 
			
		||||
@ -199,10 +187,11 @@ public class EventBroker {
 | 
			
		||||
     * do subscribing in registry<br/>
 | 
			
		||||
     * topic and consumer must not be null at the same time
 | 
			
		||||
     * <ul>
 | 
			
		||||
     *     <li>if consumer is null and topic is not, it means the topic is a temporary topic, remove it</li>
 | 
			
		||||
     *     <li>if topic is null and consumer is not,
 | 
			
		||||
     *     it means a consumer or a contract wants to unsubscribe all topics,
 | 
			
		||||
     *     remove all related consumers in topic registry and consumer registry</li>
 | 
			
		||||
     * <li>if consumer is null and topic is not, it means the topic is a temporary topic, remove
 | 
			
		||||
     * it</li>
 | 
			
		||||
     * <li>if topic is null and consumer is not, it means a consumer or a contract wants to
 | 
			
		||||
     * unsubscribe all topics, remove all related consumers in topic registry and consumer
 | 
			
		||||
     * registry</li>
 | 
			
		||||
     * <li>if two of them is not null, do unsubscribing in two registries</li>
 | 
			
		||||
     * </ul>
 | 
			
		||||
     *
 | 
			
		||||
@ -212,11 +201,8 @@ public class EventBroker {
 | 
			
		||||
     * @param id2Consumers consumer registry of broker or a check point in event recorder
 | 
			
		||||
     * @return if the subscribing succeeds
 | 
			
		||||
     */
 | 
			
		||||
    public boolean unsubInReg(
 | 
			
		||||
            String topic,
 | 
			
		||||
            IEventConsumer consumer,
 | 
			
		||||
            Map<String, Set<String>> topic2cIds,
 | 
			
		||||
            Map<String, IEventConsumer> id2Consumers) {
 | 
			
		||||
    public boolean unsubInReg(String topic, IEventConsumer consumer,
 | 
			
		||||
            Map<String, Set<String>> topic2cIds, Map<String, IEventConsumer> id2Consumers) {
 | 
			
		||||
        if (null == topic && null == consumer) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
@ -236,7 +222,8 @@ public class EventBroker {
 | 
			
		||||
            // if cId belongs to a contract, find all related consumers
 | 
			
		||||
            toRmIds = new ArrayList<>();
 | 
			
		||||
            id2Consumers.forEach((k, c) -> {
 | 
			
		||||
                if (c instanceof ContractConsumer && ((ContractConsumer) c).getContract().equals(cId)) {
 | 
			
		||||
                if (c instanceof ContractConsumer
 | 
			
		||||
                        && ((ContractConsumer) c).getContract().equals(cId)) {
 | 
			
		||||
                    toRmIds.add(k);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
@ -259,7 +246,8 @@ public class EventBroker {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * parse consumer information from content str<br/>
 | 
			
		||||
     * if caller wants to select all consumers of a contract, the content str is also parsed into a node consumer
 | 
			
		||||
     * if caller wants to select all consumers of a contract, the content str is also parsed into a
 | 
			
		||||
     * node consumer
 | 
			
		||||
     *
 | 
			
		||||
     * @param content json string, {"subscriber": "[subscriber]", "handler?": "[handler]"}
 | 
			
		||||
     * @return a node consumer or contract consumer, or null if exception is thrown
 | 
			
		||||
@ -305,19 +293,16 @@ public class EventBroker {
 | 
			
		||||
            case AT_LEAST_ONCE:
 | 
			
		||||
            case NEED_RETRY:
 | 
			
		||||
                // send events to all
 | 
			
		||||
                topicConsumers.forEach(cId ->
 | 
			
		||||
                        deliverEvent(event, cEvent, nEventStr, cId, topic, true));
 | 
			
		||||
                topicConsumers
 | 
			
		||||
                        .forEach(cId -> deliverEvent(event, cEvent, nEventStr, cId, topic, true));
 | 
			
		||||
                break;
 | 
			
		||||
            case AT_MOST_ONCE:
 | 
			
		||||
                // send event to a random consumer
 | 
			
		||||
                // AT_MOST_ONCE, so broker don't need to do anything when delivering fails
 | 
			
		||||
                deliverEvent(
 | 
			
		||||
                        event,
 | 
			
		||||
                        cEvent,
 | 
			
		||||
                        nEventStr,
 | 
			
		||||
                        topicConsumers.toArray()[(int) (Math.random() * topicConsumers.size())].toString(),
 | 
			
		||||
                        topic,
 | 
			
		||||
                        true);
 | 
			
		||||
                deliverEvent(event, cEvent, nEventStr,
 | 
			
		||||
                        topicConsumers.toArray()[(int) (Math.random() * topicConsumers.size())]
 | 
			
		||||
                                .toString(),
 | 
			
		||||
                        topic, true);
 | 
			
		||||
                break;
 | 
			
		||||
            case ONLY_ONCE:
 | 
			
		||||
                switch (event.getType()) {
 | 
			
		||||
@ -343,20 +328,14 @@ public class EventBroker {
 | 
			
		||||
                            // send PREPUB events to all consumers
 | 
			
		||||
                            // TODO if there are no consumers to receive the ONLY_ONCE events?
 | 
			
		||||
                            ContractManager.threadPool.execute(() -> {
 | 
			
		||||
                                REvent prePubMsg = new REvent(event.getTopic(),
 | 
			
		||||
                                        PREPUB,
 | 
			
		||||
                                        contentHash,
 | 
			
		||||
                                REvent prePubMsg = new REvent(event.getTopic(), PREPUB, contentHash,
 | 
			
		||||
                                        event.getRequestID());
 | 
			
		||||
                                prePubMsg.doSignature(ContractManager.instance.nodeCenterConn.getNodeKeyPair());
 | 
			
		||||
                                topicConsumers.forEach(cId ->
 | 
			
		||||
                                        deliverEvent(prePubMsg,
 | 
			
		||||
                                                new Event(event.getTopic(),
 | 
			
		||||
                                                        contentHash,
 | 
			
		||||
                                prePubMsg.doSignature(
 | 
			
		||||
                                        ContractManager.instance.nodeCenterConn.getNodeKeyPair());
 | 
			
		||||
                                topicConsumers.forEach(cId -> deliverEvent(prePubMsg,
 | 
			
		||||
                                        new Event(event.getTopic(), contentHash,
 | 
			
		||||
                                                prePubMsg.getSemantics()),
 | 
			
		||||
                                                JsonUtil.toJson(prePubMsg),
 | 
			
		||||
                                                cId,
 | 
			
		||||
                                                topic,
 | 
			
		||||
                                                false));
 | 
			
		||||
                                        JsonUtil.toJson(prePubMsg), cId, topic, false));
 | 
			
		||||
                                // wait for responses from contracts (PRESUB events)
 | 
			
		||||
                                while (true) {
 | 
			
		||||
                                    try {
 | 
			
		||||
@ -364,20 +343,20 @@ public class EventBroker {
 | 
			
		||||
                                            flag.wait(30 * 1000L);
 | 
			
		||||
                                        }
 | 
			
		||||
                                        if (!flag.get().isEmpty()) {
 | 
			
		||||
                                            REvent finalMsg = new REvent(flag.get(),
 | 
			
		||||
                                                    PUBLISH,
 | 
			
		||||
                                                    event.getContent(),
 | 
			
		||||
                                                    HashUtil.sha3(
 | 
			
		||||
                                                            contentHash + System.currentTimeMillis()));
 | 
			
		||||
                                            REvent finalMsg = new REvent(flag.get(), PUBLISH,
 | 
			
		||||
                                                    event.getContent(), HashUtil.sha3(contentHash
 | 
			
		||||
                                                            + System.currentTimeMillis()));
 | 
			
		||||
                                            // if the delivering fails, retry publishing
 | 
			
		||||
                                            finalMsg.setSemantics(NEED_RETRY);
 | 
			
		||||
                                            finalMsg.doSignature(
 | 
			
		||||
                                                    ContractManager.instance.nodeCenterConn.getNodeKeyPair());
 | 
			
		||||
                                                    ContractManager.instance.nodeCenterConn
 | 
			
		||||
                                                            .getNodeKeyPair());
 | 
			
		||||
                                            handle(finalMsg);
 | 
			
		||||
                                            break;
 | 
			
		||||
                                        }
 | 
			
		||||
                                    } catch (InterruptedException e) {
 | 
			
		||||
                                        LOGGER.warn("ONLY_ONE event delivering is interrupted: " + e.getMessage());
 | 
			
		||||
                                        LOGGER.warn("ONLY_ONE event delivering is interrupted: "
 | 
			
		||||
                                                + e.getMessage());
 | 
			
		||||
                                        // e.printStackTrace();
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
@ -396,19 +375,15 @@ public class EventBroker {
 | 
			
		||||
     * publish the event to the consumer
 | 
			
		||||
     *
 | 
			
		||||
     * @param event event message
 | 
			
		||||
     * @param cEvent    simple event message to the contract consumer, only topic, content and semantics
 | 
			
		||||
     * @param cEvent simple event message to the contract consumer, only topic, content and
 | 
			
		||||
     *        semantics
 | 
			
		||||
     * @param nEventStr event message to the node
 | 
			
		||||
     * @param cId consumer id
 | 
			
		||||
     * @param topic topic of the event
 | 
			
		||||
     * @param isPub if the event is published or pre-published
 | 
			
		||||
     */
 | 
			
		||||
    private void deliverEvent(
 | 
			
		||||
            REvent event,
 | 
			
		||||
            Event cEvent,
 | 
			
		||||
            String nEventStr,
 | 
			
		||||
            String cId,
 | 
			
		||||
            String topic,
 | 
			
		||||
            boolean isPub) {
 | 
			
		||||
    private void deliverEvent(REvent event, Event cEvent, String nEventStr, String cId,
 | 
			
		||||
            String topic, boolean isPub) {
 | 
			
		||||
        if (id2Consumers.containsKey(cId)) {
 | 
			
		||||
            IEventConsumer consumer = id2Consumers.get(cId);
 | 
			
		||||
            if (consumer instanceof ContractConsumer) {
 | 
			
		||||
@ -419,31 +394,24 @@ public class EventBroker {
 | 
			
		||||
                        public void onResult(String unused) {
 | 
			
		||||
                            // if the delivering fails, unsubscribe the consumer
 | 
			
		||||
                            ContractConsumer c = (ContractConsumer) consumer;
 | 
			
		||||
                            ContractClient client = ContractManager.instance.getClient(c.getContract());
 | 
			
		||||
                            String reqID =
 | 
			
		||||
                                    ContractManager.instance.nodeCenterConn.getNodeKeyPair().getPublicKeyStr() +
 | 
			
		||||
                                            "_" + System.currentTimeMillis();
 | 
			
		||||
                            REvent unsubEvent =
 | 
			
		||||
                                    new REvent(
 | 
			
		||||
                                            topic,
 | 
			
		||||
                                            UNSUBSCRIBE,
 | 
			
		||||
                                            "{\"subscriber\":\"" + cId + "\"}",
 | 
			
		||||
                                            reqID);
 | 
			
		||||
                            ContractClient client =
 | 
			
		||||
                                    ContractManager.instance.getClient(c.getContract());
 | 
			
		||||
                            String reqID = ContractManager.instance.nodeCenterConn.getNodeKeyPair()
 | 
			
		||||
                                    .getPublicKeyStr() + "_" + System.currentTimeMillis();
 | 
			
		||||
                            REvent unsubEvent = new REvent(topic, UNSUBSCRIBE,
 | 
			
		||||
                                    "{\"subscriber\":\"" + cId + "\"}", reqID);
 | 
			
		||||
                            unsubEvent.doSignature(client.getPubkey(), client.getContractKey());
 | 
			
		||||
                            handle(unsubEvent);
 | 
			
		||||
 | 
			
		||||
                            // if the event is an ONLY_ONCE event, retry publishing
 | 
			
		||||
                            if (NEED_RETRY.equals(event.getSemantics())) {
 | 
			
		||||
                                REvent newMsg =
 | 
			
		||||
                                        new REvent(
 | 
			
		||||
                                                topic.split("\\|")[0],
 | 
			
		||||
                                                PUBLISH,
 | 
			
		||||
                                                event.getContent(),
 | 
			
		||||
                                                event.getRequestID());
 | 
			
		||||
                                REvent newMsg = new REvent(topic.split("\\|")[0], PUBLISH,
 | 
			
		||||
                                        event.getContent(), event.getRequestID());
 | 
			
		||||
                                newMsg.setSemantics(ONLY_ONCE);
 | 
			
		||||
                                newMsg.setHash(event.getHash());
 | 
			
		||||
                                newMsg.setTxHash(event.getTxHash());
 | 
			
		||||
                                newMsg.doSignature(ContractManager.instance.nodeCenterConn.getNodeKeyPair());
 | 
			
		||||
                                newMsg.doSignature(
 | 
			
		||||
                                        ContractManager.instance.nodeCenterConn.getNodeKeyPair());
 | 
			
		||||
                                handle(newMsg);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
@ -465,8 +433,8 @@ public class EventBroker {
 | 
			
		||||
                });
 | 
			
		||||
            } else if (isPub) {
 | 
			
		||||
                // client consumer
 | 
			
		||||
                ContractManager.threadPool.execute(() ->
 | 
			
		||||
                        consumer.publishEvent(nEventStr, new ResultCallback() {
 | 
			
		||||
                ContractManager.threadPool
 | 
			
		||||
                        .execute(() -> consumer.publishEvent(nEventStr, new ResultCallback() {
 | 
			
		||||
                            @Override
 | 
			
		||||
                            public void onResult(String unused) {
 | 
			
		||||
                                unsubInReg(null, consumer, topic2cIds, id2Consumers);
 | 
			
		||||
 | 
			
		||||
@ -41,15 +41,13 @@ public class EventCenter {
 | 
			
		||||
     * @param consumer consumer
 | 
			
		||||
     * @param event original event
 | 
			
		||||
     */
 | 
			
		||||
    public void subInCenter(String topic, REvent.REventSemantics semantics, String center, IEventConsumer consumer, REvent event) {
 | 
			
		||||
    public void subInCenter(String topic, REvent.REventSemantics semantics, String center,
 | 
			
		||||
            IEventConsumer consumer, REvent event) {
 | 
			
		||||
        if (null == instance.nodeCenterConn) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        REvent msg = new REvent(topic,
 | 
			
		||||
                REvent.REventType.SUBSCRIBE,
 | 
			
		||||
                String.format("{\"subscriber\":\"%s\"}",
 | 
			
		||||
                        instance.nodeCenterConn.getNodeId()),
 | 
			
		||||
                "");
 | 
			
		||||
        REvent msg = new REvent(topic, REvent.REventType.SUBSCRIBE,
 | 
			
		||||
                String.format("{\"subscriber\":\"%s\"}", instance.nodeCenterConn.getNodeId()), "");
 | 
			
		||||
        msg.setSemantics(semantics);
 | 
			
		||||
        msg.doSignature(instance.nodeCenterConn.getNodeKeyPair());
 | 
			
		||||
        msg.setCenter(center);
 | 
			
		||||
 | 
			
		||||
@ -79,9 +79,10 @@ public class EventRecorder {
 | 
			
		||||
        String key = KeyValueRocksDBUtil.instance.getValue(dbName, LATEST_EVENT_KEY);
 | 
			
		||||
        latestEvent.set(key);
 | 
			
		||||
        CheckPoint cp = new CheckPoint();
 | 
			
		||||
        Type topic2cIdsType = TypeToken.getParameterized(ConcurrentHashMap.class, String.class,
 | 
			
		||||
                TypeToken.getParameterized(Set.class, String.class,
 | 
			
		||||
                        String.class).getType()).getType();
 | 
			
		||||
        Type topic2cIdsType = TypeToken
 | 
			
		||||
                .getParameterized(ConcurrentHashMap.class, String.class,
 | 
			
		||||
                        TypeToken.getParameterized(Set.class, String.class, String.class).getType())
 | 
			
		||||
                .getType();
 | 
			
		||||
        // retrieving transactions from database
 | 
			
		||||
        while (null != key && !key.isEmpty()) {
 | 
			
		||||
            String json = KeyValueRocksDBUtil.instance.getValue(dbName, key);
 | 
			
		||||
@ -93,14 +94,16 @@ public class EventRecorder {
 | 
			
		||||
                if (json.startsWith("cp")) {
 | 
			
		||||
                    // create check point by the transaction and stop retrieving
 | 
			
		||||
                    JsonObject data = JsonUtil.parseStringAsJsonObject(json.substring(2));
 | 
			
		||||
                    cp.topic2cIds = JsonUtil.fromJson(data.get("topic2cIds").toString(), topic2cIdsType);
 | 
			
		||||
                    cp.topic2cIds =
 | 
			
		||||
                            JsonUtil.fromJson(data.get("topic2cIds").toString(), topic2cIdsType);
 | 
			
		||||
                    JsonObject id2Consumers = data.getAsJsonObject("id2Consumers");
 | 
			
		||||
                    for (String k : id2Consumers.keySet()) {
 | 
			
		||||
                        JsonObject consumer = id2Consumers.getAsJsonObject(k);
 | 
			
		||||
                        if (!consumer.has("type")) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                        ConsumerType type = ConsumerType.valueOf(consumer.get("type").getAsString());
 | 
			
		||||
                        ConsumerType type =
 | 
			
		||||
                                ConsumerType.valueOf(consumer.get("type").getAsString());
 | 
			
		||||
                        switch (type) {
 | 
			
		||||
                            case Contract:
 | 
			
		||||
                                cp.id2Consumers.put(k,
 | 
			
		||||
@ -145,7 +148,8 @@ public class EventRecorder {
 | 
			
		||||
            // if empty, return the check point
 | 
			
		||||
            latestEvent.setCp(true);
 | 
			
		||||
        } else {
 | 
			
		||||
            // on the base of old check point, process following sub or unsub events to recover registry
 | 
			
		||||
            // on the base of old check point, process following sub or unsub events to recover
 | 
			
		||||
            // registry
 | 
			
		||||
            while (!stack.empty()) {
 | 
			
		||||
                Object record = stack.pop();
 | 
			
		||||
                if (record instanceof CheckPoint) {
 | 
			
		||||
@ -155,15 +159,19 @@ public class EventRecorder {
 | 
			
		||||
                    IEventConsumer consumer = broker.parseConsumer(tran.content);
 | 
			
		||||
                    switch (tran.type) {
 | 
			
		||||
                        case SUBSCRIBE:
 | 
			
		||||
                            if (!broker.subInReg(tran.topic, consumer, cp.topic2cIds, cp.id2Consumers)) {
 | 
			
		||||
                            if (!broker.subInReg(tran.topic, consumer, cp.topic2cIds,
 | 
			
		||||
                                    cp.id2Consumers)) {
 | 
			
		||||
                                LOGGER.warn("record damaged! " + key);
 | 
			
		||||
                                LOGGER.debug("record damaged! " + key + ": " + JsonUtil.toJson(tran));
 | 
			
		||||
                                LOGGER.debug(
 | 
			
		||||
                                        "record damaged! " + key + ": " + JsonUtil.toJson(tran));
 | 
			
		||||
                            }
 | 
			
		||||
                            break;
 | 
			
		||||
                        case UNSUBSCRIBE:
 | 
			
		||||
                            if (!broker.unsubInReg(tran.topic, consumer, cp.topic2cIds, cp.id2Consumers)) {
 | 
			
		||||
                            if (!broker.unsubInReg(tran.topic, consumer, cp.topic2cIds,
 | 
			
		||||
                                    cp.id2Consumers)) {
 | 
			
		||||
                                LOGGER.warn("record damaged! " + key);
 | 
			
		||||
                                LOGGER.debug("record damaged! " + key + ": " + JsonUtil.toJson(tran));
 | 
			
		||||
                                LOGGER.debug(
 | 
			
		||||
                                        "record damaged! " + key + ": " + JsonUtil.toJson(tran));
 | 
			
		||||
                            }
 | 
			
		||||
                        default:
 | 
			
		||||
                            break;
 | 
			
		||||
 | 
			
		||||
@ -91,19 +91,20 @@ public class ContractConsumer implements IEventConsumer {
 | 
			
		||||
                        try {
 | 
			
		||||
                            ContractResult result = JsonUtil.fromJson(str, ContractResult.class);
 | 
			
		||||
                            if (!result.status.equals(ContractResult.Status.Success)) {
 | 
			
		||||
                                if (callCount.get() == TIMEOUT_COUNT ||
 | 
			
		||||
                                        (result.status == ContractResult.Status.Exception &&
 | 
			
		||||
                                                result.result.toString().contains("not exported"))) {
 | 
			
		||||
                                    LOGGER.error(String.format(
 | 
			
		||||
                                            "receiving event error! %s.%s: %s", contract, handler, str));
 | 
			
		||||
                                if (callCount.get() == TIMEOUT_COUNT
 | 
			
		||||
                                        || (result.status == ContractResult.Status.Exception
 | 
			
		||||
                                                && result.result.toString()
 | 
			
		||||
                                                        .contains("not exported"))) {
 | 
			
		||||
                                    LOGGER.error(String.format("receiving event error! %s.%s: %s",
 | 
			
		||||
                                            contract, handler, str));
 | 
			
		||||
                                    rc.onResult((String) null);
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    ret = false;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        } catch (Exception e) {
 | 
			
		||||
                            LOGGER.error(String.format(
 | 
			
		||||
                                    "receiving event error! %s.%s: %s", contract, handler, e.getMessage()));
 | 
			
		||||
                            LOGGER.error(String.format("receiving event error! %s.%s: %s", contract,
 | 
			
		||||
                                    handler, e.getMessage()));
 | 
			
		||||
                            rc.onResult((String) null);
 | 
			
		||||
                        }
 | 
			
		||||
                        callCount.incrementAndGet();
 | 
			
		||||
@ -121,10 +122,7 @@ public class ContractConsumer implements IEventConsumer {
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }, (reqID, hashStr) -> {
 | 
			
		||||
                }),
 | 
			
		||||
                500L,
 | 
			
		||||
                2500L,
 | 
			
		||||
                TimeUnit.MILLISECONDS);
 | 
			
		||||
                }), 500L, 2500L, TimeUnit.MILLISECONDS);
 | 
			
		||||
        scheduledFutures.put(getId(), future);
 | 
			
		||||
        synchronized (flag) {
 | 
			
		||||
            flag.notify();
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
package org.bdware.sc.event.clients;
 | 
			
		||||
 | 
			
		||||
import org.bdware.sc.conn.ResultCallback;
 | 
			
		||||
import org.bdware.sc.event.Event;
 | 
			
		||||
 | 
			
		||||
public interface IEventConsumer {
 | 
			
		||||
    String getId();
 | 
			
		||||
@ -13,8 +12,6 @@ public interface IEventConsumer {
 | 
			
		||||
    void competeSub(Object msg, ResultCallback rc, String... options);
 | 
			
		||||
 | 
			
		||||
    enum ConsumerType {
 | 
			
		||||
        Contract,
 | 
			
		||||
        Node,
 | 
			
		||||
        WSClient
 | 
			
		||||
        Contract, Node, WSClient
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,5 @@ public class WSClientConsumer implements IEventConsumer {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void competeSub(Object msg, ResultCallback rc, String... options) {
 | 
			
		||||
    }
 | 
			
		||||
    public void competeSub(Object msg, ResultCallback rc, String... options) {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -34,8 +34,7 @@ public class ManagerHandler extends MsgHandler {
 | 
			
		||||
        cb.onResult(cm.getTimesOfExecution(msg.arg));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Description(
 | 
			
		||||
            value = "execute Contract, {\"contractID\":\"112233\",\"arg\":\"\"}",
 | 
			
		||||
    @Description(value = "execute Contract, {\"contractID\":\"112233\",\"arg\":\"\"}",
 | 
			
		||||
            isAsync = true)
 | 
			
		||||
    public void executeContract(GetMessage msg, ResultCallback cb) {
 | 
			
		||||
        ContractRequest c;
 | 
			
		||||
 | 
			
		||||
@ -4,81 +4,51 @@ package org.bdware.sc.units;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 节点启动后记录自己的units信息和合约的一些信息
 | 
			
		||||
 * 节点重新上线后,NC发要求让其恢复,则从本地读取自己的这些信息进行恢复
 | 
			
		||||
 * 节点启动后记录自己的units信息和合约的一些信息 节点重新上线后,NC发要求让其恢复,则从本地读取自己的这些信息进行恢复
 | 
			
		||||
 */
 | 
			
		||||
public class ContractRecord implements Serializable {
 | 
			
		||||
/*    private static final long serialVersionUID = 704775241674568688L;
 | 
			
		||||
 | 
			
		||||
    public transient RecoverFlag recoverFlag = RecoverFlag.Fine;
 | 
			
		||||
 | 
			
		||||
    public String contractID;
 | 
			
		||||
    public String contractName;
 | 
			
		||||
    public String key;
 | 
			
		||||
    public String contractpubKey;
 | 
			
		||||
    public ContractType type;
 | 
			
		||||
    public int copies = 1;
 | 
			
		||||
    public int lastExeSeq = -1;
 | 
			
		||||
    public boolean isPrivate = false;
 | 
			
		||||
    public String pubKeyPath;
 | 
			
		||||
    public String ypkName;
 | 
			
		||||
 | 
			
		||||
    //public Map<String,String> members;   //k-udpid,v-udpaddress
 | 
			
		||||
 | 
			
		||||
    public String memory = "";
 | 
			
		||||
 | 
			
		||||
    //JavaScriptEntry
 | 
			
		||||
    public String invokeID;
 | 
			
		||||
 | 
			
		||||
    public ContractRecord(String id){
 | 
			
		||||
        this.contractID = id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ContractRecord(String id,String contractName,String key,String contractpubKey,ContractType type,int copies){
 | 
			
		||||
        this.contractID = id;
 | 
			
		||||
        this.contractName = contractName;
 | 
			
		||||
        this.key = key;
 | 
			
		||||
        this.contractpubKey = contractpubKey;
 | 
			
		||||
        this.type = type;
 | 
			
		||||
        this.copies = copies;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void printContent(){
 | 
			
		||||
        System.out.println("==========ContractRecord========");
 | 
			
		||||
 | 
			
		||||
        System.out.println("contractID=" + contractID == null ? "null" : contractID);
 | 
			
		||||
        System.out.println("contractName=" + contractName == null ? "null" : contractName);
 | 
			
		||||
        System.out.println("key=" + key == null ? "null" : key);
 | 
			
		||||
        System.out.println("contractPubKey=" + contractpubKey == null ? "null" : contractpubKey);
 | 
			
		||||
        System.out.println("type=" + type == null ? "null" : type);
 | 
			
		||||
        System.out.println("lastExeSeq=" + lastExeSeq == null ? "null" : lastExeSeq);
 | 
			
		||||
        System.out.println("invokeID=" + invokeID == null ? "null" : invokeID);
 | 
			
		||||
        System.out.println("copies=" + copies);
 | 
			
		||||
        System.out.println("isPrivate=" + isPrivate);
 | 
			
		||||
        System.out.println("pubKeyPath=" + pubKeyPath == null ? "null" : pubKeyPath);
 | 
			
		||||
        System.out.println("ypkName=" + ypkName == null ? "null" : ypkName);
 | 
			
		||||
        if(members != null){
 | 
			
		||||
            for(String k : members.keySet()){
 | 
			
		||||
                System.out.println("members " + k + "-" + members.get(k));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        System.out.println("memory=" + memory == null ? "null" : memory);
 | 
			
		||||
        System.out.println("==========ContractRecord print finish=======");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void getContentFromFile(String path){
 | 
			
		||||
        File file = new File(path);
 | 
			
		||||
        try{
 | 
			
		||||
            FileInputStream os = new FileInputStream(file);
 | 
			
		||||
            ObjectInputStream oos = new ObjectInputStream(os);
 | 
			
		||||
            ContractRecord record = (ContractRecord) oos.readObject();
 | 
			
		||||
            record.printContent();
 | 
			
		||||
        } catch (FileNotFoundException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        } catch (ClassNotFoundException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
    }*/
 | 
			
		||||
    /*
 | 
			
		||||
     * private static final long serialVersionUID = 704775241674568688L;
 | 
			
		||||
     * 
 | 
			
		||||
     * public transient RecoverFlag recoverFlag = RecoverFlag.Fine;
 | 
			
		||||
     * 
 | 
			
		||||
     * public String contractID; public String contractName; public String key; public String
 | 
			
		||||
     * contractpubKey; public ContractType type; public int copies = 1; public int lastExeSeq = -1;
 | 
			
		||||
     * public boolean isPrivate = false; public String pubKeyPath; public String ypkName;
 | 
			
		||||
     * 
 | 
			
		||||
     * //public Map<String,String> members; //k-udpid,v-udpaddress
 | 
			
		||||
     * 
 | 
			
		||||
     * public String memory = "";
 | 
			
		||||
     * 
 | 
			
		||||
     * //JavaScriptEntry public String invokeID;
 | 
			
		||||
     * 
 | 
			
		||||
     * public ContractRecord(String id){ this.contractID = id; }
 | 
			
		||||
     * 
 | 
			
		||||
     * public ContractRecord(String id,String contractName,String key,String
 | 
			
		||||
     * contractpubKey,ContractType type,int copies){ this.contractID = id; this.contractName =
 | 
			
		||||
     * contractName; this.key = key; this.contractpubKey = contractpubKey; this.type = type;
 | 
			
		||||
     * this.copies = copies; }
 | 
			
		||||
     * 
 | 
			
		||||
     * public void printContent(){ System.out.println("==========ContractRecord========");
 | 
			
		||||
     * 
 | 
			
		||||
     * System.out.println("contractID=" + contractID == null ? "null" : contractID);
 | 
			
		||||
     * System.out.println("contractName=" + contractName == null ? "null" : contractName);
 | 
			
		||||
     * System.out.println("key=" + key == null ? "null" : key); System.out.println("contractPubKey="
 | 
			
		||||
     * + contractpubKey == null ? "null" : contractpubKey); System.out.println("type=" + type ==
 | 
			
		||||
     * null ? "null" : type); System.out.println("lastExeSeq=" + lastExeSeq == null ? "null" :
 | 
			
		||||
     * lastExeSeq); System.out.println("invokeID=" + invokeID == null ? "null" : invokeID);
 | 
			
		||||
     * System.out.println("copies=" + copies); System.out.println("isPrivate=" + isPrivate);
 | 
			
		||||
     * System.out.println("pubKeyPath=" + pubKeyPath == null ? "null" : pubKeyPath);
 | 
			
		||||
     * System.out.println("ypkName=" + ypkName == null ? "null" : ypkName); if(members != null){
 | 
			
		||||
     * for(String k : members.keySet()){ System.out.println("members " + k + "-" + members.get(k));
 | 
			
		||||
     * } } System.out.println("memory=" + memory == null ? "null" : memory);
 | 
			
		||||
     * System.out.println("==========ContractRecord print finish======="); }
 | 
			
		||||
     * 
 | 
			
		||||
     * public static void getContentFromFile(String path){ File file = new File(path); try{
 | 
			
		||||
     * FileInputStream os = new FileInputStream(file); ObjectInputStream oos = new
 | 
			
		||||
     * ObjectInputStream(os); ContractRecord record = (ContractRecord) oos.readObject();
 | 
			
		||||
     * record.printContent(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch
 | 
			
		||||
     * (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) {
 | 
			
		||||
     * e.printStackTrace(); } }
 | 
			
		||||
     */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,9 +16,7 @@ public class ContractUnitController {
 | 
			
		||||
    ContractManager manager;
 | 
			
		||||
    SequencingAlgorithmFactory algorithmFactory;
 | 
			
		||||
 | 
			
		||||
    public ContractUnitController(
 | 
			
		||||
            TrustfulExecutorConnection connection,
 | 
			
		||||
            ContractManager manager,
 | 
			
		||||
    public ContractUnitController(TrustfulExecutorConnection connection, ContractManager manager,
 | 
			
		||||
            SequencingAlgorithmFactory factory) {
 | 
			
		||||
        this.connection = connection;
 | 
			
		||||
        this.manager = manager;
 | 
			
		||||
@ -39,13 +37,8 @@ public class ContractUnitController {
 | 
			
		||||
                unit.node2member = new HashMap<>();
 | 
			
		||||
                units.put(req.contract.getID(), unit);
 | 
			
		||||
 | 
			
		||||
                System.out.println(
 | 
			
		||||
                        "[ContractUnitController] startContract:"
 | 
			
		||||
                                + result
 | 
			
		||||
                                + " isMaster:"
 | 
			
		||||
                                + req.isMaster
 | 
			
		||||
                                + " cid:"
 | 
			
		||||
                                + req.contract.getID());
 | 
			
		||||
                System.out.println("[ContractUnitController] startContract:" + result + " isMaster:"
 | 
			
		||||
                        + req.isMaster + " cid:" + req.contract.getID());
 | 
			
		||||
                break;
 | 
			
		||||
            case AddMember:
 | 
			
		||||
                LOGGER.debug("contractID:" + cumsg.getContractID());
 | 
			
		||||
@ -68,12 +61,8 @@ public class ContractUnitController {
 | 
			
		||||
                unit.node2member = new HashMap<>();
 | 
			
		||||
                units.put(req2.contract.getID(), unit);
 | 
			
		||||
 | 
			
		||||
                System.out.println(
 | 
			
		||||
                        "[ContractUnitController] startContract:"
 | 
			
		||||
                                + " isMaster:"
 | 
			
		||||
                                + req2.isMaster
 | 
			
		||||
                                + " cid:"
 | 
			
		||||
                                + req2.contract.getID());
 | 
			
		||||
                System.out.println("[ContractUnitController] startContract:" + " isMaster:"
 | 
			
		||||
                        + req2.isMaster + " cid:" + req2.contract.getID());
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -148,16 +137,9 @@ public class ContractUnitController {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public String getDisplayStr() {
 | 
			
		||||
            return "pSize:"
 | 
			
		||||
                    + (prepare == null ? "null" : prepare.size())
 | 
			
		||||
                    + " cSize:"
 | 
			
		||||
                    + (commit == null ? "null" : commit.size())
 | 
			
		||||
                    + " isSendCommit:"
 | 
			
		||||
                    + isSendCommit
 | 
			
		||||
                    + " isSendReply:"
 | 
			
		||||
                    + isSendReply
 | 
			
		||||
                    + " buffSize:"
 | 
			
		||||
                    + buff.size();
 | 
			
		||||
            return "pSize:" + (prepare == null ? "null" : prepare.size()) + " cSize:"
 | 
			
		||||
                    + (commit == null ? "null" : commit.size()) + " isSendCommit:" + isSendCommit
 | 
			
		||||
                    + " isSendReply:" + isSendReply + " buffSize:" + buff.size();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -61,7 +61,8 @@ public class ContractUnitMessage implements Serializable {
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    public boolean verify(ContractUnitMember member) {
 | 
			
		||||
		ECPublicKeyParameters param = BCECUtil.createECPublicKeyFromStrParameters(member.pubKey,SM2Util.CURVE,SM2Util.DOMAIN_PARAMS);
 | 
			
		||||
        ECPublicKeyParameters param = BCECUtil.createECPublicKeyFromStrParameters(member.pubKey,
 | 
			
		||||
                SM2Util.CURVE, SM2Util.DOMAIN_PARAMS);
 | 
			
		||||
 | 
			
		||||
        return SM2Util.verify(param, content, signature.getBytes());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,7 @@ import java.io.Serializable;
 | 
			
		||||
public enum ContractUnitType implements Serializable {
 | 
			
		||||
 | 
			
		||||
    Start(0), AddMember(1), Sequencing(2), Unknown(3);
 | 
			
		||||
 | 
			
		||||
    private int type;
 | 
			
		||||
 | 
			
		||||
    private ContractUnitType(int i) {
 | 
			
		||||
 | 
			
		||||
@ -101,10 +101,9 @@ public class MultiContractMeta implements IDSerializable {
 | 
			
		||||
 | 
			
		||||
    public void setLastExeSeq(int lastExeSeq) {
 | 
			
		||||
        this.lastExeSeq.set(lastExeSeq);
 | 
			
		||||
        if (KeyValueDBUtil.instance.containsKey(
 | 
			
		||||
                CMTables.LastExeSeq.toString(), contractID)) { // 如果现在是Stable模式就同步刷到磁盘
 | 
			
		||||
            KeyValueDBUtil.instance.setValue(
 | 
			
		||||
                    CMTables.LastExeSeq.toString(), contractID, String.valueOf(lastExeSeq));
 | 
			
		||||
        if (KeyValueDBUtil.instance.containsKey(CMTables.LastExeSeq.toString(), contractID)) { // 如果现在是Stable模式就同步刷到磁盘
 | 
			
		||||
            KeyValueDBUtil.instance.setValue(CMTables.LastExeSeq.toString(), contractID,
 | 
			
		||||
                    String.valueOf(lastExeSeq));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -154,16 +153,19 @@ public class MultiContractMeta implements IDSerializable {
 | 
			
		||||
    public String[] getMembers() {
 | 
			
		||||
        return members;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String joinMembers(String delimiter) {
 | 
			
		||||
        StringBuilder sb = new StringBuilder();
 | 
			
		||||
        if (members.length > 0)
 | 
			
		||||
            sb.append(members[0]);
 | 
			
		||||
        else return "";
 | 
			
		||||
        else
 | 
			
		||||
            return "";
 | 
			
		||||
        for (int i = 1; i < members.length; i++) {
 | 
			
		||||
            sb.append(delimiter).append(members[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return sb.toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setMembers(JsonArray members) {
 | 
			
		||||
        String[] copied = new String[members.size()];
 | 
			
		||||
        for (int i = 0; i < members.size(); i++) {
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,8 @@ public class RespCache {
 | 
			
		||||
                } else {
 | 
			
		||||
                    waiter.wait(5000L);
 | 
			
		||||
                    timeout &= waiter.get() * 2 > count;
 | 
			
		||||
                    if (!timeout) waiter.notifyAll();
 | 
			
		||||
                    if (!timeout)
 | 
			
		||||
                        waiter.notifyAll();
 | 
			
		||||
                    return timeout;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,8 @@ public class DHTUtil {
 | 
			
		||||
 | 
			
		||||
        String hash = HashUtil.sha3ToFixedLen(key, nodes[0].length() - 2);
 | 
			
		||||
 | 
			
		||||
        int l = 0, r = nodes.length - 1, m,
 | 
			
		||||
                h2l = hash.compareTo(nodes[l].substring(2)), r2h = nodes[r].substring(2).compareTo(hash),
 | 
			
		||||
                h2m;
 | 
			
		||||
        int l = 0, r = nodes.length - 1, m, h2l = hash.compareTo(nodes[l].substring(2)),
 | 
			
		||||
                r2h = nodes[r].substring(2).compareTo(hash), h2m;
 | 
			
		||||
        BigInteger bigH = null;
 | 
			
		||||
        String selected;
 | 
			
		||||
        do {
 | 
			
		||||
@ -42,8 +41,7 @@ public class DHTUtil {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if (l + 1 == r) {
 | 
			
		||||
                BigInteger bigL = getBigInteger(nodes[l]),
 | 
			
		||||
                        bigR = getBigInteger(nodes[r]);
 | 
			
		||||
                BigInteger bigL = getBigInteger(nodes[l]), bigR = getBigInteger(nodes[r]);
 | 
			
		||||
                bigH = new BigInteger(hash, 16);
 | 
			
		||||
                if (bigR.subtract(bigH).compareTo(bigH.subtract(bigL)) > -1) {
 | 
			
		||||
                    selected = nodes[l];
 | 
			
		||||
 | 
			
		||||
@ -10,15 +10,11 @@ import java.util.Map;
 | 
			
		||||
public interface ContractExecutor {
 | 
			
		||||
    void execute(String requestID, ContractRequest req, ResultCallback rcb, OnHashCallback hcb);
 | 
			
		||||
 | 
			
		||||
    default void onRecover(Map<String, Object> args) {
 | 
			
		||||
    }
 | 
			
		||||
    default void onRecover(Map<String, Object> args) {}
 | 
			
		||||
 | 
			
		||||
    default void onDeliverBlock(String data) {
 | 
			
		||||
    }
 | 
			
		||||
    default void onDeliverBlock(String data) {}
 | 
			
		||||
 | 
			
		||||
    default void close() {
 | 
			
		||||
    }
 | 
			
		||||
    default void close() {}
 | 
			
		||||
 | 
			
		||||
    default void onSyncMessage(Node node, byte[] data) {
 | 
			
		||||
    }
 | 
			
		||||
    default void onSyncMessage(Node node, byte[] data) {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,5 @@ package org.bdware.server.trustedmodel;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
public enum ContractUnitStatus implements Serializable {
 | 
			
		||||
    CommonMode,
 | 
			
		||||
    StableMode;
 | 
			
		||||
    CommonMode, StableMode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,8 @@ public class SingleNodeExecutor implements ContractExecutor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void execute(String requestID, ContractRequest req, ResultCallback rcb, OnHashCallback hcb) {
 | 
			
		||||
    public void execute(String requestID, ContractRequest req, ResultCallback rcb,
 | 
			
		||||
            OnHashCallback hcb) {
 | 
			
		||||
        cm.executeLocallyAsync(req, rcb, hcb);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,11 +1,7 @@
 | 
			
		||||
package org.bdware.sc.test;
 | 
			
		||||
 | 
			
		||||
import org.bdware.sc.ContractManager;
 | 
			
		||||
import org.bdware.sc.bean.Contract;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
import java.lang.reflect.Parameter;
 | 
			
		||||
 | 
			
		||||
public class ContractManagerTest {
 | 
			
		||||
    public static void main(String[] args) {
 | 
			
		||||
 | 
			
		||||
@ -12,17 +12,15 @@ public class RespCacheTest {
 | 
			
		||||
            new Thread(() -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    Thread.sleep(j * 1000);
 | 
			
		||||
                    if (j > 2) Thread.sleep(6 * 1000);
 | 
			
		||||
                    if (j > 2)
 | 
			
		||||
                        Thread.sleep(6 * 1000);
 | 
			
		||||
 | 
			
		||||
                } catch (InterruptedException e) {
 | 
			
		||||
                    e.printStackTrace();
 | 
			
		||||
                }
 | 
			
		||||
                boolean waitResult = cache.waitForHalf();
 | 
			
		||||
                System.out.println(
 | 
			
		||||
                        "tid:"
 | 
			
		||||
                                + Thread.currentThread().getId()
 | 
			
		||||
                                + " reach target, waitResult:"
 | 
			
		||||
                                + waitResult);
 | 
			
		||||
                System.out.println("tid:" + Thread.currentThread().getId()
 | 
			
		||||
                        + " reach target, waitResult:" + waitResult);
 | 
			
		||||
            }).start();
 | 
			
		||||
        }
 | 
			
		||||
        Thread.sleep(20000);
 | 
			
		||||
@ -37,17 +35,15 @@ public class RespCacheTest {
 | 
			
		||||
            new Thread(() -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    Thread.sleep(j * 1000);
 | 
			
		||||
                    if (j > 2) Thread.sleep(1900);
 | 
			
		||||
                    if (j > 2)
 | 
			
		||||
                        Thread.sleep(1900);
 | 
			
		||||
 | 
			
		||||
                } catch (InterruptedException e) {
 | 
			
		||||
                    e.printStackTrace();
 | 
			
		||||
                }
 | 
			
		||||
                boolean waitResult = cache.waitForHalf();
 | 
			
		||||
                System.out.println(
 | 
			
		||||
                        "tid:"
 | 
			
		||||
                                + Thread.currentThread().getId()
 | 
			
		||||
                                + " reach target, waitResult:"
 | 
			
		||||
                                + waitResult);
 | 
			
		||||
                System.out.println("tid:" + Thread.currentThread().getId()
 | 
			
		||||
                        + " reach target, waitResult:" + waitResult);
 | 
			
		||||
            }).start();
 | 
			
		||||
        }
 | 
			
		||||
        Thread.sleep(20000);
 | 
			
		||||
@ -66,11 +62,8 @@ public class RespCacheTest {
 | 
			
		||||
                    e.printStackTrace();
 | 
			
		||||
                }
 | 
			
		||||
                boolean waitResult = cache.waitForHalf();
 | 
			
		||||
                System.out.println(
 | 
			
		||||
                        "tid:"
 | 
			
		||||
                                + Thread.currentThread().getId()
 | 
			
		||||
                                + " reach target, waitResult:"
 | 
			
		||||
                                + waitResult);
 | 
			
		||||
                System.out.println("tid:" + Thread.currentThread().getId()
 | 
			
		||||
                        + " reach target, waitResult:" + waitResult);
 | 
			
		||||
            }).start();
 | 
			
		||||
        }
 | 
			
		||||
        Thread.sleep(10000);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user