From dc5ee173f6f72703fdd77a7f167e0b33a6b1ae36 Mon Sep 17 00:00:00 2001 From: CaiHQ Date: Fri, 24 Sep 2021 17:57:22 +0800 Subject: [PATCH] initial commit --- build.gradle | 72 +++++ .../java/org/bdware/client/AutoRegister.java | 52 ++++ src/main/java/org/bdware/client/Main.java | 105 +++++++ .../org/bdware/client/ContractRequest.java | 179 +++++++++++ .../bdware/client/EventSubscriberClient.java | 76 +++++ .../org/bdware/client/NodeManagerClient.java | 4 + src/main/sdk/org/bdware/client/Result.java | 16 + .../sdk/org/bdware/client/ResultCallback.java | 7 + .../sdk/org/bdware/client/SM2Verifiable.java | 69 ++++ .../bdware/client/SmartContractClient.java | 294 ++++++++++++++++++ .../bdware/client/SmartContractHandler.java | 113 +++++++ .../client/SmartContractHttpClient.java | 156 ++++++++++ src/main/sdk/org/bdware/client/ws/Action.java | 12 + .../sdk/org/bdware/client/ws/BaseClient.java | 52 ++++ .../sdk/org/bdware/client/ws/Handler.java | 7 + .../org/bdware/client/ws/ResponseAction.java | 5 + .../sdk/org/bdware/client/ws/WSHandler.java | 30 ++ .../bdware/client/test/EventClientTest.java | 33 ++ .../java/org/bdware/client/test/SM2Test.java | 132 ++++++++ .../bdware/client/test/SmartClientTest.java | 82 +++++ .../test/SmartContractHttpClientTest.java | 227 ++++++++++++++ src/test/resources/log4j.properties | 7 + 22 files changed, 1730 insertions(+) create mode 100644 build.gradle create mode 100644 src/main/java/org/bdware/client/AutoRegister.java create mode 100644 src/main/java/org/bdware/client/Main.java create mode 100644 src/main/sdk/org/bdware/client/ContractRequest.java create mode 100644 src/main/sdk/org/bdware/client/EventSubscriberClient.java create mode 100644 src/main/sdk/org/bdware/client/NodeManagerClient.java create mode 100644 src/main/sdk/org/bdware/client/Result.java create mode 100644 src/main/sdk/org/bdware/client/ResultCallback.java create mode 100644 src/main/sdk/org/bdware/client/SM2Verifiable.java create mode 100644 src/main/sdk/org/bdware/client/SmartContractClient.java create mode 100644 src/main/sdk/org/bdware/client/SmartContractHandler.java create mode 100644 src/main/sdk/org/bdware/client/SmartContractHttpClient.java create mode 100644 src/main/sdk/org/bdware/client/ws/Action.java create mode 100644 src/main/sdk/org/bdware/client/ws/BaseClient.java create mode 100644 src/main/sdk/org/bdware/client/ws/Handler.java create mode 100644 src/main/sdk/org/bdware/client/ws/ResponseAction.java create mode 100644 src/main/sdk/org/bdware/client/ws/WSHandler.java create mode 100644 src/test/java/org/bdware/client/test/EventClientTest.java create mode 100644 src/test/java/org/bdware/client/test/SM2Test.java create mode 100644 src/test/java/org/bdware/client/test/SmartClientTest.java create mode 100644 src/test/java/org/bdware/client/test/SmartContractHttpClientTest.java create mode 100644 src/test/resources/log4j.properties diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..edee227 --- /dev/null +++ b/build.gradle @@ -0,0 +1,72 @@ +plugins { + id 'java-library' +} + +group 'com.bdware.sc' +version '1.0-SNAPSHOT' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +sourceSets { + main { + java { + srcDirs 'src/main/java', 'src/main/sdk' + } + resources { + srcDir 'src/main/resources' + } + } + test { + java { + srcDir 'src/test/java' + } + resources { + srcDir 'src/test/resources' + } + } +} + +dependencies { + api project(":gmhelper") + api 'javax.websocket:javax.websocket-api:1.1' + api 'log4j:log4j:1.2.17' + api 'org.apache.logging.log4j:log4j-core:2.14.1' + api 'org.apache.logging.log4j:log4j-api:2.14.1' + api 'org.glassfish.tyrus.bundles:tyrus-standalone-client:1.17' + testImplementation 'junit:junit:4.13.2' +} + +jar { + String libs = '' + configurations.runtimeClasspath.each { + libs = libs + " libs/" + it.name + } + + manifest { + attributes 'Manifest-Version': archiveVersion + // attributes 'Main-Class': "com.bdware.client.AutoRegister" + attributes 'Class-Path': libs + attributes 'Main-Class': 'org.bdware.client.Main' + } +} + +task copyJar(type: Copy, dependsOn: [":sdk-java:jar", ":sdk-java:copyLibs"]) { + into "./build/output/" + from "./build/libs/$project.name-${version}.jar" +} + +task copyLibs(type: Copy) { + into "./build/output/libs/" + from configurations.runtimeClasspath +} + +task release(type: Zip, dependsOn: ["copyJar", "copyLibs"]) { + from "./build/output/" + duplicatesStrategy = DuplicatesStrategy.INCLUDE + archiveFileName = "java-client-${projectIds.version}.zip" + destinationDirectory = file('build/') +} \ No newline at end of file diff --git a/src/main/java/org/bdware/client/AutoRegister.java b/src/main/java/org/bdware/client/AutoRegister.java new file mode 100644 index 0000000..549a516 --- /dev/null +++ b/src/main/java/org/bdware/client/AutoRegister.java @@ -0,0 +1,52 @@ +package org.bdware.client; + +import com.google.gson.JsonObject; +import org.zz.gmhelper.SM2KeyPair; + +public class AutoRegister { + public static void main(String[] args) { + String keyPairStr = "{\"privateKey\":\"347caf3393482440cf5a79995b2c83f567644dfa9b4804755bd093141542db96\",\"publicKey\":\"04f5c7cc4b202047da7aff4b93e66204d8e04d0e26435e792afcfb8b4bf918b9b4ec8550e669fb1581203fcd7187ea993391d6c3ee6e348ee17febee3bdad783c3\"}"; + // "{\"privateKey\":\"589d94ee5688358a1c5c18430dd9c75097ddddebf769f139da36a807911d20f8\",\"publicKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}"; + //; "{\"privateKey\":\"b1f6223a49b9e0943016505e932a17ea0bfe357f3b23cae28f847db9566d30cf\",\"publicKey\":\"0469344c29715c32f0f45765f9446c6208eb1f9ce2c2b765a1c6a7f50e0f8fdb904be2acbaa41898e25144aa5740f5c1dfccdd8bc7fff193dee94269853b1d476b\"}"; + SM2KeyPair keyPair = SM2KeyPair.fromJson(keyPairStr); + String[] ips = new String[]{"10.10.133.38", "10.10.133.55", "10.10.133.56", "10.10.133.5"}; + for (String ip : ips) { + initialize(ip, 21030, keyPair); + } + } + + public static void initialize(String ip, int port, SM2KeyPair keyPair) { + String local = "ws://" + ip + ":" + port + "/SCIDE/SCExecutor"; + System.out.println("config:" + ip + ":" + port); + + SmartContractClient testClient = + new SmartContractClient(local, keyPair) { + public void onListContractProcess(JsonObject obj) { + super.onListContractProcess(obj); + } + + public void onLogin(JsonObject obj) { + this.setName("Node_" + port); + this.setBDLedger("127.0.0.1:18030"); + this.setMasterAddress(ip + ":" + (port + 1)); + String apply = + "{\"action\":\"applyNodeRole\",\"role\":\"_ROLE_\",\"pubKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}"; + this.sendMsg(apply.replaceAll("_ROLE_", "ContractProvider")); + this.sendMsg(apply.replaceAll("_ROLE_", "ContractUser")); + this.sendMsg(apply.replaceAll("_ROLE_", "ContractInstanceManager")); + String auth = + "{\"action\":\"authNodeRole\",\"pubKey\":\"04f5c7cc4b202047da7aff4b93e66204d8e04d0e26435e792afcfb8b4bf918b9b4ec8550e669fb1581203fcd7187ea993391d6c3ee6e348ee17febee3bdad783c3\",\"isAccept\":true}"; + this.sendMsg(auth); + this.setClusterAddress("ws://10.10.133.38:18002"); + this.listContractProcess(); + } + }; + testClient.waitForConnect(); + testClient.login(); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/org/bdware/client/Main.java b/src/main/java/org/bdware/client/Main.java new file mode 100644 index 0000000..7f88e7c --- /dev/null +++ b/src/main/java/org/bdware/client/Main.java @@ -0,0 +1,105 @@ +package org.bdware.client; + +import com.google.gson.JsonObject; +import org.bdware.client.ws.Action; +import org.zz.gmhelper.SM2KeyPair; +import org.zz.gmhelper.SM2Util; + +public class Main { + public static void main(String[] args) throws InterruptedException { + if (args.length == 0 || args[0].equals("-h") || args[0].equals("--help")) { + printUsage(null); + return; + } + int port = 18000; + String ip = "127.0.0.1"; + SM2KeyPair key = SM2Util.generateSM2KeyPair(null); + for (int i = 0; i < args.length; i += 2) { + if (i > args.length - 1) { + printUsage("Option parse error"); + } + switch (args[i]) { + case "-port": + case "-p": + port = Integer.parseInt(args[i + 1]); + break; + case "-ip": + ip = (args[i + 1].replaceAll("ws://", "")); + break; + case "-generateSm2KeyPair": + case "-g": + System.out.println(SM2Util.generateSM2KeyPair(null).toJson()); + break; + case "-k": + case "-sm2keypair": + key = SM2KeyPair.fromJson(args[i + 1]); + break; + } + } + String addr = "ws://" + ip + ":" + port + "/SCIDE/SCExecutor"; + System.out.println("connect to:" + addr + " using pubKey:" + key.getPublicKeyStr()); + SmartContractClient client = + new SmartContractClient(addr, key) { + @Override + public void onListContractProcess(JsonObject obj) { + System.exit(0); + } + + @Action + public void onChangeNodeName(JsonObject obj) { + System.out.println(obj.toString()); + } + + @Action + public void onChangeNodeCenter(JsonObject obj) { + System.out.println(obj.toString()); + } + + @Action + public void onUpdateConfig(JsonObject obj) { + System.out.println(obj.toString()); + } + }; + client.waitForConnect(); + client.login(); + Thread.sleep(1000); + System.out.println("[Connected]"); + for (int i = 0; i < args.length; i += 2) { + switch (args[i]) { + case "-setName": + client.setName(args[i + 1]); + break; + case "-setCluster": + client.setClusterAddress(args[i + 1]); + break; + case "-setMasterAddress": + client.setMasterAddress(args[i + 1]); + break; + case "-setBDLedger": + client.setBDLedger(args[i + 1]); + break; + case "-execute": + ContractRequest cr = new ContractRequest(); + cr.setContractID(args[i + 1]); + cr.setAction(args[i + 2]); + cr.setArg(args[i + 3]); + JsonObject json = client.executeContractSync(cr); + System.out.println(json.toString()); + break; + } + } + Thread.sleep(1000); + client.listContractProcess(); + } + + private static void printUsage(String msg) { + if (msg != null) { + System.out.println("Error: " + msg); + System.exit(1); + return; + } + System.out.println( + "Usage: java -cp \"./libs/:java-client.jar\" org.bdware.client.Main [-ip <127.0.0.1>] [-port/-p ] [-generateSm2KeyPair/-g ] [-sm2keypair/-k ] [-setName ] [-setCluster ] [-execute ]"); + System.exit(1); + } +} diff --git a/src/main/sdk/org/bdware/client/ContractRequest.java b/src/main/sdk/org/bdware/client/ContractRequest.java new file mode 100644 index 0000000..93000ad --- /dev/null +++ b/src/main/sdk/org/bdware/client/ContractRequest.java @@ -0,0 +1,179 @@ +package org.bdware.client; + +import com.google.gson.Gson; +import org.zz.gmhelper.SM2KeyPair; + +import java.io.*; + +public class ContractRequest extends SM2Verifiable + implements Serializable, Comparable { + + private static final long serialVersionUID = 5516141428163407726L; + public long hasValue; + public long gasLimit; + public Boolean needSeq = false; // not requestAll do not need sequent + public int seq = 0; // only requestAll type contract need + public boolean withDynamicAnalysis = false; + public boolean withEvaluatesAnalysis = false; + public String fromContract; + String contractID; + String contractDOI; + // requester = reqPubKey + String requester; + // DOI of requester + String requesterDOI; + // action = rsaPrivKeyEncoded(aesKey); + String action; + // arg = aesKeyEncoded({action,arg}); + String arg; + String requestID; + boolean fromDebug = false; + + public static void main(String[] args) { + ContractRequest req = new ContractRequest(); + // req.requester = rsa.toBase64Pubkey(); + req.contractID = "123"; + req.action = "main"; + req.arg = "arg1"; + String key = + "{\"privateKey\":\"589d94ee5688358a1c5c18430dd9c75097ddddebf769f139da36a807911d20f8\",\"publicKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}"; + SM2KeyPair pair = SM2KeyPair.fromJson(key); + req.doSignature(pair); + System.out.println(req.verifySignature()); + System.out.println(new Gson().toJson(req)); + System.out.println(req.verifySignature()); + } + + public static ContractRequest parse(byte[] content) { + try { + ObjectInputStream input = new ObjectInputStream(new ByteArrayInputStream(content)); + return (ContractRequest) input.readObject(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public String getContractID() { + return contractID; + } + + public ContractRequest setContractID(String id) { + contractID = id; + return this; + } + + public String getContractDOI() { + return contractDOI; + } + + public void setContractDOI(String doi) { + contractDOI = doi; + } + + public String getRequester() { + return requester; + } + + public void setRequester(String requester) { + this.requester = requester; + } + + public String getRequesterDOI() { + if (requesterDOI == null || requesterDOI.equals("")) return "empty"; + return requesterDOI; + } + + public void setRequesterDOI(String requesterDOI) { + this.requesterDOI = requesterDOI; + } + + public String getArg() { + return arg; + } + + public ContractRequest setArg(String arg) { + this.arg = arg; + return this; + } + + public String getAction() { + return action; + } + + public ContractRequest setAction(String action) { + this.action = action; + return this; + } + + public long getValue() { + return hasValue; + } + + public ContractRequest setValue(long hasValue) { + this.hasValue = hasValue; + return this; + } + + public long getGasLimit() { + return gasLimit; + } + + public void setGasLimit(long gasLimit) { + this.gasLimit = gasLimit; + } + + public void setFromDebug(boolean fromDebug) { + this.fromDebug = fromDebug; + } + + public boolean fromDebug() { + return fromDebug; + } + + @Override + public String getPublicKey() { + return requester; + } + + @Override + public void setPublicKey(String pubkey) { + setRequester(pubkey); + } + + @Override + public String getContentStr() { + return String.format( + "%s|%s|%s%s|%s", + (contractDOI != null && contractDOI.length() > 0) ? contractDOI : contractID, + action, + arg, + gasLimit > 0 ? "|" + gasLimit : "", + requester); + } + + public byte[] toByte() { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream bo = new ObjectOutputStream(out); + bo.writeObject(this); + return out.toByteArray(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public String getRequestID() { + return requestID; + } + + public void setRequestID(String str) { + this.requestID = str; + } + + @Override + public int compareTo(ContractRequest cr) { + return Integer.compare(seq, cr.seq); + } +} diff --git a/src/main/sdk/org/bdware/client/EventSubscriberClient.java b/src/main/sdk/org/bdware/client/EventSubscriberClient.java new file mode 100644 index 0000000..d70866b --- /dev/null +++ b/src/main/sdk/org/bdware/client/EventSubscriberClient.java @@ -0,0 +1,76 @@ +package org.bdware.client; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.bdware.client.ws.BaseClient; +import org.bdware.client.ws.Handler; +import org.bouncycastle.crypto.CryptoException; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.zz.gmhelper.SM2KeyPair; +import org.zz.gmhelper.SM2Util; + +import javax.websocket.ClientEndpointConfig; +import javax.websocket.ContainerProvider; +import javax.websocket.DeploymentException; +import java.io.IOException; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +public class EventSubscriberClient implements Handler { + BaseClient bc; + + // ws://localhost:8080/SCIDE/SCExecutor + public EventSubscriberClient(String uri) { + try { + bc = new BaseClient(this); + ContainerProvider.getWebSocketContainer() + .connectToServer( + bc, ClientEndpointConfig.Builder.create().build(), URI.create(uri)); + } catch (DeploymentException | IOException e) { + e.printStackTrace(); + } + } + + @Override + public void handle(JsonObject obj) { + System.out.println("[EventClient] receive" + obj.toString()); + } + + public void waitForConnect() { + while (!bc.connected()) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + Map setNodeID = new HashMap<>(); + setNodeID.put("action", "setNodeID"); + SM2KeyPair keyPair = SM2Util.generateSM2KeyPair(null); + setNodeID.put("id", keyPair.getPublicKeyStr()); + + byte[] sig; + try { + sig = + SM2Util.sign( + keyPair.getPrivateKeyParameter(), keyPair.getPublicKeyStr().getBytes()); + setNodeID.put("signature", ByteUtils.toHexString(sig)); + + } catch (CryptoException e) { + e.printStackTrace(); + } + setNodeID.put("nodeName", "[LiteClient_" + System.currentTimeMillis() + "]"); + bc.sendText(new Gson().toJson(setNodeID)); + } + + public void subscribeEvent(String nodeID, String contractID, String event) { + Map msg = new HashMap<>(); + msg.put("action", "subEvent"); + msg.put("target", nodeID); + msg.put("contractID", contractID); + msg.put("event", event); + bc.sendText(new Gson().toJson(msg)); + } +} diff --git a/src/main/sdk/org/bdware/client/NodeManagerClient.java b/src/main/sdk/org/bdware/client/NodeManagerClient.java new file mode 100644 index 0000000..4987800 --- /dev/null +++ b/src/main/sdk/org/bdware/client/NodeManagerClient.java @@ -0,0 +1,4 @@ +package org.bdware.client; + +public class NodeManagerClient { +} diff --git a/src/main/sdk/org/bdware/client/Result.java b/src/main/sdk/org/bdware/client/Result.java new file mode 100644 index 0000000..76cf037 --- /dev/null +++ b/src/main/sdk/org/bdware/client/Result.java @@ -0,0 +1,16 @@ +package org.bdware.client; + +import com.google.gson.JsonObject; + +public class Result implements ResultCallback { + public JsonObject result = null; + + @Override + public void onResult(JsonObject r) { + result = r; + } + + public boolean hasResult() { + return result != null; + } +} diff --git a/src/main/sdk/org/bdware/client/ResultCallback.java b/src/main/sdk/org/bdware/client/ResultCallback.java new file mode 100644 index 0000000..4200e99 --- /dev/null +++ b/src/main/sdk/org/bdware/client/ResultCallback.java @@ -0,0 +1,7 @@ +package org.bdware.client; + +import com.google.gson.JsonObject; + +public interface ResultCallback { + void onResult(JsonObject r); +} diff --git a/src/main/sdk/org/bdware/client/SM2Verifiable.java b/src/main/sdk/org/bdware/client/SM2Verifiable.java new file mode 100644 index 0000000..6c4e276 --- /dev/null +++ b/src/main/sdk/org/bdware/client/SM2Verifiable.java @@ -0,0 +1,69 @@ +package org.bdware.client; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.zz.gmhelper.BCECUtil; +import org.zz.gmhelper.SM2KeyPair; +import org.zz.gmhelper.SM2Util; + +import java.math.BigInteger; + +public abstract class SM2Verifiable { + private static final Logger LOGGER = LogManager.getLogger(SM2Verifiable.class); + // signature is der encoded + public String signature; + + public abstract String getPublicKey(); + + public abstract void setPublicKey(String pubkey); + + public abstract String getContentStr(); + + public void doSignature(String privateKey) { + BigInteger privkey = new BigInteger(privateKey, 16); + ECPoint p = SM2Util.G_POINT.multiply(privkey).normalize(); + doSignature(new SM2KeyPair(new ECPublicKeyParameters(p, SM2Util.DOMAIN_PARAMS), privkey)); + } + + public void doSignature(SM2KeyPair pair) { + try { + setPublicKey(pair.getPublicKeyStr()); + + signature = + ByteUtils.toHexString( + SM2Util.sign( + pair.getPrivateKeyParameter(), getContentStr().getBytes())); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public boolean verifySignature() { + try { + String verifiedStr = getContentStr(); + ECPublicKeyParameters pubKey = + BCECUtil.createECPublicKeyFromStrParameters( + getPublicKey(), SM2Util.CURVE, SM2Util.DOMAIN_PARAMS); + LOGGER.info(verifiedStr); + LOGGER.info(getPublicKey()); + LOGGER.info(signature); + + return SM2Util.verify( + pubKey, verifiedStr.getBytes(), ByteUtils.fromHexString(signature)); + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } +} diff --git a/src/main/sdk/org/bdware/client/SmartContractClient.java b/src/main/sdk/org/bdware/client/SmartContractClient.java new file mode 100644 index 0000000..a6c890a --- /dev/null +++ b/src/main/sdk/org/bdware/client/SmartContractClient.java @@ -0,0 +1,294 @@ +package org.bdware.client; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.client.ws.Action; +import org.bdware.client.ws.BaseClient; +import org.bouncycastle.crypto.CryptoException; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.zz.gmhelper.SM2KeyPair; +import org.zz.gmhelper.SM2Util; + +import javax.websocket.ClientEndpointConfig; +import javax.websocket.ContainerProvider; +import javax.websocket.DeploymentException; +import java.io.IOException; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class SmartContractClient extends SmartContractHandler { + private static final Logger LOGGER = LogManager.getLogger(SmartContractClient.class); + public final ConcurrentHashMap cbs = new ConcurrentHashMap<>(); + String uri; + BaseClient bc; + SM2KeyPair keyPair; + + public SmartContractClient(String uri) { + this(uri, SM2Util.generateSM2KeyPair(null)); + } + + // ws://localhost:8080/SCIDE/SCExecutor + public SmartContractClient(String uri, SM2KeyPair pair) { + try { + keyPair = pair; + bc = new BaseClient(this); + this.uri = uri; + ContainerProvider.getWebSocketContainer() + .connectToServer( + bc, ClientEndpointConfig.Builder.create().build(), URI.create(uri)); + } catch (DeploymentException | IOException e) { + e.printStackTrace(); + System.err.println("[Connect failed]:" + uri); + } + } + + public void listContractProcess() { + listContractProcess(null); + } + + public void listContractProcess(ResultCallback rc) { + JsonObject jo = new JsonObject(); + jo.addProperty("action", "listContractProcess"); + // System.out.println("SendAction:" + jo.toString()); + if (null != rc) { + cbs.put(this.uri, rc); + } + bc.sendText(jo.toString()); + } + + public void waitForConnect() { + while (!bc.connected()) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + public SM2KeyPair getKeyPair() { + return keyPair; + } + + @Override + public void onListContractProcess(JsonObject obj) { + info(obj.toString()); + obj.addProperty("responseID", this.uri); + invokeCallback(obj); + } + + @Override + public void onOutputStream(JsonObject obj) { + debug(obj.toString()); + } + + @Override + public void onStartContract(JsonObject obj) { + debug(obj.toString()); + invokeCallback(obj); + } + + @Override + public void onKillContractProcess(JsonObject obj) { + debug(obj.toString()); + } + + @Override + public void onHashResult(JsonObject obj) { + debug(obj.toString()); + } + + @Override + public void onKillAllContract(JsonObject obj) { + debug(obj.toString()); + } + + @Override + public void onExecuteResult(JsonObject obj) { + debug(obj.toString()); + // !!!!!! Important, call this method to trigger callbacks + invokeCallback(obj); + } + + protected void invokeCallback(JsonObject obj) { + if (obj.has("responseID")) { + String responseID = obj.get("responseID").getAsString(); + if (cbs.containsKey(responseID)) { + synchronized (cbs.get(responseID)) { + ResultCallback rc = cbs.get(responseID); + cbs.remove(responseID); + rc.onResult(obj); + } + } + } + } + + @Override + public void onUndefined(JsonObject obj) { + info(obj); + } + + public void login() { + String msg = "{\"action\":\"getSessionID\"}"; + bc.sendText(msg); + } + + @Override + public void onSessionID(JsonObject obj) { + String session = obj.get("session").getAsString(); + String msg = "{\"action\":\"login\",\"signature\":\""; + String signature = null; + try { + signature = + ByteUtils.toHexString( + SM2Util.sign(keyPair.getPrivateKeyParameter(), session.getBytes())); + } catch (CryptoException e) { + e.printStackTrace(); + } + msg += signature; + msg += "\",\"pubKey\":\"" + keyPair.getPublicKeyStr() + "\"}"; + debug("The second phase for login onGetNodeSession"); + bc.sendText(msg); + } + + @Override + public void onLogin(JsonObject obj) { + debug(obj.toString()); + } + + @Override + public void onLoadNodeConfig(JsonObject obj) { + ResultCallback cb = cbs.get("loadNodeConfig"); + cbs.remove("loadNodeConfig"); + cb.onResult(obj); + } + + public void loadNodeConfig(ResultCallback cb) { + cbs.put("loadNodeConfig", null == cb ? this::info : cb); + sendMsg("{\"action\":\"loadNodeConfig\"}"); + } + + @Action + public void onException(JsonObject obj) { + debug(obj.toString()); + } + + public synchronized void sendMsg(String s) { + // System.out.println("SendAction:" + s); + bc.sendText(s); + } + + public JsonObject executeContractSync(ContractRequest cr) { + String reqID = System.currentTimeMillis() + "_" + (int) (Math.random() * 10000); + Map req = fillReq(cr, reqID); + Result rc = new Result(); + cbs.put(reqID, rc); + try { + sendMsg(new Gson().toJson(req)); + while (!rc.hasResult()) { + Thread.yield(); + } + return rc.result; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void executeContract(ContractRequest cr) { + executeContract(cr, null); + } + + public void executeContract(ContractRequest cr, ResultCallback rc) { + String reqID = System.currentTimeMillis() + "_" + (int) (Math.random() * 10000); + Map req = fillReq(cr, reqID); + if (rc != null) { + cbs.put(reqID, rc); + } + sendMsg(new Gson().toJson(req)); + } + + private Map fillReq(ContractRequest cr, String reqID) { + Map req = new HashMap<>(); + req.put("action", "executeContract"); + req.put("requestID", reqID); + req.put("contractID", cr.getContractID()); + if (null == cr.getPublicKey()) { + cr.doSignature(keyPair); + } + req.put("signature", cr.signature); + req.put("pubkey", cr.getPublicKey()); + req.put("operation", cr.getAction()); + if (cr.getArg() == null) req.put("arg", "undefined"); + else req.put("arg", cr.getArg()); + return req; + } + + public String getExecuteUrl(ContractRequest cr) { + return uri.replaceFirst("ws://", "http://") + .replaceFirst("/SCIDE/SCExecutor", "/SCIDE/CMManager?") + + "action=executeContract" + + "&contractID=" + + cr.getContractID() + + "&pubkey=" + + cr.getPublicKey() + + "&operation=" + + cr.getAction() + + "&arg=" + + cr.getArg() + + "&signature=" + + cr.signature; + } + + + public String getExecuteUrlNoSign(ContractRequest cr) { + return uri.replaceFirst("ws://", "http://") + .replaceFirst("/SCIDE/SCExecutor", "/SCIDE/CMManager") + + "?action=executeContract" + + "&contractID=" + + cr.getContractID() + + "&operation=" + + cr.getAction() + + "&arg=" + + cr.getArg(); + } + + public void setClusterAddress(String addr) { + String str = "{\"action\":\"changeNodeCenter\",\"data\":\"" + addr + "\"}"; + sendMsg(str); + } + + public void setName(String name) { + String str = "{\"action\":\"changeNodeName\",\"data\":\"" + name + "\"}"; + sendMsg(str); + } + + private void updateConfig(String key, String val) { + Map req = new HashMap<>(); + req.put("action", "updateConfig"); + req.put("key", key); + req.put("val", val); + sendMsg(new Gson().toJson(req)); + } + + public void setMasterAddress(String arg) { + updateConfig("masterAddress", arg); + } + + public void setBDLedger(String arg) { + sendMsg("{\"action\":\"changeBDledger\",\"data\":\"" + arg + "\"}"); + updateConfig("dataChain", arg); + } + + private void debug(Object info) { + LOGGER.debug("[" + this.uri + "] " + info); + } + + private void info(Object info) { + LOGGER.info("[" + this.uri + "] " + info); + } +} diff --git a/src/main/sdk/org/bdware/client/SmartContractHandler.java b/src/main/sdk/org/bdware/client/SmartContractHandler.java new file mode 100644 index 0000000..601e3b8 --- /dev/null +++ b/src/main/sdk/org/bdware/client/SmartContractHandler.java @@ -0,0 +1,113 @@ +package org.bdware.client; + +import com.google.gson.JsonObject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bdware.client.ws.Action; +import org.bdware.client.ws.Handler; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public abstract class SmartContractHandler implements Handler { + private static final Logger LOGGER = LogManager.getLogger(SmartContractHandler.class); + + private final Map methodMap; + + public SmartContractHandler() { + methodMap = new HashMap<>(); + for (Class clz = this.getClass(); + clz != null && clz != Object.class; + clz = clz.getSuperclass()) { + for (Method m : clz.getDeclaredMethods()) { + String actionName = getActionName(clz, m); + if (actionName != null && !methodMap.containsKey(actionName)) { + m.setAccessible(true); + LOGGER.debug( + String.format( + "addAction: %s %s.%s", + actionName, clz.getCanonicalName(), m.getName())); + methodMap.put(actionName, m); + } + } + } + } + + private String getActionName(Class clz, Method m) { + if (m.getParameterCount() != 1) { + return null; + } + if (m.getParameterTypes()[0] != JsonObject.class) { + return null; + } + Action action = null; + for (Method m2; clz != Object.class && action == null; clz = clz.getSuperclass()) { + try { + m2 = clz.getDeclaredMethod(m.getName(), JsonObject.class); + action = m2.getAnnotation(Action.class); + } catch (Exception e) { + // e.printStackTrace(); + } + } + if (action != null) { + if (action.name().length() > 0) return action.name(); + else return m.getName(); + } + return null; + } + + @Action + public abstract void onListContractProcess(JsonObject obj); + + @Action + public abstract void onOutputStream(JsonObject obj); + + @Action + public abstract void onStartContract(JsonObject obj); + + @Action + public abstract void onKillContractProcess(JsonObject obj); + + @Action + public abstract void onHashResult(JsonObject obj); + + @Action + public abstract void onKillAllContract(JsonObject obj); + + @Action + public abstract void onExecuteResult(JsonObject obj); + + @Action + public abstract void onUndefined(JsonObject obj); + + @Action + public abstract void onSessionID(JsonObject obj); + + @Action + public abstract void onLogin(JsonObject obj); + + @Action + public abstract void onLoadNodeConfig(JsonObject obj); + + @Override + public void handle(JsonObject obj) { + try { +// LOGGER.info("receive:" + obj); + if (!obj.has("action")) { + LOGGER.warn("can't handle message without action: " + obj); + } + String methodName = obj.get("action").getAsString(); + Method method = methodMap.get(methodName); + if (method != null) { + method.invoke(this, obj); + } else { + LOGGER.warn("can't handle action: " + methodName + " -> " + obj); + } + } catch (SecurityException e) { + onUndefined(obj); + } catch (Throwable t) { + t.printStackTrace(); + } + } +} diff --git a/src/main/sdk/org/bdware/client/SmartContractHttpClient.java b/src/main/sdk/org/bdware/client/SmartContractHttpClient.java new file mode 100644 index 0000000..dc1163a --- /dev/null +++ b/src/main/sdk/org/bdware/client/SmartContractHttpClient.java @@ -0,0 +1,156 @@ +package org.bdware.client; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.zz.gmhelper.SM2KeyPair; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + +public class SmartContractHttpClient { + private final SM2KeyPair keyPair; + String ip; + int port; + boolean isPost; + + public SmartContractHttpClient(SM2KeyPair pair, String ip, int port) { + this(pair, ip, port, "GET"); + } + + public SmartContractHttpClient(SM2KeyPair pair, String ip, int port, String method) { + this.ip = ip; + this.port = port; + this.keyPair = pair; + this.isPost = method.toUpperCase().equals("POST"); + } + + public JsonObject executeContract(String id, String operation, String arg) { + ContractRequest cr = new ContractRequest(); + cr.setContractID(id); + cr.setAction(operation); + cr.setArg(arg); + cr.doSignature(keyPair); + String url = getExecuteUrl(ip, port, cr); + String str = (String) httpGet(url).get("response"); + return JsonParser.parseString(str).getAsJsonObject(); + } + + public String executeContractAsString(String id, String operation, String arg) { + ContractRequest cr = new ContractRequest(); + cr.setContractID(id); + cr.setAction(operation); + cr.setArg(arg); + cr.doSignature(keyPair); + if (isPost) { + JsonObject jo = new JsonObject(); + String url = String.format("http://%s:%d/SCIDE/CMManager", ip, port); + jo.addProperty("action", "executeContract"); + jo.addProperty("contractID", cr.getContractID()); + jo.addProperty("operation", cr.getAction()); + jo.addProperty("arg", cr.getArg()); + jo.addProperty("pubkey", cr.getPublicKey()); + jo.addProperty("signature", cr.getSignature()); + String str = (String) httpPost(url, jo.toString()).get("response"); + return str; + } else { + String url = getExecuteUrl(ip, port, cr); + String str = (String) httpGet(url).get("response"); + return str; + } + } + + public static String getExecuteUrl(String ip, int port, ContractRequest cr) { + return String.format( + "http://%s:%d/SCIDE/CMManager?action=executeContract&contractID=%s&operation=%s&arg=%s&pubkey=%s&signature=%s", + ip, + port, + cr.getContractID(), + cr.getAction(), + URLEncoder.encode(cr.getArg()), + cr.getPublicKey(), + cr.signature); + } + + public String getExecuteUrl(String id, String operation, String arg) { + ContractRequest cr = new ContractRequest(); + cr.setContractID(id); + cr.setAction(operation); + cr.setArg(arg); + cr.doSignature(keyPair); + String url = getExecuteUrl(ip, port, cr); + return url; + } + + public static Map httpPost(String str, String body) { + Map ret = new HashMap<>(); + try { + URL url = new URL(str); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setUseCaches(false); + connection.setInstanceFollowRedirects(true); + connection.setRequestMethod("POST"); + + connection.setRequestProperty("Accept", "application/json"); + connection.setRequestProperty("Content-Type", "application/json"); + + connection.connect(); + OutputStreamWriter out = + new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8); + out.append((body)); + out.flush(); + out.close(); + ret.put("responseCode", connection.getResponseCode()); + InputStream input = connection.getInputStream(); + Scanner sc = new Scanner(input); + StringBuilder sb = new StringBuilder(); + while (sc.hasNextLine()) { + sb.append(sc.nextLine()).append("\n"); + } + sc.close(); + ret.put("response", sb.toString()); + } catch (Throwable e) { + ret.put("responseCode", 505); + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + ret.put("response", bo.toString()); + } + return ret; + } + + public static Map httpGet(String str) { + Map ret = new HashMap<>(); + + try { + URL url = new URL(str); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setConnectTimeout(40000); + connection.setReadTimeout(40000); + ret.put("responseCode", connection.getResponseCode()); + InputStream input = connection.getInputStream(); + Scanner sc = new Scanner(input); + StringBuilder sb = new StringBuilder(); + while (sc.hasNextLine()) { + sb.append(sc.nextLine()).append("\n"); + } + sc.close(); + ret.put("response", sb.toString()); + } catch (Throwable e) { + ret.put("responseCode", 505); + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bo)); + ret.put("response", bo.toString()); + } + return ret; + } +} diff --git a/src/main/sdk/org/bdware/client/ws/Action.java b/src/main/sdk/org/bdware/client/ws/Action.java new file mode 100644 index 0000000..1f428b4 --- /dev/null +++ b/src/main/sdk/org/bdware/client/ws/Action.java @@ -0,0 +1,12 @@ +package org.bdware.client.ws; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Action { + String name() default ""; +} \ No newline at end of file diff --git a/src/main/sdk/org/bdware/client/ws/BaseClient.java b/src/main/sdk/org/bdware/client/ws/BaseClient.java new file mode 100644 index 0000000..d9dd5ab --- /dev/null +++ b/src/main/sdk/org/bdware/client/ws/BaseClient.java @@ -0,0 +1,52 @@ +package org.bdware.client.ws; + +import java.io.IOException; + +import javax.websocket.CloseReason; +import javax.websocket.Endpoint; +import javax.websocket.EndpointConfig; +import javax.websocket.Session; + +public class BaseClient extends Endpoint { + private Session session; + private boolean isConnected; + private WSHandler handler; + + public BaseClient(Handler client) { + isConnected = false; + handler = new WSHandler(client); + } + + @Override + public void onOpen(Session session, EndpointConfig config) { + this.session = session; + // session.getBasicRemote().sendText("Session ID: " + this.session.getId()); + session.addMessageHandler(handler); + isConnected = true; + } + + @Override + public void onClose(Session session, CloseReason config) { + this.session = null; + isConnected = false; + } + + @Override + public void onError(Session session, Throwable config) { + this.session = null; + isConnected = false; + } + + public void sendText(String text) { + try { + this.session.getBasicRemote().sendText(text); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public boolean connected() { + return isConnected; + } + +} diff --git a/src/main/sdk/org/bdware/client/ws/Handler.java b/src/main/sdk/org/bdware/client/ws/Handler.java new file mode 100644 index 0000000..3e7aa64 --- /dev/null +++ b/src/main/sdk/org/bdware/client/ws/Handler.java @@ -0,0 +1,7 @@ +package org.bdware.client.ws; + +import com.google.gson.JsonObject; + +public interface Handler { + public void handle(JsonObject obj); +} \ No newline at end of file diff --git a/src/main/sdk/org/bdware/client/ws/ResponseAction.java b/src/main/sdk/org/bdware/client/ws/ResponseAction.java new file mode 100644 index 0000000..98e2d19 --- /dev/null +++ b/src/main/sdk/org/bdware/client/ws/ResponseAction.java @@ -0,0 +1,5 @@ +package org.bdware.client.ws; + +public enum ResponseAction { + +} diff --git a/src/main/sdk/org/bdware/client/ws/WSHandler.java b/src/main/sdk/org/bdware/client/ws/WSHandler.java new file mode 100644 index 0000000..4db0c20 --- /dev/null +++ b/src/main/sdk/org/bdware/client/ws/WSHandler.java @@ -0,0 +1,30 @@ +package org.bdware.client.ws; + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; + +import javax.websocket.MessageHandler; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +public class WSHandler implements MessageHandler.Whole { + LinkedList receivedMsg = new LinkedList<>(); + LinkedHashMap> waitList; + Handler h; + + public WSHandler(Handler h) { + this.h = h; + } + + @Override + public void onMessage(String arg0) { + synchronized (receivedMsg) { + JsonObject json = new JsonParser().parse(arg0).getAsJsonObject(); + // System.out.println("[WSHandler] onMessage:" + arg0); + if (h != null) + h.handle(json); + } + } +} \ No newline at end of file diff --git a/src/test/java/org/bdware/client/test/EventClientTest.java b/src/test/java/org/bdware/client/test/EventClientTest.java new file mode 100644 index 0000000..7ce9fc6 --- /dev/null +++ b/src/test/java/org/bdware/client/test/EventClientTest.java @@ -0,0 +1,33 @@ +package org.bdware.client.test; + +import org.bdware.client.EventSubscriberClient; + +import java.util.Scanner; + +public class EventClientTest { + public static EventSubscriberClient getTestClient() { + return new EventSubscriberClient("ws://162.105.175.243:1718/SCIDE/NodeCenter"); + } + + public static void main(String[] args) { + + EventSubscriberClient testClient = getTestClient(); + System.out.println("WaitForConnect"); + testClient.waitForConnect(); + + testClient.subscribeEvent( + "04889daf457aae33f382d3d7688f154a1ffdd057b660e626314f46fd6864c3162bf941b25abe98dd9d7df4d44e31570a15166883271b0c901931db82f714aeeebf", + "BDCoinAt162", + "Transfer"); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Scanner sc = new Scanner(System.in); + for (; ; ) { + String cmd = sc.nextLine(); + System.out.println("Wait for event"); + } + } +} diff --git a/src/test/java/org/bdware/client/test/SM2Test.java b/src/test/java/org/bdware/client/test/SM2Test.java new file mode 100644 index 0000000..18540fc --- /dev/null +++ b/src/test/java/org/bdware/client/test/SM2Test.java @@ -0,0 +1,132 @@ +package org.bdware.client.test; + +import org.bouncycastle.crypto.CryptoException; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.junit.Test; +import org.zz.gmhelper.BCECUtil; +import org.zz.gmhelper.SM2KeyPair; +import org.zz.gmhelper.SM2Util; + +import java.security.SecureRandom; +import java.util.Random; + +public class SM2Test { + public static String strSign = "helloworld"; + + private static byte[] str2Byte(String str) { + byte[] ret = new byte[str.length() / 2]; + for (int i = 0; i < str.length() / 2; i++) { + int val = (char2Int(str.charAt(i * 2)) << 4) + (char2Int(str.charAt(i * 2 + 1))); + ret[i] = (byte) (val & 0xff); + } + // TODO Auto-generated method stub + return ret; + } + + private static int char2Int(char c) { + int ret = c; + if (c >= 'a' && c <= 'f') { + ret = '0' + 10 + c - 'a'; + } + ret = ret - '0'; + if (ret >= 0 && ret < 16) { + return ret; + } else + throw new IllegalArgumentException( + "the input should be 0-9 and a-f, but received " + c); + } + + private static String bytes2Str(byte[] result) { + StringBuilder sb = new StringBuilder(); + for (byte b : result) { + sb.append(String.format("%x%x", (b >> 4) & 0xf, b & 0xf)); + } + return sb.toString(); + } + + @Test + public void generateKeyPair() { + SM2KeyPair pair = SM2Util.generateSM2KeyPair(); + System.out.println("[KeyPair] " + pair.toJson()); + } + + @Test + public void loadKeyAndDoSignature() { + try { + String keyStr = + "{\"publicKey\":\"04bbc40ff490a71a1fe2e8d76b49dd73ef3b19fd90b5cf2fc4a9b2f02bdb3c55a58f32ded81c508fc894dac32e0afe5703879c059ed2e6999f17d5a4172549f0b4\",\"privateKey\":\"cc62de3037d0944854c6f3fabea078b1e92c5c2404f5421e929827a481ac4cc5\"}"; + SM2KeyPair pair = SM2KeyPair.fromJson(keyStr); + String signature = + ByteUtils.toHexString( + SM2Util.sign(pair.getPrivateKeyParameter(), strSign.getBytes())); + System.out.println("[Signature]" + signature); + + } catch (CryptoException e) { + e.printStackTrace(); + } + } + + @Test + public void verifySignature() { + String signature = + "3046022100ced6cab1c3f93b8768f14a5f69d493ba54619221375897613b6182dfd0fe2a6b02210091454953b42d8c5e07d2552b5d02c6df04d35c5c09703df41d7043953c38f71b"; + String pubKeyStr = + "04bbc40ff490a71a1fe2e8d76b49dd73ef3b19fd90b5cf2fc4a9b2f02bdb3c55a58f32ded81c508fc894dac32e0afe5703879c059ed2e6999f17d5a4172549f0b4"; + ECPublicKeyParameters pubKey = + BCECUtil.createECPublicKeyFromStrParameters( + pubKeyStr, SM2Util.CURVE, SM2Util.DOMAIN_PARAMS); + boolean b = SM2Util.plainStrVerify(pubKeyStr, strSign, signature); + System.out.println("[verifySignature] verify result:" + b); + } + + String randStr(int len) { + StringBuilder sb = new StringBuilder(); + Random r = new SecureRandom(); + for (int i = 0; i < len; i++) { + sb.append(Math.abs(r.nextInt() % 10)); + } + return sb.toString(); + } + + @Test + public void encrypt() { + String plain = randStr(20); + String key = + "{\"privateKey\":\"e45f3a594862ae71ffff827853eda0096bf643e5975224f2e2166507e70af444\",\"publicKey\":\"04337f32fe57b0f1b6f6fd729f98aad9c816770bcca1173857df337c4c8c4f96508d69f9a46f81cb429079a9b82b6232aca286b6bfe6bafb358dc4245cfdeb070e\"}"; + SM2KeyPair pair = SM2KeyPair.fromJson(key); + try { + byte[] encrypted = SM2Util.encrypt(pair.getPublicKey(), plain.getBytes()); + System.out.println("encryped:" + bytes2Str(encrypted)); + String origin = new String(SM2Util.decrypt(pair.getPrivateKeyParameter(), encrypted)); + System.out.println("decrypted:" + origin); + assert origin.equals(plain); + } catch (InvalidCipherTextException e) { + e.printStackTrace(); + } + } + + @Test + public void decryptFromJS() throws Exception { + String key = + "{\"privateKey\":\"e45f3a594862ae71ffff827853eda0096bf643e5975224f2e2166507e70af444\",\"publicKey\":\"04337f32fe57b0f1b6f6fd729f98aad9c816770bcca1173857df337c4c8c4f96508d69f9a46f81cb429079a9b82b6232aca286b6bfe6bafb358dc4245cfdeb070e\"}"; + SM2KeyPair pair = SM2KeyPair.fromJson(key); + String encrypted = + "fa68b741a21e5cb63e9bffab8e1bfa8af6b89172fa0b656c2e557df6dac5858a7a0f47273a1d457421f76510d872db9f0a3e7bd1f294c3fe0e8e524f6bf4957f3a930c2c83980593cb3875421e03116adb4c6106522d0c366affd430b8371fbc6818a7"; + String str = + new String( + org.zz.gmhelper.SM2Util.decrypt( + pair.getPrivateKeyParameter(), ByteUtils.fromHexString(encrypted))); + System.out.println(str); + } + + @Test + public void importPubkey() { + String pubKeyStr = + "04bbc40ff490a71a1fe2e8d76b49dd73ef3b19fd90b5cf2fc4a9b2f02bdb3c55a58f32ded81c508fc894dac32e0afe5703879c059ed2e6999f17d5a4172549f0b4"; + byte[] pubKeyBytes = str2Byte(pubKeyStr); + ECPoint pubKey = SM2KeyPair.publicKeyStr2ECPoint(pubKeyStr).getQ(); + } +} diff --git a/src/test/java/org/bdware/client/test/SmartClientTest.java b/src/test/java/org/bdware/client/test/SmartClientTest.java new file mode 100644 index 0000000..f8aa3e8 --- /dev/null +++ b/src/test/java/org/bdware/client/test/SmartClientTest.java @@ -0,0 +1,82 @@ +package org.bdware.client.test; + +import com.google.gson.JsonObject; +import org.bdware.client.ContractRequest; +import org.bdware.client.ResultCallback; +import org.bdware.client.SmartContractClient; +import org.bdware.client.ws.Action; +import org.junit.BeforeClass; +import org.junit.Test; + +public class SmartClientTest { + + private static SmartContractClient testClient = getTestClient(); + static boolean isLogin = false; + + public static SmartContractClient getTestClient() { + return new SmartContractClient("ws://022.node.internetapi.cn:21030/SCIDE/SCExecutor") { + @Override + public void onLogin(JsonObject jo) { + isLogin = true; + System.out.println("[SmartClientTest] --> login:" + jo.toString()); + } + // !!!!!Important!!!! + // if you want to handle onXXX message, just use @Action annotation + // there are more onXXX actions described in + // https://public.internetapi.cn/docs/bdcontract/doc/ContractAPI.html#id194 + @Action + public void onHashResult(JsonObject jo) { + System.out.println("[SmartClientTest] --> onHashResult:" + jo.toString()); + } + }; + } + + @BeforeClass + public static void connect() { + System.out.println("WaitForConnect"); + testClient.waitForConnect(); + testClient.login(); + for (; !isLogin; ) Thread.yield(); + testClient.listContractProcess(); + System.out.println("Connected!"); + } + + @Test + public void executeContractSync() throws InterruptedException { + ContractRequest cr = new ContractRequest(); + cr.setContractID("ScoreCollector"); + cr.setAction("getAllScore"); + // use the sm2keypair of the connection to do sign automatically by default. + // can use cr.doSignature(...); to sign in other sm2keypairs + JsonObject result = testClient.executeContractSync(cr); + System.out.println(result.toString()); + Thread.sleep(3000); + } + + @Test + public void executeContractAsync() { + ContractRequest cr = new ContractRequest(); + cr.setContractID("ScoreCollector"); + cr.setAction("getAllScore"); + testClient.executeContract( + cr, + new ResultCallback() { + @Override + public void onResult(JsonObject r) { + System.out.println("[Async] --> " + r.toString()); + synchronized (cr) { + cr.notify(); + } + } + }); + synchronized (cr) { + try { + cr.wait(); + Thread.sleep(10000); + + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/test/java/org/bdware/client/test/SmartContractHttpClientTest.java b/src/test/java/org/bdware/client/test/SmartContractHttpClientTest.java new file mode 100644 index 0000000..c09e6e6 --- /dev/null +++ b/src/test/java/org/bdware/client/test/SmartContractHttpClientTest.java @@ -0,0 +1,227 @@ +package org.bdware.client.test; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.bdware.client.ContractRequest; +import org.bdware.client.SmartContractClient; +import org.bdware.client.SmartContractHttpClient; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.bouncycastle.util.encoders.Base64; +import org.junit.Test; +import org.zz.gmhelper.SM2KeyPair; +import org.zz.gmhelper.SM2Util; + +import java.net.URLEncoder; +import java.security.SecureRandom; +import java.util.Random; + +public class SmartContractHttpClientTest { + @Test + public void test() { + SmartContractHttpClient client = + new SmartContractHttpClient( + SM2KeyPair.fromJson( + "{\"privateKey\":\"589d94ee5688358a1c5c18430dd9c75097ddddebf769f139da36a807911d20f8\",\"publicKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}"), + "47.99.93.24", + 21030); + System.out.println(client.executeContractAsString("AccessControlManager", "getGlobal", "")); + } + + @Test + public void test2() throws Exception { + SmartContractHttpClient client = + new SmartContractHttpClient( + SM2KeyPair.fromJson( + "{\"privateKey\":\"f42040dc542124b07f00e7f89591a671526cb64037d5bae2799c143cec19a28d\",\"publicKey\":\"0408187c054e81d79d12f67cccdfb3d2cbafe077a81869f23b63cd8ab03db1bbf72ec4ef12d50c4e2fa08b96470556d2a34f6e5982731f303aca39094906c26f0a\"}"), + "021.node.internetapi.cn", + 21030); + String pubkey = + "047ff4ec3f6b1d70e1435c2e129884f8e8af412b76a187b0a1a7fb406f0c0800d625f9e0b2b9881c8e2298db06c197d66820136f552c555b0ddbdf4603ded55c7d"; + String data = "11112121122fddtoEncrypedDaddtaaaadaaa"; + String encryped = + ByteUtils.toHexString( + SM2Util.encrypt(SM2KeyPair.publicKeyStr2ECPoint(pubkey), data.getBytes())); + System.out.println( + client.getExecuteUrl("TrustedStorage", "encryptedTextTransmission", encryped)); + System.out.println( + client.executeContractAsString( + "TrustedStorage", "encryptedTextTransmission", encryped)); + } + + String randStr(int len) { + StringBuilder sb = new StringBuilder(); + Random r = new SecureRandom(); + for (int i = 0; i < len; i++) sb.append(Math.abs(r.nextInt() % 10)); + return sb.toString(); + } + + @Test + public void largeGetAndPost() throws Exception { + String keyPair = + "{\"privateKey\":\"589d94ee5688358a1c5c18430dd9c75097ddddebf769f139da36a807911d20f8\",\"publicKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}"; + SmartContractHttpClient client = + new SmartContractHttpClient( + SM2KeyPair.fromJson(keyPair), "127.0.0.1", 18000, "POST"); + // + // "{\"privateKey\":\"f42040dc542124b07f00e7f89591a671526cb64037d5bae2799c143cec19a28d\",\"publicKey\":\"0408187c054e81d79d12f67cccdfb3d2cbafe077a81869f23b63cd8ab03db1bbf72ec4ef12d50c4e2fa08b96470556d2a34f6e5982731f303aca39094906c26f0a\"}"), + // "021.node.internetapi.cn", + // 21030); + String pubkey = + "047ff4ec3f6b1d70e1435c2e129884f8e8af412b76a187b0a1a7fb406f0c0800d625f9e0b2b9881c8e2298db06c197d66820136f552c555b0ddbdf4603ded55c7d"; + String data = randStr(9 * 1024 * 1024); + // String encryped = + // ByteUtils.toHexString( + // SM2Util.encrypt(SM2KeyPair.publicKeyStr2ECPoint(pubkey), data.getBytes())); + // System.out.println( + // client.getExecuteUrl("Hello", "encryptedTextTransmission", data)); + System.out.println( + client.executeContractAsString("Hello", "encryptedTextTransmission", data)); + } + + public byte[] randByte(int len) { + byte[] ret = new byte[len]; + Random r = new SecureRandom(); + r.nextBytes(ret); + return ret; + } + @Test + public void encryptTrans2() throws Exception { + //初始化客户端,用户传入自己的sm2密钥对。 使用"POST"方式可以传输3MB大小的内容。 + SmartContractHttpClient client = + new SmartContractHttpClient( + SM2KeyPair.fromJson( + "{\"privateKey\":\"f42040dc542124b07f00e7f89591a671526cb64037d5bae2799c143cec19a28d\",\"publicKey\":\"0408187c054e81d79d12f67cccdfb3d2cbafe077a81869f23b63cd8ab03db1bbf72ec4ef12d50c4e2fa08b96470556d2a34f6e5982731f303aca39094906c26f0a\"}"), + "023.node.internetapi.cn", + 21030,"POST"); + + //--------示例1 传输加密上链 + //使用本合约的公钥。也可直接保存下来。 + String pubkey = + "04786622f5a3fcc5c811ea34f19e81f05945f689bb6e5ecec2581cf6d16b4360c1eb3439fdc0620d14f3f2814be1cb39b5e408d345952305d9953563b16d0a53a3"; + //String pubKey = JsonParser.parseString(client.executeContractAsString("TrustedStorage", "getPubkey", "")) + // .getAsJsonObject() + // .get("result") + // .getAsString(); + String data = "汉字123abc"; + //计算加密数据 + String encryped = + ByteUtils.toHexString( + //publickeyStr2ECPoint + SM2Util.encrypt(SM2KeyPair.publicKeyStr2ECPoint(pubkey), data.getBytes())); + //获取上链的链接 + System.out.println(client.getExecuteUrl("TrustedPlain0923", "encryptedTextTransmission", encryped)); + System.out.println( + client.executeContractAsString("TrustedPlain0923", "encryptedTextTransmission", encryped)); + //------示例2 明文传输上链 + // System.out.println( + // client.executeContractAsString("TrustedPlain0923", "plainTextTransmission", data)); + //------示例3 查询链上哈希值 + String hash="7f57c634be867ab79bb81926354c007aad4c312a"; + System.out.println( + client.executeContractAsString("TrustedPlain0923", "queryByHash", hash)); + } + + + @Test + public void encryptTrans() throws Exception { + //初始化客户端,用户传入自己的sm2密钥对。 使用"POST"方式可以传输3MB大小的内容。 + SmartContractHttpClient client = + new SmartContractHttpClient( + SM2KeyPair.fromJson( + "{\"privateKey\":\"f42040dc542124b07f00e7f89591a671526cb64037d5bae2799c143cec19a28d\",\"publicKey\":\"0408187c054e81d79d12f67cccdfb3d2cbafe077a81869f23b63cd8ab03db1bbf72ec4ef12d50c4e2fa08b96470556d2a34f6e5982731f303aca39094906c26f0a\"}"), + "023.node.internetapi.cn", + 21030,"POST"); + + //--------示例1 传输加密上链 + //使用本合约的公钥。也可直接保存下来。 + String pubkey = + "045c9ae29614371378206399242fc051a8599ac10d43ae51e051d698a1e14bc6f0c3b79e602865a370066d990038c14f029ae6fbc13c272ac43d19108674299dbc"; + //String pubKey = JsonParser.parseString(client.executeContractAsString("TrustedStorage", "getPubkey", "")) + // .getAsJsonObject() + // .get("result") + // .getAsString(); + String data = "汉字123abc"; + //计算加密数据 + String encryped = + ByteUtils.toHexString( + SM2Util.encrypt(SM2KeyPair.publicKeyStr2ECPoint(pubkey), data.getBytes())); + //获取上链的链接 + System.out.println(client.getExecuteUrl("TrustedStorage0707", "encryptedTextTransmission", encryped)); + // System.out.println( + // client.executeContractAsString("TrustedStorage0707", "encryptedTextTransmission", encryped)); + //------示例2 明文传输上链 + // System.out.println( + // client.executeContractAsString("TrustedStorage0707", "plainTextTransmission", data)); + //------示例3 查询链上哈希值 + String hash="fa2d81311e45c6ed238bcd935f3391a2ca8c8c53"; + System.out.println( + client.executeContractAsString("TrustedStorage0707", "queryByHash", hash)); + } + + @Test + public void getPublicKey() throws Exception { + SmartContractHttpClient client = + new SmartContractHttpClient( + SM2KeyPair.fromJson( + "{\"privateKey\":\"f42040dc542124b07f00e7f89591a671526cb64037d5bae2799c143cec19a28d\",\"publicKey\":\"0408187c054e81d79d12f67cccdfb3d2cbafe077a81869f23b63cd8ab03db1bbf72ec4ef12d50c4e2fa08b96470556d2a34f6e5982731f303aca39094906c26f0a\"}"), + "021.node.internetapi.cn", + 21030); + System.out.println(client.getExecuteUrl("TrustedStorage", "getPubkey", "")); + String pubKey = + JsonParser.parseString( + client.executeContractAsString("TrustedStorage", "getPubkey", "")) + .getAsJsonObject() + .get("result") + .getAsString(); + System.out.println(pubKey); + } + + @Test + public void queryData() { + String hash = "6f9a2f0b76a9e6142fdcccea544f5e3883db73d7"; + hash = URLEncoder.encode(new String(Base64.encode((ByteUtils.fromHexString(hash))))); + String url = + String.format( + "http://021.node.internetapi.cn:21121/v0/ledgers/default/transaction?hash=%s", + hash); + System.out.println(url); + } + + @Test + public void hex2Str() { + System.out.println( + new String( + ByteUtils.fromHexString( + "0473e0276bfc6260ff89842c552d44b976677c46bb2abd377349c23f85cef3326efa4bc0e56f18a50e40bee9e3fedd2a34b8a1757d77717a71ea718529485df18f2b38a636f25fe18e464983bc786736e4d2a67822fe87ee29dff4c3d54cf0f2ac74dbad92f72863008b90631db358c1b504435a4b92ab85de8a97c5a7f6fcf785dd2ad0fc97d92c170293772d3a5c21b5fae25cf8de8382a5464684d5037d1366acdbb498114f9f220ecd6907ccecd8a32fee766054ebd2bd72568faabe92d8947104b34a892fd5cc5f679049eb6aa8cc6ca55387c82f2d71b1044a58269202693168a1fb1745b12e484752131d60f592da1791a3239789136f42afbc948798b2387f0de40dc14f7b8dacd70e4f73998707cf591489e85de1cfc6f95c8ae71131fd757b26c18b75ff0d6cdd8d851bab68c8fda315283d2b653024007079cd40779d4b559475c0db67b1eb5b27c467c1c0033a5e433fc763ce73bf1268927f1dcd891386db3abcbfb824df66ed"))); + } + + @Test + public void test3() throws Exception { + SmartContractHttpClient client = + new SmartContractHttpClient( + SM2KeyPair.fromJson( + "{\"privateKey\":\"589d94ee5688358a1c5c18430dd9c75097ddddebf769f139da36a807911d20f8\",\"publicKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}"), + "59.110.125.211", + 21030); + System.out.println(client.getExecuteUrl("AccessControlManager", "search", "玉")); + System.out.println(client.executeContractAsString("AccessControlManager", "search", "玉")); + } + + @Test + public void testExecuteSync() { + SM2KeyPair keyPair = + SM2KeyPair.fromJson( + "{\"privateKey\":\"589d94ee5688358a1c5c18430dd9c75097ddddebf769f139da36a807911d20f8\",\"publicKey\":\"04d1924329f72ced148f6f333fb985ccbaa31b1e3aacf10be5f43d4a4ff5ad88899a005e79e37fc06993e1d66ada8cf8b711cb36f59538bb7d3e39e70fa9360ddd\"}"); + + SmartContractClient client = + new SmartContractClient("ws://127.0.0.1:18000/SCIDE/SCExecutor", keyPair); + client.waitForConnect(); + client.login(); + ContractRequest cr = new ContractRequest(); + cr.setContractID("AccessControlManager"); + cr.setAction("getRequester"); + cr.setArg("玉"); + JsonObject json = client.executeContractSync(cr); + System.out.println(json.toString()); + } +} diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties new file mode 100644 index 0000000..f0372d8 --- /dev/null +++ b/src/test/resources/log4j.properties @@ -0,0 +1,7 @@ +### 设置### +log4j.rootLogger=debug,info,stdout +### 输出信息到控制台 ### +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %m (%F:%L)[%M]%n \ No newline at end of file