From 56a07ca17681ef7db8e3b9c7e9e3273d458e1a70 Mon Sep 17 00:00:00 2001 From: jayTseng Date: Thu, 6 Sep 2018 17:24:15 -0400 Subject: [PATCH 01/16] zmq secure connection implement --- modAionImpl/build.xml | 2 + .../src/org/aion/zero/impl/cli/Cli.java | 73 ++++++++++++++++++- .../api/server/zmq/ProtocolProcessor.java | 9 +++ modMcf/src/org/aion/mcf/config/CfgApiZmq.java | 17 ++++- 4 files changed, 98 insertions(+), 3 deletions(-) diff --git a/modAionImpl/build.xml b/modAionImpl/build.xml index 00542522a1..c056d95280 100644 --- a/modAionImpl/build.xml +++ b/modAionImpl/build.xml @@ -167,6 +167,8 @@ + + diff --git a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java index 037f144f19..f39c6fed11 100644 --- a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java +++ b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java @@ -24,25 +24,45 @@ package org.aion.zero.impl.cli; +import static org.aion.mcf.account.Keystore.exist; + import java.io.BufferedReader; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.lang.ProcessBuilder.Redirect; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.List; +import java.util.Set; +import java.util.TimeZone; +import javax.annotation.Nonnull; +import org.aion.base.util.ByteUtil; import org.aion.base.util.Hex; +import org.aion.base.util.TypeConverter; import org.aion.crypto.ECKey; import org.aion.crypto.ECKeyFac; import org.aion.mcf.account.Keystore; +import org.aion.mcf.account.KeystoreFormat; import org.aion.mcf.config.Cfg; +import org.aion.mcf.config.CfgApiZmq; import org.aion.mcf.config.CfgSsl; import org.aion.zero.impl.Version; import org.aion.zero.impl.db.RecoveryUtils; import java.io.Console; import java.util.UUID; +import org.zeromq.ZMQ; /** * Command line interface. @@ -51,9 +71,12 @@ */ public class Cli { - File keystoreDir = new File( + private File keystoreDir = new File( System.getProperty("user.dir") + File.separator + CfgSsl.SSL_KEYSTORE_DIR); + private File zmqkeyDir = new File( + System.getProperty("user.dir") + File.separator + CfgApiZmq.ZMQ_KEY_DIR); + public int call(final String[] args, final Cfg cfg) { try { cfg.fromXML(); @@ -139,6 +162,12 @@ public int call(final String[] args, final Cfg cfg) { return 1; } break; + case "-zs": + checkZmqKeystoreDir(); + ZMQ.Curve.KeyPair kp = ZMQ.Curve.generateKeyPair(); + genKeyFile(kp.publicKey, kp.secretKey); + System.out.println("genZmqKeyPairFinished!"); + return 1; case "-r": if (args.length < 2) { System.out.println("Starting database clean-up."); @@ -269,6 +298,46 @@ public int call(final String[] args, final Cfg cfg) { return 0; } + private void genKeyFile(@Nonnull final String publicKey, @Nonnull final String secretKey) + throws IOException { + + DateFormat df = new SimpleDateFormat("yy-MM-dd'T'HH:mm:ss'Z'"); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + String iso_date = df.format(new Date(System.currentTimeMillis())); + + String fileName = "UTC--" + iso_date + "--zmqCurvePubkey"; + getFile(fileName, publicKey); + + fileName = "UTC--" + iso_date + "--zmqCurveSeckey"; + getFile(fileName, secretKey); + } + + private void getFile(@Nonnull final String fileName, @Nonnull final String key) throws IOException { + Set perms = PosixFilePermissions.fromString("rwxr-----"); + FileAttribute> attr = PosixFilePermissions.asFileAttribute(perms); + + Path p = Paths.get(zmqkeyDir.getPath()); + Path keyFile = p.resolve(fileName); + if (!Files.exists(keyFile)) { + keyFile = Files.createFile(keyFile, attr); + } + + FileOutputStream fos = new FileOutputStream(keyFile.toString()); + fos.write(key.getBytes()); + fos.close(); + } + + private void checkZmqKeystoreDir() { + if (!zmqkeyDir.isDirectory()) { + if (!zmqkeyDir.mkdir()) { + System.out.println("zmq keystore directory could not be created. " + + "Please check user permissions or create directory manually."); + System.exit(1); + } + System.out.println(); + } + } + /** * Print the CLI help info. */ @@ -353,7 +422,7 @@ private boolean listAccounts() { * @return boolean */ private boolean exportPrivateKey(String address) { - if (!Keystore.exist(address)) { + if (!exist(address)) { System.out.println("The account does not exist!"); return false; } diff --git a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java index ff0338b7bf..c2b515903e 100644 --- a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java +++ b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java @@ -90,6 +90,15 @@ public void run() { // create router sock. Socket feSock = ctx.socket(ROUTER); + if (cfgApi.isSecureConnectEnabledEnabled()) { + feSock.setZAPDomain("global".getBytes()); + feSock.setCurveServer(true); + + } + + + + feSock.setSndHWM(zmqHWM); feSock.bind(bindAddr); diff --git a/modMcf/src/org/aion/mcf/config/CfgApiZmq.java b/modMcf/src/org/aion/mcf/config/CfgApiZmq.java index b86bdfe93c..34fd79264b 100644 --- a/modMcf/src/org/aion/mcf/config/CfgApiZmq.java +++ b/modMcf/src/org/aion/mcf/config/CfgApiZmq.java @@ -38,12 +38,15 @@ public class CfgApiZmq { + public static final String ZMQ_KEY_DIR = "zmq_keystore"; + CfgApiZmq() { this.active = true; this.ip = "127.0.0.1"; this.port = 8547; this.filtersEnabled = true; this.blockSummaryCacheEnabled = false; + this.secureConnectEnabled = false; } protected boolean active; @@ -51,6 +54,7 @@ public class CfgApiZmq { protected int port; protected boolean filtersEnabled; protected boolean blockSummaryCacheEnabled; + protected boolean secureConnectEnabled; public void fromXML(final XMLStreamReader sr) throws XMLStreamException { this.active = Boolean.parseBoolean(sr.getAttributeValue(null, "active")); @@ -81,6 +85,14 @@ public void fromXML(final XMLStreamReader sr) throws XMLStreamException { //e.printStackTrace(); } break; + case "secure-connect": + try { + secureConnectEnabled = Boolean.parseBoolean(Cfg.readValue(sr)); + } catch (Exception e) { + //System.out.println("failed to read config node: aion.api.rpc.filters-enabled; using preset: " + this.filtersEnabled); + //e.printStackTrace(); + } + break; default: Cfg.skipElement(sr); break; @@ -135,6 +147,8 @@ public int getPort() { } public boolean isFiltersEnabled() { return this.filtersEnabled; } public boolean isBlockSummaryCacheEnabled() { return this.blockSummaryCacheEnabled; } + public boolean isSecureConnectEnabledEnabled() { return this.secureConnectEnabled; } + @Override public boolean equals(Object o) { @@ -145,11 +159,12 @@ public boolean equals(Object o) { port == cfgApiZmq.port && filtersEnabled == cfgApiZmq.filtersEnabled && blockSummaryCacheEnabled == cfgApiZmq.blockSummaryCacheEnabled && + secureConnectEnabled == cfgApiZmq.secureConnectEnabled && Objects.equal(ip, cfgApiZmq.ip); } @Override public int hashCode() { - return Objects.hashCode(active, ip, port, filtersEnabled, blockSummaryCacheEnabled); + return Objects.hashCode(active, ip, port, filtersEnabled, blockSummaryCacheEnabled, secureConnectEnabled); } } From 49c46a7e66d962521f34288886ea3179e99162d5 Mon Sep 17 00:00:00 2001 From: jayTseng Date: Thu, 6 Sep 2018 18:13:55 -0400 Subject: [PATCH 02/16] implement the curve key loading in the zmq ProtocolProcessor --- .../src/org/aion/zero/impl/cli/Cli.java | 2 +- .../api/server/zmq/ProtocolProcessor.java | 107 ++++++++++++++---- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java index f39c6fed11..284b0b7161 100644 --- a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java +++ b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java @@ -166,7 +166,7 @@ public int call(final String[] args, final Cfg cfg) { checkZmqKeystoreDir(); ZMQ.Curve.KeyPair kp = ZMQ.Curve.generateKeyPair(); genKeyFile(kp.publicKey, kp.secretKey); - System.out.println("genZmqKeyPairFinished!"); + System.out.println("Generate ZmqKeyPairFinished!"); return 1; case "-r": if (args.length < 2) { diff --git a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java index c2b515903e..e23d371f5a 100644 --- a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java +++ b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java @@ -27,8 +27,15 @@ import static org.zeromq.ZMQ.DEALER; import static org.zeromq.ZMQ.ROUTER; +import java.io.File; +import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; @@ -44,6 +51,7 @@ import org.aion.base.util.Hex; import org.aion.log.AionLoggerFactory; import org.aion.log.LogEnum; +import org.aion.mcf.account.KeystoreFormat; import org.aion.mcf.config.CfgApiZmq; import org.slf4j.Logger; import org.zeromq.ZMQ; @@ -53,24 +61,41 @@ public class ProtocolProcessor implements Runnable { protected static final Logger LOG = AionLoggerFactory.getLogger(LogEnum.API.name()); - private final IHdlr handler; private static final String AION_ZMQ_WK_TH = "inproc://aionZmqWkTh"; private static final String AION_ZMQ_CB_TH = "inproc://aionZmqCbTh"; private static final String AION_ZMQ_EV_TH = "inproc://aionZmqEvTh"; private static final String AION_ZMQ_HB_TH = "inproc://aionZmqHbTh"; - - private CfgApiZmq cfgApi; - private AtomicBoolean shutDown = new AtomicBoolean(); - + private static final String CURVEKEY_PATH; + private static final Path PATH; private static final long zmqHWM = 100_000; private static final int SOCKETID_LEN = 5; private static final int SOCKET_RECV_TIMEOUT = 3000; + static { + String storageDir = System.getProperty("local.storage.dir"); + if (storageDir == null || storageDir.equalsIgnoreCase("")) { + storageDir = System.getProperty("user.dir"); + } + CURVEKEY_PATH = storageDir + "/" + CfgApiZmq.ZMQ_KEY_DIR; + PATH = Paths.get(CURVEKEY_PATH); + } + + private final IHdlr handler; + private CfgApiZmq cfgApi; + private AtomicBoolean shutDown = new AtomicBoolean(); + private byte[] curvePubKey; + private byte[] curveSecKey; + public ProtocolProcessor(IHdlr _handler, final CfgApiZmq cfg) { this.handler = _handler; this.cfgApi = cfg; } + private static List getFiles() { + File[] files = PATH.toFile().listFiles(); + return files != null ? Arrays.asList(files) : Collections.emptyList(); + } + public void shutdown() throws InterruptedException { handler.shutDown(); shutDown.set(true); @@ -91,14 +116,22 @@ public void run() { // create router sock. Socket feSock = ctx.socket(ROUTER); if (cfgApi.isSecureConnectEnabledEnabled()) { - feSock.setZAPDomain("global".getBytes()); - feSock.setCurveServer(true); - + // Currently the system will only load the first pair of the key files. + loadCurveKeyPair(); + + if (curveSecKey != null && curvePubKey != null) { + feSock.setZAPDomain("global".getBytes()); + feSock.setCurveServer(true); + feSock.setCurvePublicKey(curvePubKey); + feSock.setCurveSecretKey(curveSecKey); + LOG.info("Secure connection enabled!"); + } else { + LOG.info("Secure connection disabled!"); + } + } else { + LOG.info("Secure connection disabled!"); } - - - feSock.setSndHWM(zmqHWM); feSock.bind(bindAddr); @@ -153,6 +186,28 @@ public void run() { } } + private void loadCurveKeyPair() { + List files = getFiles(); + String nextLoad = ""; + for (File f : files) { + if (f.getName().contains("zmqCurvePubkey")) { + try { + curvePubKey = Files.readAllBytes(f.toPath()); + nextLoad = f.getName().replace("zmqCurvePubkey", "zmqCurveSeckey"); + } catch (IOException e) { + LOG.error("Get zmqCurvePubkey exception! {}", e.toString()); + } + } else if (nextLoad.contentEquals(f.getName())){ + try { + curveSecKey = Files.readAllBytes(f.toPath()); + } catch (IOException e) { + LOG.error("Get zmqCurveSeckey exception! {}", e.toString()); + } + break; + } + } + } + private void eventRun(Context ctx) { Socket sock = ctx.socket(ZMQ.DEALER); sock.connect(AION_ZMQ_EV_TH); @@ -177,15 +232,18 @@ private void eventRun(Context ctx) { } if (!al.isEmpty()) { - Message.rsp_EventCtCallback ecb = Message.rsp_EventCtCallback.newBuilder().addAllEc(al).build(); + Message.rsp_EventCtCallback ecb = Message.rsp_EventCtCallback.newBuilder() + .addAllEc(al).build(); byte[] rsp = ((HdlrZmq) this.handler).toRspEvtMsg(ecb.toByteArray()); try { - byte[] socketId = ByteBuffer.allocate(5).put(ByteUtil.longToBytes(i), 3, 5).array(); + byte[] socketId = ByteBuffer.allocate(5) + .put(ByteUtil.longToBytes(i), 3, 5).array(); sock.send(socketId, ZMQ.SNDMORE); sock.send(rsp, ZMQ.DONTWAIT); } catch (Exception e) { - LOG.error("ProtocolProcessor.callbackRun sock.send exception: " + e.getMessage()); + LOG.error("ProtocolProcessor.callbackRun sock.send exception: " + e + .getMessage()); } } } @@ -229,19 +287,25 @@ private void callbackRun(Context ctx) { } byte[] rsp = tps.toTxReturnCode() != 105 - ? ((HdlrZmq) this.handler).toRspMsg(tps.getMsgHash(), tps.toTxReturnCode(), tps.getError()) - : ((HdlrZmq) this.handler).toRspMsg(tps.getMsgHash(), tps.toTxReturnCode(), tps.getError(), tps.getTxResult()); + ? ((HdlrZmq) this.handler) + .toRspMsg(tps.getMsgHash(), tps.toTxReturnCode(), tps.getError()) + : ((HdlrZmq) this.handler) + .toRspMsg(tps.getMsgHash(), tps.toTxReturnCode(), tps.getError(), + tps.getTxResult()); if (LOG.isTraceEnabled()) { - LOG.trace("callbackRun send. socketID: [{}], msgHash: [{}], txReturnCode: [{}]/n rspMsg: [{}]", - Hex.toHexString(tps.getSocketId()), Hex.toHexString(tps.getMsgHash()), tps.toTxReturnCode(), - Hex.toHexString(rsp)); + LOG.trace( + "callbackRun send. socketID: [{}], msgHash: [{}], txReturnCode: [{}]/n rspMsg: [{}]", + Hex.toHexString(tps.getSocketId()), Hex.toHexString(tps.getMsgHash()), + tps.toTxReturnCode(), + Hex.toHexString(rsp)); } try { sock.send(tps.getSocketId(), ZMQ.SNDMORE); sock.send(rsp, ZMQ.DONTWAIT); } catch (Exception e) { if (LOG.isErrorEnabled()) { - LOG.error("ProtocolProcessor.callbackRun sock.send exception: " + e.getMessage()); + LOG.error( + "ProtocolProcessor.callbackRun sock.send exception: " + e.getMessage()); } } } @@ -260,7 +324,8 @@ private void workerRun(ZMQ.Context ctx) { try { byte[] socketId = sock.recv(0); if (LOG.isTraceEnabled()) { - LOG.trace("ProtocolProcessor.workerRun socketID: [{}]", Hex.toHexString(socketId)); + LOG.trace("ProtocolProcessor.workerRun socketID: [{}]", + Hex.toHexString(socketId)); } if (socketId != null && socketId.length == SOCKETID_LEN) { byte[] req = sock.recv(0); From f994aea0349d1cedd37f8b39f9756193f5241a7d Mon Sep 17 00:00:00 2001 From: jayTseng Date: Thu, 6 Sep 2018 18:30:09 -0400 Subject: [PATCH 03/16] more detail for the log and the config settings --- .../src/org/aion/api/server/zmq/ProtocolProcessor.java | 2 +- modBoot/resource/config.xml | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java index e23d371f5a..e561964881 100644 --- a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java +++ b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java @@ -126,7 +126,7 @@ public void run() { feSock.setCurveSecretKey(curveSecKey); LOG.info("Secure connection enabled!"); } else { - LOG.info("Secure connection disabled!"); + LOG.info("Can't find the keyfile for setup the connection. Secure connection disabled!"); } } else { LOG.info("Secure connection disabled!"); diff --git a/modBoot/resource/config.xml b/modBoot/resource/config.xml index bba2b205a5..685b063d30 100644 --- a/modBoot/resource/config.xml +++ b/modBoot/resource/config.xml @@ -9,7 +9,10 @@ web3,eth,personal,stratum,ops - + + true + + 10E9 @@ -97,4 +100,4 @@ - \ No newline at end of file + From 91c64b1343e930e75fed91cf4aafe615e572ba99 Mon Sep 17 00:00:00 2001 From: jayTseng Date: Mon, 10 Sep 2018 12:07:32 -0400 Subject: [PATCH 04/16] fix zmq key loading error --- .../org/aion/api/server/zmq/ProtocolProcessor.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java index e561964881..70fc97057e 100644 --- a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java +++ b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java @@ -197,9 +197,20 @@ private void loadCurveKeyPair() { } catch (IOException e) { LOG.error("Get zmqCurvePubkey exception! {}", e.toString()); } - } else if (nextLoad.contentEquals(f.getName())){ + } else if (f.getName().contains("zmqCurveSeckey")) { try { curveSecKey = Files.readAllBytes(f.toPath()); + nextLoad = f.getName().replace("zmqCurveSeckey", "zmqCurvePubkey"); + } catch (IOException e) { + LOG.error("Get zmqCurveSeckey exception! {}", e.toString()); + } + } else if (nextLoad.contentEquals(f.getName())){ + try { + if (nextLoad.contains("zmqCurveSeckey")) { + curveSecKey = Files.readAllBytes(f.toPath()); + } else { + curvePubKey = Files.readAllBytes(f.toPath()); + } } catch (IOException e) { LOG.error("Get zmqCurveSeckey exception! {}", e.toString()); } From 3d570d624c3dda01b92db6374ffd70d4631497b3 Mon Sep 17 00:00:00 2001 From: jayTseng Date: Mon, 10 Sep 2018 13:32:46 -0400 Subject: [PATCH 05/16] fix api secure connect config reset after kernel launch --- modMcf/src/org/aion/mcf/config/CfgApiZmq.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modMcf/src/org/aion/mcf/config/CfgApiZmq.java b/modMcf/src/org/aion/mcf/config/CfgApiZmq.java index 34fd79264b..2ed9215658 100644 --- a/modMcf/src/org/aion/mcf/config/CfgApiZmq.java +++ b/modMcf/src/org/aion/mcf/config/CfgApiZmq.java @@ -123,6 +123,12 @@ String toXML() { xmlWriter.writeAttribute("ip", this.ip); xmlWriter.writeAttribute("port", this.port + ""); + xmlWriter.writeCharacters("\r\n\t\t\t"); + xmlWriter.writeStartElement("secure-connect"); + xmlWriter.writeCharacters(String.valueOf(this.secureConnectEnabled)); + xmlWriter.writeEndElement(); + + xmlWriter.writeCharacters("\r\n\t\t"); xmlWriter.writeEndElement(); xml = strWriter.toString(); strWriter.flush(); From 17fc73cff13ea32738cf50b99b19747d24e15712 Mon Sep 17 00:00:00 2001 From: jayTseng Date: Mon, 10 Sep 2018 16:27:41 -0400 Subject: [PATCH 06/16] modify zmq key naming rule for the OS compatibility --- modAionImpl/src/org/aion/zero/impl/cli/Cli.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java index 284b0b7161..9743cbb8ba 100644 --- a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java +++ b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java @@ -301,7 +301,7 @@ public int call(final String[] args, final Cfg cfg) { private void genKeyFile(@Nonnull final String publicKey, @Nonnull final String secretKey) throws IOException { - DateFormat df = new SimpleDateFormat("yy-MM-dd'T'HH:mm:ss'Z'"); + DateFormat df = new SimpleDateFormat("yy-MM-dd'T'HH-mm-ss'Z'"); df.setTimeZone(TimeZone.getTimeZone("UTC")); String iso_date = df.format(new Date(System.currentTimeMillis())); From 49c0ea77e4bb88a7ab11b6c709cb306ed1183246 Mon Sep 17 00:00:00 2001 From: jayTseng Date: Tue, 25 Sep 2018 15:08:45 -0400 Subject: [PATCH 07/16] add zmq_keystore into gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 926e896cdd..69bf8d3217 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ /log/ /rt/ /web3/ +/zmq_keystore/ # ide /.idea/ From 3f84a20bad8ce67a72796d74284aeae576926d7f Mon Sep 17 00:00:00 2001 From: jayTseng Date: Tue, 25 Sep 2018 16:19:00 -0400 Subject: [PATCH 08/16] refactoring the getFiles method to a class --- modAionBase/module-info.java | 1 + modAionBase/src/org/aion/base/io/File.java | 46 +++++++++++++++++++ .../src/org/aion/zero/impl/cli/Cli.java | 17 +++++++ .../src/org/aion/api/server/ApiAion.java | 4 +- .../src/org/aion/api/server/zmq/HdlrZmq.java | 15 +++--- .../api/server/zmq/ProtocolProcessor.java | 10 +--- modMcf/src/org/aion/mcf/account/Keystore.java | 29 ++++-------- 7 files changed, 82 insertions(+), 40 deletions(-) create mode 100644 modAionBase/src/org/aion/base/io/File.java diff --git a/modAionBase/module-info.java b/modAionBase/module-info.java index db43d3f590..20bbee63bf 100644 --- a/modAionBase/module-info.java +++ b/modAionBase/module-info.java @@ -4,5 +4,6 @@ exports org.aion.base.util; exports org.aion.base.vm; exports org.aion.base.db; + exports org.aion.base.io; exports org.aion.base; } diff --git a/modAionBase/src/org/aion/base/io/File.java b/modAionBase/src/org/aion/base/io/File.java new file mode 100644 index 0000000000..fabfeaf005 --- /dev/null +++ b/modAionBase/src/org/aion/base/io/File.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2018 Aion foundation. + * + * This file is part of the aion network project. + * + * The aion network project is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or any later version. + * + * The aion network project is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the aion network project source files. + * If not, see . + * + * Contributors: + * Aion foundation. + */ + +package org.aion.base.io; + +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class File { + public static List getFiles(final Path path) { + if (path == null) { + System.out.println("getFiles null path input!"); + return Collections.emptyList(); + } + + try { + java.io.File[] files = path.toFile().listFiles(); + return files != null ? Arrays.asList(files) : Collections.emptyList(); + } catch (UnsupportedOperationException | NullPointerException e) { + System.out.println("getFiles exception: " + e.toString()); + return Collections.emptyList(); + } + } +} diff --git a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java index 145770b5a8..cf7f8011dd 100644 --- a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java +++ b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java @@ -236,6 +236,11 @@ public int call(final String[] args, Cfg cfg, String path) { break; case "-zs": checkZmqKeystoreDir(); + if (existZmqSecKeyFile()) { + System.out.println("Found existing secret key file. Please backup or remove it!"); + return 1; + } + ZMQ.Curve.KeyPair kp = ZMQ.Curve.generateKeyPair(); genKeyFile(kp.publicKey, kp.secretKey); System.out.println("Generate ZmqKeyPairFinished!"); @@ -484,6 +489,18 @@ else if (isValid(args[3])) { return 0; } + private boolean existZmqSecKeyFile() { + List files = org.aion.base.io.File.getFiles(zmqkeyDir.toPath()); + + for (File file : files) { + if (file.getName().contains("zmqCurveSeckey")) { + return true; + } + } + + return false; + } + private void genKeyFile(@Nonnull final String publicKey, @Nonnull final String secretKey) throws IOException { diff --git a/modApiServer/src/org/aion/api/server/ApiAion.java b/modApiServer/src/org/aion/api/server/ApiAion.java index cc2e3f74c6..5a7e87c638 100644 --- a/modApiServer/src/org/aion/api/server/ApiAion.java +++ b/modApiServer/src/org/aion/api/server/ApiAion.java @@ -80,7 +80,7 @@ public abstract class ApiAion extends Api { // 2. underlying datastructure provides concurrency guarntees // delegate concurrency to underlying object - protected static NrgOracle NRG_ORACLE; + private static NrgOracle NRG_ORACLE; protected IAionChain ac; // assumption: blockchainImpl et al. provide concurrency guarantee // using java.util.concurrent library objects @@ -224,7 +224,7 @@ public AionBlock getBlock(long blkNr) { } } - public Map.Entry getBlockWithTotalDifficulty(long blkNr) { + protected Map.Entry getBlockWithTotalDifficulty(long blkNr) { if (blkNr > 0) { return ((AionBlockStore) this.ac.getBlockchain().getBlockStore()) .getChainBlockByNumberWithTotalDifficulty(blkNr); diff --git a/modApiServer/src/org/aion/api/server/zmq/HdlrZmq.java b/modApiServer/src/org/aion/api/server/zmq/HdlrZmq.java index 5a7de9acdf..7e5da4b64c 100644 --- a/modApiServer/src/org/aion/api/server/zmq/HdlrZmq.java +++ b/modApiServer/src/org/aion/api/server/zmq/HdlrZmq.java @@ -1,4 +1,4 @@ -/******************************************************************************* +/* * Copyright (c) 2017-2018 Aion foundation. * * This file is part of the aion network project. @@ -19,8 +19,7 @@ * * Contributors: * Aion foundation. - * - ******************************************************************************/ + */ package org.aion.api.server.zmq; @@ -70,7 +69,7 @@ public byte[] process(byte[] request, byte[] socketId) { } } - public void getTxWait() { + void getTxWait() { TxWaitingMappingUpdate txWait = null; try { txWait = this.api.takeTxWait(); @@ -107,15 +106,15 @@ public Map getFilter() { return this.api.getFilter(); } - public BlockingQueue getTxStatusQueue() { + BlockingQueue getTxStatusQueue() { return this.api.getPendingStatus(); } - public byte[] toRspMsg(byte[] msgHash, int txCode, String error) { + byte[] toRspMsg(byte[] msgHash, int txCode, String error) { return ApiUtil.toReturnHeader(this.api.getApiVersion(), txCode, msgHash, error.getBytes()); } - public byte[] toRspMsg(byte[] msgHash, int txCode, String error, byte[] result) { + byte[] toRspMsg(byte[] msgHash, int txCode, String error, byte[] result) { return ApiUtil.toReturnHeader(this.api.getApiVersion(), txCode, msgHash, error.getBytes(), result); } @@ -124,7 +123,7 @@ public byte[] process(byte[] request) { return null; } - public byte[] toRspEvtMsg(byte[] ecb) { + byte[] toRspEvtMsg(byte[] ecb) { return ApiUtil.toReturnEvtHeader(this.api.getApiVersion(), ecb); } diff --git a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java index 70fc97057e..4234854ed9 100644 --- a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java +++ b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java @@ -34,8 +34,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; @@ -51,7 +49,6 @@ import org.aion.base.util.Hex; import org.aion.log.AionLoggerFactory; import org.aion.log.LogEnum; -import org.aion.mcf.account.KeystoreFormat; import org.aion.mcf.config.CfgApiZmq; import org.slf4j.Logger; import org.zeromq.ZMQ; @@ -91,11 +88,6 @@ public ProtocolProcessor(IHdlr _handler, final CfgApiZmq cfg) { this.cfgApi = cfg; } - private static List getFiles() { - File[] files = PATH.toFile().listFiles(); - return files != null ? Arrays.asList(files) : Collections.emptyList(); - } - public void shutdown() throws InterruptedException { handler.shutDown(); shutDown.set(true); @@ -187,7 +179,7 @@ public void run() { } private void loadCurveKeyPair() { - List files = getFiles(); + List files = org.aion.base.io.File.getFiles(PATH); String nextLoad = ""; for (File f : files) { if (f.getName().contains("zmqCurvePubkey")) { diff --git a/modMcf/src/org/aion/mcf/account/Keystore.java b/modMcf/src/org/aion/mcf/account/Keystore.java index b2b572888f..7d1013db8d 100644 --- a/modMcf/src/org/aion/mcf/account/Keystore.java +++ b/modMcf/src/org/aion/mcf/account/Keystore.java @@ -1,5 +1,4 @@ /* - ****************************************************************************** * Copyright (c) 2017-2018 Aion foundation. * * This file is part of the aion network project. @@ -18,12 +17,6 @@ * along with the aion network project source files. * If not, see . * - * The aion network project leverages useful source code from other - * open source projects. We greatly appreciate the effort that was - * invested in these projects and we thank the individual contributors - * for their work. For provenance information and contributors - * please see . - * * Contributors to the aion source files in decreasing order of code volume: * Aion foundation. * team through the ethereumJ library. @@ -32,8 +25,9 @@ * Samuel Neves through the BLAKE2 implementation. * Zcash project team. * Bitcoinj team. - ***************************************************************************** */ + + package org.aion.mcf.account; import java.io.File; @@ -48,8 +42,6 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -92,11 +84,6 @@ public class Keystore { PATH = Paths.get(KEYSTORE_PATH); } - private static List getFiles() { - File[] files = PATH.toFile().listFiles(); - return files != null ? Arrays.asList(files) : Collections.emptyList(); - } - public static String create(String password) { return create(password, ECKeyFac.inst().create()); } @@ -160,7 +147,7 @@ public static Map backupAccount(Map throw new NullPointerException(); } - List files = getFiles(); + List files = org.aion.base.io.File.getFiles(PATH); if (files == null) { if (LOG.isWarnEnabled()) { LOG.warn("No key file been stored in the kernel."); @@ -213,7 +200,7 @@ public static Map backupAccount(Map } public static String[] list() { - return addAddrs(getFiles()).toArray(new String[0]); + return addAddrs(org.aion.base.io.File.getFiles(PATH)).toArray(new String[0]); } private static List addAddrs(List files) { @@ -240,7 +227,7 @@ private static List addAddrs(List files) { * @return address represent by String as a List */ public static List accountsSorted() { - List files = getFiles(); + List files = org.aion.base.io.File.getFiles(PATH); files.sort(COMPARE); return addAddrs(files); } @@ -252,7 +239,7 @@ public static ECKey getKey(String _address, String _password) { ECKey key = null; if (_address.startsWith(AION_PREFIX)) { - List files = getFiles(); + List files = org.aion.base.io.File.getFiles(PATH); for (File file : files) { if (HEX_64.matcher(_address).find() && file.getName().contains(_address)) { try { @@ -282,7 +269,7 @@ public static boolean exist(String _address) { boolean flag = false; if (_address.startsWith(AION_PREFIX)) { - List files = getFiles(); + List files = org.aion.base.io.File.getFiles(PATH); for (File file : files) { if (HEX_64.matcher(_address).find() && file.getName().contains(_address)) { flag = true; @@ -338,7 +325,7 @@ public static Set importAccount(Map importKey) { * Test method. Don't use it for the code dev. */ static File getAccountFile(String address, String password) { - List files = getFiles(); + List files = org.aion.base.io.File.getFiles(PATH); if (files == null) { if (LOG.isWarnEnabled()) { LOG.warn("No key file been stored in the kernel."); From 1c75109885bef0d22e1ffe48b5d3bdcba0c8bab0 Mon Sep 17 00:00:00 2001 From: jayTseng Date: Tue, 25 Sep 2018 16:36:20 -0400 Subject: [PATCH 09/16] refactoring zmq secure connection for logging --- .../src/org/aion/zero/impl/cli/Cli.java | 6 ++-- modMcf/src/org/aion/mcf/config/CfgApiZmq.java | 35 ++++++++----------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java index cf7f8011dd..8dee7a2c37 100644 --- a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java +++ b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java @@ -509,13 +509,13 @@ private void genKeyFile(@Nonnull final String publicKey, @Nonnull final String s String iso_date = df.format(new Date(System.currentTimeMillis())); String fileName = "UTC--" + iso_date + "--zmqCurvePubkey"; - getFile(fileName, publicKey); + writeKeyToFile(fileName, publicKey); fileName = "UTC--" + iso_date + "--zmqCurveSeckey"; - getFile(fileName, secretKey); + writeKeyToFile(fileName, secretKey); } - private void getFile(@Nonnull final String fileName, @Nonnull final String key) throws IOException { + private void writeKeyToFile(@Nonnull final String fileName, @Nonnull final String key) throws IOException { Set perms = PosixFilePermissions.fromString("rwxr-----"); FileAttribute> attr = PosixFilePermissions.asFileAttribute(perms); diff --git a/modMcf/src/org/aion/mcf/config/CfgApiZmq.java b/modMcf/src/org/aion/mcf/config/CfgApiZmq.java index 2ed9215658..12ca52ab75 100644 --- a/modMcf/src/org/aion/mcf/config/CfgApiZmq.java +++ b/modMcf/src/org/aion/mcf/config/CfgApiZmq.java @@ -1,11 +1,11 @@ -/******************************************************************************* +/* * Copyright (c) 2017-2018 Aion foundation. * * This file is part of the aion network project. * * The aion network project is free software: you can redistribute it * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 of + * as published by the Free Software Foundation, either versio 3 of * the License, or any later version. * * The aion network project is distributed in the hope that it will @@ -19,22 +19,17 @@ * * Contributors: * Aion foundation. - * - ******************************************************************************/ + */ package org.aion.mcf.config; import com.google.common.base.Objects; - +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.stream.Collectors; -import java.util.stream.Stream; public class CfgApiZmq { @@ -52,9 +47,9 @@ public class CfgApiZmq { protected boolean active; protected String ip; protected int port; - protected boolean filtersEnabled; - protected boolean blockSummaryCacheEnabled; - protected boolean secureConnectEnabled; + private boolean filtersEnabled; + private boolean blockSummaryCacheEnabled; + private boolean secureConnectEnabled; public void fromXML(final XMLStreamReader sr) throws XMLStreamException { this.active = Boolean.parseBoolean(sr.getAttributeValue(null, "active")); @@ -73,24 +68,24 @@ public void fromXML(final XMLStreamReader sr) throws XMLStreamException { try { filtersEnabled = Boolean.parseBoolean(Cfg.readValue(sr)); } catch (Exception e) { - //System.out.println("failed to read config node: aion.api.rpc.filters-enabled; using preset: " + this.filtersEnabled); - //e.printStackTrace(); + System.out.println("failed to read config node: aion.api.zmq.filters-enabled; using preset: " + this.filtersEnabled); + e.printStackTrace(); } break; case "block-summary-cache": try { blockSummaryCacheEnabled = Boolean.parseBoolean(Cfg.readValue(sr)); } catch (Exception e) { - //System.out.println("failed to read config node: aion.api.rpc.filters-enabled; using preset: " + this.filtersEnabled); - //e.printStackTrace(); + System.out.println("failed to read config node: aion.api.zmq.block-summary-cache; using preset: " + this.blockSummaryCacheEnabled); + e.printStackTrace(); } break; case "secure-connect": try { secureConnectEnabled = Boolean.parseBoolean(Cfg.readValue(sr)); } catch (Exception e) { - //System.out.println("failed to read config node: aion.api.rpc.filters-enabled; using preset: " + this.filtersEnabled); - //e.printStackTrace(); + System.out.println("failed to read config node: aion.api.zmq.secure-connect; using preset: " + this.secureConnectEnabled); + e.printStackTrace(); } break; default: From 33c68bde63e2093f846b9c9b11ebfd85f014ea2c Mon Sep 17 00:00:00 2001 From: jayTseng Date: Tue, 25 Sep 2018 16:57:44 -0400 Subject: [PATCH 10/16] refactoring CfgApiZmq logging, ProtocolProcessor construct process and cli return logic fix for secure connect --- .../src/org/aion/zero/impl/cli/Cli.java | 6 +++--- .../api/server/zmq/ProtocolProcessor.java | 20 +++++++++---------- modMcf/src/org/aion/mcf/config/CfgApiZmq.java | 12 ++++++----- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java index 8dee7a2c37..cadeb3d5ff 100644 --- a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java +++ b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java @@ -244,7 +244,7 @@ public int call(final String[] args, Cfg cfg, String path) { ZMQ.Curve.KeyPair kp = ZMQ.Curve.generateKeyPair(); genKeyFile(kp.publicKey, kp.secretKey); System.out.println("Generate ZmqKeyPairFinished!"); - return 1; + break; case "-r": if (args.length < 2) { System.out.println("Starting database clean-up."); @@ -480,9 +480,9 @@ else if (isValid(args[3])) { return 1; } - System.out.println(""); + System.out.println(); } catch (Throwable e) { - System.out.println(""); + System.out.println(e.toString()); return 1; } diff --git a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java index 4234854ed9..50def756a7 100644 --- a/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java +++ b/modApiServer/src/org/aion/api/server/zmq/ProtocolProcessor.java @@ -62,21 +62,11 @@ public class ProtocolProcessor implements Runnable { private static final String AION_ZMQ_CB_TH = "inproc://aionZmqCbTh"; private static final String AION_ZMQ_EV_TH = "inproc://aionZmqEvTh"; private static final String AION_ZMQ_HB_TH = "inproc://aionZmqHbTh"; - private static final String CURVEKEY_PATH; - private static final Path PATH; + private final Path PATH; private static final long zmqHWM = 100_000; private static final int SOCKETID_LEN = 5; private static final int SOCKET_RECV_TIMEOUT = 3000; - static { - String storageDir = System.getProperty("local.storage.dir"); - if (storageDir == null || storageDir.equalsIgnoreCase("")) { - storageDir = System.getProperty("user.dir"); - } - CURVEKEY_PATH = storageDir + "/" + CfgApiZmq.ZMQ_KEY_DIR; - PATH = Paths.get(CURVEKEY_PATH); - } - private final IHdlr handler; private CfgApiZmq cfgApi; private AtomicBoolean shutDown = new AtomicBoolean(); @@ -86,6 +76,14 @@ public class ProtocolProcessor implements Runnable { public ProtocolProcessor(IHdlr _handler, final CfgApiZmq cfg) { this.handler = _handler; this.cfgApi = cfg; + + String storageDir = System.getProperty("local.storage.dir"); + if (storageDir == null || storageDir.equalsIgnoreCase("")) { + storageDir = System.getProperty("user.dir"); + } + + String curveKeyPath = storageDir + "/" + CfgApiZmq.ZMQ_KEY_DIR; + PATH = Paths.get(curveKeyPath); } public void shutdown() throws InterruptedException { diff --git a/modMcf/src/org/aion/mcf/config/CfgApiZmq.java b/modMcf/src/org/aion/mcf/config/CfgApiZmq.java index 12ca52ab75..74520ef5ca 100644 --- a/modMcf/src/org/aion/mcf/config/CfgApiZmq.java +++ b/modMcf/src/org/aion/mcf/config/CfgApiZmq.java @@ -30,6 +30,8 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; +import org.aion.log.AionLoggerFactory; +import org.slf4j.Logger; public class CfgApiZmq { @@ -51,6 +53,8 @@ public class CfgApiZmq { private boolean blockSummaryCacheEnabled; private boolean secureConnectEnabled; + private static Logger LOG_GEN = AionLoggerFactory.getLogger("GEN"); + public void fromXML(final XMLStreamReader sr) throws XMLStreamException { this.active = Boolean.parseBoolean(sr.getAttributeValue(null, "active")); this.ip = sr.getAttributeValue(null, "ip"); @@ -68,7 +72,7 @@ public void fromXML(final XMLStreamReader sr) throws XMLStreamException { try { filtersEnabled = Boolean.parseBoolean(Cfg.readValue(sr)); } catch (Exception e) { - System.out.println("failed to read config node: aion.api.zmq.filters-enabled; using preset: " + this.filtersEnabled); + LOG_GEN.warn("failed to read config node: aion.api.zmq.filters-enabled; using preset: {}\n {}" + this.filtersEnabled, e); e.printStackTrace(); } break; @@ -76,16 +80,14 @@ public void fromXML(final XMLStreamReader sr) throws XMLStreamException { try { blockSummaryCacheEnabled = Boolean.parseBoolean(Cfg.readValue(sr)); } catch (Exception e) { - System.out.println("failed to read config node: aion.api.zmq.block-summary-cache; using preset: " + this.blockSummaryCacheEnabled); - e.printStackTrace(); + LOG_GEN.warn("failed to read config node: aion.api.zmq.block-summary-cache; using preset: {}\n {}", this.blockSummaryCacheEnabled, e); } break; case "secure-connect": try { secureConnectEnabled = Boolean.parseBoolean(Cfg.readValue(sr)); } catch (Exception e) { - System.out.println("failed to read config node: aion.api.zmq.secure-connect; using preset: " + this.secureConnectEnabled); - e.printStackTrace(); + LOG_GEN.warn("failed to read config node: aion.api.zmq.secure-connect; using preset: {}\n {}" + this.secureConnectEnabled, e); } break; default: From 04672de6c9ea6848b7c69de0ab4e05bcc8420c30 Mon Sep 17 00:00:00 2001 From: AionJayT Date: Mon, 1 Oct 2018 16:40:59 -0400 Subject: [PATCH 11/16] update api repo ref --- aion_api | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aion_api b/aion_api index e21f8e878d..6adb12f81c 160000 --- a/aion_api +++ b/aion_api @@ -1 +1 @@ -Subproject commit e21f8e878d598724176a6d0c51fceafc85239020 +Subproject commit 6adb12f81ce775989da3acb134d4b1c3a9e146eb From 415caeaa67ca8ac2342d271b3738400e8ecb2ab1 Mon Sep 17 00:00:00 2001 From: AionJayT Date: Tue, 2 Oct 2018 15:44:46 -0400 Subject: [PATCH 12/16] move zmq key pair generate ouside of Cli. Will be checked after config settings has been loaded --- modAionImpl/src/module-info.java | 3 + .../src/org/aion/zero/impl/cli/Cli.java | 216 ++++++------------ modBoot/src/module-info.java | 6 +- modBoot/src/org/aion/Aion.java | 138 +++++++++-- modCrypto/src/module-info.java | 1 + modMcf/src/module-info.java | 1 + 6 files changed, 203 insertions(+), 162 deletions(-) diff --git a/modAionImpl/src/module-info.java b/modAionImpl/src/module-info.java index d59cc69e97..56f3f718ea 100644 --- a/modAionImpl/src/module-info.java +++ b/modAionImpl/src/module-info.java @@ -1,4 +1,6 @@ module aion.zero.impl { + uses org.aion.evtmgr.EventMgrModule; + uses org.aion.txpool.TxPoolModule; requires aion.base; requires aion.mcf; requires aion.log; @@ -17,6 +19,7 @@ requires jdk.management; requires java.xml; requires slf4j.api; + requires com.google.common; exports org.aion.equihash; exports org.aion.zero.impl.blockchain; diff --git a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java index cadeb3d5ff..139bf6117c 100644 --- a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java +++ b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java @@ -24,31 +24,8 @@ package org.aion.zero.impl.cli; -import static org.aion.mcf.account.Keystore.exist; - import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; -import java.io.BufferedReader; -import java.io.Console; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.FileAttribute; -import java.nio.file.attribute.PosixFilePermission; -import java.nio.file.attribute.PosixFilePermissions; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.TimeZone; -import java.util.UUID; -import javax.annotation.Nonnull; import org.aion.base.util.Hex; import org.aion.crypto.ECKey; import org.aion.crypto.ECKeyFac; @@ -59,7 +36,14 @@ import org.aion.zero.impl.Version; import org.aion.zero.impl.config.CfgAion; import org.aion.zero.impl.db.RecoveryUtils; -import org.zeromq.ZMQ; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static org.aion.mcf.account.Keystore.exist; /** @@ -77,7 +61,7 @@ public class Cli { private final String BASE_PATH = System.getProperty("user.dir"); - private String BASE_PATH_WITH_NETWORK = BASE_PATH + "/config/" + CfgAion.getNetwork(); + private String BASE_PATH_WITH_NETWORK = BASE_PATH + "/config/" + CfgAion.getNetwork(); private String dstConfig = BASE_PATH_WITH_NETWORK + "/config.xml"; @@ -88,10 +72,13 @@ enum Network { @Override public String toString() { - switch(this) { - case MAINNET: return "mainnet"; - case CONQUEST: return "conquest"; - default: throw new IllegalArgumentException(); + switch (this) { + case MAINNET: + return "mainnet"; + case CONQUEST: + return "conquest"; + default: + throw new IllegalArgumentException(); } } } @@ -119,7 +106,8 @@ public int call(final String[] args, Cfg cfg, String path) { return 1; } else { while (index < args.length) { - if(args[index].equals("-d")||args[index].equals("-n")||args[index].equals("--datadir")||args[index].equals("--network")) { + if (args[index].equals("-d") || args[index].equals("-n") || args[index] + .equals("--datadir") || args[index].equals("--network")) { multi = true; break; } @@ -128,12 +116,11 @@ public int call(final String[] args, Cfg cfg, String path) { } // Switches datadir && network - if(multi) { + if (multi) { String[] newArgs = Arrays.copyOfRange(args, index, args.length); call(newArgs, cfg); } - switch (args[1]) { case "create": if (!createAccount()) { @@ -170,10 +157,11 @@ public int call(final String[] args, Cfg cfg, String path) { case CONQUEST: CfgAion.setNetwork(net.toString()); File dir = new File(BASE_PATH + "/config/" + net); - if(!dir.exists()) { + if (!dir.exists()) { dir.mkdirs(); } - CfgAion.setConfFilePath(BASE_PATH + "/config/" + args[1] + "/config.xml"); + CfgAion.setConfFilePath( + BASE_PATH + "/config/" + args[1] + "/config.xml"); System.out.println("\nNew config generated for " + args[1]); break; default: @@ -234,17 +222,6 @@ public int call(final String[] args, Cfg cfg, String path) { return 1; } break; - case "-zs": - checkZmqKeystoreDir(); - if (existZmqSecKeyFile()) { - System.out.println("Found existing secret key file. Please backup or remove it!"); - return 1; - } - - ZMQ.Curve.KeyPair kp = ZMQ.Curve.generateKeyPair(); - genKeyFile(kp.publicKey, kp.secretKey); - System.out.println("Generate ZmqKeyPairFinished!"); - break; case "-r": if (args.length < 2) { System.out.println("Starting database clean-up."); @@ -270,7 +247,7 @@ public int call(final String[] args, Cfg cfg, String path) { case "-n": case "--network": - if ( (args.length == 2 || args.length == 4) && isValid(args[1])) { + if ((args.length == 2 || args.length == 4) && isValid(args[1])) { net = determineNetwork(args[1].toLowerCase()); @@ -282,31 +259,37 @@ public int call(final String[] args, Cfg cfg, String path) { if (args.length == 2) { CfgAion.setNetwork(net.toString()); - BASE_PATH_WITH_NETWORK = BASE_PATH + "/config/" + CfgAion.getNetwork(); + BASE_PATH_WITH_NETWORK = + BASE_PATH + "/config/" + CfgAion.getNetwork(); CfgAion.setConfFilePath(BASE_PATH_WITH_NETWORK + "/config.xml"); - CfgAion.setGenesisFilePath((BASE_PATH_WITH_NETWORK + "/genesis.json")); + CfgAion.setGenesisFilePath( + (BASE_PATH_WITH_NETWORK + "/genesis.json")); copyNetwork(path, net); cfg.getLog().setLogPath(net.toString() + "/log"); cfg.getDb().setDatabasePath(net.toString() + "/database"); - Keystore.setKeystorePath(path + "/" + net.toString() + "/keystore"); + Keystore + .setKeystorePath(path + "/" + net.toString() + "/keystore"); return 2; } // -n [network] -d [directory] - else if ((args[2].equals("-d")||args[2].equals("--datadir")) && isValid(args[3])) { + else if ((args[2].equals("-d") || args[2].equals("--datadir")) + && isValid(args[3])) { CfgAion.setNetwork(net.toString()); - BASE_PATH_WITH_NETWORK = BASE_PATH + "/config/" + CfgAion.getNetwork(); + BASE_PATH_WITH_NETWORK = + BASE_PATH + "/config/" + CfgAion.getNetwork(); CfgAion.setConfFilePath(BASE_PATH_WITH_NETWORK + "/config.xml"); - CfgAion.setGenesisFilePath((BASE_PATH_WITH_NETWORK + "/genesis.json")); + CfgAion.setGenesisFilePath( + (BASE_PATH_WITH_NETWORK + "/genesis.json")); String[] newArgs = Arrays.copyOfRange(args, 2, args.length); call(newArgs, cfg); return 2; - } else if (!(args[2].equals("-d")||args[2].equals("--datadir"))) { + } else if (!(args[2].equals("-d") || args[2].equals("--datadir"))) { System.out.println("\nInvalid multi arguments!\n"); printHelp(); return 1; @@ -333,10 +316,10 @@ else if ((args[2].equals("-d")||args[2].equals("--datadir")) && isValid(args[3]) return 1; } - // Determines database folder path + // Determines database folder path case "-d": case "--datadir": - if ( (args.length == 2 || args.length == 4) && isValid(args[1])) { + if ((args.length == 2 || args.length == 4) && isValid(args[1])) { // -d [directory] if (args.length == 2) { @@ -344,7 +327,8 @@ else if ((args[2].equals("-d")||args[2].equals("--datadir")) && isValid(args[3]) copyNetwork(path + "/" + args[1], net); cfg.getLog().setLogPath(args[1] + "/" + net + "/log"); cfg.getDb().setDatabasePath(args[1] + "/" + net + "/database"); - Keystore.setKeystorePath(path + "/" + args[1] + "/" + net + "/keystore"); + Keystore + .setKeystorePath(path + "/" + args[1] + "/" + net + "/keystore"); return 2; } @@ -358,10 +342,11 @@ else if (isValid(args[3])) { copyNetwork(path + "/" + args[1], net); cfg.getLog().setLogPath(args[1] + "/" + net + "/log"); cfg.getDb().setDatabasePath(args[1] + "/" + net + "/database"); - Keystore.setKeystorePath(path + "/" + args[1] + "/" + net + "/keystore"); + Keystore + .setKeystorePath(path + "/" + args[1] + "/" + net + "/keystore"); return 2; - } else if (!(args[2].equals("-n")||args[2].equals("--network"))) { + } else if (!(args[2].equals("-n") || args[2].equals("--network"))) { System.out.println("\nInvalid multi arguments!\n"); printHelp(); return 1; @@ -489,58 +474,6 @@ else if (isValid(args[3])) { return 0; } - private boolean existZmqSecKeyFile() { - List files = org.aion.base.io.File.getFiles(zmqkeyDir.toPath()); - - for (File file : files) { - if (file.getName().contains("zmqCurveSeckey")) { - return true; - } - } - - return false; - } - - private void genKeyFile(@Nonnull final String publicKey, @Nonnull final String secretKey) - throws IOException { - - DateFormat df = new SimpleDateFormat("yy-MM-dd'T'HH-mm-ss'Z'"); - df.setTimeZone(TimeZone.getTimeZone("UTC")); - String iso_date = df.format(new Date(System.currentTimeMillis())); - - String fileName = "UTC--" + iso_date + "--zmqCurvePubkey"; - writeKeyToFile(fileName, publicKey); - - fileName = "UTC--" + iso_date + "--zmqCurveSeckey"; - writeKeyToFile(fileName, secretKey); - } - - private void writeKeyToFile(@Nonnull final String fileName, @Nonnull final String key) throws IOException { - Set perms = PosixFilePermissions.fromString("rwxr-----"); - FileAttribute> attr = PosixFilePermissions.asFileAttribute(perms); - - Path p = Paths.get(zmqkeyDir.getPath()); - Path keyFile = p.resolve(fileName); - if (!java.nio.file.Files.exists(keyFile)) { - keyFile = java.nio.file.Files.createFile(keyFile, attr); - } - - FileOutputStream fos = new FileOutputStream(keyFile.toString()); - fos.write(key.getBytes()); - fos.close(); - } - - private void checkZmqKeystoreDir() { - if (!zmqkeyDir.isDirectory()) { - if (!zmqkeyDir.mkdir()) { - System.out.println("zmq keystore directory could not be created. " + - "Please check user permissions or create directory manually."); - System.exit(1); - } - System.out.println(); - } - } - /** * Print the CLI help info. */ @@ -550,23 +483,32 @@ private void printHelp() { System.out.println(" -h show help info"); System.out.println(); System.out.println(" -a create create a new account"); - System.out.println(" -a list list all existing accounts"); - System.out.println(" -a export [address] export private key of an account"); + System.out + .println(" -a list list all existing accounts"); + System.out.println( + " -a export [address] export private key of an account"); System.out.println(" -a import [private_key] import private key"); System.out.println(); - System.out.println(" -c [network] create config to selected network; mainnet, conquest"); + System.out.println( + " -c [network] create config to selected network; mainnet, conquest"); System.out.println(); - System.out.println(" -n, --network [network] execute kernel with selected network; mainnet, conquest"); + System.out.println( + " -n, --network [network] execute kernel with selected network; mainnet, conquest"); System.out.println(); - System.out.println(" -d, --datadir [directory] execute kernel with selected database directory"); + System.out.println( + " -d, --datadir [directory] execute kernel with selected database directory"); System.out.println(); System.out.println(" -i show information"); System.out.println(); - System.out.println(" -s create create an ssl certificate for localhost"); - System.out.println(" -s create [[hostname] [ip]] create an ssl certificate for a custom hostname and ip"); + System.out.println( + " -s create create an ssl certificate for localhost"); + System.out.println( + " -s create [[hostname] [ip]] create an ssl certificate for a custom hostname and ip"); System.out.println(); - System.out.println(" -r remove blocks on side chains and correct block info"); - System.out.println(" -r [block_number] revert db up to specific block number"); + System.out.println( + " -r remove blocks on side chains and correct block info"); + System.out.println( + " -r [block_number] revert db up to specific block number"); System.out.println(); System.out.println(" -v show version"); } @@ -579,7 +521,7 @@ private void printHelp() { */ private Network determineNetwork(String arg) { Network net; - switch(arg) { + switch (arg) { case "mainnet": net = Network.MAINNET; break; @@ -601,7 +543,7 @@ private Network determineNetwork(String arg) { * @param path input to append base directory to copy to * @param net input to determine network to copy from */ - private void copyNetwork(String path, Network net) { + private void copyNetwork(String path, Network net) { File dir1 = new File(path + "/" + net + "/config"); File dir2 = new File(path + "/" + net + "/keystore"); @@ -800,8 +742,6 @@ private RecoveryUtils.Status revertTo(String blockNumber) { /** * Checks for illegal inputs (for datadir && network names) - * @param value - * @return */ public static boolean isValid(String value) { return !value.isEmpty() && !value.matches(".*[-=+,.?;:'!@#$%^&*].*"); @@ -842,7 +782,7 @@ private String getCertName(Console console) { private String getCertPass(Console console) { int minPassLen = 7; String certPass = String.valueOf(console.readPassword( - "Enter certificate password (at least " + minPassLen + " characters):\n")); + "Enter certificate password (at least " + minPassLen + " characters):\n")); if ((certPass == null) || (certPass.isEmpty())) { System.out.println("Error: no certificate password entered."); System.exit(1); @@ -863,24 +803,20 @@ public String getDstGenesis() { } // Methods below taken from FileUtils class - private static boolean copyRecursively(File src, File target) - { + private static boolean copyRecursively(File src, File target) { if (src.isDirectory()) { return copyDirectoryContents(src, target); - } - else { + } else { try { com.google.common.io.Files.copy(src, target); return true; - } - catch (IOException e) { + } catch (IOException e) { return false; } } } - private static boolean copyDirectoryContents(File src, File target) - { + private static boolean copyDirectoryContents(File src, File target) { Preconditions.checkArgument(src.isDirectory(), "Source dir is not a directory: %s", src); // Don't delete symbolic link directories @@ -898,26 +834,24 @@ private static boolean copyDirectoryContents(File src, File target) return success; } - private static boolean isSymbolicLink(File file) - { + private static boolean isSymbolicLink(File file) { try { File canonicalFile = file.getCanonicalFile(); File absoluteFile = file.getAbsoluteFile(); File parentFile = file.getParentFile(); // a symbolic link has a different name between the canonical and absolute path return !canonicalFile.getName().equals(absoluteFile.getName()) || - // or the canonical parent path is not the same as the file's parent path, - // provided the file has a parent path - parentFile != null && !parentFile.getCanonicalPath().equals(canonicalFile.getParent()); - } - catch (IOException e) { + // or the canonical parent path is not the same as the file's parent path, + // provided the file has a parent path + parentFile != null && !parentFile.getCanonicalPath() + .equals(canonicalFile.getParent()); + } catch (IOException e) { // error on the side of caution return true; } } - private static ImmutableList listFiles(File dir) - { + private static ImmutableList listFiles(File dir) { File[] files = dir.listFiles(); if (files == null) { return ImmutableList.of(); diff --git a/modBoot/src/module-info.java b/modBoot/src/module-info.java index fb01f68383..d0fd73da79 100644 --- a/modBoot/src/module-info.java +++ b/modBoot/src/module-info.java @@ -1,4 +1,6 @@ module aion.boot { + uses org.aion.evtmgr.EventMgrModule; + uses org.aion.log.AionLoggerFactory; requires aion.crypto; requires aion.apiserver; @@ -9,8 +11,8 @@ requires slf4j.api; requires aion.p2p; requires aion.fastvm; - - + requires aion.base; + requires libnzmq; exports org.aion; } diff --git a/modBoot/src/org/aion/Aion.java b/modBoot/src/org/aion/Aion.java index bffeda2b8b..32b0b9fe93 100644 --- a/modBoot/src/org/aion/Aion.java +++ b/modBoot/src/org/aion/Aion.java @@ -29,8 +29,17 @@ import static org.aion.zero.impl.Version.KERNEL_VERSION; import java.io.Console; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; -import java.util.ServiceLoader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; import java.util.function.Consumer; import org.aion.api.server.http.RpcServer; import org.aion.api.server.http.RpcServerBuilder; @@ -48,6 +57,7 @@ import org.aion.log.LogEnum; import org.aion.mcf.account.Keystore; import org.aion.mcf.config.CfgApiRpc; +import org.aion.mcf.config.CfgApiZmq; import org.aion.mcf.config.CfgSsl; import org.aion.mcf.mine.IMineRunner; import org.aion.solidity.Compiler; @@ -57,6 +67,7 @@ import org.aion.zero.impl.cli.Cli; import org.aion.zero.impl.config.CfgAion; import org.slf4j.Logger; +import org.zeromq.ZMQ; public class Aion { @@ -87,11 +98,23 @@ public static void main(String args[]) { * return true which means should save back to xml config */ if (cfg.fromXML()) { - if(args != null && args.length > 0 && !(args[0].equals("-v")||args[0].equals("--version"))) { + if (args != null && args.length > 0 && !(args[0].equals("-v") || args[0] + .equals("--version"))) { cfg.toXML(new String[]{"--id=" + cfg.getId()}); } } + //Check ZMQ server secure connect settings, generate keypair when the settings enabled and can't find the keypair. + if (cfg.getApi().getZmq().getActive() && cfg.getApi().getZmq() + .isSecureConnectEnabledEnabled()) { + try { + checkZmqKeyPair(); + } catch (Exception e) { + System.out.println("Check zmq keypair fail! " + e.toString()); + exit(1); + } + } + // Reads CLI (must be after the cfg.fromXML()) if (args != null && args.length > 0) { int ret = new Cli().call(args, cfg); @@ -104,7 +127,7 @@ public static void main(String args[]) { String UUID = cfg.getId(); if (!UUID.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { System.out.println("Invalid UUID; please check setting in config.xml"); - exit(-1); + exit(1); } try { @@ -131,7 +154,8 @@ public static void main(String args[]) { String[] filePath = new String[7]; // Log/Database path if (!cfg.getLog().getLogFile()) { - System.out.println("Logger disabled; to enable please check log settings in config.xml"); + System.out + .println("Logger disabled; to enable please check log settings in config.xml"); } else if (!cfg.getLog().isValidPath() && cfg.getLog().getLogFile()) { System.out.println("File path is invalid; please check log setting in config.xml"); return; @@ -146,7 +170,7 @@ public static void main(String args[]) { filePath[6] = CfgAion.getGenesisFilePath(); String path = - "\n-------------------------------- USED PATHS --------------------------------" + + "\n-------------------------------- USED PATHS --------------------------------" + "\n> Logger path: " + filePath[0] + "\n> Database path: " + filePath[1] + "\n> Keystore path: " + filePath[2] + @@ -158,14 +182,14 @@ public static void main(String args[]) { "\n----------------------------------------------------------------------------\n\n"; String logo = - "\n _____ \n" + + "\n _____ \n" + " .'. | .~ ~. |.. |\n" + " .' `. | | | | ``.. |\n" + " .''''''''`. | | | | ``.. |\n" + ".' `. | `._____.' | ``|\n\n"; // always print the version string in the center of the Aion logo - String versionStr = "v"+KERNEL_VERSION; + String versionStr = "v" + KERNEL_VERSION; String networkStr = CfgAion.getNetwork(); logo = appendLogo(logo, versionStr); logo = appendLogo(logo, networkStr); @@ -218,8 +242,8 @@ public static void main(String args[]) { } RpcServer rpcServer = null; - if(cfg.getApi().getRpc().isActive()) { - CfgApiRpc rpcCfg = cfg.getApi().getRpc(); + if (cfg.getApi().getRpc().isActive()) { + CfgApiRpc rpcCfg = cfg.getApi().getRpc(); Consumer>> commonRpcConfig = (rpcBuilder) -> { rpcBuilder.setUrl(rpcCfg.getIp(), rpcCfg.getPort()); @@ -232,14 +256,17 @@ public static void main(String args[]) { rpcBuilder.setRequestQueueSize(rpcCfg.getRequestQueueSize()); rpcBuilder.setStuckThreadDetectorEnabled(rpcCfg.isStuckThreadDetectorEnabled()); - if (rpcCfg.isCorsEnabled()) + if (rpcCfg.isCorsEnabled()) { rpcBuilder.enableCorsWithOrigin(rpcCfg.getCorsOrigin()); + } CfgSsl cfgSsl = rpcCfg.getSsl(); - if (cfgSsl.getEnabled()) + if (cfgSsl.getEnabled()) { rpcBuilder.enableSsl(cfgSsl.getCert(), sslPass); + } }; - RpcServerVendor rpcVendor = RpcServerVendor.fromString(rpcCfg.getVendor()).orElse(RpcServerVendor.UNDERTOW); + RpcServerVendor rpcVendor = RpcServerVendor.fromString(rpcCfg.getVendor()) + .orElse(RpcServerVendor.UNDERTOW); try { switch (rpcVendor) { case NANO: { @@ -260,9 +287,11 @@ public static void main(String args[]) { genLog.error("Failed to instantiate RPC server.", e); } - if (rpcServer == null) - throw new IllegalStateException("Issue with RPC settings caused server instantiation to fail. " + + if (rpcServer == null) { + throw new IllegalStateException( + "Issue with RPC settings caused server instantiation to fail. " + "Please check RPC settings in config file."); + } rpcServer.start(); } @@ -278,7 +307,8 @@ class ShutdownThreadHolder { private final ProtocolProcessor pp; private final RpcServer rpc; - private ShutdownThreadHolder(Thread zmqThread, IMineRunner nm, ProtocolProcessor pp, RpcServer rpc) { + private ShutdownThreadHolder(Thread zmqThread, IMineRunner nm, ProtocolProcessor pp, + RpcServer rpc) { this.zmqThread = zmqThread; this.miner = nm; this.pp = pp; @@ -338,10 +368,79 @@ private ShutdownThreadHolder(Thread zmqThread, IMineRunner nm, ProtocolProcessor } - public static String appendLogo(String value, String input) { + private static void checkZmqKeyPair() throws IOException { + File zmqkeyDir = new File( + System.getProperty("user.dir") + File.separator + CfgApiZmq.ZMQ_KEY_DIR); + + if (!zmqkeyDir.isDirectory()) { + if (!zmqkeyDir.mkdir()) { + System.out.println("zmq keystore directory could not be created. " + + "Please check user permissions or create directory manually."); + System.exit(1); + } + System.out.println(); + } + + if (!existZmqSecKeyFile(zmqkeyDir.toPath())) { + //System.out.println("Found existing secret key file. Please backup or remove it!"); + System.out.print("Can't find zmq key pair, generate new pair! \n"); + ZMQ.Curve.KeyPair kp = ZMQ.Curve.generateKeyPair(); + genKeyFile(zmqkeyDir.getPath(), kp.publicKey, kp.secretKey); + } else { + System.out.print("Find zmq key pair! \n"); + } + + } + + private static boolean existZmqSecKeyFile(final Path path) { + List files = org.aion.base.io.File.getFiles(path); + + for (File file : files) { + if (file.getName().contains("zmqCurveSeckey")) { + return true; + } + } + + return false; + } + + private static void genKeyFile(final String path, final String publicKey, + final String secretKey) throws IOException { + DateFormat df = new SimpleDateFormat("yy-MM-dd'T'HH-mm-ss'Z'"); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + String iso_date = df.format(new Date(System.currentTimeMillis())); + + String fileName = "UTC--" + iso_date + "--zmqCurvePubkey"; + writeKeyToFile(path, fileName, publicKey); + + fileName = "UTC--" + iso_date + "--zmqCurveSeckey"; + writeKeyToFile(path, fileName, secretKey); + } + + private static void writeKeyToFile(final String path, final String fileName, final String key) + throws IOException { + Set perms = PosixFilePermissions.fromString("rwxr-----"); + FileAttribute> attr = PosixFilePermissions.asFileAttribute(perms); + + Path p = Paths.get(path).resolve(fileName); + Path keyFile; + if (!java.nio.file.Files.exists(p)) { + keyFile = java.nio.file.Files.createFile(p, attr); + } else { + keyFile = p; + } + + FileOutputStream fos = new FileOutputStream(keyFile.toString()); + fos.write(key.getBytes()); + fos.close(); + } + + private static String appendLogo(String value, String input) { int leftPad = Math.round((44 - input.length()) / 2.0f) + 1; StringBuilder padInput = new StringBuilder(); - for (int i = 0; i < leftPad; i++) padInput.append(" "); + for (int i = 0; i < leftPad; i++) { + padInput.append(" "); + } padInput.append(input); value += padInput.toString(); value += "\n\n"; @@ -360,7 +459,8 @@ private static char[] getSslPassword(CfgAion cfg) { // 2) process started in non-interactive mode (background scheduler, redirected output, etc.) // don't wan't to compromise security in these scenarios if (console == null) { - System.out.println("SSL-certificate-use requested with RPC server and no console found. " + + System.out.println( + "SSL-certificate-use requested with RPC server and no console found. " + "Please set the ssl password in the config file (insecure) to run kernel non-interactively with this option."); exit(1); } else { @@ -368,7 +468,7 @@ private static char[] getSslPassword(CfgAion cfg) { console.printf("----------- INTERACTION REQUIRED ------------\n"); console.printf("---------------------------------------------\n"); sslPass = console.readPassword("Password for SSL keystore file [" - +sslCfg.getCert()+"]\n"); + + sslCfg.getCert() + "]\n"); } } diff --git a/modCrypto/src/module-info.java b/modCrypto/src/module-info.java index 8d38edb738..1c8388def6 100644 --- a/modCrypto/src/module-info.java +++ b/modCrypto/src/module-info.java @@ -2,6 +2,7 @@ requires slf4j.api; requires aion.base; requires aion.rlp; + requires libnsc; exports org.aion.crypto; exports org.aion.crypto.hash; exports org.aion.crypto.ed25519; diff --git a/modMcf/src/module-info.java b/modMcf/src/module-info.java index d902a5bd56..8c0589c0fe 100644 --- a/modMcf/src/module-info.java +++ b/modMcf/src/module-info.java @@ -7,6 +7,7 @@ requires aion.db.impl; requires slf4j.api; requires aion.p2p; + requires com.google.common; exports org.aion.mcf.account; exports org.aion.mcf.blockchain; From 27caad4afcf0599ecb6003a004ad089bba5c04ee Mon Sep 17 00:00:00 2001 From: AionJayT Date: Tue, 2 Oct 2018 16:03:17 -0400 Subject: [PATCH 13/16] undo format Cli and remove comment in Aion class --- .../src/org/aion/zero/impl/cli/Cli.java | 154 ++++++++---------- modBoot/src/org/aion/Aion.java | 1 - 2 files changed, 68 insertions(+), 87 deletions(-) diff --git a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java index 139bf6117c..e9bc87d33f 100644 --- a/modAionImpl/src/org/aion/zero/impl/cli/Cli.java +++ b/modAionImpl/src/org/aion/zero/impl/cli/Cli.java @@ -24,27 +24,26 @@ package org.aion.zero.impl.cli; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; + import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import com.google.common.io.Files; import org.aion.base.util.Hex; import org.aion.crypto.ECKey; import org.aion.crypto.ECKeyFac; import org.aion.mcf.account.Keystore; import org.aion.mcf.config.Cfg; -import org.aion.mcf.config.CfgApiZmq; import org.aion.mcf.config.CfgSsl; import org.aion.zero.impl.Version; import org.aion.zero.impl.config.CfgAion; import org.aion.zero.impl.db.RecoveryUtils; -import java.io.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - -import static org.aion.mcf.account.Keystore.exist; - +import java.io.Console; /** * Command line interface. @@ -53,32 +52,25 @@ */ public class Cli { - private File keystoreDir = new File( - System.getProperty("user.dir") + File.separator + CfgSsl.SSL_KEYSTORE_DIR); - - private File zmqkeyDir = new File( - System.getProperty("user.dir") + File.separator + CfgApiZmq.ZMQ_KEY_DIR); - private final String BASE_PATH = System.getProperty("user.dir"); - private String BASE_PATH_WITH_NETWORK = BASE_PATH + "/config/" + CfgAion.getNetwork(); + private String BASE_PATH_WITH_NETWORK = BASE_PATH + "/config/" + CfgAion.getNetwork(); private String dstConfig = BASE_PATH_WITH_NETWORK + "/config.xml"; private String dstGenesis = BASE_PATH_WITH_NETWORK + "/genesis.json"; + File keystoreDir = new File(System.getProperty("user.dir") + File.separator + CfgSsl.SSL_KEYSTORE_DIR); + enum Network { MAINNET, CONQUEST; @Override public String toString() { - switch (this) { - case MAINNET: - return "mainnet"; - case CONQUEST: - return "conquest"; - default: - throw new IllegalArgumentException(); + switch(this) { + case MAINNET: return "mainnet"; + case CONQUEST: return "conquest"; + default: throw new IllegalArgumentException(); } } } @@ -106,8 +98,7 @@ public int call(final String[] args, Cfg cfg, String path) { return 1; } else { while (index < args.length) { - if (args[index].equals("-d") || args[index].equals("-n") || args[index] - .equals("--datadir") || args[index].equals("--network")) { + if(args[index].equals("-d")||args[index].equals("-n")||args[index].equals("--datadir")||args[index].equals("--network")) { multi = true; break; } @@ -116,11 +107,12 @@ public int call(final String[] args, Cfg cfg, String path) { } // Switches datadir && network - if (multi) { + if(multi) { String[] newArgs = Arrays.copyOfRange(args, index, args.length); call(newArgs, cfg); } + switch (args[1]) { case "create": if (!createAccount()) { @@ -157,11 +149,10 @@ public int call(final String[] args, Cfg cfg, String path) { case CONQUEST: CfgAion.setNetwork(net.toString()); File dir = new File(BASE_PATH + "/config/" + net); - if (!dir.exists()) { + if(!dir.exists()) { dir.mkdirs(); } - CfgAion.setConfFilePath( - BASE_PATH + "/config/" + args[1] + "/config.xml"); + CfgAion.setConfFilePath(BASE_PATH + "/config/" + args[1] + "/config.xml"); System.out.println("\nNew config generated for " + args[1]); break; default: @@ -247,7 +238,7 @@ public int call(final String[] args, Cfg cfg, String path) { case "-n": case "--network": - if ((args.length == 2 || args.length == 4) && isValid(args[1])) { + if ( (args.length == 2 || args.length == 4) && isValid(args[1])) { net = determineNetwork(args[1].toLowerCase()); @@ -259,37 +250,31 @@ public int call(final String[] args, Cfg cfg, String path) { if (args.length == 2) { CfgAion.setNetwork(net.toString()); - BASE_PATH_WITH_NETWORK = - BASE_PATH + "/config/" + CfgAion.getNetwork(); + BASE_PATH_WITH_NETWORK = BASE_PATH + "/config/" + CfgAion.getNetwork(); CfgAion.setConfFilePath(BASE_PATH_WITH_NETWORK + "/config.xml"); - CfgAion.setGenesisFilePath( - (BASE_PATH_WITH_NETWORK + "/genesis.json")); + CfgAion.setGenesisFilePath((BASE_PATH_WITH_NETWORK + "/genesis.json")); copyNetwork(path, net); cfg.getLog().setLogPath(net.toString() + "/log"); cfg.getDb().setDatabasePath(net.toString() + "/database"); - Keystore - .setKeystorePath(path + "/" + net.toString() + "/keystore"); + Keystore.setKeystorePath(path + "/" + net.toString() + "/keystore"); return 2; } // -n [network] -d [directory] - else if ((args[2].equals("-d") || args[2].equals("--datadir")) - && isValid(args[3])) { + else if ((args[2].equals("-d")||args[2].equals("--datadir")) && isValid(args[3])) { CfgAion.setNetwork(net.toString()); - BASE_PATH_WITH_NETWORK = - BASE_PATH + "/config/" + CfgAion.getNetwork(); + BASE_PATH_WITH_NETWORK = BASE_PATH + "/config/" + CfgAion.getNetwork(); CfgAion.setConfFilePath(BASE_PATH_WITH_NETWORK + "/config.xml"); - CfgAion.setGenesisFilePath( - (BASE_PATH_WITH_NETWORK + "/genesis.json")); + CfgAion.setGenesisFilePath((BASE_PATH_WITH_NETWORK + "/genesis.json")); String[] newArgs = Arrays.copyOfRange(args, 2, args.length); call(newArgs, cfg); return 2; - } else if (!(args[2].equals("-d") || args[2].equals("--datadir"))) { + } else if (!(args[2].equals("-d")||args[2].equals("--datadir"))) { System.out.println("\nInvalid multi arguments!\n"); printHelp(); return 1; @@ -316,10 +301,10 @@ && isValid(args[3])) { return 1; } - // Determines database folder path + // Determines database folder path case "-d": case "--datadir": - if ((args.length == 2 || args.length == 4) && isValid(args[1])) { + if ( (args.length == 2 || args.length == 4) && isValid(args[1])) { // -d [directory] if (args.length == 2) { @@ -327,8 +312,7 @@ && isValid(args[3])) { copyNetwork(path + "/" + args[1], net); cfg.getLog().setLogPath(args[1] + "/" + net + "/log"); cfg.getDb().setDatabasePath(args[1] + "/" + net + "/database"); - Keystore - .setKeystorePath(path + "/" + args[1] + "/" + net + "/keystore"); + Keystore.setKeystorePath(path + "/" + args[1] + "/" + net + "/keystore"); return 2; } @@ -342,11 +326,10 @@ else if (isValid(args[3])) { copyNetwork(path + "/" + args[1], net); cfg.getLog().setLogPath(args[1] + "/" + net + "/log"); cfg.getDb().setDatabasePath(args[1] + "/" + net + "/database"); - Keystore - .setKeystorePath(path + "/" + args[1] + "/" + net + "/keystore"); + Keystore.setKeystorePath(path + "/" + args[1] + "/" + net + "/keystore"); return 2; - } else if (!(args[2].equals("-n") || args[2].equals("--network"))) { + } else if (!(args[2].equals("-n")||args[2].equals("--network"))) { System.out.println("\nInvalid multi arguments!\n"); printHelp(); return 1; @@ -465,9 +448,9 @@ else if (isValid(args[3])) { return 1; } - System.out.println(); + System.out.println(""); } catch (Throwable e) { - System.out.println(e.toString()); + System.out.println(""); return 1; } @@ -483,32 +466,23 @@ private void printHelp() { System.out.println(" -h show help info"); System.out.println(); System.out.println(" -a create create a new account"); - System.out - .println(" -a list list all existing accounts"); - System.out.println( - " -a export [address] export private key of an account"); + System.out.println(" -a list list all existing accounts"); + System.out.println(" -a export [address] export private key of an account"); System.out.println(" -a import [private_key] import private key"); System.out.println(); - System.out.println( - " -c [network] create config to selected network; mainnet, conquest"); + System.out.println(" -c [network] create config to selected network; mainnet, conquest"); System.out.println(); - System.out.println( - " -n, --network [network] execute kernel with selected network; mainnet, conquest"); + System.out.println(" -n, --network [network] execute kernel with selected network; mainnet, conquest"); System.out.println(); - System.out.println( - " -d, --datadir [directory] execute kernel with selected database directory"); + System.out.println(" -d, --datadir [directory] execute kernel with selected database directory"); System.out.println(); System.out.println(" -i show information"); System.out.println(); - System.out.println( - " -s create create an ssl certificate for localhost"); - System.out.println( - " -s create [[hostname] [ip]] create an ssl certificate for a custom hostname and ip"); + System.out.println(" -s create create an ssl certificate for localhost"); + System.out.println(" -s create [[hostname] [ip]] create an ssl certificate for a custom hostname and ip"); System.out.println(); - System.out.println( - " -r remove blocks on side chains and correct block info"); - System.out.println( - " -r [block_number] revert db up to specific block number"); + System.out.println(" -r remove blocks on side chains and correct block info"); + System.out.println(" -r [block_number] revert db up to specific block number"); System.out.println(); System.out.println(" -v show version"); } @@ -521,7 +495,7 @@ private void printHelp() { */ private Network determineNetwork(String arg) { Network net; - switch (arg) { + switch(arg) { case "mainnet": net = Network.MAINNET; break; @@ -543,7 +517,7 @@ private Network determineNetwork(String arg) { * @param path input to append base directory to copy to * @param net input to determine network to copy from */ - private void copyNetwork(String path, Network net) { + private void copyNetwork(String path, Network net) { File dir1 = new File(path + "/" + net + "/config"); File dir2 = new File(path + "/" + net + "/keystore"); @@ -612,7 +586,7 @@ private boolean listAccounts() { * @return boolean */ private boolean exportPrivateKey(String address) { - if (!exist(address)) { + if (!Keystore.exist(address)) { System.out.println("The account does not exist!"); return false; } @@ -742,6 +716,8 @@ private RecoveryUtils.Status revertTo(String blockNumber) { /** * Checks for illegal inputs (for datadir && network names) + * @param value + * @return */ public static boolean isValid(String value) { return !value.isEmpty() && !value.matches(".*[-=+,.?;:'!@#$%^&*].*"); @@ -782,7 +758,7 @@ private String getCertName(Console console) { private String getCertPass(Console console) { int minPassLen = 7; String certPass = String.valueOf(console.readPassword( - "Enter certificate password (at least " + minPassLen + " characters):\n")); + "Enter certificate password (at least " + minPassLen + " characters):\n")); if ((certPass == null) || (certPass.isEmpty())) { System.out.println("Error: no certificate password entered."); System.exit(1); @@ -803,20 +779,24 @@ public String getDstGenesis() { } // Methods below taken from FileUtils class - private static boolean copyRecursively(File src, File target) { + private static boolean copyRecursively(File src, File target) + { if (src.isDirectory()) { return copyDirectoryContents(src, target); - } else { + } + else { try { - com.google.common.io.Files.copy(src, target); + Files.copy(src, target); return true; - } catch (IOException e) { + } + catch (IOException e) { return false; } } } - private static boolean copyDirectoryContents(File src, File target) { + private static boolean copyDirectoryContents(File src, File target) + { Preconditions.checkArgument(src.isDirectory(), "Source dir is not a directory: %s", src); // Don't delete symbolic link directories @@ -834,24 +814,26 @@ private static boolean copyDirectoryContents(File src, File target) { return success; } - private static boolean isSymbolicLink(File file) { + private static boolean isSymbolicLink(File file) + { try { File canonicalFile = file.getCanonicalFile(); File absoluteFile = file.getAbsoluteFile(); File parentFile = file.getParentFile(); // a symbolic link has a different name between the canonical and absolute path return !canonicalFile.getName().equals(absoluteFile.getName()) || - // or the canonical parent path is not the same as the file's parent path, - // provided the file has a parent path - parentFile != null && !parentFile.getCanonicalPath() - .equals(canonicalFile.getParent()); - } catch (IOException e) { + // or the canonical parent path is not the same as the file's parent path, + // provided the file has a parent path + parentFile != null && !parentFile.getCanonicalPath().equals(canonicalFile.getParent()); + } + catch (IOException e) { // error on the side of caution return true; } } - private static ImmutableList listFiles(File dir) { + private static ImmutableList listFiles(File dir) + { File[] files = dir.listFiles(); if (files == null) { return ImmutableList.of(); diff --git a/modBoot/src/org/aion/Aion.java b/modBoot/src/org/aion/Aion.java index 32b0b9fe93..b1ea9713eb 100644 --- a/modBoot/src/org/aion/Aion.java +++ b/modBoot/src/org/aion/Aion.java @@ -382,7 +382,6 @@ private static void checkZmqKeyPair() throws IOException { } if (!existZmqSecKeyFile(zmqkeyDir.toPath())) { - //System.out.println("Found existing secret key file. Please backup or remove it!"); System.out.print("Can't find zmq key pair, generate new pair! \n"); ZMQ.Curve.KeyPair kp = ZMQ.Curve.generateKeyPair(); genKeyFile(zmqkeyDir.getPath(), kp.publicKey, kp.secretKey); From a51c94495ae03048fe81e09b2ee55f5c1575be14 Mon Sep 17 00:00:00 2001 From: AionJayT Date: Tue, 2 Oct 2018 16:33:05 -0400 Subject: [PATCH 14/16] fix pack issue --- modBoot/src/org/aion/Aion.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/modBoot/src/org/aion/Aion.java b/modBoot/src/org/aion/Aion.java index b1ea9713eb..fc092b9e6a 100644 --- a/modBoot/src/org/aion/Aion.java +++ b/modBoot/src/org/aion/Aion.java @@ -104,6 +104,15 @@ public static void main(String args[]) { } } + + // Reads CLI (must be after the cfg.fromXML()) + if (args != null && args.length > 0) { + int ret = new Cli().call(args, cfg); + if (ret != 2) { + exit(ret); + } + } + //Check ZMQ server secure connect settings, generate keypair when the settings enabled and can't find the keypair. if (cfg.getApi().getZmq().getActive() && cfg.getApi().getZmq() .isSecureConnectEnabledEnabled()) { @@ -115,14 +124,6 @@ public static void main(String args[]) { } } - // Reads CLI (must be after the cfg.fromXML()) - if (args != null && args.length > 0) { - int ret = new Cli().call(args, cfg); - if (ret != 2) { - exit(ret); - } - } - // UUID check String UUID = cfg.getId(); if (!UUID.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { From 699080a1a1e30ffe6ff0b2c5de3a6073ec337d94 Mon Sep 17 00:00:00 2001 From: AionJayT Date: Wed, 3 Oct 2018 17:47:44 -0400 Subject: [PATCH 15/16] fix module-info settings for modAionImpl --- modAionImpl/src/module-info.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modAionImpl/src/module-info.java b/modAionImpl/src/module-info.java index 56f3f718ea..0fa7b4df30 100644 --- a/modAionImpl/src/module-info.java +++ b/modAionImpl/src/module-info.java @@ -20,6 +20,8 @@ requires java.xml; requires slf4j.api; requires com.google.common; + requires info.picocli; + requires commons.lang3; exports org.aion.equihash; exports org.aion.zero.impl.blockchain; @@ -28,6 +30,7 @@ exports org.aion.zero.impl.types; exports org.aion.zero.impl.config; exports org.aion.zero.impl.cli; + opens org.aion.zero.impl.cli; exports org.aion.zero.impl.db; exports org.aion.zero.impl.sync; exports org.aion.zero.impl.config.dynamic; From 2208f82a2f79f86bed1f1198bd381e531790b942 Mon Sep 17 00:00:00 2001 From: AionJayT Date: Wed, 3 Oct 2018 17:52:07 -0400 Subject: [PATCH 16/16] update default config settings for the Java API secure connect --- modBoot/resource/custom/config.xml | 4 +++- modBoot/resource/mainnet/config.xml | 4 ++-- modBoot/resource/mastery/config.xml | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modBoot/resource/custom/config.xml b/modBoot/resource/custom/config.xml index 645f43f1ec..46885fbb6d 100644 --- a/modBoot/resource/custom/config.xml +++ b/modBoot/resource/custom/config.xml @@ -11,7 +11,9 @@ 1 - + + true + 10E9 diff --git a/modBoot/resource/mainnet/config.xml b/modBoot/resource/mainnet/config.xml index 685b063d30..60d31003eb 100644 --- a/modBoot/resource/mainnet/config.xml +++ b/modBoot/resource/mainnet/config.xml @@ -4,12 +4,12 @@ [NODE-ID-PLACEHOLDER] - + false web3,eth,personal,stratum,ops - + true diff --git a/modBoot/resource/mastery/config.xml b/modBoot/resource/mastery/config.xml index 1f1ec44ce6..20e59bc45e 100755 --- a/modBoot/resource/mastery/config.xml +++ b/modBoot/resource/mastery/config.xml @@ -9,7 +9,9 @@ web3,eth,personal,stratum,ops - + + true + 10E9