All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bdware.client.SmartContractClient Maven / Gradle / Ivy

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 (null == cr.getArg()) {
            req.put("arg", "undefined");
        } else {
            if (cr.getArg().isJsonPrimitive())
                req.put("arg", cr.getArg().getAsString());
            else
                req.put("arg", cr.getArg().toString());
        }
        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);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy