From 7f75fd53f65e069fce2e183624d4d2f7cc4b3cd3 Mon Sep 17 00:00:00 2001 From: myz Date: Mon, 7 Mar 2022 00:14:12 +0900 Subject: [PATCH] add PriceProver and integration test --- .gitmodules | 6 +- .gitsubmodule | 3 - README.md | 42 +-- .../akosba/xjsnark/1.0/_remote.repositories | 4 + .../xjsnark/1.0/xjsnark-1.0.jar} | Bin depends/akosba/xjsnark/1.0/xjsnark-1.0.pom | 9 + .../akosba/xjsnark/maven-metadata-local.xml | 12 + depends/libsnark/run_ppzksnark | 0 .../java/com/abstrlabs/priceprover/CLI.java | 43 --- .../abstrlabs/priceprover/CircuitBuilder.java | 28 +- .../priceprover/LibsnarkCallBack.java | 9 +- .../priceprover/PageSignerCallBack.java | 153 +++++------ .../abstrlabs/priceprover/PriceProver.java | 90 +++++++ .../abstrlabs/priceprover/util/Utility.java | 254 +++++++++--------- .../priceprover/LibsnarkCallBackTest.java | 4 - .../priceprover/PageSignerCallBackTest.java | 31 ++- .../priceprover/PriceProverTest.java | 24 ++ 17 files changed, 411 insertions(+), 301 deletions(-) delete mode 100644 .gitsubmodule create mode 100644 depends/akosba/xjsnark/1.0/_remote.repositories rename depends/{xjsnark/xjsnark_backend.jar => akosba/xjsnark/1.0/xjsnark-1.0.jar} (100%) create mode 100644 depends/akosba/xjsnark/1.0/xjsnark-1.0.pom create mode 100644 depends/akosba/xjsnark/maven-metadata-local.xml mode change 100644 => 100755 depends/libsnark/run_ppzksnark delete mode 100644 src/main/java/com/abstrlabs/priceprover/CLI.java create mode 100644 src/main/java/com/abstrlabs/priceprover/PriceProver.java create mode 100644 src/test/java/com/abstrlabs/priceprover/PriceProverTest.java diff --git a/.gitmodules b/.gitmodules index cbbbb97..8ed8ded 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "depends/pagesigner-cli"] - path = depends/pagesigner-cli - url = git@github.com:AbstrLabs/pagesigner-cli.git +[submodule "depends/pagesigner-cli"] + path = depends/pagesigner-cli + url = git@github.com:AbstrLabs/pagesigner-cli.git diff --git a/.gitsubmodule b/.gitsubmodule deleted file mode 100644 index cb4c3db..0000000 --- a/.gitsubmodule +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "depends/pagesigner-cli"] - path = depends/pagesigner-cli - url = git@github.com:AbstrLabs/pagesigner-cli.git \ No newline at end of file diff --git a/README.md b/README.md index 230b82e..4381026 100644 --- a/README.md +++ b/README.md @@ -16,32 +16,34 @@ create a transaction payload: call price contract’s submit_price method, with ### Usage This CLI is built on [picocli](https://www.picocli.info). +(Optional) define an alias: -#### trigger pagersigner-cli +```alias priceprover='java -cp priceprover-0.0.2.jar com.abstrlabs.priceprover.PriceProver``` -This step will normalize the asset name to the ones supported by our selected API: Alphadvantage. E.g. aIBM → IBM -Generate a headers.txt that contains HTTP request to stock price API -Invoke pagersigner-cli and output the notary file. - -CLI usage (for now, will be improved soon): -``` -java -cp priceprover-0.0.1.jar com.abstrlabs.priceprover.PageSignerCallBack -as aIBM -op ./out +Usage: `priceprover [-hVv] [-fi] [-as=] [-op=] [COMMAND]` ``` -This is quite verbose. You can define an alias. For example: +given the stock symbol, notarize the price and generate the proof -```alias pagesigner='java -cp priceprover-0.0.1.jar com.abstrlabs.priceprover.PageSignerCallBack``` +-as, --asset the asset name used to obtain the price data. -#### notary json parser -This step could parse the notary.json and get the required input java objects. +-fi, --firstTime if it is first time run -CLI usage : -``` -java -cp priceprover-0.0.1.jar com.abstrlabs.priceprover.NotaryJsonParser -nf ./out/notary.json +-h, --help show help message and exit. + +-op, --outputPath output path for generated files + +-v, --verbose specify multiple -v options to increase verbosity. + for example, `-v` - info, '-vv' - debug,'-vvv' -trace + +-V, --version print version information and exit. + +SubCommands: +notarize Call pagesigner-cli and notarize the stock price +build Parse the notary json from pagesinger, and build the circuit/input +by xjsnark +prove Trigger libsnark and generate the proof ``` -### Todo -- [ ] *update the rest steps and cli usage* -- [ ] *combine submodules together* ### Build (Please install [maven](https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html) if you haven't). To build an executable jar: @@ -50,4 +52,8 @@ java -cp priceprover-0.0.1.jar com.abstrlabs.priceprover.NotaryJsonParser -nf ./ ### Q&A +#### Cannot run program "./depends/libsnark/run_ppzksnark": error=13, Permission denied +Try +`chmod u+x ./depends/libsnark/run_ppzksnark` + ### References diff --git a/depends/akosba/xjsnark/1.0/_remote.repositories b/depends/akosba/xjsnark/1.0/_remote.repositories new file mode 100644 index 0000000..c0fe4b5 --- /dev/null +++ b/depends/akosba/xjsnark/1.0/_remote.repositories @@ -0,0 +1,4 @@ +#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice. +#Sun Mar 06 23:48:53 JST 2022 +xjsnark-1.0.jar>= +xjsnark-1.0.pom>= diff --git a/depends/xjsnark/xjsnark_backend.jar b/depends/akosba/xjsnark/1.0/xjsnark-1.0.jar similarity index 100% rename from depends/xjsnark/xjsnark_backend.jar rename to depends/akosba/xjsnark/1.0/xjsnark-1.0.jar diff --git a/depends/akosba/xjsnark/1.0/xjsnark-1.0.pom b/depends/akosba/xjsnark/1.0/xjsnark-1.0.pom new file mode 100644 index 0000000..34eebab --- /dev/null +++ b/depends/akosba/xjsnark/1.0/xjsnark-1.0.pom @@ -0,0 +1,9 @@ + + + 4.0.0 + akosba + xjsnark + 1.0 + POM was created from install:install-file + diff --git a/depends/akosba/xjsnark/maven-metadata-local.xml b/depends/akosba/xjsnark/maven-metadata-local.xml new file mode 100644 index 0000000..7afa35d --- /dev/null +++ b/depends/akosba/xjsnark/maven-metadata-local.xml @@ -0,0 +1,12 @@ + + + akosba + xjsnark + + 1.0 + + 1.0 + + 20220306144853 + + diff --git a/depends/libsnark/run_ppzksnark b/depends/libsnark/run_ppzksnark old mode 100644 new mode 100755 diff --git a/src/main/java/com/abstrlabs/priceprover/CLI.java b/src/main/java/com/abstrlabs/priceprover/CLI.java deleted file mode 100644 index f8817f9..0000000 --- a/src/main/java/com/abstrlabs/priceprover/CLI.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.abstrlabs.priceprover; - -import picocli.CommandLine; - -import java.util.concurrent.Callable; - -@CommandLine.Command(name = "priceprover", subcommands = { - PageSignerCallBack.class, - CircuitBuilder.class}) -public class CLI implements Callable { - public Integer call() { - /* todo: wrap up all the steps: - * 1. PageSignerCallBack - * 2. NotaryJsonParser - * 3. CircuitCompile (using xjsnark_backend) - * 4. Prove (using libsnark) - * 5. Generate verifier contract - */ - return 0; // exit code - } - - - // A reference to this method can be used as a custom execution strategy - // that first calls the init() method, - // and then delegates to the default execution strategy. - private int executionStrategy(CommandLine.ParseResult parseResult) { - init(); // custom initialization to be done before executing any command or subcommand - return new CommandLine.RunLast().execute(parseResult); // default execution strategy - } - - - private void init() { - // ... - } - - public static void main(String[] args) { - CLI app = new CLI(); - new CommandLine(app) - .setExecutionStrategy(app::executionStrategy) - .execute(args); - } - -} diff --git a/src/main/java/com/abstrlabs/priceprover/CircuitBuilder.java b/src/main/java/com/abstrlabs/priceprover/CircuitBuilder.java index a1dc8c8..3c3b2de 100644 --- a/src/main/java/com/abstrlabs/priceprover/CircuitBuilder.java +++ b/src/main/java/com/abstrlabs/priceprover/CircuitBuilder.java @@ -11,36 +11,50 @@ import picocli.CommandLine.Option; import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.concurrent.Callable; @Log4j2 -@Command(name = "preprocess", description = "Parse the notary json from pagesinger, do the preprocess, and build the circuit by xjsnark") +@Command(name = "build", mixinStandardHelpOptions = true, description = "Parse the notary json from pagesinger, and build the circuit/input by xjsnark") public class CircuitBuilder implements Callable { public NotaryCheckInput notaryCheckInput = new NotaryCheckInput(); - private final String NOTARY_PUBKEY = "-----BEGIN PUBLIC KEY-----\n" + + private static final String NOTARY_FILE_NAME = "notary.json"; + private static final String NOTARY_PUBKEY = "-----BEGIN PUBLIC KEY-----\n" + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAp3iALChsj8lOkEpY1F5BeCMcyd6\n" + "282weDfsNf8lMYi7xEVVVq0W+is27cCnHZAc0resZHTdX4KoSrFgehhPcA==\n" + "-----END PUBLIC KEY-----"; // recent notary pubkey (22-3-5), keep the old pubkey for test // "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdxg4idfkVEnjIwW8OwNtg9rG0EmajcIR3P6dmq10ZZBFxkTUCPX5BkrFT0cIFAWp2FU9Jt30pl4W4E7UEaDX+g=="; - @Option(names = {"-nf", "--notaryfile"}, defaultValue = "./out/notary.json", description = "decode and preprocess notary json.") - String notaryFilePath; - @Option(names = {"-op", "--outputPath"}, defaultValue = "./out", description = "output path for generated headers and notary files") String outputPath; + @Option(names = {"-nf", "--notaryfile"}, description = "notary file that usually named notary.json") + String notaryFilePath; + + @CommandLine.Option(names = {"-fi", "--firstTime"}, description = "if it is first time run") + boolean firstTime; + @Override public Integer call() throws Exception { + if (notaryFilePath == null) { + notaryFilePath = String.valueOf(Paths.get(outputPath, NOTARY_FILE_NAME)); + } + // parse notary json parseNotaryJson(notaryFilePath); // build circuit - new TLSNotaryCheck(notaryCheckInput, outputPath); - + if (firstTime) { + new TLSNotaryCheck(notaryCheckInput, outputPath); + } else { + // todo: only translate input + new TLSNotaryCheck(notaryCheckInput, outputPath); + } return 0; } diff --git a/src/main/java/com/abstrlabs/priceprover/LibsnarkCallBack.java b/src/main/java/com/abstrlabs/priceprover/LibsnarkCallBack.java index e12f4ce..d74806d 100644 --- a/src/main/java/com/abstrlabs/priceprover/LibsnarkCallBack.java +++ b/src/main/java/com/abstrlabs/priceprover/LibsnarkCallBack.java @@ -8,7 +8,7 @@ import java.util.concurrent.Callable; @Log4j2 -@CommandLine.Command(name = "libsnark", description = "Trigger libsnark and generate the proof") +@CommandLine.Command(name = "prove", mixinStandardHelpOptions = true, description = "Trigger libsnark and generate the proof") public class LibsnarkCallBack implements Callable { private static final String CIRCUIT_NAME = "priceProver.circuit"; @@ -21,6 +21,8 @@ public class LibsnarkCallBack implements Callable { private static final String GENERATE = "generate"; private static final String PROVE = "prove"; + @CommandLine.Option(names = {"-op", "--outputPath"}, defaultValue = "./out", description = "output path for generated headers and notary files") + String outputPath; @CommandLine.Option(names = {"-xc", "--xjsnarkCircuit"}, defaultValue = "./out/TLSNotaryCheck.arith", description = "the xjsnark generated circuit") String xjsnarkCircuit; @@ -28,10 +30,7 @@ public class LibsnarkCallBack implements Callable { @CommandLine.Option(names = {"-xi", "--xjsnarkInput"}, defaultValue = "./out/TLSNotaryCheck_Sample_Run1.in", description = "the xjsnark generated input") String xjsnarkInput; - @CommandLine.Option(names = {"-op", "--outputPath"}, defaultValue = "./out", description = "output path for generated headers and notary files") - String outputPath; - - @CommandLine.Option(names = {"-fi", "--firstTime"}, description = "first time run the circuit") + @CommandLine.Option(names = {"-fi", "--firstTime"}, description = "if it is first time run") boolean firstTime; @Override diff --git a/src/main/java/com/abstrlabs/priceprover/PageSignerCallBack.java b/src/main/java/com/abstrlabs/priceprover/PageSignerCallBack.java index 46ce20f..2793b58 100644 --- a/src/main/java/com/abstrlabs/priceprover/PageSignerCallBack.java +++ b/src/main/java/com/abstrlabs/priceprover/PageSignerCallBack.java @@ -1,75 +1,78 @@ -package com.abstrlabs.priceprover; - -import com.abstrlabs.priceprover.util.CommandExecutor; -import lombok.extern.log4j.Log4j2; -import picocli.CommandLine; -import picocli.CommandLine.Command; -import picocli.CommandLine.Option; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.concurrent.Callable; - -@Log4j2 -@Command(name = "pagesigner", description = "Call pagesigner-cli and generate a stock price notray json") -public class PageSignerCallBack implements Callable { - - @Option(names = {"-as", "--asset"}, defaultValue = "aIBM", description = "the asset name used to obtain the price data jason and the notary file via PageSinger.") - String asset; - - @Option(names = {"-op", "--outputPath"}, defaultValue = "./out", description = "output path for generated headers and notary files") - String outputPath; - - @Override - public Integer call(){ - String assetName = normalizeAssetName(asset); - - try { - //generate header.txt - String currentWorkingDir = System.getProperty("user.dir"); - String headersPath = currentWorkingDir + "/headers.txt"; - String content = "GET /query?function=GLOBAL_QUOTE&symbol=" + assetName + "&apikey=demo HTTP/1.1\n" + - "Host: www.alphavantage.co"; - File headersFile = new File(headersPath); - if (headersFile.createNewFile()) { - log.info("Headers file created successfully"); - }; - FileWriter headersWriter = new FileWriter(headersFile); - headersWriter.write(content); - headersWriter.close(); - - //call pagesigner-cli - String[] pagesignerCommand = new String[]{"./depends/pagesigner-cli/pgsg-node.js", "notarize", "www.alphavantage.co", "--headers", headersPath, outputPath}; - CommandExecutor ce = new CommandExecutor(); - String missionName = "Call pagesigner-cli"; - if (ce.execute(missionName, pagesignerCommand)) { - log.info("saved the notary file into path:" + outputPath); - return 0; - } else { - return -1; - } - - } catch (IOException e) { - e.printStackTrace(); - return -2; - } - } - - /** - * input : asset name, eg. aIBM, aAAPL - * output: normalized asset name, eg. IBM, AAPL - */ - private String normalizeAssetName(String asset) { - if (asset.length() > 1 && asset.charAt(0) == 'a') { - asset = asset.substring(1); - } - log.info("The normalized asset name is " + asset); - return asset; - } - - public static void main(String[] args) { - int exitCode = new CommandLine(new PageSignerCallBack()).execute(args); - System.exit(exitCode); - } -} +package com.abstrlabs.priceprover; + +import com.abstrlabs.priceprover.util.CommandExecutor; +import lombok.extern.log4j.Log4j2; +import picocli.CommandLine; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.Callable; + +@Log4j2 +@Command(name = "notarize", description = "Call pagesigner-cli and notarize the stock price") +public class PageSignerCallBack implements Callable { + + private static final String HEADERS = "headers"; + + @Option(names = {"-as", "--asset"}, defaultValue = "aIBM", description = "the asset name used to obtain the price data jason and the notary file via PageSinger.") + String asset; + + @Option(names = {"-op", "--outputPath"}, defaultValue = "./out", description = "output path for generated headers and notary files") + String outputPath; + + @Override + public Integer call(){ + String assetName = normalizeAssetName(asset); + + try { + // generate header.txt + String headersPath = String.valueOf(Paths.get(outputPath, HEADERS)); + String content = "GET /query?function=GLOBAL_QUOTE&symbol=" + assetName + "&apikey=demo HTTP/1.1\n" + + "Host: www.alphavantage.co"; + File headersFile = new File(headersPath); + if (headersFile.createNewFile()) { + log.info("Headers file created successfully"); + }; + FileWriter headersWriter = new FileWriter(headersFile); + headersWriter.write(content); + headersWriter.close(); + + // call pagesigner-cli + String[] pagesignerCommand = new String[]{"./depends/pagesigner-cli/pgsg-node.js", "notarize", "www.alphavantage.co", "--headers", headersPath, outputPath}; + CommandExecutor ce = new CommandExecutor(); + String missionName = "Call pagesigner-cli"; + if (ce.execute(missionName, pagesignerCommand)) { + log.info("saved the notary file into path:" + outputPath); + return 0; + } else { + return -1; + } + + } catch (IOException e) { + e.printStackTrace(); + return -2; + } + } + + /** + * input : asset name, eg. aIBM, aAAPL + * output: normalized asset name, eg. IBM, AAPL + */ + private String normalizeAssetName(String asset) { + if (asset.length() > 1 && asset.charAt(0) == 'a') { + asset = asset.substring(1); + } + log.debug("The normalized asset name is " + asset); + return asset; + } + + public static void main(String[] args) { + int exitCode = new CommandLine(new PageSignerCallBack()).execute(args); + System.exit(exitCode); + } +} diff --git a/src/main/java/com/abstrlabs/priceprover/PriceProver.java b/src/main/java/com/abstrlabs/priceprover/PriceProver.java new file mode 100644 index 0000000..7edea5c --- /dev/null +++ b/src/main/java/com/abstrlabs/priceprover/PriceProver.java @@ -0,0 +1,90 @@ +package com.abstrlabs.priceprover; + +import lombok.extern.log4j.Log4j2; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.config.Configurator; +import picocli.CommandLine; + +import java.util.concurrent.Callable; + +@Log4j2 +@CommandLine.Command(name = "priceprover", mixinStandardHelpOptions = true, version = "0.0.2", + description = "given the stock symbol, notarize the price and generate the proof", subcommands = { + PageSignerCallBack.class, + CircuitBuilder.class, + LibsnarkCallBack.class}) +public class PriceProver implements Callable { + @CommandLine.Option(names = {"-as", "--asset"}, defaultValue = "aIBM", description = "the asset name used to obtain the price data.") + String asset; + + @CommandLine.Option(names = {"-op", "--outputPath"}, defaultValue = "./out", description = "output path for generated files") + String outputPath; + + @CommandLine.Option(names = {"-fi", "--firstTime"}, description = "if it is first time run") + boolean firstTime; + + @CommandLine.Option(names = {"-v", "--verbose"}, description = + {"Specify multiple -v options to increase verbosity.", "For example, `-v` - info, '-vv' - debug,'-vvv' - trace "}) + boolean[] verbosity = new boolean[1]; + + /** wrap up all the steps: + * 1. PageSignerCallBack (notary the price data) + * 2. CircuitBuilder (parse notary json, build circuit and input) + * 3. LibsnarkCallBack (generate proof) + * 4. Generate verifier contract (todo) + */ + public Integer call() { + + // PageSignerCallBack + CommandLine cmd = new CommandLine(new PageSignerCallBack()); + if (cmd.execute("-as", asset, "-op", outputPath) == 0) { + // CircuitBuilder + if (firstTime) { + cmd = new CommandLine(new CircuitBuilder()); + if (cmd.execute("-fi", "-op", outputPath) == 0) { + // LibsnarkCallBack + cmd = new CommandLine(new LibsnarkCallBack()); + return cmd.execute("-fi"); + } + } else { + cmd = new CommandLine(new CircuitBuilder()); + if (cmd.execute("-op", outputPath) == 0) { + // LibsnarkCallBack + cmd = new CommandLine(new LibsnarkCallBack()); + return cmd.execute(); + } + } + } + return -1; // exit code + } + + + // A reference to this method can be used as a custom execution strategy + // that first calls the init() method, + // and then delegates to the default execution strategy. + int executionStrategy(CommandLine.ParseResult parseResult) { + configureLoggers(); + return new CommandLine.RunLast().execute(parseResult); // default execution strategy + } + + private void configureLoggers() { + if (verbosity.length >= 3) { + Configurator.setAllLevels(LogManager.getRootLogger().getName(), Level.TRACE); + } else if (verbosity.length == 2) { + Configurator.setAllLevels(LogManager.getRootLogger().getName(), Level.DEBUG); + } else if (verbosity.length == 1) { + Configurator.setAllLevels(LogManager.getRootLogger().getName(), Level.INFO); + } else { + Configurator.setAllLevels(LogManager.getRootLogger().getName(), Level.WARN); + } + } + + public static void main(String[] args) { + PriceProver app = new PriceProver(); + new CommandLine(app) + .setExecutionStrategy(app::executionStrategy) + .execute(args); + } + +} diff --git a/src/main/java/com/abstrlabs/priceprover/util/Utility.java b/src/main/java/com/abstrlabs/priceprover/util/Utility.java index cccf2bd..d86f6d4 100644 --- a/src/main/java/com/abstrlabs/priceprover/util/Utility.java +++ b/src/main/java/com/abstrlabs/priceprover/util/Utility.java @@ -1,127 +1,127 @@ -package com.abstrlabs.priceprover.util; - -import lombok.experimental.UtilityClass; -import lombok.extern.log4j.Log4j2; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigInteger; -import java.util.Arrays; - -@Log4j2 -@UtilityClass -public class Utility { - - public byte[] concat(byte[]... arrays) { - ByteArrayOutputStream byte_stream = new ByteArrayOutputStream(); - try { - for (byte[] array : arrays) { - byte_stream.write(array); - } - } catch (IOException e) { - log.error(e); - } - return byte_stream.toByteArray(); - } - - public long[] concat(long[]... arrays) { - return Arrays.stream(arrays) - .flatMapToLong(Arrays::stream) - .toArray(); - } - - public byte[] xor(byte[] arr1, byte[] arr2) { - byte[] result = new byte[arr1.length]; - int i = 0; - for (byte b : arr1) { - result[i] = (byte) (b ^ arr2[i++]); - } - return result; - } - - public long[] toLongArray(byte[] arr) { - long[] result = new long[arr.length]; - for (int i = 0; i < result.length; i++) { - result[i] = (long) arr[i] & 0xff; - } - return result; - } - - public byte[] toByteArray(int num) { - return BigInteger.valueOf(num).toByteArray(); - } - - public byte[] toByteArray(long[] arr) { - byte[] result = new byte[arr.length]; - for (int i = 0; i < arr.length; i++) { - result[i] = (byte) arr[i]; - } - return result; - } - - public long[] toLongArray(byte[] byteArr, int size) { - long[] result = new long[byteArr.length / size]; - int i = 0; - while (i < byteArr.length) { - result[i / size] = byteArr[i] & 0xff; - i++; - for (int j = 1; j < size; j++) { - result[i / size] = (result[i / size] << 8) + (byteArr[i] & 0xff); - i++; - } - } - return result; - } - - public long[] padding(long[] arr) { - int len = arr.length; - int n = len / 64; - int mod = len % 64; - int retLength = (mod == 63) ? ((n + 2) * 64) : ((n + 1) * 64); - long[] ret = new long[retLength]; - System.arraycopy(arr, 0, ret, 0, len); - ret[len] = 0x80; - for (int i = len + 1; i < retLength - 4; i++) { - ret[i] = 0; - } - for (int i = retLength - 4; i < retLength; i++) { - ret[i] = ((len * 8L) >> ((retLength - i - 1) * 8)) & 0xff; - } - return ret; - } - - public long[] pubkeyPEMToRaw(String pkPEM) { - int[] preasn1 = new int[]{0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00}; - String[] lines = pkPEM.split(System.lineSeparator()); - log.debug(lines); - StringBuilder encoded = new StringBuilder(); - for (String line : lines) { - if (line.trim().length() > 0 && - !line.contains("-BEGIN CERTIFICATE-") && - !line.contains("-BEGIN PUBLIC KEY-") && - !line.contains("-END PUBLIC KEY-") && - !line.contains("-END CERTIFICATE-")) { - encoded.append(line.trim()); - } - } - log.debug(encoded); - long[] res = Crypto.base64Decode(encoded.toString()); - return Arrays.copyOfRange(res, preasn1.length, res.length); - } - - public String getByteBinaryString(byte b) { - StringBuilder sb = new StringBuilder(); - for (int i = 7; i >= 0; --i) { - sb.append(b >>> i & 1); - } - return sb.toString(); - } - - public String getByteBinaryString(long b) { - StringBuilder sb = new StringBuilder(); - for (int i = 31; i >= 0; --i) { - sb.append(b >>> i & 1); - } - return sb.toString(); - } -} +package com.abstrlabs.priceprover.util; + +import lombok.experimental.UtilityClass; +import lombok.extern.log4j.Log4j2; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.util.Arrays; + +@Log4j2 +@UtilityClass +public class Utility { + + public byte[] concat(byte[]... arrays) { + ByteArrayOutputStream byte_stream = new ByteArrayOutputStream(); + try { + for (byte[] array : arrays) { + byte_stream.write(array); + } + } catch (IOException e) { + log.error(e); + } + return byte_stream.toByteArray(); + } + + public long[] concat(long[]... arrays) { + return Arrays.stream(arrays) + .flatMapToLong(Arrays::stream) + .toArray(); + } + + public byte[] xor(byte[] arr1, byte[] arr2) { + byte[] result = new byte[arr1.length]; + int i = 0; + for (byte b : arr1) { + result[i] = (byte) (b ^ arr2[i++]); + } + return result; + } + + public long[] toLongArray(byte[] arr) { + long[] result = new long[arr.length]; + for (int i = 0; i < result.length; i++) { + result[i] = (long) arr[i] & 0xff; + } + return result; + } + + public byte[] toByteArray(int num) { + return BigInteger.valueOf(num).toByteArray(); + } + + public byte[] toByteArray(long[] arr) { + byte[] result = new byte[arr.length]; + for (int i = 0; i < arr.length; i++) { + result[i] = (byte) arr[i]; + } + return result; + } + + public long[] toLongArray(byte[] byteArr, int size) { + long[] result = new long[byteArr.length / size]; + int i = 0; + while (i < byteArr.length) { + result[i / size] = byteArr[i] & 0xff; + i++; + for (int j = 1; j < size; j++) { + result[i / size] = (result[i / size] << 8) + (byteArr[i] & 0xff); + i++; + } + } + return result; + } + + public long[] padding(long[] arr) { + int len = arr.length; + int n = len / 64; + int mod = len % 64; + int retLength = (mod == 63) ? ((n + 2) * 64) : ((n + 1) * 64); + long[] ret = new long[retLength]; + System.arraycopy(arr, 0, ret, 0, len); + ret[len] = 0x80; + for (int i = len + 1; i < retLength - 4; i++) { + ret[i] = 0; + } + for (int i = retLength - 4; i < retLength; i++) { + ret[i] = ((len * 8L) >> ((retLength - i - 1) * 8)) & 0xff; + } + return ret; + } + + public long[] pubkeyPEMToRaw(String pkPEM) { + int[] preasn1 = new int[]{0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00}; + String[] lines = pkPEM.split(System.lineSeparator()); + log.debug(lines); + StringBuilder encoded = new StringBuilder(); + for (String line : lines) { + if (line.trim().length() > 0 && + !line.contains("-BEGIN CERTIFICATE-") && + !line.contains("-BEGIN PUBLIC KEY-") && + !line.contains("-END PUBLIC KEY-") && + !line.contains("-END CERTIFICATE-")) { + encoded.append(line.trim()); + } + } + log.debug(encoded); + long[] res = Crypto.base64Decode(encoded.toString()); + return Arrays.copyOfRange(res, preasn1.length, res.length); + } + + public String getByteBinaryString(byte b) { + StringBuilder sb = new StringBuilder(); + for (int i = 7; i >= 0; --i) { + sb.append(b >>> i & 1); + } + return sb.toString(); + } + + public String getByteBinaryString(long b) { + StringBuilder sb = new StringBuilder(); + for (int i = 31; i >= 0; --i) { + sb.append(b >>> i & 1); + } + return sb.toString(); + } +} diff --git a/src/test/java/com/abstrlabs/priceprover/LibsnarkCallBackTest.java b/src/test/java/com/abstrlabs/priceprover/LibsnarkCallBackTest.java index 0c44fcf..0eaf494 100644 --- a/src/test/java/com/abstrlabs/priceprover/LibsnarkCallBackTest.java +++ b/src/test/java/com/abstrlabs/priceprover/LibsnarkCallBackTest.java @@ -8,8 +8,6 @@ public class LibsnarkCallBackTest { @Test public void callLibsnarkFirstTime() { - // if permission denied, try - // chmod u+x ./depends/libsnark/run_ppzksnark CommandLine cmd = new CommandLine(new LibsnarkCallBack()); int exitCode = cmd.execute("-fi"); assertEquals(exitCode, 0); @@ -17,8 +15,6 @@ public void callLibsnarkFirstTime() { @Test public void callLibsnarkNonFirstTime() { - // if permission denied, try - // chmod u+x ./depends/libsnark/run_ppzksnark CommandLine cmd = new CommandLine(new LibsnarkCallBack()); int exitCode = cmd.execute(); assertEquals(exitCode, 0); diff --git a/src/test/java/com/abstrlabs/priceprover/PageSignerCallBackTest.java b/src/test/java/com/abstrlabs/priceprover/PageSignerCallBackTest.java index a0cd0c4..d141820 100644 --- a/src/test/java/com/abstrlabs/priceprover/PageSignerCallBackTest.java +++ b/src/test/java/com/abstrlabs/priceprover/PageSignerCallBackTest.java @@ -1,16 +1,15 @@ -package com.abstrlabs.priceprover; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import picocli.CommandLine; - -public class PageSignerCallBackTest { - @Test - public void callPageSignerWithAsset() { -// black box testing - CommandLine cmd = new CommandLine(new PageSignerCallBack()); - int exitCode = cmd.execute("-as", "aIBM"); - assertEquals(exitCode, 0); - } -} +package com.abstrlabs.priceprover; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import picocli.CommandLine; + +public class PageSignerCallBackTest { + @Test + public void callPageSignerWithAsset() { + CommandLine cmd = new CommandLine(new PageSignerCallBack()); + int exitCode = cmd.execute("-as", "aIBM"); + assertEquals(exitCode, 0); + } +} diff --git a/src/test/java/com/abstrlabs/priceprover/PriceProverTest.java b/src/test/java/com/abstrlabs/priceprover/PriceProverTest.java new file mode 100644 index 0000000..3fa129f --- /dev/null +++ b/src/test/java/com/abstrlabs/priceprover/PriceProverTest.java @@ -0,0 +1,24 @@ +package com.abstrlabs.priceprover; + +import org.junit.Test; +import picocli.CommandLine; + +import static org.junit.Assert.assertEquals; + +public class PriceProverTest { + @Test + public void callPriceProverFirstTime() { + CommandLine cmd = new CommandLine(new PriceProver()); + int exitCode = cmd.execute("-fi"); + assertEquals(exitCode, 0); + } + + @Test + public void callPriceProverNonFirstTime() { + PriceProver app = new PriceProver(); + int exitCode = new CommandLine(app) + .setExecutionStrategy(app::executionStrategy) + .execute(); + assertEquals(exitCode, 0); + } +}