diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ac5db85..a6a3667 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -24,3 +24,19 @@ jobs: - name: Test with Gradle run: xvfb-run ./gradlew test --info + code_quality: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: run style check on main source sets + run: ./gradlew checkstyleMain --info + - name: run style check on test source sets + run: ./gradlew checkstyleTest --info + diff --git a/build.gradle b/build.gradle index d9bfad5..d324178 100755 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,13 @@ subprojects { apply plugin: 'java' apply plugin: 'org.javamodularity.moduleplugin' + apply plugin: 'checkstyle' + + checkstyle { + toolVersion = '8.29' + configFile = rootProject.file('config/checkstyle/checkstyle.xml') + } + repositories { jcenter() mavenCentral() diff --git a/client/src/main/java/sigblockchain/projectred/client/AurumClient.java b/client/src/main/java/sigblockchain/projectred/client/AurumClient.java index 88128c5..663e1c2 100644 --- a/client/src/main/java/sigblockchain/projectred/client/AurumClient.java +++ b/client/src/main/java/sigblockchain/projectred/client/AurumClient.java @@ -1,11 +1,11 @@ package sigblockchain.projectred.client; +import com.google.gson.Gson; +import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.net.URI; -import com.google.gson.Gson; public class AurumClient { diff --git a/client/src/main/java/sigblockchain/projectred/client/Block.java b/client/src/main/java/sigblockchain/projectred/client/Block.java index 39bbd8f..9653f21 100644 --- a/client/src/main/java/sigblockchain/projectred/client/Block.java +++ b/client/src/main/java/sigblockchain/projectred/client/Block.java @@ -12,28 +12,34 @@ public class Block { private final byte[][] data; // [][]byte /** + * Stores data (typically contracts). The entire block is either added to the blockchain or the entirety + * of it is rejected. + * * @param version Version of the blockChain the block was created on - * @param height A hex encoded 2's complement 64 bit integer string (without the prefix '0x'). Note, the height cannot be negative Represents the height of the block in the blockChain. + * @param height A hex encoded 2's complement 64 bit integer string (without the prefix '0x'). Note, + * the height cannot be negative Represents the height of the block in the blockChain. * @param timestamp Unix time, representing the number of nanoseconds elapsed since January 1, 1970 UTC * @param previousHash Hash of the previous block * @param merkleRootHash Hash of the merkle-root of all inputs * @param dataLen Number of objects in the Data section * @param data Actual contents of block */ - public Block(int version, String height, long timestamp, byte[] previousHash, byte[] merkleRootHash, int dataLen, byte[][] data) { + + public Block(int version, String height, long timestamp, byte[] previousHash, + byte[] merkleRootHash, int dataLen, byte[][] data) { //Individual values Checking - if (checkUnsigned16(version)) { - throw new IllegalArgumentException("Invalid Input version"); - } - if (!checkUnsigned64(new BigInteger(height, 16))) { - throw new IllegalArgumentException("Invalid Input height"); - } - if (!checkSigned64(timestamp)) { - throw new IllegalArgumentException("Invalid Input timeStamp"); - } - if (checkUnsigned16(dataLen)) { - throw new IllegalArgumentException("Invalid Input dataLen"); - } + if (checkUnsigned16(version)) { + throw new IllegalArgumentException("Invalid Input version"); + } + if (!checkUnsigned64(new BigInteger(height, 16))) { + throw new IllegalArgumentException("Invalid Input height"); + } + if (!checkSigned64(timestamp)) { + throw new IllegalArgumentException("Invalid Input timeStamp"); + } + if (checkUnsigned16(dataLen)) { + throw new IllegalArgumentException("Invalid Input dataLen"); + } this.height = new BigInteger(height, 16); this.version = version; @@ -49,7 +55,8 @@ private boolean checkUnsigned16(int value) { } private boolean checkUnsigned64(BigInteger value) { - return (value.compareTo(BigInteger.ZERO) >= 0) && (value.compareTo(new BigInteger("ffffffffffffffff", 16)) <= 0); + return (value.compareTo(BigInteger.ZERO) >= 0) + && (value.compareTo(new BigInteger("ffffffffffffffff", 16)) <= 0); } private boolean checkSigned64(long value) { @@ -57,49 +64,63 @@ private boolean checkSigned64(long value) { } /** - * @return This function returns the value of version from the data + * Returns the version of Aurum in which the block was added/created. + * + * @return int value of version. Will be guaranteed to be unsigned 16bit value */ public int getVersion() { return this.version; } /** - * @return This function returns the value of height from the data + * Returns height of the block. + * + * @return int value of the height of the block. Will be positive value less than 2^64 */ public BigInteger getHeight() { return this.height; } /** - * @return This function returns the value of timestamp from the data + * Returns the unix timestamp of block. + * + * @return long timestamp. */ public long getTimestamp() { return this.timestamp; } /** - * @return This function returns the value of previousHash from the data + * The hash of the previous block. + * + * @return byte array representing the hash */ public byte[] getPreviousHash() { return this.previousHash; } /** - * @return This function returns the value of merkleRootHash from the data + * Returns the merkle root hash of the block. + * + * @return byte array representing the hash */ public byte[] getMerkleRootHash() { return this.merkleRootHash; } /** - * @return This function returns the value of dataLen from the data + * Returns the length of data present in the block. + * + * @return int value, garuanteed to be unsigned 16 bit value */ public int getDataLen() { return this.dataLen; } /** - * @return This function returns the data from the data + * Returns the data actually present in the block. + * + * @return An array of byte arrays. */ public byte[][] getData() { return this.data; diff --git a/client/src/test/java/sigblockchain/projectred/client/AccountTest.java b/client/src/test/java/sigblockchain/projectred/client/AccountTest.java index 70b8f2a..416f0d3 100644 --- a/client/src/test/java/sigblockchain/projectred/client/AccountTest.java +++ b/client/src/test/java/sigblockchain/projectred/client/AccountTest.java @@ -3,7 +3,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; - import java.math.BigInteger; import org.junit.jupiter.api.Test; @@ -39,11 +38,14 @@ public void testAccountTest3() { var addr = "81aaf16d7e4b626dc1c34c47bf9973496a3698a6e7ab0255af867169b43529fb"; var balance = new BigInteger("-2", 16); var nonce = new BigInteger("-2", 16); + try { Account account = new Account(addr, balance, nonce); fail("Account object was allowed to be made with invalid arguments"); - } catch (Exception ignored) { + } catch (Exception e) { + return; } + } @Test diff --git a/client/src/test/java/sigblockchain/projectred/client/AurumClientTest.java b/client/src/test/java/sigblockchain/projectred/client/AurumClientTest.java index a0c6ee2..86120c7 100644 --- a/client/src/test/java/sigblockchain/projectred/client/AurumClientTest.java +++ b/client/src/test/java/sigblockchain/projectred/client/AurumClientTest.java @@ -7,7 +7,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; - import io.specto.hoverfly.junit.core.Hoverfly; import io.specto.hoverfly.junit.rule.HoverflyRule; import io.specto.hoverfly.junit5.HoverflyExtension; @@ -30,6 +29,9 @@ public class AurumClientTest { private static HoverflyRule hoverflyRule; + /** + * Gets a JSON resources from the resources directory. + */ @BeforeAll public static void setUpJsonResponse() { var inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(jsonFile); @@ -42,12 +44,11 @@ public static void setUpJsonResponse() { } - @Test public void testGetAccount(Hoverfly hoverfly) { hoverfly.simulate(dsl( - service(host). - get(startsWith("/accountinfo")) + service(host) + .get(startsWith("/accountinfo")) .queryParam("w", validAddress) .willReturn( success(validJson, "application/json")) diff --git a/client/src/test/java/sigblockchain/projectred/client/BlockTest.java b/client/src/test/java/sigblockchain/projectred/client/BlockTest.java index 20646cf..552534b 100644 --- a/client/src/test/java/sigblockchain/projectred/client/BlockTest.java +++ b/client/src/test/java/sigblockchain/projectred/client/BlockTest.java @@ -1,74 +1,70 @@ package sigblockchain.projectred.client; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + import java.math.BigInteger; -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; class BlockTest { - private byte[] previousHash = "Previous Hash".getBytes(); - private byte[] hash = "Block hash".getBytes(); - private byte[][] data = - { - {1, 2, 3, 4}, - {'H', 'E', 'L', 'L', 'O'}, - {5, 6, 7, 8}, - {'W', 'O', 'R', 'L', 'D'} - }; + private byte[] previousHash = "Previous Hash".getBytes(); + private byte[] hash = "Block hash".getBytes(); + private byte[][] data = {{1, 2, 3, 4}, {'H', 'E', 'L', 'L', 'O'}, {5, 6, 7, 8}, {'W', 'O', 'R', 'L', 'D'}}; - @Test - void testConstructor() { - Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); - assertNotNull(block); - } + @Test + void testConstructor() { + Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); + assertNotNull(block); + } - @Test - void testGetVersion() { - Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); - int v = block.getVersion(); - assertEquals(v, 10); - } + @Test + void testGetVersion() { + Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); + int v = block.getVersion(); + assertEquals(v, 10); + } - @Test - void testGetHeight() { - Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); - var v = block.getHeight(); - assertEquals(v, new BigInteger("2B", 16)); - } + @Test + void testGetHeight() { + Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); + var v = block.getHeight(); + assertEquals(v, new BigInteger("2B", 16)); + } - @Test - void testGetTimestamp() { - Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); - long v = block.getTimestamp(); - assertEquals(v, -3556L); - } + @Test + void testGetTimestamp() { + Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); + long v = block.getTimestamp(); + assertEquals(v, -3556L); + } - @Test - void testGetPreviousHash() { - Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); - byte[] v = block.getPreviousHash(); - assertEquals(v, previousHash); - } + @Test + void testGetPreviousHash() { + Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); + byte[] v = block.getPreviousHash(); + assertEquals(v, previousHash); + } - @Test - void testGetMerkleRootHash() { - Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); - byte[] v = block.getMerkleRootHash(); - assertEquals(v, hash); - } + @Test + void testGetMerkleRootHash() { + Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); + byte[] v = block.getMerkleRootHash(); + assertEquals(v, hash); + } - @Test - void testGetDataLen() { - Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); - int v = block.getDataLen(); - assertEquals(v, 10); - } + @Test + void testGetDataLen() { + Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); + int v = block.getDataLen(); + assertEquals(v, 10); + } - @Test - void testGetData() { - Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); - byte[][] v = block.getData(); - assertEquals(v, data); - } + @Test + void testGetData() { + Block block = new Block(10, "2B", -3556L, previousHash, hash, 10, data); + byte[][] v = block.getData(); + assertEquals(v, data); + } } diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100755 index 0000000..c42a183 --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/src/test/java/sigblockchain/projectred/gui/MultiplePaneTest.java b/gui/src/test/java/sigblockchain/projectred/gui/MultiplePaneTest.java index 5a2f25e..cd45569 100644 --- a/gui/src/test/java/sigblockchain/projectred/gui/MultiplePaneTest.java +++ b/gui/src/test/java/sigblockchain/projectred/gui/MultiplePaneTest.java @@ -1,5 +1,8 @@ package sigblockchain.projectred.gui; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; @@ -13,14 +16,10 @@ import org.testfx.framework.junit5.Start; import org.testfx.matcher.control.LabeledMatchers; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - @ExtendWith(ApplicationExtension.class) public class MultiplePaneTest { - @Start public void start(Stage stage) throws Exception { Parent root = FXMLLoader.load(Main.class.getResource("scene.fxml")); diff --git a/keys/src/main/java/sigblockchain/projectred/keys/KeyManager.java b/keys/src/main/java/sigblockchain/projectred/keys/KeyManager.java index 06534a5..df2275a 100644 --- a/keys/src/main/java/sigblockchain/projectred/keys/KeyManager.java +++ b/keys/src/main/java/sigblockchain/projectred/keys/KeyManager.java @@ -1,6 +1,14 @@ package sigblockchain.projectred.keys; -import org.bouncycastle.asn1.*; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.SecureRandom; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.DERSequenceGenerator; +import org.bouncycastle.asn1.DLSequence; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; @@ -12,17 +20,12 @@ import org.bouncycastle.crypto.signers.ECDSASigner; import org.bouncycastle.util.Properties; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigInteger; -import java.security.SecureRandom; - - public class KeyManager { public static final X9ECParameters ecp = SECNamedCurves.getByName("secp256r1"); public static final ECDomainParameters domainParams = new ECDomainParameters(ecp.getCurve(), - ecp.getG(), ecp.getN(), ecp.getH(), ecp.getSeed()); + ecp.getG(), ecp.getN(), ecp.getH(), ecp.getSeed()); + /** * Will generate a public/private key pair according to the NIST P-256 standards. @@ -30,8 +33,8 @@ public class KeyManager { * @return a AsymmetricCipherKeyPair object */ public static AsymmetricCipherKeyPair generateKeyPair() { - ECKeyGenerationParameters keyGenParams = new ECKeyGenerationParameters(domainParams, new SecureRandom()); - ECKeyPairGenerator generator = new ECKeyPairGenerator(); + var keyGenParams = new ECKeyGenerationParameters(domainParams, new SecureRandom()); + var generator = new ECKeyPairGenerator(); generator.init(keyGenParams); return generator.generateKeyPair(); } @@ -65,21 +68,22 @@ public static byte[] sign(ECPrivateKeyParameters privateKey, byte[] data) { */ public static boolean verify(ECPublicKeyParameters publicKey, byte[] signature, byte[] data) { - BigInteger[] rAndS = decodeDerSignature(signature); - if (rAndS == null) + BigInteger[] randS = decodeDerSignature(signature); + if (randS == null) { return false; - var r = rAndS[0]; - var s = rAndS[1]; + } + var r = randS[0]; + var s = randS[1]; ECDSASigner signer = new ECDSASigner(); signer.init(false, publicKey); - - return signer.verifySignature(data, r, s); + return signer.verifySignature(data, r, s); } - private static BigInteger[] decodeDerSignature(byte[] signature){ + private static BigInteger[] decodeDerSignature(byte[] signature) { //first we have to decode the the DER encoded byte array - BigInteger r, s; + BigInteger r; + BigInteger s; ASN1InputStream decoder = null; try { // BouncyCastle by default is strict about parsing ASN.1 integers. diff --git a/keys/src/test/java/sigblockchain/projectred/keys/KeyManagerTest.java b/keys/src/test/java/sigblockchain/projectred/keys/KeyManagerTest.java index 7e859bf..0478b00 100644 --- a/keys/src/test/java/sigblockchain/projectred/keys/KeyManagerTest.java +++ b/keys/src/test/java/sigblockchain/projectred/keys/KeyManagerTest.java @@ -4,7 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; - import java.math.BigInteger; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; @@ -13,23 +12,8 @@ import org.bouncycastle.util.encoders.Hex; import org.junit.jupiter.api.Test; - class KeyManagerTest { - @Test - public void testGenerateKeyPair() { - var keyPair = KeyManager.generateKeyPair(); - var privateKey = (ECPrivateKeyParameters) keyPair.getPrivate(); - var actualPublicKey = (ECPublicKeyParameters) keyPair.getPublic(); - - ECPoint Q = KeyManager.domainParams.getG().multiply(privateKey.getD()); - var expectedPublicKey = new ECPublicKeyParameters(Q, KeyManager.domainParams); - assertEquals(actualPublicKey.getQ().getRawXCoord().toBigInteger(), expectedPublicKey.getQ().getRawXCoord().toBigInteger()); - assertEquals(actualPublicKey.getQ().getRawYCoord().toBigInteger(), expectedPublicKey.getQ().getRawYCoord().toBigInteger()); - - } - - @Test public void testEcParameters() { // an example of the P-256 public private key pair. @@ -38,17 +22,30 @@ public void testEcParameters() { var expectedPublicKeyY = new BigInteger("a797eb07a5d8eef80d5705a7a627c73cf4e683ab98c7245101025be935c4053b", 16); var fpMultiplier = new FixedPointCombMultiplier(); - ECPoint Q = fpMultiplier.multiply(KeyManager.domainParams.getG(), expectedPrivateKey); + ECPoint q = fpMultiplier.multiply(KeyManager.domainParams.getG(), expectedPrivateKey); - var actualPublicKey = new ECPublicKeyParameters(Q, KeyManager.domainParams); + var actualPublicKey = new ECPublicKeyParameters(q, KeyManager.domainParams); var actualPrivateKey = new ECPrivateKeyParameters(expectedPrivateKey, KeyManager.domainParams); assertEquals(actualPrivateKey.getD(), expectedPrivateKey); assertEquals(actualPublicKey.getQ().getRawXCoord().toBigInteger(), expectedPublicKeyX); assertEquals(actualPublicKey.getQ().getRawYCoord().toBigInteger(), expectedPublicKeyY); - } + @Test + public void testGenerateKeyPair() { + var keyPair = KeyManager.generateKeyPair(); + var privateKey = (ECPrivateKeyParameters) keyPair.getPrivate(); + var actualPublicKey = (ECPublicKeyParameters) keyPair.getPublic(); + + ECPoint q = KeyManager.domainParams.getG().multiply(privateKey.getD()); + var expectedPublicKey = new ECPublicKeyParameters(q, KeyManager.domainParams); + assertEquals(actualPublicKey.getQ().getRawXCoord().toBigInteger(), + expectedPublicKey.getQ().getRawXCoord().toBigInteger()); + assertEquals(actualPublicKey.getQ().getRawYCoord().toBigInteger(), + expectedPublicKey.getQ().getRawYCoord().toBigInteger()); + + } @Test public void testSigning1() { @@ -63,8 +60,12 @@ public void testSigning1() { @Test public void testSigning2() { - var signature = Hex.decode("3045022100ff2c146535e75f0b5c8fb3548077f799429f72b4eb2e5412e89678b29fb165e3022036332b243d0f28fd05e9dca1be6eb1ff577622148e245732951fdfb71a4e684b"); - var fakeSignature = Hex.decode("1045022100ff2c146535e75f0b5c8fb3548077f799429f72b4eb2e5412e89678b29fb165e3022036332b243d0f28fd05e9dca1be6eb1ff577622148e245732951fdfb71a4e684b"); + var signature = Hex.decode( + "3045022100ff2c146535e75f0b5c8fb3548077f799429f72b4eb2e5412e89678b29fb16" + + "5e3022036332b243d0f28fd05e9dca1be6eb1ff577622148e245732951fdfb71a4e684b"); + var fakeSignature = Hex.decode( + "1045022100ff2c146535e75f0b5c8fb3548077f799429f72b4eb2e5412e89678b29fb16" + + "5e3022036332b243d0f28fd05e9dca1be6eb1ff577622148e245732951fdfb71a4e684b"); var data = "Data".getBytes(); var privateKeyNum = new BigInteger("d8353db7fe564c633f94274d7bc1d7200740e3ac5b617dc1f438feecfebec562", 16); @@ -77,5 +78,4 @@ public void testSigning2() { assertFalse(KeyManager.verify(constructedPrivateKey, fakeSignature, data)); } - }