Files
gm-java/test/Testinator.java
T
2026-08-20 21:15:06 +09:00

417 lines
18 KiB
Java

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.math.BigInteger;
import swiss.qpq.gajumaru.core.encoding.Base58;
import swiss.qpq.gajumaru.core.encoding.RLP;
import swiss.qpq.gajumaru.core.encoding.ApiEncoder;
import swiss.qpq.gajumaru.core.formatting.GajuFormat;
import swiss.qpq.gajumaru.core.crypto.Keccak256;
import swiss.qpq.gajumaru.core.crypto.Blake2b;
import swiss.qpq.gajumaru.core.crypto.Ed25519;
import swiss.qpq.gajumaru.core.data.Id;
import swiss.qpq.gajumaru.core.tools.CryptoUtils;
public class Testinator {
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("Error: Provide the test suite name and the required arguments.");
System.exit(1);
}
try {
switch (args[0]) {
case "base64" -> { System.out.print(base64(args[1])); }
case "base58" -> { System.out.print(base58(args[1])); }
case "base58_check" -> { System.out.print(base58_check(args[1])); }
case "rlp" -> { System.out.print(rlp(args[1])); }
case "rlp_stream" -> { System.out.print(rlp_stream(args[1])); }
case "rlp_fail" -> { System.out.print(rlp_fail(args[1])); }
case "gaju_format" -> { System.out.print(gaju_format(args[1])); }
case "keccak256" -> { System.out.print(keccak256(args[1])); }
case "blake2b" -> { System.out.print(blake2b(args[1])); }
case "ed25519" -> { System.out.print(ed25519(args[1])); }
case "ed25519_verify" -> { System.out.print(ed25519_verify(args[1])); }
case "api_encode" -> { System.out.print(api_encode(args[1])); }
case "id_serialization" -> { System.out.print(id_serialization(args[1])); }
case "fe_parity" -> { System.out.print(fe_parity(args[1])); }
case "reduce_parity" -> { System.out.print(reduce_parity(args[1])); }
case "smb_parity" -> { System.out.print(smb_parity(args[1])); }
case "femul_parity" -> { System.out.print(femul_parity(args[1])); }
case "frombytes_parity" -> { System.out.print(frombytes_parity(args[1])); }
case "ge_parity" -> { System.out.print(ge_parity(args[1], args[2])); }
case "keccak" -> {
byte[] in = CryptoUtils.hexToBin(args[1]);
System.out.println(CryptoUtils.binToHex(Keccak256.hash(in)));
}
case "blake2b_direct" -> {
byte[] in = CryptoUtils.hexToBin(args[1]);
System.out.println(CryptoUtils.binToHex(Blake2b.hash(in)));
}
case "ak_encode" -> {
byte[] in = CryptoUtils.hexToBin(args[1]);
System.out.println(ApiEncoder.encode(ApiEncoder.Type.ACCOUNT_PUBKEY, in));
}
case "ed25519_pub" -> {
byte[] seed = CryptoUtils.hexToBin(args[1]);
System.out.println(CryptoUtils.binToHex(Ed25519.publicKey(seed)));
}
case "id_serialize" -> {
int tag = Integer.parseInt(args[1]);
byte[] val = CryptoUtils.hexToBin(args[2]);
Id id = new Id(Id.Tag.fromValue(tag), val);
System.out.println(CryptoUtils.binToHex(id.serialize()));
}
default -> {
System.out.println("Error: Unknown test suite or command: " + args[0]);
System.exit(1);
}
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
}
private static String ge_parity(String aHex, String bHex) throws IOException {
byte[] a = CryptoUtils.hexToBin(aHex);
byte[] b = CryptoUtils.hexToBin(bHex);
Ed25519.Scratch sc = new Ed25519.Scratch();
Ed25519.Ge p1 = Ed25519.scalarMulBase(a, sc);
Ed25519.Ge p2 = Ed25519.scalarMulBase(b, sc);
Ed25519.Ge p3 = new Ed25519.Ge();
Ed25519.ge_add(p3, p1, p2, sc);
byte[] res = Ed25519.compress(p3, sc);
p1.wipe(); p2.wipe(); p3.wipe(); sc.wipe();
return CryptoUtils.binToHex(res) + "|||";
}
private static String frombytes_parity(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "frombytes.test");
Path resPath = Path.of(workingPath, "frombytes.java.txt");
List<String> lines = Files.readAllLines(testPath);
List<String> results = new ArrayList<>();
for (String hex : lines) {
if (hex.trim().isEmpty()) continue;
byte[] in = CryptoUtils.hexToBin(hex);
long[] h = new long[10];
Ed25519.fe_frombytes(h, in);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
if (i > 0) sb.append(",");
sb.append(h[i]);
}
results.add(sb.toString());
}
Files.write(resPath, results);
return resPath.toString();
}
private static String femul_parity(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "femul.test");
Path resPath = Path.of(workingPath, "femul.java.txt");
List<String> lines = Files.readAllLines(testPath);
List<String> results = new ArrayList<>();
for (String line : lines) {
if (line.trim().isEmpty()) continue;
String[] parts = line.split("\\|");
byte[] a = CryptoUtils.hexToBin(parts[0]);
byte[] b = CryptoUtils.hexToBin(parts[1]);
long[] ha = new long[10], hb = new long[10];
Ed25519.fe_frombytes(ha, a);
Ed25519.fe_frombytes(hb, b);
long[] hr = new long[10];
Ed25519.fe_mul(hr, ha, hb, new long[19]);
byte[] out = Ed25519.fe_contract(hr);
results.add(CryptoUtils.binToHex(out));
}
Files.write(resPath, results);
return resPath.toString();
}
private static String smb_parity(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "smb.test");
Path resPath = Path.of(workingPath, "smb.java.txt");
List<String> lines = Files.readAllLines(testPath);
List<String> results = new ArrayList<>();
for (String hex : lines) {
if (hex.trim().isEmpty()) continue;
byte[] in = CryptoUtils.hexToBin(hex);
Ed25519.Scratch sc = new Ed25519.Scratch();
Ed25519.Ge p = Ed25519.scalarMulBase(in, sc);
byte[] out = Ed25519.compress(p, sc);
p.wipe(); sc.wipe();
results.add(CryptoUtils.binToHex(out));
}
Files.write(resPath, results);
return resPath.toString();
}
private static String reduce_parity(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "reduce.test");
Path resPath = Path.of(workingPath, "reduce.java.txt");
List<String> lines = Files.readAllLines(testPath);
List<String> results = new ArrayList<>();
for (String hex : lines) {
if (hex.trim().isEmpty()) continue;
byte[] in = CryptoUtils.hexToBin(hex);
byte[] s = Arrays.copyOf(in, 64);
Ed25519.reduceScalar(s);
byte[] out = Arrays.copyOf(s, 32);
results.add(CryptoUtils.binToHex(out));
}
Files.write(resPath, results);
return resPath.toString();
}
private static String fe_parity(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "fe.test");
Path resPath = Path.of(workingPath, "fe.java.txt");
List<String> lines = Files.readAllLines(testPath);
List<String> results = new ArrayList<>();
for (String hex : lines) {
if (hex.trim().isEmpty()) continue;
byte[] in = CryptoUtils.hexToBin(hex);
long[] h = new long[10];
Ed25519.fe_frombytes(h, in);
byte[] out = Ed25519.fe_contract(h);
results.add(CryptoUtils.binToHex(out));
}
Files.write(resPath, results);
return resPath.toString();
}
private static String base64(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "base64.test");
Path encPath = Path.of(workingPath, "base64.java.txt");
Path decPath = Path.of(workingPath, "base64.java.back");
byte[] rawB = Files.readAllBytes(testPath);
byte[] encB = Base64.getEncoder().encode(rawB);
Files.write(encPath, encB);
byte[] readE = Files.readAllBytes(encPath);
byte[] decB = Base64.getDecoder().decode(readE);
Files.write(decPath, decB);
return encPath.toString() + " " + decPath.toString();
}
private static String base58(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "base58.test");
Path encPath = Path.of(workingPath, "base58.java.txt");
Path decPath = Path.of(workingPath, "base58.java.back");
byte[] rawB = Files.readAllBytes(testPath);
String encS = Base58.encode(rawB);
Files.write(encPath, encS.getBytes());
byte[] readE = Files.readAllBytes(encPath);
String readS = new String(readE);
byte[] decB = Base58.decode(readS);
Files.write(decPath, decB);
return encPath.toString() + " " + decPath.toString();
}
private static String base58_check(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "base58_check.test");
Path encPath = Path.of(workingPath, "base58_check.java.txt");
Path decPath = Path.of(workingPath, "base58_check.java.back");
byte[] rawB = Files.readAllBytes(testPath);
String encS = Base58.checkEncode(rawB);
Files.write(encPath, encS.getBytes());
byte[] readE = Files.readAllBytes(encPath);
String readS = new String(readE);
byte[] decB = Base58.checkDecode(readS);
Files.write(decPath, decB);
return encPath.toString() + " " + decPath.toString();
}
private static String rlp(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "rlp.test");
Path resPath = Path.of(workingPath, "rlp.java.back");
byte[] encB = Files.readAllBytes(testPath);
RLP.RLP_Data decRLP = RLP.decode(encB);
RLP.RLP_List root = decRLP.asList();
RLP.RLP_List sub = root.getItems().get(1).asList();
byte[] anchor = sub.getItems().get(1).asItem().getBytes();
byte[] reEnc = RLP.encode(decRLP);
Files.write(resPath, reEnc);
return new String(anchor) + "|" + resPath.toString();
}
private static String rlp_stream(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "rlp_stream.test");
byte[] buffer = Files.readAllBytes(testPath);
List<String> hashes = new ArrayList<>();
int offset = 0;
while (offset < buffer.length) {
RLP.DecodeResult res = RLP.decodeFrom(buffer, offset);
hashes.add(Integer.toString(res.data().hashCode())); // Just to verify we got objects
offset += res.consumed();
}
return Integer.toString(hashes.size());
}
private static String rlp_fail(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "rlp_fail.test");
byte[] buffer = Files.readAllBytes(testPath);
try {
RLP.decode(buffer);
return "SUCCESS";
} catch (RLP.RLPException e) {
return "RLP_EXCEPTION: " + e.getMessage();
} catch (Exception e) {
return "OTHER_EXCEPTION: " + e.getClass().getSimpleName();
}
}
private static String gaju_format(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "gaju_format.test");
Path resPath = Path.of(workingPath, "gaju_format.java.txt");
List<String> lines = Files.readAllLines(testPath);
List<String> results = new ArrayList<>();
for (String line : lines) {
if (line.trim().isEmpty()) continue;
String[] p = line.split("\\|");
String op = p[0];
switch (op) {
case "amount" -> {
GajuFormat.Type style = GajuFormat.Type.valueOf(p[1]);
GajuFormat.Unit unit = GajuFormat.Unit.valueOf(p[2]);
char sep = p[3].charAt(0);
int span = Integer.parseInt(p[4]);
BigInteger val = new BigInteger(p[5]);
results.add(GajuFormat.amount(new GajuFormat.FormatSpec(style, unit, sep, span), val));
}
case "approx" -> {
GajuFormat.Type style = GajuFormat.Type.valueOf(p[1]);
GajuFormat.Unit unit = GajuFormat.Unit.valueOf(p[2]);
char sep = p[3].charAt(0);
int span = Integer.parseInt(p[4]);
BigInteger val = new BigInteger(p[5]);
int prec = Integer.parseInt(p[6]);
results.add(GajuFormat.approxAmount(new GajuFormat.FormatSpec(style, unit, sep, span), val, prec));
}
case "read" -> {
byte[] b = GajuFormat.read(p[1]);
results.add(new BigInteger(b).toString());
}
}
}
Files.write(resPath, results);
return resPath.toString();
}
private static String keccak256(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "keccak256.test");
Path resPath = Path.of(workingPath, "keccak256.java.txt");
byte[] input = Files.readAllBytes(testPath);
byte[] hash = Keccak256.hash(input);
Files.write(resPath, CryptoUtils.binToHex(hash).getBytes());
return resPath.toString();
}
private static String blake2b(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "blake2b.test");
Path resPath = Path.of(workingPath, "blake2b.java.txt");
byte[] input = Files.readAllBytes(testPath);
byte[] hash = Blake2b.hash(input);
Files.write(resPath, CryptoUtils.binToHex(hash).getBytes());
return resPath.toString();
}
private static String ed25519(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "ed25519.test");
Path resPath = Path.of(workingPath, "ed25519.java.txt");
List<String> lines = Files.readAllLines(testPath);
List<String> results = new ArrayList<>();
for (String line : lines) {
if (line.trim().isEmpty()) continue;
String[] parts = line.split("\\|");
byte[] seed = CryptoUtils.hexToBin(parts[0]);
byte[] msg = CryptoUtils.hexToBin(parts[1]);
byte[] pub = Ed25519.publicKey(seed);
byte[] sig = Ed25519.sign(seed, msg);
boolean verify = Ed25519.verify(pub, msg, sig);
results.add(CryptoUtils.binToHex(pub) + "|" + CryptoUtils.binToHex(sig) + "|" + verify);
CryptoUtils.wipe(seed);
CryptoUtils.wipe(msg);
CryptoUtils.wipe(pub);
CryptoUtils.wipe(sig);
}
Files.write(resPath, results);
return resPath.toString();
}
private static String ed25519_verify(String workingPath) throws IOException {
Path seedPath = Path.of(workingPath, "ed25519_seed.test");
Path msgPath = Path.of(workingPath, "ed25519_msg.test");
byte[] seed = CryptoUtils.hexToBin(Files.readString(seedPath).trim());
byte[] message = Files.readAllBytes(msgPath);
byte[] pub = Ed25519.publicKey(seed);
byte[] sig = Ed25519.sign(seed, message);
boolean verify = Ed25519.verify(pub, message, sig);
return CryptoUtils.binToHex(pub) + "|" + CryptoUtils.binToHex(sig) + "|" + verify;
}
private static String api_encode(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "api_encode.test");
Path resPath = Path.of(workingPath, "api_encode.java.txt");
List<String> lines = Files.readAllLines(testPath);
List<String> results = new ArrayList<>();
for (String line : lines) {
if (line.trim().isEmpty()) continue;
String[] p = line.split("\\|");
ApiEncoder.Type type = ApiEncoder.Type.valueOf(p[0]);
byte[] payload = CryptoUtils.hexToBin(p[1]);
results.add(ApiEncoder.encode(type, payload));
if (type == ApiEncoder.Type.ACCOUNT_SECKEY) {
CryptoUtils.wipe(payload);
}
}
Files.write(resPath, results);
return resPath.toString();
}
private static String id_serialization(String workingPath) throws IOException {
Path testPath = Path.of(workingPath, "id_serialization.test");
Path resPath = Path.of(workingPath, "id_serialization.java.txt");
List<String> lines = Files.readAllLines(testPath);
List<String> results = new ArrayList<>();
for (String line : lines) {
if (line.trim().isEmpty()) continue;
String[] p = line.split("\\|");
Id.Tag tag = Id.Tag.fromValue(Integer.parseInt(p[0]));
byte[] val = CryptoUtils.hexToBin(p[1]);
Id id = new Id(tag, val);
results.add(CryptoUtils.binToHex(id.serialize()));
}
Files.write(resPath, results);
return resPath.toString();
}
}