From 18861eca68a17cd1b18e07606ad32b06d36a7860 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Wed, 31 Jul 2024 13:43:49 -0600 Subject: [PATCH 01/74] add java major versions --- .github/workflows/test.yml | 78 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6aa0bd63..52a6f4fa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,65 +6,65 @@ on: - "master" - "develop" pull_request: - types: [ ready_for_review, synchronize, opened ] + types: [ready_for_review, synchronize, opened] jobs: format: runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} + - name: Checkout code + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} - - name: Merge Conflict finder - uses: olivernybroe/action-conflict-finder@v1.1 + - name: Merge Conflict finder + uses: olivernybroe/action-conflict-finder@v1.1 - - name: Use Java Version ${{ matrix.java }} - uses: actions/setup-java@v2 - with: - distribution: 'adopt' - java-version: 8 - cache: 'gradle' + - name: Use Java Version ${{ matrix.java }} + uses: actions/setup-java@v2 + with: + distribution: "adopt" + java-version: 8 + cache: "gradle" - - name: Format code - run: gradle format + - name: Format code + run: gradle format - - name: Commit fixed code - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "style: resolve style guide violations" - branch: ${{ github.head_ref }} + - name: Commit fixed code + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: "style: resolve style guide violations" + branch: ${{ github.head_ref }} unit: runs-on: ubuntu-latest strategy: matrix: # test against the latest update of each major Java version, as well as specific updates of LTS versions: - java: [ 8, 11, 15, 16, 17 ] + java: [8, 11, 15, 16, 17, 18, 19, 20, 21, 22] steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} + - name: Checkout code + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} - - name: Merge Conflict finder - uses: olivernybroe/action-conflict-finder@v1.1 + - name: Merge Conflict finder + uses: olivernybroe/action-conflict-finder@v1.1 - - name: Use Java Version ${{ matrix.java }} - uses: actions/setup-java@v2 - with: - distribution: 'zulu' - java-version: ${{ matrix.java }} - cache: 'gradle' + - name: Use Java Version ${{ matrix.java }} + uses: actions/setup-java@v2 + with: + distribution: "zulu" + java-version: ${{ matrix.java }} + cache: "gradle" - - name: Install - run: gradle dependencies + - name: Install + run: gradle dependencies - - name: Test - run: gradle test && gradle jacocoTestReport + - name: Test + run: gradle test && gradle jacocoTestReport - - name: Codecov - run: bash <(curl -s https://codecov.io/bash) -t ${{ secrets.CODECOV_TOKEN }} + - name: Codecov + run: bash <(curl -s https://codecov.io/bash) -t ${{ secrets.CODECOV_TOKEN }} From 7ba8c2dc54f09d90b0ce14d0c31b8cacb4dc4dc8 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Wed, 31 Jul 2024 14:15:45 -0600 Subject: [PATCH 02/74] remove deprecated signer/verifier --- .../crypto/signature/ECDSASigner.java | 11 ----- .../crypto/signature/ECDSAVerifier.java | 15 ------- .../transactions/types/Transaction.java | 4 +- .../crypto/signature/ECDSASignerTest.java | 31 ------------- .../crypto/signature/ECDSAVerifierTest.java | 44 ------------------- 5 files changed, 1 insertion(+), 104 deletions(-) delete mode 100644 src/main/java/org/arkecosystem/crypto/signature/ECDSASigner.java delete mode 100644 src/main/java/org/arkecosystem/crypto/signature/ECDSAVerifier.java delete mode 100644 src/test/java/org/arkecosystem/crypto/signature/ECDSASignerTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/signature/ECDSAVerifierTest.java diff --git a/src/main/java/org/arkecosystem/crypto/signature/ECDSASigner.java b/src/main/java/org/arkecosystem/crypto/signature/ECDSASigner.java deleted file mode 100644 index 3936407c..00000000 --- a/src/main/java/org/arkecosystem/crypto/signature/ECDSASigner.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.arkecosystem.crypto.signature; - -import org.bitcoinj.core.ECKey; -import org.bitcoinj.core.Sha256Hash; - -public class ECDSASigner implements Signer { - @Override - public byte[] sign(byte[] message, ECKey privateKey) { - return privateKey.sign(Sha256Hash.wrap(message)).encodeToDER(); - } -} diff --git a/src/main/java/org/arkecosystem/crypto/signature/ECDSAVerifier.java b/src/main/java/org/arkecosystem/crypto/signature/ECDSAVerifier.java deleted file mode 100644 index 6bb0fd2a..00000000 --- a/src/main/java/org/arkecosystem/crypto/signature/ECDSAVerifier.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.arkecosystem.crypto.signature; - -import org.bitcoinj.core.ECKey; -import org.bitcoinj.core.SignatureDecodeException; - -public class ECDSAVerifier implements Verifier { - @Override - public boolean verify(byte[] hash, ECKey key, byte[] signature) { - try { - return ECKey.verify(hash, signature, key.getPubKey()); - } catch (SignatureDecodeException e) { - return false; - } - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java b/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java index c61e82b0..0530eca3 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java @@ -9,7 +9,6 @@ import java.util.Set; import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.identities.PrivateKey; -import org.arkecosystem.crypto.signature.ECDSAVerifier; import org.arkecosystem.crypto.signature.SchnorrSigner; import org.arkecosystem.crypto.signature.SchnorrVerifier; import org.arkecosystem.crypto.signature.Signer; @@ -208,7 +207,6 @@ private Signer signer() { } private Verifier verifier(String signature) { - // 128 string length => 64 bits - return signature.length() == 128 ? new SchnorrVerifier() : new ECDSAVerifier(); + return new SchnorrVerifier(); } } diff --git a/src/test/java/org/arkecosystem/crypto/signature/ECDSASignerTest.java b/src/test/java/org/arkecosystem/crypto/signature/ECDSASignerTest.java deleted file mode 100644 index f1ca3a1d..00000000 --- a/src/test/java/org/arkecosystem/crypto/signature/ECDSASignerTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.arkecosystem.crypto.signature; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.arkecosystem.crypto.Schnorr; -import org.arkecosystem.crypto.identities.PrivateKey; -import org.bitcoinj.core.ECKey; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class ECDSASignerTest { - - private Signer signer; - - @BeforeEach - void setUp() { - signer = new ECDSASigner(); - } - - @Test - void sign() { - String message = "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"; - ECKey privateKey = PrivateKey.fromPassphrase("some passphrase"); - String signature = - "304402207856D22D9C1E146492117B61D83F0A8D2E046C5A75F471172689A0A0C26907C6022035A1368F38EC63BC9B7BEEC7BCE49BD2C1AE28179EE83EBE7FD9C17824E2514B"; - - assertEquals( - signature, - Schnorr.bytesToHex(signer.sign(Schnorr.hexStringToByteArray(message), privateKey))); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/signature/ECDSAVerifierTest.java b/src/test/java/org/arkecosystem/crypto/signature/ECDSAVerifierTest.java deleted file mode 100644 index 5f568319..00000000 --- a/src/test/java/org/arkecosystem/crypto/signature/ECDSAVerifierTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.arkecosystem.crypto.signature; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.arkecosystem.crypto.Schnorr; -import org.arkecosystem.crypto.identities.PrivateKey; -import org.bitcoinj.core.ECKey; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class ECDSAVerifierTest { - - private Verifier verifier; - - @BeforeEach - void setUp() { - verifier = new ECDSAVerifier(); - } - - @Test - void verify() { - byte[] message = - Schnorr.hexStringToByteArray( - "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); - ECKey privateKey = PrivateKey.fromPassphrase("some passphrase"); - String signature = - "304402207856D22D9C1E146492117B61D83F0A8D2E046C5A75F471172689A0A0C26907C6022035A1368F38EC63BC9B7BEEC7BCE49BD2C1AE28179EE83EBE7FD9C17824E2514B"; - - assertTrue(verifier.verify(message, privateKey, Schnorr.hexStringToByteArray(signature))); - } - - @Test - void verifyInvalid() { - byte[] message = - Schnorr.hexStringToByteArray( - "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); - ECKey privateKey = PrivateKey.fromPassphrase("some passphrase"); - String signature = - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"; - - assertFalse(verifier.verify(message, privateKey, Schnorr.hexStringToByteArray(signature))); - } -} From a2556d8250ccc72846041740d34974105f98f278 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Thu, 1 Aug 2024 12:13:04 -0600 Subject: [PATCH 03/74] add secp256k1 library for schnorr --- build.gradle | 5 +++++ libs/secp256k1-api-0.0.1.jar | Bin 0 -> 12671 bytes 2 files changed, 5 insertions(+) create mode 100644 libs/secp256k1-api-0.0.1.jar diff --git a/build.gradle b/build.gradle index 0e176451..b0a97ec6 100644 --- a/build.gradle +++ b/build.gradle @@ -15,12 +15,17 @@ targetCompatibility = 1.8 repositories { mavenLocal() mavenCentral() + flatDir { + dirs 'libs' + } } dependencies { implementation group: 'org.bitcoinj', name: 'bitcoinj-core', version: '0.15.8' implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6' implementation 'com.google.guava:guava:30.1.1-jre' + // Compiled from https://gitlab.com/bitcoinj/secp256k1-jdk + implementation name: 'secp256k1-api-0.0.1' testCompileOnly 'org.slf4j:slf4j-api:1.7.32' testRuntimeOnly 'org.slf4j:slf4j-simple:1.7.32' diff --git a/libs/secp256k1-api-0.0.1.jar b/libs/secp256k1-api-0.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..23de910d380f16ce40851eac9713a292955cb7c9 GIT binary patch literal 12671 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 literal 0 HcmV?d00001 From ba35322597eed272e970eca1acbaa01f93446ede Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Thu, 1 Aug 2024 13:45:01 -0600 Subject: [PATCH 04/74] upgrade gradle --- build.gradle | 43 +++++++++++------------- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/build.gradle b/build.gradle index b0a97ec6..99bca533 100644 --- a/build.gradle +++ b/build.gradle @@ -3,35 +3,30 @@ plugins { id 'maven-publish' id 'signing' id 'jacoco' - id 'com.diffplug.spotless' version '5.6.1' + id 'com.diffplug.spotless' version '5.14.3' } group = 'org.arkecosystem' version = '2.0.0' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 +sourceCompatibility = '1.8' +targetCompatibility = '1.8' repositories { mavenLocal() mavenCentral() - flatDir { - dirs 'libs' - } } dependencies { - implementation group: 'org.bitcoinj', name: 'bitcoinj-core', version: '0.15.8' - implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6' + implementation 'org.bitcoinj:bitcoinj-core:0.16.3' + implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.guava:guava:30.1.1-jre' - // Compiled from https://gitlab.com/bitcoinj/secp256k1-jdk - implementation name: 'secp256k1-api-0.0.1' - testCompileOnly 'org.slf4j:slf4j-api:1.7.32' + testImplementation 'org.slf4j:slf4j-api:1.7.32' testRuntimeOnly 'org.slf4j:slf4j-simple:1.7.32' testImplementation 'org.hamcrest:hamcrest-library:2.2' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' - testCompileOnly 'org.junit.jupiter:junit-jupiter-params:5.7.2' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.2' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' } @@ -56,25 +51,25 @@ jacocoTestReport { spotless { java { - target fileTree(projectDir) { - include 'src/main/**/*.java' - include 'src/test/**/*.java' - exclude '**/build/**' - } + target 'src/**/*.java' googleJavaFormat('1.1').aosp() } } -task formatCode(dependsOn: ['spotlessApply']) +tasks.register('formatCode') { + dependsOn 'spotlessApply' +} -task fatJar(type: Jar) { - manifest.from jar.manifest +tasks.register('fatJar', Jar) { + manifest { + attributes 'Main-Class': 'com.example.Main' + } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } { - exclude "META-INF/*.SF" - exclude "META-INF/*.DSA" - exclude "META-INF/*.RSA" + exclude 'META-INF/*.SF' + exclude 'META-INF/*.DSA' + exclude 'META-INF/*.RSA' } with jar } @@ -82,7 +77,7 @@ task fatJar(type: Jar) { build.dependsOn 'spotlessApply' wrapper { - gradleVersion = '7.2' + gradleVersion = '8.1.1' } publishing { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ffed3a25..19cfad96 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 4421cecbfc70c40e1eec39de3857a5158f11f74d Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Thu, 1 Aug 2024 13:48:54 -0600 Subject: [PATCH 05/74] add schnorr signature library --- build.gradle | 1 + libs/secp256k1-api-0.0.1.jar | Bin 12671 -> 12671 bytes 2 files changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 99bca533..22ee80eb 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,7 @@ repositories { } dependencies { + implementation files('libs/secp256k1-api-0.0.1.jar') implementation 'org.bitcoinj:bitcoinj-core:0.16.3' implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.guava:guava:30.1.1-jre' diff --git a/libs/secp256k1-api-0.0.1.jar b/libs/secp256k1-api-0.0.1.jar index 23de910d380f16ce40851eac9713a292955cb7c9..2795c7fb661dbae252828d37f0fa41155f4d2455 100644 GIT binary patch delta 298 zcmeyL^goFwz?+#xgn@yBgJEaZL>_e}AZc0wBG)T{$jjP5auTB{keqDJXbGe?7crVJ zgXk43ADBSGv)HeKxP=@tVBvo5A{LM^v%m|G@LPdttRT8oY#~^+hU8liS6s@O4WueY z;R%TAr1%9SyV*kJE=cucajp9x>W3ECVts7~5U)_%07Na;203H$J#A+YrL5x)qH=V? zK-3YPI1r_x8wH{obi+Z^P2FG+rKgtyqNeCYf~fa;B_JwQAFT4AK3Kb?K_W=7#sDmM L!vJiUg`qnDVd8NH delta 298 zcmeyL^goFwz?+#xgn@yBgTXawB9A%~kTk6Tk?WN}B}NKQ6qv;Odo_^rS+RuJ7Pwh*jZL-H+%D=y{C22vHH z@C3wlQv3pv-E5(97o>W!xYm6T^+OA6vA(tgh*zj>0HPLagPbw>p0+cHQr2+?Q8_wc zAnJ%t9EeiUjRH{(y5S(|rfx8Z($h-;QB(9HLDYM_5)hTD4_0|lAFN%{AQ2>3V*nPs LVE{JF!q6Q6w2EA2 From 916b499938b91f87524f16083fa55f5c7978ef4b Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 10:03:30 -0600 Subject: [PATCH 06/74] upgrade dependencies --- .github/workflows/test.yml | 78 +++--- .vscode/settings.json | 4 + build.gradle | 52 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- .../java/org/arkecosystem/crypto/Schnorr.java | 3 +- .../FixtureSignVerificationTest.java | 233 +++++++++--------- 6 files changed, 186 insertions(+), 186 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6aa0bd63..52a6f4fa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,65 +6,65 @@ on: - "master" - "develop" pull_request: - types: [ ready_for_review, synchronize, opened ] + types: [ready_for_review, synchronize, opened] jobs: format: runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} + - name: Checkout code + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} - - name: Merge Conflict finder - uses: olivernybroe/action-conflict-finder@v1.1 + - name: Merge Conflict finder + uses: olivernybroe/action-conflict-finder@v1.1 - - name: Use Java Version ${{ matrix.java }} - uses: actions/setup-java@v2 - with: - distribution: 'adopt' - java-version: 8 - cache: 'gradle' + - name: Use Java Version ${{ matrix.java }} + uses: actions/setup-java@v2 + with: + distribution: "adopt" + java-version: 8 + cache: "gradle" - - name: Format code - run: gradle format + - name: Format code + run: gradle format - - name: Commit fixed code - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "style: resolve style guide violations" - branch: ${{ github.head_ref }} + - name: Commit fixed code + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: "style: resolve style guide violations" + branch: ${{ github.head_ref }} unit: runs-on: ubuntu-latest strategy: matrix: # test against the latest update of each major Java version, as well as specific updates of LTS versions: - java: [ 8, 11, 15, 16, 17 ] + java: [8, 11, 15, 16, 17, 18, 19, 20, 21, 22] steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} + - name: Checkout code + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} - - name: Merge Conflict finder - uses: olivernybroe/action-conflict-finder@v1.1 + - name: Merge Conflict finder + uses: olivernybroe/action-conflict-finder@v1.1 - - name: Use Java Version ${{ matrix.java }} - uses: actions/setup-java@v2 - with: - distribution: 'zulu' - java-version: ${{ matrix.java }} - cache: 'gradle' + - name: Use Java Version ${{ matrix.java }} + uses: actions/setup-java@v2 + with: + distribution: "zulu" + java-version: ${{ matrix.java }} + cache: "gradle" - - name: Install - run: gradle dependencies + - name: Install + run: gradle dependencies - - name: Test - run: gradle test && gradle jacocoTestReport + - name: Test + run: gradle test && gradle jacocoTestReport - - name: Codecov - run: bash <(curl -s https://codecov.io/bash) -t ${{ secrets.CODECOV_TOKEN }} + - name: Codecov + run: bash <(curl -s https://codecov.io/bash) -t ${{ secrets.CODECOV_TOKEN }} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..1323e0dc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "java.compile.nullAnalysis.mode": "automatic", + "java.configuration.updateBuildConfiguration": "automatic" +} diff --git a/build.gradle b/build.gradle index 0e176451..e754133d 100644 --- a/build.gradle +++ b/build.gradle @@ -3,14 +3,14 @@ plugins { id 'maven-publish' id 'signing' id 'jacoco' - id 'com.diffplug.spotless' version '5.6.1' + id 'com.diffplug.spotless' version '6.25.0' } group = 'org.arkecosystem' version = '2.0.0' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 +sourceCompatibility = '1.8' +targetCompatibility = '1.8' repositories { mavenLocal() @@ -18,16 +18,16 @@ repositories { } dependencies { - implementation group: 'org.bitcoinj', name: 'bitcoinj-core', version: '0.15.8' - implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6' - implementation 'com.google.guava:guava:30.1.1-jre' - - testCompileOnly 'org.slf4j:slf4j-api:1.7.32' - testRuntimeOnly 'org.slf4j:slf4j-simple:1.7.32' - testImplementation 'org.hamcrest:hamcrest-library:2.2' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' - testCompileOnly 'org.junit.jupiter:junit-jupiter-params:5.7.2' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' + implementation 'org.bitcoinj:bitcoinj-core:0.16.3' + implementation 'com.google.code.gson:gson:2.11.0' + implementation 'com.google.guava:guava:30.2.0-jre' + + testImplementation 'org.slf4j:slf4j-api:2.0.13' + testRuntimeOnly 'org.slf4j:slf4j-simple:2.0.13' + testImplementation 'org.hamcrest:hamcrest-library:3.0' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.3' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.3' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.3' } java { @@ -51,25 +51,25 @@ jacocoTestReport { spotless { java { - target fileTree(projectDir) { - include 'src/main/**/*.java' - include 'src/test/**/*.java' - exclude '**/build/**' - } - googleJavaFormat('1.1').aosp() + target 'src/**/*.java' + googleJavaFormat('1.17.0').aosp() } } -task formatCode(dependsOn: ['spotlessApply']) +tasks.register('formatCode') { + dependsOn 'spotlessApply' +} -task fatJar(type: Jar) { - manifest.from jar.manifest +tasks.register('fatJar', Jar) { + manifest { + attributes 'Main-Class': 'com.example.Main' + } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } { - exclude "META-INF/*.SF" - exclude "META-INF/*.DSA" - exclude "META-INF/*.RSA" + exclude 'META-INF/*.SF' + exclude 'META-INF/*.DSA' + exclude 'META-INF/*.RSA' } with jar } @@ -77,7 +77,7 @@ task fatJar(type: Jar) { build.dependsOn 'spotlessApply' wrapper { - gradleVersion = '7.2' + gradleVersion = '8.1.1' } publishing { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ffed3a25..19cfad96 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/org/arkecosystem/crypto/Schnorr.java b/src/main/java/org/arkecosystem/crypto/Schnorr.java index 688c33a9..2b91b775 100644 --- a/src/main/java/org/arkecosystem/crypto/Schnorr.java +++ b/src/main/java/org/arkecosystem/crypto/Schnorr.java @@ -35,8 +35,7 @@ public static BigInteger[] addPoint(BigInteger[] p1, BigInteger[] p2) { .mod(p); else lam = - (p2[1] - .subtract(p1[1]) + (p2[1].subtract(p1[1]) .multiply(p2[0].subtract(p1[0]).modPow(p.subtract(TWO), p))) .mod(p); diff --git a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java index 1835f0bc..7d5099f8 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java @@ -27,36 +27,35 @@ public class FixtureSignVerificationTest { @ParameterizedTest @ValueSource( - strings = { - "transactions/v2-ecdsa/second-signature-registration", - "transactions/v2-ecdsa/transfer-with-vendor-field-secondSign", - "transactions/v2-ecdsa/transfer-secondSign", - "transactions/v2-ecdsa/transfer-sign", - "transactions/v2-ecdsa/multi-payment-secondSign", - "transactions/v2-ecdsa/delegate-resignation-secondSign", - "transactions/v2-ecdsa/htlc-claim-sign", - "transactions/v2-ecdsa/htlc-claim-secondSign", - "transactions/v2-ecdsa/htlc-lock-sign", - "transactions/v2-ecdsa/htlc-refund-secondSign", - "transactions/v2-ecdsa/delegate-registration-sign", - "transactions/v2-ecdsa/vote-sign", - "transactions/v2-ecdsa/multi-payment-sign", - "transactions/v2-ecdsa/multi-payment-with-vendor-field-sign", - "transactions/v2-ecdsa/delegate-registration-secondSign", - "transactions/v2-ecdsa/ipfs-secondSign", - "transactions/v2-ecdsa/htlc-lock-secondSign", - "transactions/v2-ecdsa/unvote-sign", - "transactions/v2-ecdsa/vote-secondSign", - "transactions/v2-ecdsa/delegate-resignation-sign", - "transactions/v2-ecdsa/htlc-lock-with-vendor-field-sign", - "transactions/v2-ecdsa/ipfs-sign", - "transactions/v2-ecdsa/htlc-lock-with-vendor-field-secondSign", - "transactions/v2-ecdsa/unvote-secondSign", - "transactions/v2-ecdsa/transfer-with-vendor-field-sign", - "transactions/v2-ecdsa/multi-payment-with-vendor-field-secondSign", - "transactions/v2-ecdsa/htlc-refund-sign", - } - ) + strings = { + "transactions/v2-ecdsa/second-signature-registration", + "transactions/v2-ecdsa/transfer-with-vendor-field-secondSign", + "transactions/v2-ecdsa/transfer-secondSign", + "transactions/v2-ecdsa/transfer-sign", + "transactions/v2-ecdsa/multi-payment-secondSign", + "transactions/v2-ecdsa/delegate-resignation-secondSign", + "transactions/v2-ecdsa/htlc-claim-sign", + "transactions/v2-ecdsa/htlc-claim-secondSign", + "transactions/v2-ecdsa/htlc-lock-sign", + "transactions/v2-ecdsa/htlc-refund-secondSign", + "transactions/v2-ecdsa/delegate-registration-sign", + "transactions/v2-ecdsa/vote-sign", + "transactions/v2-ecdsa/multi-payment-sign", + "transactions/v2-ecdsa/multi-payment-with-vendor-field-sign", + "transactions/v2-ecdsa/delegate-registration-secondSign", + "transactions/v2-ecdsa/ipfs-secondSign", + "transactions/v2-ecdsa/htlc-lock-secondSign", + "transactions/v2-ecdsa/unvote-sign", + "transactions/v2-ecdsa/vote-secondSign", + "transactions/v2-ecdsa/delegate-resignation-sign", + "transactions/v2-ecdsa/htlc-lock-with-vendor-field-sign", + "transactions/v2-ecdsa/ipfs-sign", + "transactions/v2-ecdsa/htlc-lock-with-vendor-field-secondSign", + "transactions/v2-ecdsa/unvote-secondSign", + "transactions/v2-ecdsa/transfer-with-vendor-field-sign", + "transactions/v2-ecdsa/multi-payment-with-vendor-field-secondSign", + "transactions/v2-ecdsa/htlc-refund-sign", + }) void checkEcdsa(String file) { LinkedTreeMap fixture = FixtureLoader.load(file); @@ -67,50 +66,49 @@ void checkEcdsa(String file) { @ParameterizedTest @ValueSource( - strings = { - "transactions/v2-schnorr/second-signature-registration", - "transactions/v2-schnorr/transfer-with-vendor-field-secondSign", - "transactions/v2-schnorr/transfer-secondSign", - "transactions/v2-schnorr/multi-signature-registration", - "transactions/v2-schnorr/transfer-sign", - "transactions/v2-schnorr/multi-payment-secondSign", - "transactions/v2-schnorr/delegate-resignation-secondSign", - "transactions/v2-schnorr/htlc-claim-sign", - "transactions/v2-schnorr/htlc-claim-secondSign", - "transactions/v2-schnorr/htlc-lock-sign", - "transactions/v2-schnorr/htlc-refund-secondSign", - "transactions/v2-schnorr/delegate-registration-sign", - "transactions/v2-schnorr/vote-sign", - "transactions/v2-schnorr/multi-payment-sign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-sign", - "transactions/v2-schnorr/delegate-registration-secondSign", - "transactions/v2-schnorr/ipfs-secondSign", - "transactions/v2-schnorr/htlc-lock-secondSign", - "transactions/v2-schnorr/unvote-sign", - "transactions/v2-schnorr/vote-secondSign", - "transactions/v2-schnorr/delegate-resignation-sign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-sign", - "transactions/v2-schnorr/ipfs-sign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign", - "transactions/v2-schnorr/unvote-secondSign", - "transactions/v2-schnorr/transfer-with-vendor-field-sign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign", - "transactions/v2-schnorr/htlc-refund-sign", - "transactions/v2-schnorr/htlc-lock-multiSign", - "transactions/v2-schnorr/htlc-claim-multiSign", - "transactions/v2-schnorr/htlc-refund-multiSign", - "transactions/v2-schnorr/ipfs-multiSign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign", - "transactions/v2-schnorr/vote-multiSign", - "transactions/v2-schnorr/multi-payment-multiSign", - "transactions/v2-schnorr/transfer-with-vendor-field-multiSign", - "transactions/v2-schnorr/unvote-multiSign", - "transactions/v2-schnorr/delegate-registration-multiSign", - "transactions/v2-schnorr/transfer-multiSign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign", - "transactions/v2-schnorr/delegate-resignation-multiSign", - } - ) + strings = { + "transactions/v2-schnorr/second-signature-registration", + "transactions/v2-schnorr/transfer-with-vendor-field-secondSign", + "transactions/v2-schnorr/transfer-secondSign", + "transactions/v2-schnorr/multi-signature-registration", + "transactions/v2-schnorr/transfer-sign", + "transactions/v2-schnorr/multi-payment-secondSign", + "transactions/v2-schnorr/delegate-resignation-secondSign", + "transactions/v2-schnorr/htlc-claim-sign", + "transactions/v2-schnorr/htlc-claim-secondSign", + "transactions/v2-schnorr/htlc-lock-sign", + "transactions/v2-schnorr/htlc-refund-secondSign", + "transactions/v2-schnorr/delegate-registration-sign", + "transactions/v2-schnorr/vote-sign", + "transactions/v2-schnorr/multi-payment-sign", + "transactions/v2-schnorr/multi-payment-with-vendor-field-sign", + "transactions/v2-schnorr/delegate-registration-secondSign", + "transactions/v2-schnorr/ipfs-secondSign", + "transactions/v2-schnorr/htlc-lock-secondSign", + "transactions/v2-schnorr/unvote-sign", + "transactions/v2-schnorr/vote-secondSign", + "transactions/v2-schnorr/delegate-resignation-sign", + "transactions/v2-schnorr/htlc-lock-with-vendor-field-sign", + "transactions/v2-schnorr/ipfs-sign", + "transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign", + "transactions/v2-schnorr/unvote-secondSign", + "transactions/v2-schnorr/transfer-with-vendor-field-sign", + "transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign", + "transactions/v2-schnorr/htlc-refund-sign", + "transactions/v2-schnorr/htlc-lock-multiSign", + "transactions/v2-schnorr/htlc-claim-multiSign", + "transactions/v2-schnorr/htlc-refund-multiSign", + "transactions/v2-schnorr/ipfs-multiSign", + "transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign", + "transactions/v2-schnorr/vote-multiSign", + "transactions/v2-schnorr/multi-payment-multiSign", + "transactions/v2-schnorr/transfer-with-vendor-field-multiSign", + "transactions/v2-schnorr/unvote-multiSign", + "transactions/v2-schnorr/delegate-registration-multiSign", + "transactions/v2-schnorr/transfer-multiSign", + "transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign", + "transactions/v2-schnorr/delegate-resignation-multiSign", + }) void checkSchnorrSignature(String file) { LinkedTreeMap fixture = FixtureLoader.load(file); @@ -129,50 +127,49 @@ void checkSchnorrSignature(String file) { @ParameterizedTest @ValueSource( - strings = { - "transactions/v2-schnorr/second-signature-registration", - "transactions/v2-schnorr/transfer-with-vendor-field-secondSign", - "transactions/v2-schnorr/transfer-secondSign", - "transactions/v2-schnorr/multi-signature-registration", - "transactions/v2-schnorr/transfer-sign", - "transactions/v2-schnorr/multi-payment-secondSign", - "transactions/v2-schnorr/delegate-resignation-secondSign", - "transactions/v2-schnorr/htlc-claim-sign", - "transactions/v2-schnorr/htlc-claim-secondSign", - "transactions/v2-schnorr/htlc-lock-sign", - "transactions/v2-schnorr/htlc-refund-secondSign", - "transactions/v2-schnorr/delegate-registration-sign", - "transactions/v2-schnorr/vote-sign", - "transactions/v2-schnorr/multi-payment-sign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-sign", - "transactions/v2-schnorr/delegate-registration-secondSign", - "transactions/v2-schnorr/ipfs-secondSign", - "transactions/v2-schnorr/htlc-lock-secondSign", - "transactions/v2-schnorr/unvote-sign", - "transactions/v2-schnorr/vote-secondSign", - "transactions/v2-schnorr/delegate-resignation-sign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-sign", - "transactions/v2-schnorr/ipfs-sign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign", - "transactions/v2-schnorr/unvote-secondSign", - "transactions/v2-schnorr/transfer-with-vendor-field-sign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign", - "transactions/v2-schnorr/htlc-refund-sign", - "transactions/v2-schnorr/htlc-lock-multiSign", - "transactions/v2-schnorr/htlc-claim-multiSign", - "transactions/v2-schnorr/htlc-refund-multiSign", - "transactions/v2-schnorr/ipfs-multiSign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign", - "transactions/v2-schnorr/vote-multiSign", - "transactions/v2-schnorr/multi-payment-multiSign", - "transactions/v2-schnorr/transfer-with-vendor-field-multiSign", - "transactions/v2-schnorr/unvote-multiSign", - "transactions/v2-schnorr/delegate-registration-multiSign", - "transactions/v2-schnorr/transfer-multiSign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign", - "transactions/v2-schnorr/delegate-resignation-multiSign", - } - ) + strings = { + "transactions/v2-schnorr/second-signature-registration", + "transactions/v2-schnorr/transfer-with-vendor-field-secondSign", + "transactions/v2-schnorr/transfer-secondSign", + "transactions/v2-schnorr/multi-signature-registration", + "transactions/v2-schnorr/transfer-sign", + "transactions/v2-schnorr/multi-payment-secondSign", + "transactions/v2-schnorr/delegate-resignation-secondSign", + "transactions/v2-schnorr/htlc-claim-sign", + "transactions/v2-schnorr/htlc-claim-secondSign", + "transactions/v2-schnorr/htlc-lock-sign", + "transactions/v2-schnorr/htlc-refund-secondSign", + "transactions/v2-schnorr/delegate-registration-sign", + "transactions/v2-schnorr/vote-sign", + "transactions/v2-schnorr/multi-payment-sign", + "transactions/v2-schnorr/multi-payment-with-vendor-field-sign", + "transactions/v2-schnorr/delegate-registration-secondSign", + "transactions/v2-schnorr/ipfs-secondSign", + "transactions/v2-schnorr/htlc-lock-secondSign", + "transactions/v2-schnorr/unvote-sign", + "transactions/v2-schnorr/vote-secondSign", + "transactions/v2-schnorr/delegate-resignation-sign", + "transactions/v2-schnorr/htlc-lock-with-vendor-field-sign", + "transactions/v2-schnorr/ipfs-sign", + "transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign", + "transactions/v2-schnorr/unvote-secondSign", + "transactions/v2-schnorr/transfer-with-vendor-field-sign", + "transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign", + "transactions/v2-schnorr/htlc-refund-sign", + "transactions/v2-schnorr/htlc-lock-multiSign", + "transactions/v2-schnorr/htlc-claim-multiSign", + "transactions/v2-schnorr/htlc-refund-multiSign", + "transactions/v2-schnorr/ipfs-multiSign", + "transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign", + "transactions/v2-schnorr/vote-multiSign", + "transactions/v2-schnorr/multi-payment-multiSign", + "transactions/v2-schnorr/transfer-with-vendor-field-multiSign", + "transactions/v2-schnorr/unvote-multiSign", + "transactions/v2-schnorr/delegate-registration-multiSign", + "transactions/v2-schnorr/transfer-multiSign", + "transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign", + "transactions/v2-schnorr/delegate-resignation-multiSign", + }) void checkSigningAgainProducesSameSignature(String file) { LinkedTreeMap fixture = FixtureLoader.load(file); From a8a47641f4358b423bc8ec799b14bde41b1e9b9c Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 10:08:02 -0600 Subject: [PATCH 07/74] update to java 22 --- .github/workflows/release.yml | 4 ++-- .github/workflows/test.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1761f28d..ab13ee3b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,8 +23,8 @@ jobs: - name: Set up Java uses: actions/setup-java@v2 with: - java-version: '8' - distribution: 'adopt' + java-version: "22" + distribution: "adopt" - name: Publish to the Maven Central Repository run: gradle publish diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 52a6f4fa..60e1c65d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,7 @@ jobs: uses: actions/setup-java@v2 with: distribution: "adopt" - java-version: 8 + java-version: 22 cache: "gradle" - name: Format code From 759fe532d4a0be996b5d4e77b4f66ef397bebfac Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 10:12:35 -0600 Subject: [PATCH 08/74] remove java 8 compatibility --- .github/workflows/test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 60e1c65d..315aa052 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,8 +41,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # test against the latest update of each major Java version, as well as specific updates of LTS versions: - java: [8, 11, 15, 16, 17, 18, 19, 20, 21, 22] + java: [11, 15, 16, 17, 18, 19, 20, 21, 22] steps: - name: Checkout code From f698dbee8e188cb17837681ba32ffebb7253202b Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 10:22:26 -0600 Subject: [PATCH 09/74] include secp api --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index e754133d..0a3a73cd 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ repositories { dependencies { implementation 'org.bitcoinj:bitcoinj-core:0.16.3' + implementation files('libs/secp256k1-api-0.0.1.jar') implementation 'com.google.code.gson:gson:2.11.0' implementation 'com.google.guava:guava:30.2.0-jre' From 093dad183369176ef61a3a3a0d87eca949e83a49 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 10:24:44 -0600 Subject: [PATCH 10/74] compatibility issues --- build.gradle | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index e754133d..fac5a106 100644 --- a/build.gradle +++ b/build.gradle @@ -9,8 +9,12 @@ plugins { group = 'org.arkecosystem' version = '2.0.0' -sourceCompatibility = '1.8' -targetCompatibility = '1.8' +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + withJavadocJar() + withSourcesJar() +} repositories { mavenLocal() @@ -28,11 +32,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.3' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.3' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.3' -} - -java { - withJavadocJar() - withSourcesJar() + testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.10.3' } test { From e680c0325a073aea7bbe7500d32f178a4afc39ea Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 11:59:31 -0600 Subject: [PATCH 11/74] influde foreign library --- build.gradle | 5 +++-- libs/secp256k1-foreign-0.0.1.jar | Bin 0 -> 94605 bytes 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 libs/secp256k1-foreign-0.0.1.jar diff --git a/build.gradle b/build.gradle index ce31dc5d..b58ef063 100644 --- a/build.gradle +++ b/build.gradle @@ -10,8 +10,8 @@ group = 'org.arkecosystem' version = '2.0.0' java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.toVersion("22") + targetCompatibility = JavaVersion.toVersion("22") withJavadocJar() withSourcesJar() } @@ -24,6 +24,7 @@ repositories { dependencies { implementation 'org.bitcoinj:bitcoinj-core:0.16.3' implementation files('libs/secp256k1-api-0.0.1.jar') + implementation files('libs/secp256k1-foreign-0.0.1.jar') implementation 'com.google.code.gson:gson:2.11.0' implementation 'com.google.guava:guava:30.2.0-jre' diff --git a/libs/secp256k1-foreign-0.0.1.jar b/libs/secp256k1-foreign-0.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..38414c6a768aa8b3ff5140322aad08f8ad96e987 GIT binary patch literal 94605 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 Date: Fri, 2 Aug 2024 11:59:49 -0600 Subject: [PATCH 12/74] add schnorr signature --- .../signature/CompressedPubKeyDataImpl.java | 21 ++++++++ .../crypto/signature/P256k1PrivKeyImpl.java | 54 +++++++++++++++++++ .../crypto/signature/SchnorrSigner.java | 31 ++++++++++- .../crypto/signature/SchnorrVerifier.java | 16 +++++- .../transactions/transfer/transfer-sign.json | 17 ++++++ 5 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/arkecosystem/crypto/signature/CompressedPubKeyDataImpl.java create mode 100644 src/main/java/org/arkecosystem/crypto/signature/P256k1PrivKeyImpl.java create mode 100644 src/test/resources/transactions/transfer/transfer-sign.json diff --git a/src/main/java/org/arkecosystem/crypto/signature/CompressedPubKeyDataImpl.java b/src/main/java/org/arkecosystem/crypto/signature/CompressedPubKeyDataImpl.java new file mode 100644 index 00000000..f6bc50cb --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/signature/CompressedPubKeyDataImpl.java @@ -0,0 +1,21 @@ +package org.arkecosystem.crypto.signature; + +import java.util.Arrays; +import org.bitcoinj.secp256k1.api.CompressedPubKeyData; + +public class CompressedPubKeyDataImpl implements CompressedPubKeyData { + + private final byte[] bytes; + + public CompressedPubKeyDataImpl(byte[] bytes) { + if (bytes.length != 33) { + throw new IllegalArgumentException("Compressed public key must be 33 bytes"); + } + this.bytes = Arrays.copyOf(bytes, bytes.length); + } + + @Override + public byte[] bytes() { + return Arrays.copyOf(bytes, bytes.length); + } +} diff --git a/src/main/java/org/arkecosystem/crypto/signature/P256k1PrivKeyImpl.java b/src/main/java/org/arkecosystem/crypto/signature/P256k1PrivKeyImpl.java new file mode 100644 index 00000000..15c5955e --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/signature/P256k1PrivKeyImpl.java @@ -0,0 +1,54 @@ +package org.arkecosystem.crypto.signature; + +import java.math.BigInteger; +import java.util.Arrays; +import org.bitcoinj.secp256k1.api.P256k1PrivKey; + +public class P256k1PrivKeyImpl implements P256k1PrivKey { + private final byte[] encoded; + private boolean destroyed; + + public P256k1PrivKeyImpl(byte[] encoded) { + if (encoded.length != 32) { + throw new IllegalArgumentException("Private key must be 32 bytes"); + } + this.encoded = Arrays.copyOf(encoded, encoded.length); + this.destroyed = false; + } + + @Override + public byte[] getEncoded() { + if (destroyed) { + throw new IllegalStateException("Private key has been destroyed"); + } + return Arrays.copyOf(encoded, encoded.length); + } + + @Override + public void destroy() { + Arrays.fill(encoded, (byte) 0); + this.destroyed = true; + } + + @Override + public BigInteger getS() { + return toInteger(getEncoded()); + } + + /** + * Converts a byte array into a BigInteger. Assumes the byte array represents an unsigned + * integer in big-endian order. + * + * @param bytes the byte array to convert. + * @return the BigInteger representation. + */ + private BigInteger toInteger(byte[] bytes) { + // BigInteger interprets the byte array as a signed integer in big-endian order. + // To handle this correctly for unsigned values (like private keys), we prepend a zero byte + // to ensure the value is always positive. + byte[] unsignedBytes = new byte[bytes.length + 1]; + unsignedBytes[0] = 0; // Leading zero for positive sign + System.arraycopy(bytes, 0, unsignedBytes, 1, bytes.length); + return new BigInteger(unsignedBytes); + } +} diff --git a/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java b/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java index 3d3616d8..ab96ff4c 100644 --- a/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java +++ b/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java @@ -1,11 +1,38 @@ package org.arkecosystem.crypto.signature; -import org.arkecosystem.crypto.Schnorr; import org.bitcoinj.core.ECKey; +import org.bitcoinj.secp256k1.api.P256K1KeyPair; +import org.bitcoinj.secp256k1.api.P256k1PrivKey; +import org.bitcoinj.secp256k1.api.Secp256k1; public class SchnorrSigner implements Signer { @Override public byte[] sign(byte[] message, ECKey privateKey) { - return Schnorr.schnorrSign(message, privateKey.getPrivKey()); + + Secp256k1 secp = Secp256k1.get(); + + // @TODO: check if this is the correct way to get the private key + // String privateKeyHex = privateKey.getPrivateKeyAsHex(); + + byte[] privKeyBytes = hexStringToByteArray(privateKey.getPrivateKeyAsHex()); + + P256k1PrivKey privKey = new P256k1PrivKeyImpl(privKeyBytes); + + P256K1KeyPair keyPair = secp.ecKeyPairCreate(privKey); + + return secp.schnorrSigSign32(message, keyPair); + } + + // Helper method to convert hex string to byte array + private static byte[] hexStringToByteArray(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = + (byte) + ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i + 1), 16)); + } + return data; } } diff --git a/src/main/java/org/arkecosystem/crypto/signature/SchnorrVerifier.java b/src/main/java/org/arkecosystem/crypto/signature/SchnorrVerifier.java index 91f05d89..00117739 100644 --- a/src/main/java/org/arkecosystem/crypto/signature/SchnorrVerifier.java +++ b/src/main/java/org/arkecosystem/crypto/signature/SchnorrVerifier.java @@ -1,11 +1,23 @@ package org.arkecosystem.crypto.signature; -import org.arkecosystem.crypto.Schnorr; import org.bitcoinj.core.ECKey; +import org.bitcoinj.secp256k1.api.P256K1XOnlyPubKey; +import org.bitcoinj.secp256k1.api.P256k1PubKey; +import org.bitcoinj.secp256k1.api.Secp256k1; public class SchnorrVerifier implements Verifier { @Override public boolean verify(byte[] hash, ECKey keys, byte[] signature) { - return Schnorr.schnorrVerify(hash, keys.getPubKey(), signature); + byte[] pubKey = keys.getPubKey(); + + try (Secp256k1 secp = Secp256k1.get()) { + P256k1PubKey pubkey = secp.ecPubKeyParse(new CompressedPubKeyDataImpl(pubKey)).get(); + + P256K1XOnlyPubKey xOnly = pubkey.getXOnly(); + + P256K1XOnlyPubKey xOnly2 = P256K1XOnlyPubKey.parse(xOnly.getSerialized()).get(); + + return secp.schnorrSigVerify(signature, hash, xOnly2).get(); + } } } diff --git a/src/test/resources/transactions/transfer/transfer-sign.json b/src/test/resources/transactions/transfer/transfer-sign.json new file mode 100644 index 00000000..c1032bcf --- /dev/null +++ b/src/test/resources/transactions/transfer/transfer-sign.json @@ -0,0 +1,17 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 0, + "nonce": "1", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "10000000", + "amount": "1", + "expiration": 0, + "recipientId": "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", + "signature": "97dd98ed1066aab76011114cbf5ac00d741812cac326cda7966e1af08874d7212f350d769221d2a78ea185d77ac4e2c5c718e4a84b1a1ddcbf504d642eb94b6a", + "id": "e20265dba26594c4202e224e8d1069dfae840a8db7cc6acfafefa2b3b02787e5" + }, + "serialized": "ff011e0100000000000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3809698000000000000010000000000000000000000b693449adda7efc015d87944eae8b7c37eb1690a97dd98ed1066aab76011114cbf5ac00d741812cac326cda7966e1af08874d7212f350d769221d2a78ea185d77ac4e2c5c718e4a84b1a1ddcbf504d642eb94b6a" +} From d9101609881d27728eaba8d75c2ac33598fe3d12 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 13:47:58 -0600 Subject: [PATCH 13/74] generate keccak address --- build.gradle | 1 + .../crypto/identities/Address.java | 62 ++++++++----------- .../crypto/identities/AddressTest.java | 12 ++-- 3 files changed, 32 insertions(+), 43 deletions(-) diff --git a/build.gradle b/build.gradle index fac5a106..a81f6ca9 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ repositories { } dependencies { + implementation 'org.web3j:core:4.8.7' implementation 'org.bitcoinj:bitcoinj-core:0.16.3' implementation 'com.google.code.gson:gson:2.11.0' implementation 'com.google.guava:guava:30.2.0-jre' diff --git a/src/main/java/org/arkecosystem/crypto/identities/Address.java b/src/main/java/org/arkecosystem/crypto/identities/Address.java index d9d429eb..6973f3c4 100644 --- a/src/main/java/org/arkecosystem/crypto/identities/Address.java +++ b/src/main/java/org/arkecosystem/crypto/identities/Address.java @@ -1,58 +1,50 @@ package org.arkecosystem.crypto.identities; -import com.google.common.primitives.Bytes; -import org.arkecosystem.crypto.configuration.Network; -import org.arkecosystem.crypto.encoding.Base58; import org.arkecosystem.crypto.encoding.Hex; import org.bitcoinj.core.ECKey; -import org.bouncycastle.crypto.digests.RIPEMD160Digest; +import org.web3j.crypto.Hash; +import org.web3j.crypto.Keys; public class Address { - public static String fromPassphrase(String passphrase, Integer networkVersion) { - return fromPrivateKey(PrivateKey.fromPassphrase(passphrase), networkVersion); - } - public static String fromPassphrase(String passphrase) { - return Address.fromPassphrase(passphrase, null); + ECKey privateKey = PrivateKey.fromPassphrase(passphrase); + return fromPrivateKey(privateKey); } - public static String fromPublicKey(String publicKey, Integer networkVersion) { + public static String fromPublicKey(String publicKey) { byte[] publicKeyBytes = Hex.decode(publicKey); - RIPEMD160Digest digest = new RIPEMD160Digest(); - digest.update(publicKeyBytes, 0, publicKeyBytes.length); - byte[] out = new byte[20]; - digest.doFinal(out, 0); + // Ensure the public key is uncompressed + ECKey ecKey = ECKey.fromPublicOnly(publicKeyBytes); + byte[] uncompressedPublicKeyBytes = ecKey.getPubKeyPoint().getEncoded(false); - if (networkVersion == null) { - networkVersion = Network.get().version(); - } + // Remove the prefix (0x04) + byte[] rawPublicKey = new byte[uncompressedPublicKeyBytes.length - 1]; + System.arraycopy(uncompressedPublicKeyBytes, 1, rawPublicKey, 0, rawPublicKey.length); - byte[] bytes = Bytes.concat(new byte[] {networkVersion.byteValue()}, out); - return Base58.encodeChecked(bytes); - } + // Hash the public key using Keccak-256 + byte[] keccakHash = Hash.sha3(rawPublicKey); - public static String fromPublicKey(String publicKey) { - return Address.fromPublicKey(publicKey, null); - } + // Take the last 20 bytes of the Keccak-256 hash + byte[] addressBytes = new byte[20]; - public static String fromPrivateKey(ECKey privateKey, Integer networkVersion) { - return fromPublicKey(privateKey.getPublicKeyAsHex(), networkVersion); + System.arraycopy(keccakHash, keccakHash.length - 20, addressBytes, 0, 20); + + // Convert to checksum address + String address = "0x" + Hex.encode(addressBytes); + + return Keys.toChecksumAddress(address); } public static String fromPrivateKey(ECKey privateKey) { - return Address.fromPrivateKey(privateKey, null); - } - - public static Boolean validate(String address, Integer networkVersion) { - if (networkVersion == null) { - networkVersion = Network.get().version(); - } - - return Base58.decodeChecked(address)[0] == networkVersion; + byte[] publicKeyBytes = privateKey.getPubKey(); + return fromPublicKey(Hex.encode(publicKeyBytes)); } public static Boolean validate(String address) { - return Address.validate(address, null); + if (address == null || !address.matches("^0x[a-fA-F0-9]{40}$")) { + return false; + } + return address.equals(Keys.toChecksumAddress(address)); } } diff --git a/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java b/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java index 33cde63c..774622ad 100644 --- a/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java +++ b/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java @@ -3,8 +3,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.arkecosystem.crypto.configuration.Network; -import org.arkecosystem.crypto.networks.Devnet; import org.bitcoinj.core.ECKey; import org.junit.jupiter.api.Test; @@ -12,9 +10,8 @@ public class AddressTest { @Test public void fromPassphrase() { - Network.set(new Devnet()); String actual = Address.fromPassphrase("this is a top secret passphrase"); - assertEquals("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", actual); + assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual); } @Test @@ -22,19 +19,18 @@ public void fromPublicKey() { String actual = Address.fromPublicKey( "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192"); - assertEquals("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", actual); + assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual); } @Test public void fromPrivateKey() { ECKey privateKey = PrivateKey.fromPassphrase("this is a top secret passphrase"); String actual = Address.fromPrivateKey(privateKey); - assertEquals("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", actual); + assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual); } @Test public void validate() { - Network.set(new Devnet()); - assertTrue(Address.validate("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib")); + assertTrue(Address.validate("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01")); } } From 5c05d5800983476456b117b1833e67c80f24f956 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 13:48:16 -0600 Subject: [PATCH 14/74] Update VoteBuilder.java --- .../arkecosystem/crypto/transactions/builder/VoteBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java index 1cb1b1f2..d0209cf8 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java @@ -24,7 +24,7 @@ public VoteBuilder addVote(String vote) { } public VoteBuilder sign(String passphrase) { - this.transaction.recipientId = Address.fromPassphrase(passphrase, this.transaction.network); + this.transaction.recipientId = Address.fromPassphrase(passphrase); super.sign(passphrase); From f504c03648c787062932ca1bc53f0c482be5b00f Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 13:49:55 -0600 Subject: [PATCH 15/74] remplace old address --- src/test/resources/identity.json | 2 +- .../V1/transfer/passphrase-with-vendor-field-hex.json | 2 +- .../transactions/V1/transfer/passphrase-with-vendor-field.json | 2 +- src/test/resources/transactions/V1/transfer/passphrase.json | 2 +- .../V1/transfer/second-passphrase-with-vendor-field-hex.json | 2 +- .../V1/transfer/second-passphrase-with-vendor-field.json | 2 +- .../resources/transactions/V1/transfer/second-passphrase.json | 2 +- src/test/resources/transactions/V1/vote/passphrase.json | 2 +- src/test/resources/transactions/V1/vote/second-passphrase.json | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/resources/identity.json b/src/test/resources/identity.json index 5b566039..662d91b6 100644 --- a/src/test/resources/identity.json +++ b/src/test/resources/identity.json @@ -2,7 +2,7 @@ "data": { "privateKey": "d8839c2432bfd0a67ef10a804ba991eabba19f154a3d707917681d45822a5712", "publicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "address": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "address": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "wif": "SGq4xLgZKCGxs7bjmwnBrWcT4C1ADFEermj846KC97FSv1WFD1dA" }, "passphrase": "this is a top secret passphrase" diff --git a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json index ebab1ca2..419d700a 100644 --- a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json +++ b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41443847, "asset": {}, "vendorFieldHex": "48656c6c6f20576f726c64", diff --git a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json index fac09076..20e50e0f 100644 --- a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json +++ b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41443847, "asset": {}, "vendorField": "Hello World", diff --git a/src/test/resources/transactions/V1/transfer/passphrase.json b/src/test/resources/transactions/V1/transfer/passphrase.json index 70490d28..2ea021d2 100644 --- a/src/test/resources/transactions/V1/transfer/passphrase.json +++ b/src/test/resources/transactions/V1/transfer/passphrase.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41268326, "asset": {}, "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", diff --git a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json index c30f7ada..02f6b2eb 100644 --- a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json +++ b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41443865, "asset": {}, "vendorFieldHex": "48656c6c6f20576f726c64", diff --git a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json index c7473f10..8c8e38dd 100644 --- a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json +++ b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41443865, "asset": {}, "vendorField": "Hello World", diff --git a/src/test/resources/transactions/V1/transfer/second-passphrase.json b/src/test/resources/transactions/V1/transfer/second-passphrase.json index 8a0ebe09..ed6d9fe9 100644 --- a/src/test/resources/transactions/V1/transfer/second-passphrase.json +++ b/src/test/resources/transactions/V1/transfer/second-passphrase.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41268430, "asset": {}, "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", diff --git a/src/test/resources/transactions/V1/vote/passphrase.json b/src/test/resources/transactions/V1/vote/passphrase.json index 7b0612f1..1a66f0a6 100644 --- a/src/test/resources/transactions/V1/vote/passphrase.json +++ b/src/test/resources/transactions/V1/vote/passphrase.json @@ -3,7 +3,7 @@ "type": 3, "amount": 0, "fee": 100000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", "timestamp": 41269349, "asset": { diff --git a/src/test/resources/transactions/V1/vote/second-passphrase.json b/src/test/resources/transactions/V1/vote/second-passphrase.json index c694f360..e5e666c5 100644 --- a/src/test/resources/transactions/V1/vote/second-passphrase.json +++ b/src/test/resources/transactions/V1/vote/second-passphrase.json @@ -3,7 +3,7 @@ "type": 3, "amount": 0, "fee": 100000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", "timestamp": 41269366, "asset": { From cc9746549c82a7b949d64104f70fd71b17416d93 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 15:33:02 -0600 Subject: [PATCH 16/74] wip --- build.gradle | 2 + .../crypto/identities/Address.java | 7 --- .../crypto/transactions/Serializer.java | 2 +- .../crypto/transactions/types/Transfer.java | 18 +++++-- .../arkecosystem/crypto/utils/Address.java | 50 +++++++++++++++++++ .../crypto/identities/AddressTest.java | 6 --- .../serializers/TransferTest.java | 11 +++- 7 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/arkecosystem/crypto/utils/Address.java diff --git a/build.gradle b/build.gradle index b545e05b..8278c492 100644 --- a/build.gradle +++ b/build.gradle @@ -42,6 +42,8 @@ test { useJUnitPlatform() testLogging { events 'PASSED', 'FAILED', 'SKIPPED' + showStandardStreams = true + } } diff --git a/src/main/java/org/arkecosystem/crypto/identities/Address.java b/src/main/java/org/arkecosystem/crypto/identities/Address.java index 6973f3c4..0a4a15a9 100644 --- a/src/main/java/org/arkecosystem/crypto/identities/Address.java +++ b/src/main/java/org/arkecosystem/crypto/identities/Address.java @@ -40,11 +40,4 @@ public static String fromPrivateKey(ECKey privateKey) { byte[] publicKeyBytes = privateKey.getPubKey(); return fromPublicKey(Hex.encode(publicKeyBytes)); } - - public static Boolean validate(String address) { - if (address == null || !address.matches("^0x[a-fA-F0-9]{40}$")) { - return false; - } - return address.equals(Keys.toChecksumAddress(address)); - } } diff --git a/src/main/java/org/arkecosystem/crypto/transactions/Serializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Serializer.java index 5a350303..3c1a0463 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Serializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Serializer.java @@ -107,7 +107,7 @@ private byte[] serializeVendorField() { private byte[] serializeSignatures( boolean skipSignature, boolean skipSecondSignature, boolean skipMultiSignature) { - ByteBuffer buffer = ByteBuffer.allocate(16 * 65); + ByteBuffer buffer = ByteBuffer.allocate(14 * 128); buffer.order(ByteOrder.LITTLE_ENDIAN); if (!skipSignature && this.transaction.signature != null) { diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java b/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java index 30567260..5bb19e11 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java @@ -3,9 +3,11 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.HashMap; -import org.arkecosystem.crypto.encoding.Base58; +import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.enums.CoreTransactionTypes; import org.arkecosystem.crypto.enums.TransactionTypeGroup; +import org.arkecosystem.crypto.utils.Address; +import org.web3j.crypto.Keys; public class Transfer extends Transaction { @Override @@ -30,21 +32,27 @@ public HashMap assetToHashMap() { @Override public byte[] serialize() { - ByteBuffer buffer = ByteBuffer.allocate(33); + ByteBuffer buffer = ByteBuffer.allocate(24 + 20); // 24 bytes for amount and expiration, 20 bytes for address buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.putLong(this.amount); buffer.putInt(this.expiration); - buffer.put(Base58.decodeChecked(this.recipientId)); + + // Convert recipientId to a hex string without the 0x prefix and then to bytes + byte[] recipientBytes = Hex.decode(Address.toBufferHexString(this.recipientId)); + buffer.put(recipientBytes); + return buffer.array(); } @Override public void deserialize(ByteBuffer buffer) { + buffer.order(ByteOrder.LITTLE_ENDIAN); + this.amount = buffer.getLong(); this.expiration = buffer.getInt(); - byte[] recipientId = new byte[21]; + byte[] recipientId = new byte[20]; buffer.get(recipientId); - this.recipientId = Base58.encodeChecked(recipientId); + this.recipientId = Keys.toChecksumAddress("0x" + Hex.encode(recipientId)); } } diff --git a/src/main/java/org/arkecosystem/crypto/utils/Address.java b/src/main/java/org/arkecosystem/crypto/utils/Address.java new file mode 100644 index 00000000..9c399797 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/utils/Address.java @@ -0,0 +1,50 @@ +package org.arkecosystem.crypto.utils; + +import org.web3j.crypto.Hash; +import org.web3j.crypto.Keys; + +import java.nio.ByteBuffer; + +import org.bouncycastle.util.encoders.Hex; + +public class Address { + + /** + * Validate the given address. + * + * @param address The address to validate + * @return true if the address is valid, false otherwise + */ + public static boolean validate(String address) { + if (address == null || !address.matches("^0x[a-fA-F0-9]{40}$")) { + return false; + } + return address.equals(Keys.toChecksumAddress(address)); + } + + /** + * Convert to hex string without 0x prefix. + * + * @param address The address to convert + * @return The hex string without 0x prefix + */ + public static String toBufferHexString(String address) { + if (address.startsWith("0x")) { + return address.substring(2).toLowerCase(); + } + return address.toLowerCase(); + } + + /** + * Extract the address from a byte buffer. + * + * @param buffer The ByteBuffer containing the address + * @return The extracted address as a checksum address + */ + public static String fromByteBuffer(ByteBuffer buffer) { + byte[] addressBytes = new byte[20]; + buffer.get(addressBytes); + String hexAddress = "0x" + Hex.toHexString(addressBytes); + return Keys.toChecksumAddress(hexAddress); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java b/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java index 774622ad..647d0149 100644 --- a/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java +++ b/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java @@ -1,7 +1,6 @@ package org.arkecosystem.crypto.identities; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; import org.bitcoinj.core.ECKey; import org.junit.jupiter.api.Test; @@ -28,9 +27,4 @@ public void fromPrivateKey() { String actual = Address.fromPrivateKey(privateKey); assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual); } - - @Test - public void validate() { - assertTrue(Address.validate("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01")); - } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java index 6cd796e9..93964a90 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java @@ -15,13 +15,22 @@ class TransferTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-sign"); + FixtureLoader.load("transactions/transfer/transfer-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); String actual = Hex.encode(Serializer.serialize(transaction)); + + // Check serialization length + // assertEquals(fixture.get("serialized").toString().length(), actual.length()); + + // Signatures is not deterministic so we need to remove them from the comparison + // in pho I do this: substr($expected, 0, -128), substr($actual, 0, -128) + + // assertEquals(fixture.get("serialized").toString().substring(0, 256), actual.substring(0, 256)); assertEquals(fixture.get("serialized").toString(), actual); + } @Test From 4c1302c2d778c59b2435b5218eeccd6fcc5e699b Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Fri, 2 Aug 2024 15:59:03 -0600 Subject: [PATCH 17/74] transfer serialize test --- .../crypto/transactions/Serializer.java | 2 +- .../crypto/transactions/types/Transfer.java | 2 +- .../serializers/TransferTest.java | 27 +++---------------- .../transfer-with-vendor-field-sign.json | 17 ++++++++++++ 4 files changed, 22 insertions(+), 26 deletions(-) create mode 100644 src/test/resources/transactions/transfer/transfer-with-vendor-field-sign.json diff --git a/src/main/java/org/arkecosystem/crypto/transactions/Serializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Serializer.java index 3c1a0463..5a350303 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Serializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Serializer.java @@ -107,7 +107,7 @@ private byte[] serializeVendorField() { private byte[] serializeSignatures( boolean skipSignature, boolean skipSecondSignature, boolean skipMultiSignature) { - ByteBuffer buffer = ByteBuffer.allocate(14 * 128); + ByteBuffer buffer = ByteBuffer.allocate(16 * 65); buffer.order(ByteOrder.LITTLE_ENDIAN); if (!skipSignature && this.transaction.signature != null) { diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java b/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java index 5bb19e11..235a5bb0 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java @@ -32,7 +32,7 @@ public HashMap assetToHashMap() { @Override public byte[] serialize() { - ByteBuffer buffer = ByteBuffer.allocate(24 + 20); // 24 bytes for amount and expiration, 20 bytes for address + ByteBuffer buffer = ByteBuffer.allocate(32); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.putLong(this.amount); buffer.putInt(this.expiration); diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java index 93964a90..9fd95f40 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java @@ -20,23 +20,14 @@ void passphrase() { new Deserializer(fixture.get("serialized").toString()).deserialize(); String actual = Hex.encode(Serializer.serialize(transaction)); - - - // Check serialization length - // assertEquals(fixture.get("serialized").toString().length(), actual.length()); - - // Signatures is not deterministic so we need to remove them from the comparison - // in pho I do this: substr($expected, 0, -128), substr($actual, 0, -128) - - // assertEquals(fixture.get("serialized").toString().substring(0, 256), actual.substring(0, 256)); - assertEquals(fixture.get("serialized").toString(), actual); + assertEquals(fixture.get("serialized").toString(), actual); } @Test void passphraseVendorField() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-with-vendor-field-sign"); + FixtureLoader.load("transactions/transfer/transfer-with-vendor-field-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); @@ -48,19 +39,7 @@ void passphraseVendorField() { @Test void secondPassphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-with-vendor-field-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphraseVendorField() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-with-vendor-field-secondSign"); + FixtureLoader.load("transactions/transfer/transfer-with-vendor-field-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); diff --git a/src/test/resources/transactions/transfer/transfer-with-vendor-field-sign.json b/src/test/resources/transactions/transfer/transfer-with-vendor-field-sign.json new file mode 100644 index 00000000..c1032bcf --- /dev/null +++ b/src/test/resources/transactions/transfer/transfer-with-vendor-field-sign.json @@ -0,0 +1,17 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 0, + "nonce": "1", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "10000000", + "amount": "1", + "expiration": 0, + "recipientId": "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", + "signature": "97dd98ed1066aab76011114cbf5ac00d741812cac326cda7966e1af08874d7212f350d769221d2a78ea185d77ac4e2c5c718e4a84b1a1ddcbf504d642eb94b6a", + "id": "e20265dba26594c4202e224e8d1069dfae840a8db7cc6acfafefa2b3b02787e5" + }, + "serialized": "ff011e0100000000000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3809698000000000000010000000000000000000000b693449adda7efc015d87944eae8b7c37eb1690a97dd98ed1066aab76011114cbf5ac00d741812cac326cda7966e1af08874d7212f350d769221d2a78ea185d77ac4e2c5c718e4a84b1a1ddcbf504d642eb94b6a" +} From 997aca8df28f040d3677aa08353c8e5f5a22faa5 Mon Sep 17 00:00:00 2001 From: alfonsobries Date: Fri, 2 Aug 2024 21:59:56 +0000 Subject: [PATCH 18/74] style: resolve style guide violations --- .../java/org/arkecosystem/crypto/identities/Address.java | 4 ++-- .../org/arkecosystem/crypto/transactions/types/Transfer.java | 4 ++-- src/main/java/org/arkecosystem/crypto/utils/Address.java | 5 +---- .../crypto/transactions/serializers/TransferTest.java | 4 ++-- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/arkecosystem/crypto/identities/Address.java b/src/main/java/org/arkecosystem/crypto/identities/Address.java index 0a4a15a9..bc9de785 100644 --- a/src/main/java/org/arkecosystem/crypto/identities/Address.java +++ b/src/main/java/org/arkecosystem/crypto/identities/Address.java @@ -29,10 +29,10 @@ public static String fromPublicKey(String publicKey) { byte[] addressBytes = new byte[20]; System.arraycopy(keccakHash, keccakHash.length - 20, addressBytes, 0, 20); - + // Convert to checksum address String address = "0x" + Hex.encode(addressBytes); - + return Keys.toChecksumAddress(address); } diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java b/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java index 235a5bb0..18dbbf01 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/Transfer.java @@ -36,7 +36,7 @@ public byte[] serialize() { buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.putLong(this.amount); buffer.putInt(this.expiration); - + // Convert recipientId to a hex string without the 0x prefix and then to bytes byte[] recipientBytes = Hex.decode(Address.toBufferHexString(this.recipientId)); buffer.put(recipientBytes); @@ -47,7 +47,7 @@ public byte[] serialize() { @Override public void deserialize(ByteBuffer buffer) { buffer.order(ByteOrder.LITTLE_ENDIAN); - + this.amount = buffer.getLong(); this.expiration = buffer.getInt(); diff --git a/src/main/java/org/arkecosystem/crypto/utils/Address.java b/src/main/java/org/arkecosystem/crypto/utils/Address.java index 9c399797..65bcc697 100644 --- a/src/main/java/org/arkecosystem/crypto/utils/Address.java +++ b/src/main/java/org/arkecosystem/crypto/utils/Address.java @@ -1,11 +1,8 @@ package org.arkecosystem.crypto.utils; -import org.web3j.crypto.Hash; -import org.web3j.crypto.Keys; - import java.nio.ByteBuffer; - import org.bouncycastle.util.encoders.Hex; +import org.web3j.crypto.Keys; public class Address { diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java index 9fd95f40..9b2d26ea 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/TransferTest.java @@ -20,8 +20,8 @@ void passphrase() { new Deserializer(fixture.get("serialized").toString()).deserialize(); String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); + + assertEquals(fixture.get("serialized").toString(), actual); } @Test From 281aae511840ac210541e78b7708786e88f9fc60 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 03:05:27 -0600 Subject: [PATCH 19/74] feat: keccak address support (#179) --- build.gradle | 1 + .../crypto/identities/Address.java | 62 ++++++++----------- .../transactions/builder/VoteBuilder.java | 2 +- .../crypto/identities/AddressTest.java | 12 ++-- src/test/resources/identity.json | 2 +- .../passphrase-with-vendor-field-hex.json | 2 +- .../passphrase-with-vendor-field.json | 2 +- .../transactions/V1/transfer/passphrase.json | 2 +- ...cond-passphrase-with-vendor-field-hex.json | 2 +- .../second-passphrase-with-vendor-field.json | 2 +- .../V1/transfer/second-passphrase.json | 2 +- .../transactions/V1/vote/passphrase.json | 2 +- .../V1/vote/second-passphrase.json | 2 +- 13 files changed, 42 insertions(+), 53 deletions(-) diff --git a/build.gradle b/build.gradle index fac5a106..a81f6ca9 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ repositories { } dependencies { + implementation 'org.web3j:core:4.8.7' implementation 'org.bitcoinj:bitcoinj-core:0.16.3' implementation 'com.google.code.gson:gson:2.11.0' implementation 'com.google.guava:guava:30.2.0-jre' diff --git a/src/main/java/org/arkecosystem/crypto/identities/Address.java b/src/main/java/org/arkecosystem/crypto/identities/Address.java index d9d429eb..e4cb6ba5 100644 --- a/src/main/java/org/arkecosystem/crypto/identities/Address.java +++ b/src/main/java/org/arkecosystem/crypto/identities/Address.java @@ -1,58 +1,50 @@ package org.arkecosystem.crypto.identities; -import com.google.common.primitives.Bytes; -import org.arkecosystem.crypto.configuration.Network; -import org.arkecosystem.crypto.encoding.Base58; import org.arkecosystem.crypto.encoding.Hex; import org.bitcoinj.core.ECKey; -import org.bouncycastle.crypto.digests.RIPEMD160Digest; +import org.web3j.crypto.Hash; +import org.web3j.crypto.Keys; public class Address { - public static String fromPassphrase(String passphrase, Integer networkVersion) { - return fromPrivateKey(PrivateKey.fromPassphrase(passphrase), networkVersion); - } - public static String fromPassphrase(String passphrase) { - return Address.fromPassphrase(passphrase, null); + ECKey privateKey = PrivateKey.fromPassphrase(passphrase); + return fromPrivateKey(privateKey); } - public static String fromPublicKey(String publicKey, Integer networkVersion) { + public static String fromPublicKey(String publicKey) { byte[] publicKeyBytes = Hex.decode(publicKey); - RIPEMD160Digest digest = new RIPEMD160Digest(); - digest.update(publicKeyBytes, 0, publicKeyBytes.length); - byte[] out = new byte[20]; - digest.doFinal(out, 0); + // Ensure the public key is uncompressed + ECKey ecKey = ECKey.fromPublicOnly(publicKeyBytes); + byte[] uncompressedPublicKeyBytes = ecKey.getPubKeyPoint().getEncoded(false); - if (networkVersion == null) { - networkVersion = Network.get().version(); - } + // Remove the prefix (0x04) + byte[] rawPublicKey = new byte[uncompressedPublicKeyBytes.length - 1]; + System.arraycopy(uncompressedPublicKeyBytes, 1, rawPublicKey, 0, rawPublicKey.length); - byte[] bytes = Bytes.concat(new byte[] {networkVersion.byteValue()}, out); - return Base58.encodeChecked(bytes); - } + // Hash the public key using Keccak-256 + byte[] keccakHash = Hash.sha3(rawPublicKey); - public static String fromPublicKey(String publicKey) { - return Address.fromPublicKey(publicKey, null); - } + // Take the last 20 bytes of the Keccak-256 hash + byte[] addressBytes = new byte[20]; - public static String fromPrivateKey(ECKey privateKey, Integer networkVersion) { - return fromPublicKey(privateKey.getPublicKeyAsHex(), networkVersion); - } + System.arraycopy(keccakHash, keccakHash.length - 20, addressBytes, 0, 20); - public static String fromPrivateKey(ECKey privateKey) { - return Address.fromPrivateKey(privateKey, null); - } + // Convert to checksum address + String address = "0x" + Hex.encode(addressBytes); - public static Boolean validate(String address, Integer networkVersion) { - if (networkVersion == null) { - networkVersion = Network.get().version(); - } + return Keys.toChecksumAddress(address); + } - return Base58.decodeChecked(address)[0] == networkVersion; + public static String fromPrivateKey(ECKey privateKey) { + byte[] publicKeyBytes = privateKey.getPubKey(); + return fromPublicKey(Hex.encode(publicKeyBytes)); } public static Boolean validate(String address) { - return Address.validate(address, null); + if (address == null || !address.matches("^0x[a-fA-F0-9]{40}$")) { + return false; + } + return address.equals(Keys.toChecksumAddress(address)); } } diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java index 1cb1b1f2..d0209cf8 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java @@ -24,7 +24,7 @@ public VoteBuilder addVote(String vote) { } public VoteBuilder sign(String passphrase) { - this.transaction.recipientId = Address.fromPassphrase(passphrase, this.transaction.network); + this.transaction.recipientId = Address.fromPassphrase(passphrase); super.sign(passphrase); diff --git a/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java b/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java index 33cde63c..774622ad 100644 --- a/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java +++ b/src/test/java/org/arkecosystem/crypto/identities/AddressTest.java @@ -3,8 +3,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.arkecosystem.crypto.configuration.Network; -import org.arkecosystem.crypto.networks.Devnet; import org.bitcoinj.core.ECKey; import org.junit.jupiter.api.Test; @@ -12,9 +10,8 @@ public class AddressTest { @Test public void fromPassphrase() { - Network.set(new Devnet()); String actual = Address.fromPassphrase("this is a top secret passphrase"); - assertEquals("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", actual); + assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual); } @Test @@ -22,19 +19,18 @@ public void fromPublicKey() { String actual = Address.fromPublicKey( "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192"); - assertEquals("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", actual); + assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual); } @Test public void fromPrivateKey() { ECKey privateKey = PrivateKey.fromPassphrase("this is a top secret passphrase"); String actual = Address.fromPrivateKey(privateKey); - assertEquals("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", actual); + assertEquals("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", actual); } @Test public void validate() { - Network.set(new Devnet()); - assertTrue(Address.validate("D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib")); + assertTrue(Address.validate("0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01")); } } diff --git a/src/test/resources/identity.json b/src/test/resources/identity.json index 5b566039..662d91b6 100644 --- a/src/test/resources/identity.json +++ b/src/test/resources/identity.json @@ -2,7 +2,7 @@ "data": { "privateKey": "d8839c2432bfd0a67ef10a804ba991eabba19f154a3d707917681d45822a5712", "publicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "address": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "address": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "wif": "SGq4xLgZKCGxs7bjmwnBrWcT4C1ADFEermj846KC97FSv1WFD1dA" }, "passphrase": "this is a top secret passphrase" diff --git a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json index ebab1ca2..419d700a 100644 --- a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json +++ b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41443847, "asset": {}, "vendorFieldHex": "48656c6c6f20576f726c64", diff --git a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json index fac09076..20e50e0f 100644 --- a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json +++ b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41443847, "asset": {}, "vendorField": "Hello World", diff --git a/src/test/resources/transactions/V1/transfer/passphrase.json b/src/test/resources/transactions/V1/transfer/passphrase.json index 70490d28..2ea021d2 100644 --- a/src/test/resources/transactions/V1/transfer/passphrase.json +++ b/src/test/resources/transactions/V1/transfer/passphrase.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41268326, "asset": {}, "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", diff --git a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json index c30f7ada..02f6b2eb 100644 --- a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json +++ b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41443865, "asset": {}, "vendorFieldHex": "48656c6c6f20576f726c64", diff --git a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json index c7473f10..8c8e38dd 100644 --- a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json +++ b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41443865, "asset": {}, "vendorField": "Hello World", diff --git a/src/test/resources/transactions/V1/transfer/second-passphrase.json b/src/test/resources/transactions/V1/transfer/second-passphrase.json index 8a0ebe09..ed6d9fe9 100644 --- a/src/test/resources/transactions/V1/transfer/second-passphrase.json +++ b/src/test/resources/transactions/V1/transfer/second-passphrase.json @@ -3,7 +3,7 @@ "type": 0, "amount": 200000000, "fee": 10000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "timestamp": 41268430, "asset": {}, "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", diff --git a/src/test/resources/transactions/V1/vote/passphrase.json b/src/test/resources/transactions/V1/vote/passphrase.json index 7b0612f1..1a66f0a6 100644 --- a/src/test/resources/transactions/V1/vote/passphrase.json +++ b/src/test/resources/transactions/V1/vote/passphrase.json @@ -3,7 +3,7 @@ "type": 3, "amount": 0, "fee": 100000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", "timestamp": 41269349, "asset": { diff --git a/src/test/resources/transactions/V1/vote/second-passphrase.json b/src/test/resources/transactions/V1/vote/second-passphrase.json index c694f360..e5e666c5 100644 --- a/src/test/resources/transactions/V1/vote/second-passphrase.json +++ b/src/test/resources/transactions/V1/vote/second-passphrase.json @@ -3,7 +3,7 @@ "type": 3, "amount": 0, "fee": 100000000, - "recipientId": "D61mfSggzbvQgTUe6JhYKH2doHaqJ3Dyib", + "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", "timestamp": 41269366, "asset": { From 1c8fc0b51697c624910e4f211d144079c9594215 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 10:48:36 -0600 Subject: [PATCH 20/74] wip --- .github/workflows/test.yml | 2 +- build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 315aa052..79d867a2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,7 @@ jobs: uses: actions/setup-java@v2 with: distribution: "adopt" - java-version: 22 + java-version: "22" cache: "gradle" - name: Format code diff --git a/build.gradle b/build.gradle index 8278c492..81028ac0 100644 --- a/build.gradle +++ b/build.gradle @@ -10,8 +10,8 @@ group = 'org.arkecosystem' version = '2.0.0' java { - sourceCompatibility = JavaVersion.toVersion("22") - targetCompatibility = JavaVersion.toVersion("22") + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 withJavadocJar() withSourcesJar() } From 29657fb618bf05618fe3d1953c01e8b44b97d4d4 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 10:58:31 -0600 Subject: [PATCH 21/74] fix tests --- build.gradle | 1 - .../deserializers/TransferTest.java | 56 ++----------------- .../transfer-with-vendor-field-sign.json | 7 ++- 3 files changed, 8 insertions(+), 56 deletions(-) diff --git a/build.gradle b/build.gradle index 81028ac0..31eb39ef 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,6 @@ test { testLogging { events 'PASSED', 'FAILED', 'SKIPPED' showStandardStreams = true - } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/TransferTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/TransferTest.java index 40860ed8..c8a44ac3 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/TransferTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/TransferTest.java @@ -14,7 +14,7 @@ class TransferTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-sign"); + FixtureLoader.load("transactions/transfer/transfer-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -38,7 +38,7 @@ void passphrase() { @Test void passphraseVendorField() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-with-vendor-field-sign"); + FixtureLoader.load("transactions/transfer/transfer-with-vendor-field-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -54,60 +54,12 @@ void passphraseVendorField() { assertEquals(data.get("signature").toString(), actual.signature); assertEquals(data.get("id").toString(), actual.id); - assertEquals(data.get("recipientId").toString(), actual.recipientId); - assertEquals((Long.valueOf((String) data.get("amount"))), actual.amount); - assertEquals(((Double) data.get("expiration")).intValue(), actual.expiration); - assertEquals(data.get("vendorField").toString(), actual.vendorField); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - assertEquals(data.get("recipientId").toString(), actual.recipientId); - assertEquals((Long.valueOf((String) data.get("amount"))), actual.amount); - assertEquals(((Double) data.get("expiration")).intValue(), actual.expiration); - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - } - - @Test - void secondPassphraseVendorField() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-with-vendor-field-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); + System.out.println("AAAA"); + System.out.println(data.get("vendorField").toString()); assertEquals(data.get("recipientId").toString(), actual.recipientId); assertEquals((Long.valueOf((String) data.get("amount"))), actual.amount); assertEquals(((Double) data.get("expiration")).intValue(), actual.expiration); assertEquals(data.get("vendorField").toString(), actual.vendorField); - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); } } diff --git a/src/test/resources/transactions/transfer/transfer-with-vendor-field-sign.json b/src/test/resources/transactions/transfer/transfer-with-vendor-field-sign.json index c1032bcf..f2f57e11 100644 --- a/src/test/resources/transactions/transfer/transfer-with-vendor-field-sign.json +++ b/src/test/resources/transactions/transfer/transfer-with-vendor-field-sign.json @@ -8,10 +8,11 @@ "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", "fee": "10000000", "amount": "1", + "vendorField": "this is a top secret vendor field", "expiration": 0, "recipientId": "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", - "signature": "97dd98ed1066aab76011114cbf5ac00d741812cac326cda7966e1af08874d7212f350d769221d2a78ea185d77ac4e2c5c718e4a84b1a1ddcbf504d642eb94b6a", - "id": "e20265dba26594c4202e224e8d1069dfae840a8db7cc6acfafefa2b3b02787e5" + "signature": "d7062dd749406741ab848cc0bb6bcc82c04d8b46b699803154a30bda8d13bd6dc6c06fcbbb6a6edab3b83772008e50524b4563a33c0f08009b4cc72f38986981", + "id": "59cc59e3609f86418ef04fff270fb0f59ea2ff5a383857a3c157056f0925d59d" }, - "serialized": "ff011e0100000000000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3809698000000000000010000000000000000000000b693449adda7efc015d87944eae8b7c37eb1690a97dd98ed1066aab76011114cbf5ac00d741812cac326cda7966e1af08874d7212f350d769221d2a78ea185d77ac4e2c5c718e4a84b1a1ddcbf504d642eb94b6a" + "serialized": "ff011e0100000000000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d380969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c64010000000000000000000000b693449adda7efc015d87944eae8b7c37eb1690ad7062dd749406741ab848cc0bb6bcc82c04d8b46b699803154a30bda8d13bd6dc6c06fcbbb6a6edab3b83772008e50524b4563a33c0f08009b4cc72f38986981" } From 07a6a5dcf01fd5a404d88b59b599dfc60e757b5a Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 11:11:42 -0600 Subject: [PATCH 22/74] replace deprecated fixtures with new ones --- .../V1/delegate_registration/passphrase.json | 19 ----------- .../second-passphrase.json | 20 ----------- .../passphrase.json | 33 ------------------- .../second-passphrase.json | 18 ---------- .../passphrase-with-vendor-field-hex.json | 15 --------- .../passphrase-with-vendor-field.json | 15 --------- .../transactions/V1/transfer/passphrase.json | 14 -------- ...cond-passphrase-with-vendor-field-hex.json | 16 --------- .../second-passphrase-with-vendor-field.json | 16 --------- .../V1/transfer/second-passphrase.json | 15 --------- .../transactions/V1/vote/passphrase.json | 18 ---------- .../V1/vote/second-passphrase.json | 19 ----------- .../multi-payment-multi-sign.json | 32 ++++++++++++++++++ .../multi_payment/multi-payment-sign.json | 27 +++++++++++++++ .../multi-payment-with-vendor-field-sign.json | 28 ++++++++++++++++ .../multi-signature-registration-sign.json | 30 +++++++++++++++++ .../transfer/transfer-multi-sign.json | 22 +++++++++++++ .../username-registration-multi-sign.json | 23 +++++++++++++ .../username-registration-sign.json | 18 ++++++++++ .../username-resignation-multi-sign.json | 20 +++++++++++ .../username-resignation-sign.json | 15 +++++++++ .../delegate-registration-secondSign.json | 21 ------------ .../v2-ecdsa/delegate-registration-sign.json | 20 ----------- .../delegate-resignation-secondSign.json | 16 --------- .../v2-ecdsa/delegate-resignation-sign.json | 15 --------- .../v2-ecdsa/htlc-claim-secondSign.json | 22 ------------- .../v2-ecdsa/htlc-claim-sign.json | 21 ------------ .../v2-ecdsa/htlc-lock-secondSign.json | 26 --------------- .../transactions/v2-ecdsa/htlc-lock-sign.json | 25 -------------- ...tlc-lock-with-vendor-field-secondSign.json | 27 --------------- .../htlc-lock-with-vendor-field-sign.json | 26 --------------- .../v2-ecdsa/htlc-refund-secondSign.json | 21 ------------ .../v2-ecdsa/htlc-refund-sign.json | 20 ----------- .../v2-ecdsa/ipfs-secondSign.json | 19 ----------- .../transactions/v2-ecdsa/ipfs-sign.json | 18 ---------- .../v2-ecdsa/multi-payment-secondSign.json | 28 ---------------- .../v2-ecdsa/multi-payment-sign.json | 27 --------------- ...-payment-with-vendor-field-secondSign.json | 29 ---------------- .../multi-payment-with-vendor-field-sign.json | 28 ---------------- .../second-signature-registration.json | 20 ----------- .../resources/transactions/v2-ecdsa/test.json | 6 ---- .../v2-ecdsa/transfer-secondSign.json | 18 ---------- .../transactions/v2-ecdsa/transfer-sign.json | 17 ---------- ...transfer-with-vendor-field-secondSign.json | 19 ----------- .../transfer-with-vendor-field-sign.json | 18 ---------- .../v2-ecdsa/unvote-secondSign.json | 21 ------------ .../transactions/v2-ecdsa/unvote-sign.json | 20 ----------- .../v2-ecdsa/vote-secondSign.json | 21 ------------ .../transactions/v2-ecdsa/vote-sign.json | 20 ----------- .../delegate-registration-multiSign.json | 24 -------------- .../delegate-registration-secondSign.json | 21 ------------ .../delegate-registration-sign.json | 20 ----------- .../delegate-resignation-multiSign.json | 19 ----------- .../delegate-resignation-secondSign.json | 16 --------- .../v2-schnorr/delegate-resignation-sign.json | 15 --------- .../v2-schnorr/htlc-claim-multiSign.json | 25 -------------- .../v2-schnorr/htlc-claim-secondSign.json | 22 ------------- .../v2-schnorr/htlc-claim-sign.json | 21 ------------ .../v2-schnorr/htlc-lock-multiSign.json | 29 ---------------- .../v2-schnorr/htlc-lock-secondSign.json | 26 --------------- .../v2-schnorr/htlc-lock-sign.json | 25 -------------- ...htlc-lock-with-vendor-field-multiSign.json | 31 ----------------- ...tlc-lock-with-vendor-field-secondSign.json | 28 ---------------- .../htlc-lock-with-vendor-field-sign.json | 27 --------------- .../v2-schnorr/htlc-refund-multiSign.json | 24 -------------- .../v2-schnorr/htlc-refund-secondSign.json | 21 ------------ .../v2-schnorr/htlc-refund-sign.json | 20 ----------- .../v2-schnorr/ipfs-multiSign.json | 22 ------------- .../v2-schnorr/ipfs-secondSign.json | 19 ----------- .../transactions/v2-schnorr/ipfs-sign.json | 18 ---------- .../v2-schnorr/multi-payment-multiSign.json | 31 ----------------- .../v2-schnorr/multi-payment-secondSign.json | 28 ---------------- .../v2-schnorr/multi-payment-sign.json | 27 --------------- ...i-payment-with-vendor-field-multiSign.json | 33 ------------------- ...-payment-with-vendor-field-secondSign.json | 30 ----------------- .../multi-payment-with-vendor-field-sign.json | 29 ---------------- .../multi-signature-registration.json | 30 ----------------- .../second-signature-registration.json | 20 ----------- .../v2-schnorr/transfer-multiSign.json | 21 ------------ .../v2-schnorr/transfer-secondSign.json | 18 ---------- .../v2-schnorr/transfer-sign.json | 17 ---------- .../transfer-with-vendor-field-multiSign.json | 23 ------------- ...transfer-with-vendor-field-secondSign.json | 20 ----------- .../transfer-with-vendor-field-sign.json | 19 ----------- .../v2-schnorr/unvote-multiSign.json | 24 -------------- .../v2-schnorr/unvote-secondSign.json | 21 ------------ .../transactions/v2-schnorr/unvote-sign.json | 20 ----------- .../v2-schnorr/vote-multiSign.json | 24 -------------- .../v2-schnorr/vote-secondSign.json | 21 ------------ .../transactions/v2-schnorr/vote-sign.json | 21 ------------ .../validator-registration-multi-sign.json | 23 +++++++++++++ .../validator-registration-sign.json | 18 ++++++++++ .../validator-resignation-multi-sign.json | 20 +++++++++++ .../validator-resignation-sign.json | 15 +++++++++ .../transactions/vote/vote-multi-sign.json | 25 ++++++++++++++ .../transactions/vote/vote-sign.json | 20 +++++++++++ 96 files changed, 336 insertions(+), 1757 deletions(-) delete mode 100644 src/test/resources/transactions/V1/delegate_registration/passphrase.json delete mode 100644 src/test/resources/transactions/V1/delegate_registration/second-passphrase.json delete mode 100644 src/test/resources/transactions/V1/multi_signature_registration/passphrase.json delete mode 100644 src/test/resources/transactions/V1/second_signature_registration/second-passphrase.json delete mode 100644 src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json delete mode 100644 src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json delete mode 100644 src/test/resources/transactions/V1/transfer/passphrase.json delete mode 100644 src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json delete mode 100644 src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json delete mode 100644 src/test/resources/transactions/V1/transfer/second-passphrase.json delete mode 100644 src/test/resources/transactions/V1/vote/passphrase.json delete mode 100644 src/test/resources/transactions/V1/vote/second-passphrase.json create mode 100644 src/test/resources/transactions/multi_payment/multi-payment-multi-sign.json create mode 100644 src/test/resources/transactions/multi_payment/multi-payment-sign.json create mode 100644 src/test/resources/transactions/multi_payment/multi-payment-with-vendor-field-sign.json create mode 100644 src/test/resources/transactions/multi_signature_registration/multi-signature-registration-sign.json create mode 100644 src/test/resources/transactions/transfer/transfer-multi-sign.json create mode 100644 src/test/resources/transactions/username_registration/username-registration-multi-sign.json create mode 100644 src/test/resources/transactions/username_registration/username-registration-sign.json create mode 100644 src/test/resources/transactions/username_resignation/username-resignation-multi-sign.json create mode 100644 src/test/resources/transactions/username_resignation/username-resignation-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/delegate-registration-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/delegate-registration-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/delegate-resignation-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/delegate-resignation-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/htlc-claim-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/htlc-claim-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/htlc-lock-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/htlc-lock-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/htlc-lock-with-vendor-field-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/htlc-lock-with-vendor-field-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/htlc-refund-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/htlc-refund-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/ipfs-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/ipfs-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/multi-payment-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/multi-payment-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/multi-payment-with-vendor-field-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/multi-payment-with-vendor-field-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/second-signature-registration.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/test.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/transfer-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/transfer-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/transfer-with-vendor-field-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/transfer-with-vendor-field-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/unvote-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/unvote-sign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/vote-secondSign.json delete mode 100644 src/test/resources/transactions/v2-ecdsa/vote-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/delegate-registration-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/delegate-registration-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/delegate-registration-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/delegate-resignation-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/delegate-resignation-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/delegate-resignation-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-claim-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-claim-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-claim-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-lock-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-lock-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-lock-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-refund-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-refund-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/htlc-refund-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/ipfs-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/ipfs-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/ipfs-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/multi-payment-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/multi-payment-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/multi-payment-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/multi-signature-registration.json delete mode 100644 src/test/resources/transactions/v2-schnorr/second-signature-registration.json delete mode 100644 src/test/resources/transactions/v2-schnorr/transfer-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/transfer-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/transfer-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/unvote-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/unvote-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/unvote-sign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/vote-multiSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/vote-secondSign.json delete mode 100644 src/test/resources/transactions/v2-schnorr/vote-sign.json create mode 100644 src/test/resources/transactions/validator_registration/validator-registration-multi-sign.json create mode 100644 src/test/resources/transactions/validator_registration/validator-registration-sign.json create mode 100644 src/test/resources/transactions/validator_resignation/validator-resignation-multi-sign.json create mode 100644 src/test/resources/transactions/validator_resignation/validator-resignation-sign.json create mode 100644 src/test/resources/transactions/vote/vote-multi-sign.json create mode 100644 src/test/resources/transactions/vote/vote-sign.json diff --git a/src/test/resources/transactions/V1/delegate_registration/passphrase.json b/src/test/resources/transactions/V1/delegate_registration/passphrase.json deleted file mode 100644 index 64f15a4c..00000000 --- a/src/test/resources/transactions/V1/delegate_registration/passphrase.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "data": { - "type": 2, - "amount": 0, - "fee": 2500000000, - "recipientId": null, - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "timestamp": 41269413, - "asset": { - "delegate": { - "username": "boldninja", - "publicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192" - } - }, - "signature": "304402205fe105d2d23b66d2dbae3bd12bc0d1df498936a7614c71c0481bbf5159ad8d2002201084f5c24e802964b3075ac6feac91429c356c960a5faa8ef3c397a4b25c299a", - "id": "dccdd2de52f437b2b0f7dadbf9f5eb1717cefaed5f51cab3d0feadf2d94392a3" - }, - "serialized": "ff011e02a5b87502034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f90295000000000009626f6c646e696e6a61304402205fe105d2d23b66d2dbae3bd12bc0d1df498936a7614c71c0481bbf5159ad8d2002201084f5c24e802964b3075ac6feac91429c356c960a5faa8ef3c397a4b25c299a" -} diff --git a/src/test/resources/transactions/V1/delegate_registration/second-passphrase.json b/src/test/resources/transactions/V1/delegate_registration/second-passphrase.json deleted file mode 100644 index 2584b58a..00000000 --- a/src/test/resources/transactions/V1/delegate_registration/second-passphrase.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "type": 2, - "amount": 0, - "fee": 2500000000, - "recipientId": null, - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "timestamp": 41269424, - "asset": { - "delegate": { - "username": "boldninja", - "publicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192" - } - }, - "signature": "3045022100f21b742fa052cd18de43328e1d068539ba7cbe9d33a9dcbd862a82871383955d0220053b06d22ed3e3ad6168c6b27aa0ec68e7e40958c7709aec0e1555087ea9ad94", - "signSignature": "304402207da580da4feec955edcb8e8eb36947867b439de3d28d38e58c844fd8c45b564302200e6741b6ad11c2588a57b3afd180df1e9b345d48a9c2ae98be57dced869cf38c", - "id": "bf7e018ff9c0066f7a9f51e95d3f78c08cad5dd8581325d630d64350181a91bb" - }, - "serialized": "ff011e02b0b87502034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f90295000000000009626f6c646e696e6a613045022100f21b742fa052cd18de43328e1d068539ba7cbe9d33a9dcbd862a82871383955d0220053b06d22ed3e3ad6168c6b27aa0ec68e7e40958c7709aec0e1555087ea9ad94304402207da580da4feec955edcb8e8eb36947867b439de3d28d38e58c844fd8c45b564302200e6741b6ad11c2588a57b3afd180df1e9b345d48a9c2ae98be57dced869cf38c" -} diff --git a/src/test/resources/transactions/V1/multi_signature_registration/passphrase.json b/src/test/resources/transactions/V1/multi_signature_registration/passphrase.json deleted file mode 100644 index ee6c77b5..00000000 --- a/src/test/resources/transactions/V1/multi_signature_registration/passphrase.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "data": { - "version": 1, - "network": 23, - "id": "cbd6862966bb1b03ba742397b7e5a88d6eefb393a362ead0d605723b840db2af", - "blockid": "1844069042066945391", - "type": 4, - "timestamp": 10112114, - "amount": 0, - "fee": 2000000000, - "senderId": "AMw3TiLrmVmwmFVwRzn96kkUsUpFTqsAEX", - "senderPublicKey": "036928c98ee53a1f52ed01dd87db10ffe1980eb47cd7c0a7d688321f47b5d7d760", - "signature": "30440220324d89c5792e4a54ae70b4f1e27e2f87a8b7169cc6f2f7b2c83dba894960f987022053b8d0ae23ff9d1769364db7b6fd03216d93753c82a711c3558045e787bc01a5", - "signSignature": "304402201fcd54a9ac9c0269b8cec213566ddf43207798e2cf9ca1ce3c5d315d66321c6902201aa94c4ed3e5e479a12220aa886b259e488eb89b697c711f91e8c03b9620e0b1", - "signatures": [ - "304502210097f17c8eecf36f86a967cc52a83fa661e4ffc70cc4ea08df58673669406d424c0220798f5710897b75dda42f6548f841afbe4ed1fa262097112cf5a1b3f7dade60e4", - "304402201a4a4c718bfdc699bbb891b2e89be018027d2dcd10640b5ddf07802424dab78e02204ec7c7d505d2158c3b51fdd3843d16aecd2eaaa4c6c7a555ef123c5e59fd41fb", - "304402207e660489bced5ce80c33d45c86781b63898775ab4a231bb48780f97b40073a63022026f0cefd0d83022d822522ab4366a82e3b89085c328817919939f2efeabd913d" - ], - "asset": { - "multisignature": { - "min": 2, - "keysgroup": [ - "+03543c6cc3545be6bac09c82721973a052c690658283472e88f24d14739f75acc8", - "+0276dc5b8706a85ca9fdc46e571ac84e52fbb48e13ec7a165a80731b44ae89f1fc", - "+02e8d5d17eb17bbc8d7bf1001d29a2d25d1249b7bb7a5b7ad8b7422063091f4b31" - ], - "lifetime": 24 - } - } - }, - "serialized": "ff011704724c9a00036928c98ee53a1f52ed01dd87db10ffe1980eb47cd7c0a7d688321f47b5d7d76000943577000000000002031803543c6cc3545be6bac09c82721973a052c690658283472e88f24d14739f75acc80276dc5b8706a85ca9fdc46e571ac84e52fbb48e13ec7a165a80731b44ae89f1fc02e8d5d17eb17bbc8d7bf1001d29a2d25d1249b7bb7a5b7ad8b7422063091f4b3130440220324d89c5792e4a54ae70b4f1e27e2f87a8b7169cc6f2f7b2c83dba894960f987022053b8d0ae23ff9d1769364db7b6fd03216d93753c82a711c3558045e787bc01a5304402201fcd54a9ac9c0269b8cec213566ddf43207798e2cf9ca1ce3c5d315d66321c6902201aa94c4ed3e5e479a12220aa886b259e488eb89b697c711f91e8c03b9620e0b1ff304502210097f17c8eecf36f86a967cc52a83fa661e4ffc70cc4ea08df58673669406d424c0220798f5710897b75dda42f6548f841afbe4ed1fa262097112cf5a1b3f7dade60e4304402201a4a4c718bfdc699bbb891b2e89be018027d2dcd10640b5ddf07802424dab78e02204ec7c7d505d2158c3b51fdd3843d16aecd2eaaa4c6c7a555ef123c5e59fd41fb304402207e660489bced5ce80c33d45c86781b63898775ab4a231bb48780f97b40073a63022026f0cefd0d83022d822522ab4366a82e3b89085c328817919939f2efeabd913d" -} diff --git a/src/test/resources/transactions/V1/second_signature_registration/second-passphrase.json b/src/test/resources/transactions/V1/second_signature_registration/second-passphrase.json deleted file mode 100644 index 5717760a..00000000 --- a/src/test/resources/transactions/V1/second_signature_registration/second-passphrase.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "data": { - "type": 1, - "amount": 0, - "fee": 500000000, - "recipientId": null, - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "timestamp": 41271867, - "asset": { - "signature": { - "publicKey": "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609" - } - }, - "signature": "304402202aab49477dd3531e4473196d08fbd7c00ebb79223d5eaaeaf02c52c4041a86cf02201a7d82655f9b1d22af3ea94e6f183649bb4610cdeca3b9e20d6c8773f869831c", - "id": "6d1615924d172d352c8f44d4ded84cbbece3c03ebb3e4fc3f3334784ae332590" - }, - "serialized": "ff011e013bc27502034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920065cd1d000000000003699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609304402202aab49477dd3531e4473196d08fbd7c00ebb79223d5eaaeaf02c52c4041a86cf02201a7d82655f9b1d22af3ea94e6f183649bb4610cdeca3b9e20d6c8773f869831c" -} diff --git a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json deleted file mode 100644 index 419d700a..00000000 --- a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field-hex.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "data": { - "type": 0, - "amount": 200000000, - "fee": 10000000, - "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", - "timestamp": 41443847, - "asset": {}, - "vendorFieldHex": "48656c6c6f20576f726c64", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "signature": "304402205616d6e361439d67a5c2067bbfc8fce61b93061a4fa113315a1c5cf965ff6f3202200a1d99caaa98aeebcec04edd5365352500addb830c79f49b9de484ec616bb1e1", - "id": "ecf558fbddd62ae42edcfcba02f402d987a94b72a7636ef1121e8625487e2a1e" - }, - "serialized": "ff011e0007627802034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000b48656c6c6f20576f726c6400c2eb0b00000000000000001e0995750207ecaf0ccf251c1265b92ad84f553662304402205616d6e361439d67a5c2067bbfc8fce61b93061a4fa113315a1c5cf965ff6f3202200a1d99caaa98aeebcec04edd5365352500addb830c79f49b9de484ec616bb1e1" -} diff --git a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json b/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json deleted file mode 100644 index 20e50e0f..00000000 --- a/src/test/resources/transactions/V1/transfer/passphrase-with-vendor-field.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "data": { - "type": 0, - "amount": 200000000, - "fee": 10000000, - "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", - "timestamp": 41443847, - "asset": {}, - "vendorField": "Hello World", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "signature": "304402205616d6e361439d67a5c2067bbfc8fce61b93061a4fa113315a1c5cf965ff6f3202200a1d99caaa98aeebcec04edd5365352500addb830c79f49b9de484ec616bb1e1", - "id": "ecf558fbddd62ae42edcfcba02f402d987a94b72a7636ef1121e8625487e2a1e" - }, - "serialized": "ff011e0007627802034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000b48656c6c6f20576f726c6400c2eb0b00000000000000001e0995750207ecaf0ccf251c1265b92ad84f553662304402205616d6e361439d67a5c2067bbfc8fce61b93061a4fa113315a1c5cf965ff6f3202200a1d99caaa98aeebcec04edd5365352500addb830c79f49b9de484ec616bb1e1" -} diff --git a/src/test/resources/transactions/V1/transfer/passphrase.json b/src/test/resources/transactions/V1/transfer/passphrase.json deleted file mode 100644 index 2ea021d2..00000000 --- a/src/test/resources/transactions/V1/transfer/passphrase.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "data": { - "type": 0, - "amount": 200000000, - "fee": 10000000, - "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", - "timestamp": 41268326, - "asset": {}, - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "signature": "3044022002994b30e08b58825c8c16ebf2cc693cfe706fb26571674784ead098accc89d702205b79dedc752a84504ecfe4b9e1292997f22260ee4daa102d2d9a61432d93b286", - "id": "da61c6cba363cc39baa0ca3f9ba2c5db81b9805045bd0b9fc58af07ad4206856" - }, - "serialized": "ff011e0066b47502034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b00000000000000001e0995750207ecaf0ccf251c1265b92ad84f5536623044022002994b30e08b58825c8c16ebf2cc693cfe706fb26571674784ead098accc89d702205b79dedc752a84504ecfe4b9e1292997f22260ee4daa102d2d9a61432d93b286" -} diff --git a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json deleted file mode 100644 index 02f6b2eb..00000000 --- a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field-hex.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "data": { - "type": 0, - "amount": 200000000, - "fee": 10000000, - "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", - "timestamp": 41443865, - "asset": {}, - "vendorFieldHex": "48656c6c6f20576f726c64", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "signature": "3045022100c0356f2f667c0d8df8370d9b6803a282cb142b8e85f6b87dfffe45e7aeeba8dc0220446b11b44e8a968a9d29a065e3dd1383a2a4c03efe663a7d1b9cf232df68c6d0", - "signSignature": "3045022100a16eaf2d869fe8ee57f5b611a5f7b6c9359e52797e99240ec2a56cc92d3df7a10220688c5ef2225a5b54adf92c43ea551963c8b1240d7a9fc93e670d5fa819b8f09f", - "id": "248e0c6159113659103a84dfa3882d82abefdbc0a30472b683c689d482cfb2f5" - }, - "serialized": "ff011e0019627802034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000b48656c6c6f20576f726c6400c2eb0b00000000000000001e0995750207ecaf0ccf251c1265b92ad84f5536623045022100c0356f2f667c0d8df8370d9b6803a282cb142b8e85f6b87dfffe45e7aeeba8dc0220446b11b44e8a968a9d29a065e3dd1383a2a4c03efe663a7d1b9cf232df68c6d03045022100a16eaf2d869fe8ee57f5b611a5f7b6c9359e52797e99240ec2a56cc92d3df7a10220688c5ef2225a5b54adf92c43ea551963c8b1240d7a9fc93e670d5fa819b8f09f" -} diff --git a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json b/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json deleted file mode 100644 index 8c8e38dd..00000000 --- a/src/test/resources/transactions/V1/transfer/second-passphrase-with-vendor-field.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "data": { - "type": 0, - "amount": 200000000, - "fee": 10000000, - "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", - "timestamp": 41443865, - "asset": {}, - "vendorField": "Hello World", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "signature": "3045022100c0356f2f667c0d8df8370d9b6803a282cb142b8e85f6b87dfffe45e7aeeba8dc0220446b11b44e8a968a9d29a065e3dd1383a2a4c03efe663a7d1b9cf232df68c6d0", - "signSignature": "3045022100a16eaf2d869fe8ee57f5b611a5f7b6c9359e52797e99240ec2a56cc92d3df7a10220688c5ef2225a5b54adf92c43ea551963c8b1240d7a9fc93e670d5fa819b8f09f", - "id": "248e0c6159113659103a84dfa3882d82abefdbc0a30472b683c689d482cfb2f5" - }, - "serialized": "ff011e0019627802034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000b48656c6c6f20576f726c6400c2eb0b00000000000000001e0995750207ecaf0ccf251c1265b92ad84f5536623045022100c0356f2f667c0d8df8370d9b6803a282cb142b8e85f6b87dfffe45e7aeeba8dc0220446b11b44e8a968a9d29a065e3dd1383a2a4c03efe663a7d1b9cf232df68c6d03045022100a16eaf2d869fe8ee57f5b611a5f7b6c9359e52797e99240ec2a56cc92d3df7a10220688c5ef2225a5b54adf92c43ea551963c8b1240d7a9fc93e670d5fa819b8f09f" -} diff --git a/src/test/resources/transactions/V1/transfer/second-passphrase.json b/src/test/resources/transactions/V1/transfer/second-passphrase.json deleted file mode 100644 index ed6d9fe9..00000000 --- a/src/test/resources/transactions/V1/transfer/second-passphrase.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "data": { - "type": 0, - "amount": 200000000, - "fee": 10000000, - "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", - "timestamp": 41268430, - "asset": {}, - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "signature": "304402206da703bfcc11ec2ccb3f363fa0e23fc64050fdf68e1f1852b7d4a5bb07824166022031ed1d86b586a79f9c1e5010dbc4f4cb36641c62a196536f90b1dfd6be1c9868", - "signSignature": "304402200759b6f9de5257aa3fcf54b9cd7a426a00af9368b7ea3d5ea2b13a91b97fb277022076e4d2d7deb9bdd8245b2533cab1eeeef72981e18576ef8455a61ee3e6f3fb57", - "id": "bb8054b6298d659d4b5d655e82de17b3504ba27655ec3d6e35d311f3104b1c43" - }, - "serialized": "ff011e00ceb47502034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b00000000000000001e0995750207ecaf0ccf251c1265b92ad84f553662304402206da703bfcc11ec2ccb3f363fa0e23fc64050fdf68e1f1852b7d4a5bb07824166022031ed1d86b586a79f9c1e5010dbc4f4cb36641c62a196536f90b1dfd6be1c9868304402200759b6f9de5257aa3fcf54b9cd7a426a00af9368b7ea3d5ea2b13a91b97fb277022076e4d2d7deb9bdd8245b2533cab1eeeef72981e18576ef8455a61ee3e6f3fb57" -} diff --git a/src/test/resources/transactions/V1/vote/passphrase.json b/src/test/resources/transactions/V1/vote/passphrase.json deleted file mode 100644 index 1a66f0a6..00000000 --- a/src/test/resources/transactions/V1/vote/passphrase.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "data": { - "type": 3, - "amount": 0, - "fee": 100000000, - "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "timestamp": 41269349, - "asset": { - "votes": [ - "+022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "3045022100bb39554e077c0cd23ef8376731f6b0457edea0aa04c92a9ef07c84228aa5542c0220648365448a0b19c49ff0bab5cde0bee7999a9cfd5eaefc4a7f03b6f93a2efb51", - "id": "b6db143df7eb847389ff34f173571375851823bdb6dbfe24463ae36cd9d6b024" - }, - "serialized": "ff011e0365b87502034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000101022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d3045022100bb39554e077c0cd23ef8376731f6b0457edea0aa04c92a9ef07c84228aa5542c0220648365448a0b19c49ff0bab5cde0bee7999a9cfd5eaefc4a7f03b6f93a2efb51" -} diff --git a/src/test/resources/transactions/V1/vote/second-passphrase.json b/src/test/resources/transactions/V1/vote/second-passphrase.json deleted file mode 100644 index e5e666c5..00000000 --- a/src/test/resources/transactions/V1/vote/second-passphrase.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "data": { - "type": 3, - "amount": 0, - "fee": 100000000, - "recipientId": "0xb0FF9213f7226bBB72b84dE16af86e56f1f38B01", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "timestamp": 41269366, - "asset": { - "votes": [ - "+022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "304402204b8bb403e2db7f9599d46d0f5d39f8bb1d0663d875af7ec1154448e98466e86302201e92fb57e13fb729b07e1027fa3d6e3f28e0d5828ed2d7c53a5e8db08cb6d068", - "signSignature": "304402201329882762a42d1af9079c822a9e3feefa47b7476b0afe61440637408958a64402206da179b08e31d9c784fbb23abe2c9b50353ed7881dc29787a5e8ecbee2dfda66", - "id": "16f28a180cd6f3ea46c10f358a457989e956e9d355258230d0c7b07acec10b73" - }, - "serialized": "ff011e0376b87502034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000101022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d304402204b8bb403e2db7f9599d46d0f5d39f8bb1d0663d875af7ec1154448e98466e86302201e92fb57e13fb729b07e1027fa3d6e3f28e0d5828ed2d7c53a5e8db08cb6d068304402201329882762a42d1af9079c822a9e3feefa47b7476b0afe61440637408958a64402206da179b08e31d9c784fbb23abe2c9b50353ed7881dc29787a5e8ecbee2dfda66" -} diff --git a/src/test/resources/transactions/multi_payment/multi-payment-multi-sign.json b/src/test/resources/transactions/multi_payment/multi-payment-multi-sign.json new file mode 100644 index 00000000..07f4b78b --- /dev/null +++ b/src/test/resources/transactions/multi_payment/multi-payment-multi-sign.json @@ -0,0 +1,32 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 6, + "nonce": "0", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "10000000", + "amount": "3", + "asset": { + "payments": [ + { + "amount": "1", + "recipientId": "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A" + }, + { + "amount": "2", + "recipientId": "0x27FA7CaFFaAE77dDb9AB232FDBDa56D5e5Af2393" + } + ] + }, + "signature": "cf4e94776e768110e62961747f39b68993d4ff5ec2171cad2fab6d77babb2ce31181f005876031d43e6d7732770c6aca73b33057c7aad6279cf2da03829a7b62", + "signatures": [ + "006581c24bbe49e57127604b18d2efdd8d1d2bfe23f9b1e7f15b3f46a647b976e79884b61331546c5844ded781974e181a03a4066f858020fb347ad9628773b465", + "011fb86a8ddbddbed012ff46fc0f3c9a30f3c1544d7a32b9355c318ad453837615e8399f676856c97cf6dcb8d18507ff9c0ffe195d23624e296182477644ed3689", + "023aa80e3663d737716818978ffbae59a8a9f32257a341e1391ca1e0fd744f3382b41e507dca92fa91f98e2024b67938420aaf0c268266dfe4d1f92e81cb3a0421" + ], + "id": "5349b6d57228cb2aeb77e198d6adc93f745e3abb9b4624929b7e29f4a920c0a5" + }, + "serialized": "ff011e0100000006000000000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d380969800000000000002000100000000000000b693449adda7efc015d87944eae8b7c37eb1690a020000000000000027fa7caffaae77ddb9ab232fdbda56d5e5af2393cf4e94776e768110e62961747f39b68993d4ff5ec2171cad2fab6d77babb2ce31181f005876031d43e6d7732770c6aca73b33057c7aad6279cf2da03829a7b62006581c24bbe49e57127604b18d2efdd8d1d2bfe23f9b1e7f15b3f46a647b976e79884b61331546c5844ded781974e181a03a4066f858020fb347ad9628773b465011fb86a8ddbddbed012ff46fc0f3c9a30f3c1544d7a32b9355c318ad453837615e8399f676856c97cf6dcb8d18507ff9c0ffe195d23624e296182477644ed3689023aa80e3663d737716818978ffbae59a8a9f32257a341e1391ca1e0fd744f3382b41e507dca92fa91f98e2024b67938420aaf0c268266dfe4d1f92e81cb3a0421" +} diff --git a/src/test/resources/transactions/multi_payment/multi-payment-sign.json b/src/test/resources/transactions/multi_payment/multi-payment-sign.json new file mode 100644 index 00000000..f936e771 --- /dev/null +++ b/src/test/resources/transactions/multi_payment/multi-payment-sign.json @@ -0,0 +1,27 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 6, + "nonce": "0", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "10000000", + "amount": "3", + "asset": { + "payments": [ + { + "amount": "1", + "recipientId": "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A" + }, + { + "amount": "2", + "recipientId": "0x27FA7CaFFaAE77dDb9AB232FDBDa56D5e5Af2393" + } + ] + }, + "signature": "e782cc5a7622ea23463aa3d6795850b7163abf6b02c29795f9230f4b0537404cbccf82de6a44ecf6e98391bff601f033524c8704f4081ada4f72e98aea5ae173", + "id": "c820af7342cde48a2d578e6324329fc557ffb4e40fa3208b348cf07fd2020e43" + }, + "serialized": "ff011e0100000006000000000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d380969800000000000002000100000000000000b693449adda7efc015d87944eae8b7c37eb1690a020000000000000027fa7caffaae77ddb9ab232fdbda56d5e5af2393e782cc5a7622ea23463aa3d6795850b7163abf6b02c29795f9230f4b0537404cbccf82de6a44ecf6e98391bff601f033524c8704f4081ada4f72e98aea5ae173" +} diff --git a/src/test/resources/transactions/multi_payment/multi-payment-with-vendor-field-sign.json b/src/test/resources/transactions/multi_payment/multi-payment-with-vendor-field-sign.json new file mode 100644 index 00000000..685b9222 --- /dev/null +++ b/src/test/resources/transactions/multi_payment/multi-payment-with-vendor-field-sign.json @@ -0,0 +1,28 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 6, + "nonce": "0", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "10000000", + "amount": "3", + "vendorField": "this is a top secret vendor field", + "asset": { + "payments": [ + { + "amount": "1", + "recipientId": "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A" + }, + { + "amount": "2", + "recipientId": "0x27FA7CaFFaAE77dDb9AB232FDBDa56D5e5Af2393" + } + ] + }, + "signature": "ff68aa386548aba97004d99d616d5bdd1f13074dd85fdb0ab636d18585d4436030f66f42fa257c2b18873a076906af31a2b3b838081d9ec79f685f32d4640955", + "id": "4c759d085999e25996e2af264c79aac76c44e48d3f5f2432c56d8a2e4fd99349" + }, + "serialized": "ff011e0100000006000000000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d380969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6402000100000000000000b693449adda7efc015d87944eae8b7c37eb1690a020000000000000027fa7caffaae77ddb9ab232fdbda56d5e5af2393ff68aa386548aba97004d99d616d5bdd1f13074dd85fdb0ab636d18585d4436030f66f42fa257c2b18873a076906af31a2b3b838081d9ec79f685f32d4640955" +} diff --git a/src/test/resources/transactions/multi_signature_registration/multi-signature-registration-sign.json b/src/test/resources/transactions/multi_signature_registration/multi-signature-registration-sign.json new file mode 100644 index 00000000..bf65bea5 --- /dev/null +++ b/src/test/resources/transactions/multi_signature_registration/multi-signature-registration-sign.json @@ -0,0 +1,30 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 4, + "nonce": "2", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "500000000", + "amount": "0", + "asset": { + "multiSignature": { + "min": 2, + "publicKeys": [ + "029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca92", + "03629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48", + "027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc5" + ] + } + }, + "signature": "2b33558cdc62933ff56feb646d1f47a98104bf34b894895d5e816f86e556f87fce8485e55aa32dfa1cd86456a66a58ef7a68dff4af51e2f7fcf75b983540872e", + "signatures": [ + "000caa6864c71362b369c71107f463f29c43c361e54260cbc54d791b7385dbe76f29d12b9befbe4f98792d7046481afcf0c156408310192a93d8413e5380438f27", + "0153a22c5ce2b1894f0a141adc19de567077d2d268f4c7e1476e9558ecb4411d486cd0d7aa3e9c7716739a055a8a1a64a162d0362645d63d13791a9876ef8b5a88", + "021d56997f0c9e21201c59e1b7b6be8d5a609908a4f65bf266144baf5e61e3f14bc2651f62187f4ffa17c8b010fcb0fba94a04df56bc25e5cb20935ec5fb7ad632" + ], + "id": "1941926b880ab606633b3a2361df784f6085ded8b5d3cf52e94998e1468b3197" + }, + "serialized": "ff011e0100000004000200000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d30065cd1d00000000000203029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca9203629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc52b33558cdc62933ff56feb646d1f47a98104bf34b894895d5e816f86e556f87fce8485e55aa32dfa1cd86456a66a58ef7a68dff4af51e2f7fcf75b983540872e000caa6864c71362b369c71107f463f29c43c361e54260cbc54d791b7385dbe76f29d12b9befbe4f98792d7046481afcf0c156408310192a93d8413e5380438f270153a22c5ce2b1894f0a141adc19de567077d2d268f4c7e1476e9558ecb4411d486cd0d7aa3e9c7716739a055a8a1a64a162d0362645d63d13791a9876ef8b5a88021d56997f0c9e21201c59e1b7b6be8d5a609908a4f65bf266144baf5e61e3f14bc2651f62187f4ffa17c8b010fcb0fba94a04df56bc25e5cb20935ec5fb7ad632" +} diff --git a/src/test/resources/transactions/transfer/transfer-multi-sign.json b/src/test/resources/transactions/transfer/transfer-multi-sign.json new file mode 100644 index 00000000..1db6a1de --- /dev/null +++ b/src/test/resources/transactions/transfer/transfer-multi-sign.json @@ -0,0 +1,22 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 0, + "nonce": "1", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "10000000", + "amount": "1", + "expiration": 0, + "recipientId": "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", + "signature": "f25db2b781b79f671b7848284de63f3cb898f9938c0b6203a11cace4aaa4b962eabe9c4a67c207a3f8baea3b4f4cef90a0b67a2bfd84cd61dcc771597f52656d", + "signatures": [ + "005afa0050c85a2ac9b34accb0f47c6a9cc9eee831ac713e62e846898d1b75d6a33034680bce95f638c6dfabf8056f8afa9ef73a3c35741234faf01d0a346e3e7d", + "0104bd019e5a6ea9ee5cc41d9f39efe2a2df2cc653369fdfcb56d5219fa282a8368067586748feb2483883c9eca50a5ae73abd7139d4d1885914ed9d5e5c63f8fb", + "02d6af0f5a85a7967d677b2f1f86e00b8ca37facb714467e12810a692d5bcbdfcac4e4c2d4b79a70c7366405339bf84a854308d20cb48652816a9cf37fb3e86e00" + ], + "id": "dcb9d29590313cf6e1b53f120e621e34c39e45fce9114272158036cb99be9c89" + }, + "serialized": "ff011e0100000000000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3809698000000000000010000000000000000000000b693449adda7efc015d87944eae8b7c37eb1690af25db2b781b79f671b7848284de63f3cb898f9938c0b6203a11cace4aaa4b962eabe9c4a67c207a3f8baea3b4f4cef90a0b67a2bfd84cd61dcc771597f52656d005afa0050c85a2ac9b34accb0f47c6a9cc9eee831ac713e62e846898d1b75d6a33034680bce95f638c6dfabf8056f8afa9ef73a3c35741234faf01d0a346e3e7d0104bd019e5a6ea9ee5cc41d9f39efe2a2df2cc653369fdfcb56d5219fa282a8368067586748feb2483883c9eca50a5ae73abd7139d4d1885914ed9d5e5c63f8fb02d6af0f5a85a7967d677b2f1f86e00b8ca37facb714467e12810a692d5bcbdfcac4e4c2d4b79a70c7366405339bf84a854308d20cb48652816a9cf37fb3e86e00" +} diff --git a/src/test/resources/transactions/username_registration/username-registration-multi-sign.json b/src/test/resources/transactions/username_registration/username-registration-multi-sign.json new file mode 100644 index 00000000..9f69e174 --- /dev/null +++ b/src/test/resources/transactions/username_registration/username-registration-multi-sign.json @@ -0,0 +1,23 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 8, + "nonce": "6", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "2500000000", + "amount": "0", + "asset": { + "username": "simple_tx_tester" + }, + "signature": "9a74c959d0cd4ad4352292417de3ed8ed0cac9aad390bb5d93a5ef5d2bdbf54dad9bbf690f2079ad397141acd182b6e5c4285bd64b068083431daffd5dbc5b09", + "signatures": [ + "003b5b94d80da3d41f514d77a624f26f7a2336c34ce1ec62f06c61635db31b27135a58b9ee705cbaa45addd6e75098833c80935541ccc050199443a3d4c62c7fdd", + "01335feff7cc3d6e3524dd9892e029d2dea77c76afdeb9445bc0d14c587fd922c6c38e3542b978aeb370dc349b4a1221015f33051407f10ca051a1caa2109fc510", + "02fe8b1d0be5a77455b38f9df31a379e1a80bcab4003a225cbf79d426fcd248e03ff5f499a404d879270086e292aa45ac1af979aa9af4a64e4881ec559fc87e779" + ], + "id": "ffaead0f6003e125bb2a66169e87efe29c05dedaec71898abfcbc7a1f846f2b3" + }, + "serialized": "ff011e0100000008000600000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f9029500000000001073696d706c655f74785f7465737465729a74c959d0cd4ad4352292417de3ed8ed0cac9aad390bb5d93a5ef5d2bdbf54dad9bbf690f2079ad397141acd182b6e5c4285bd64b068083431daffd5dbc5b09003b5b94d80da3d41f514d77a624f26f7a2336c34ce1ec62f06c61635db31b27135a58b9ee705cbaa45addd6e75098833c80935541ccc050199443a3d4c62c7fdd01335feff7cc3d6e3524dd9892e029d2dea77c76afdeb9445bc0d14c587fd922c6c38e3542b978aeb370dc349b4a1221015f33051407f10ca051a1caa2109fc51002fe8b1d0be5a77455b38f9df31a379e1a80bcab4003a225cbf79d426fcd248e03ff5f499a404d879270086e292aa45ac1af979aa9af4a64e4881ec559fc87e779" +} diff --git a/src/test/resources/transactions/username_registration/username-registration-sign.json b/src/test/resources/transactions/username_registration/username-registration-sign.json new file mode 100644 index 00000000..f40a509d --- /dev/null +++ b/src/test/resources/transactions/username_registration/username-registration-sign.json @@ -0,0 +1,18 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 8, + "nonce": "4", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "2500000000", + "amount": "0", + "asset": { + "username": "simple_tx_tester" + }, + "signature": "70014805da364407f71ca7e09dae5a685af562b985279e370d1a936ebbe7c2545dca35b0f0f30b72eaee0ca042beb6ef2cab5666dd42831a7d0dacac3d962563", + "id": "a50b909f5b483ef1a9bebff66582de169782d3a8adc3e8fca7b183c39738c721" + }, + "serialized": "ff011e0100000008000400000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f9029500000000001073696d706c655f74785f74657374657270014805da364407f71ca7e09dae5a685af562b985279e370d1a936ebbe7c2545dca35b0f0f30b72eaee0ca042beb6ef2cab5666dd42831a7d0dacac3d962563" +} diff --git a/src/test/resources/transactions/username_resignation/username-resignation-multi-sign.json b/src/test/resources/transactions/username_resignation/username-resignation-multi-sign.json new file mode 100644 index 00000000..bc2d7e17 --- /dev/null +++ b/src/test/resources/transactions/username_resignation/username-resignation-multi-sign.json @@ -0,0 +1,20 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 9, + "nonce": "6", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "2500000000", + "amount": "0", + "signature": "730f5d46f0ee978f5437899cea0912a87d9854f384a94f3b5b88fbdd527573bb6c6ed13b3da0a695e41efe2b14bafd587db4563b8f29e10f78736959250e8414", + "signatures": [ + "00fe3edd3082e95f42177e6f786f22e3df982e1b85446f9291b6effcdbfe311ec7b9d4df7e68a36ddb6afe04564586c9a3c4245d47077bda91c1fda53d294d7317", + "014e0ca11609da9444233dd13a3561c4ac6f779a177389b498749d70076126b1081d6bab0106938b2431c04c8b4cecb78f8d348ba81e7a03eee5f9fc9b0f1a3131", + "023a7826b28719baf87f4a3a5a10b51d2ce26172a01d92d41691edf7630fd5bd51d9ace6fdfa1361c7a0834d6a6017c3fba4f642fcb2a49e251fbcf6464b5256cc" + ], + "id": "d0210c375d32eec25ca9513099b98e559c3acb136d08011874149217e17ff8f1" + }, + "serialized": "ff011e0100000009000600000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f902950000000000730f5d46f0ee978f5437899cea0912a87d9854f384a94f3b5b88fbdd527573bb6c6ed13b3da0a695e41efe2b14bafd587db4563b8f29e10f78736959250e841400fe3edd3082e95f42177e6f786f22e3df982e1b85446f9291b6effcdbfe311ec7b9d4df7e68a36ddb6afe04564586c9a3c4245d47077bda91c1fda53d294d7317014e0ca11609da9444233dd13a3561c4ac6f779a177389b498749d70076126b1081d6bab0106938b2431c04c8b4cecb78f8d348ba81e7a03eee5f9fc9b0f1a3131023a7826b28719baf87f4a3a5a10b51d2ce26172a01d92d41691edf7630fd5bd51d9ace6fdfa1361c7a0834d6a6017c3fba4f642fcb2a49e251fbcf6464b5256cc" +} diff --git a/src/test/resources/transactions/username_resignation/username-resignation-sign.json b/src/test/resources/transactions/username_resignation/username-resignation-sign.json new file mode 100644 index 00000000..9209da01 --- /dev/null +++ b/src/test/resources/transactions/username_resignation/username-resignation-sign.json @@ -0,0 +1,15 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 9, + "nonce": "4", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "2500000000", + "amount": "0", + "signature": "72b0322b72019f688fc21f367d68b38828c6e3966e52b3fd46f0813cc7c2cdfd58097c4eef8b52896aba1300098e20a38659529b45db9dfca7aa23d560457769", + "id": "1f90e26793dd55b6b2464002dc537882df94199249ba0bd07fcb4512851ed22b" + }, + "serialized": "ff011e0100000009000400000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f90295000000000072b0322b72019f688fc21f367d68b38828c6e3966e52b3fd46f0813cc7c2cdfd58097c4eef8b52896aba1300098e20a38659529b45db9dfca7aa23d560457769" +} diff --git a/src/test/resources/transactions/v2-ecdsa/delegate-registration-secondSign.json b/src/test/resources/transactions/v2-ecdsa/delegate-registration-secondSign.json deleted file mode 100644 index a83b52f1..00000000 --- a/src/test/resources/transactions/v2-ecdsa/delegate-registration-secondSign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 2, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "2500000000", - "amount": "0", - "asset": { - "delegate": { - "username": "boldninja" - } - }, - "signature": "304502210094d93b799526337256850011fd9a065a944c5bb58e730882393be62a01991cd70220715d66eb3377b59f2b51ca9616e7c252cb66ebf40f96cf469987dd4a9aaa60cd", - "secondSignature": "3045022100f6098d565170c3bf7b031098c4b1287dc12dbca6ebc5d824180cb070c97c208602205e6be08766e6a5649407867d3d5caa24431387427ab5057a699839e4000174a1", - "id": "4f00274e818eb3defdbe3ce5cc1d7637664f015c68c649ebc6cf1cbd24a9f94c" - }, - "serialized": "ff02170100000002000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f90295000000000009626f6c646e696e6a61304502210094d93b799526337256850011fd9a065a944c5bb58e730882393be62a01991cd70220715d66eb3377b59f2b51ca9616e7c252cb66ebf40f96cf469987dd4a9aaa60cd3045022100f6098d565170c3bf7b031098c4b1287dc12dbca6ebc5d824180cb070c97c208602205e6be08766e6a5649407867d3d5caa24431387427ab5057a699839e4000174a1" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/delegate-registration-sign.json b/src/test/resources/transactions/v2-ecdsa/delegate-registration-sign.json deleted file mode 100644 index aa18c641..00000000 --- a/src/test/resources/transactions/v2-ecdsa/delegate-registration-sign.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 2, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "2500000000", - "amount": "0", - "asset": { - "delegate": { - "username": "boldninja" - } - }, - "signature": "304502210094d93b799526337256850011fd9a065a944c5bb58e730882393be62a01991cd70220715d66eb3377b59f2b51ca9616e7c252cb66ebf40f96cf469987dd4a9aaa60cd", - "id": "59a41e4411c9fac688ac22a10ba88a6ef6f513b2b8de05c94793e5434b1eb2e5" - }, - "serialized": "ff02170100000002000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f90295000000000009626f6c646e696e6a61304502210094d93b799526337256850011fd9a065a944c5bb58e730882393be62a01991cd70220715d66eb3377b59f2b51ca9616e7c252cb66ebf40f96cf469987dd4a9aaa60cd" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/delegate-resignation-secondSign.json b/src/test/resources/transactions/v2-ecdsa/delegate-resignation-secondSign.json deleted file mode 100644 index 78483326..00000000 --- a/src/test/resources/transactions/v2-ecdsa/delegate-resignation-secondSign.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 7, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "2500000000", - "amount": "0", - "signature": "3045022100aa113ddefb502d868219339d16b8d448c8e69c8e320664e12903cc84420c159d02201b6206c7cb9442f6ef07dd0824aeb0cc393d8f9f9909988da6687c44ef897070", - "secondSignature": "3045022100979dc1c57b2bfb033676ba9f659f995b688b5e9ed726d4a42523c4cdf2503731022072e13f61defa89a07369c9ef090a4bdc80eb36a2abc61e801bf66525e96adb7f", - "id": "cb6764194faeee2e283c0238adf57c08ffbf068407937bc13eddea1bc02b2a42" - }, - "serialized": "ff02170100000007000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f9029500000000003045022100aa113ddefb502d868219339d16b8d448c8e69c8e320664e12903cc84420c159d02201b6206c7cb9442f6ef07dd0824aeb0cc393d8f9f9909988da6687c44ef8970703045022100979dc1c57b2bfb033676ba9f659f995b688b5e9ed726d4a42523c4cdf2503731022072e13f61defa89a07369c9ef090a4bdc80eb36a2abc61e801bf66525e96adb7f" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/delegate-resignation-sign.json b/src/test/resources/transactions/v2-ecdsa/delegate-resignation-sign.json deleted file mode 100644 index 494e5359..00000000 --- a/src/test/resources/transactions/v2-ecdsa/delegate-resignation-sign.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 7, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "2500000000", - "amount": "0", - "signature": "3045022100aa113ddefb502d868219339d16b8d448c8e69c8e320664e12903cc84420c159d02201b6206c7cb9442f6ef07dd0824aeb0cc393d8f9f9909988da6687c44ef897070", - "id": "a8cf10c6a7d2e5c82bff0860f83f917f426bdd1ee25bd8d5dad2358973ce4ecb" - }, - "serialized": "ff02170100000007000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f9029500000000003045022100aa113ddefb502d868219339d16b8d448c8e69c8e320664e12903cc84420c159d02201b6206c7cb9442f6ef07dd0824aeb0cc393d8f9f9909988da6687c44ef897070" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/htlc-claim-secondSign.json b/src/test/resources/transactions/v2-ecdsa/htlc-claim-secondSign.json deleted file mode 100644 index 813794c1..00000000 --- a/src/test/resources/transactions/v2-ecdsa/htlc-claim-secondSign.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 9, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "0", - "amount": "0", - "asset": { - "claim": { - "lockTransactionId": "9c1a3815d49e0c9f78b872bfb017e825ea2db708158b70815526a830c85912b4", - "unlockSecret": "c27f1ce845d8c29eebc9006be932b604fd06755521b1a8b0be4204c65377151a" - } - }, - "signature": "3045022100f4115db125d14edd248b39459ae8a6d112f8d9cdbcf69da03dce597c048d99260220069d4a07229684f91b492979f0050400c323eb4096f586dedc101f0f5a3ac476", - "secondSignature": "3045022100abe4c9bce127caeb5856a3f01dc216a6ac1100c2f9ec04ebcb3a2bb184fff0de022058b3045a4a4fd14fcd2e9a80edcb616582e28cfd0b6a78966e91a3786bbc8c8d", - "id": "3e857d6d7851340ff47cd9ccb8d3faf55add8e35d7a24128ac033102d3abb986" - }, - "serialized": "ff02170100000009000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920000000000000000009c1a3815d49e0c9f78b872bfb017e825ea2db708158b70815526a830c85912b4c27f1ce845d8c29eebc9006be932b604fd06755521b1a8b0be4204c65377151a3045022100f4115db125d14edd248b39459ae8a6d112f8d9cdbcf69da03dce597c048d99260220069d4a07229684f91b492979f0050400c323eb4096f586dedc101f0f5a3ac4763045022100abe4c9bce127caeb5856a3f01dc216a6ac1100c2f9ec04ebcb3a2bb184fff0de022058b3045a4a4fd14fcd2e9a80edcb616582e28cfd0b6a78966e91a3786bbc8c8d" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/htlc-claim-sign.json b/src/test/resources/transactions/v2-ecdsa/htlc-claim-sign.json deleted file mode 100644 index 76e87284..00000000 --- a/src/test/resources/transactions/v2-ecdsa/htlc-claim-sign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 9, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "0", - "amount": "0", - "asset": { - "claim": { - "lockTransactionId": "9c1a3815d49e0c9f78b872bfb017e825ea2db708158b70815526a830c85912b4", - "unlockSecret": "c27f1ce845d8c29eebc9006be932b604fd06755521b1a8b0be4204c65377151a" - } - }, - "signature": "3045022100f4115db125d14edd248b39459ae8a6d112f8d9cdbcf69da03dce597c048d99260220069d4a07229684f91b492979f0050400c323eb4096f586dedc101f0f5a3ac476", - "id": "fd6eb162c34dadcd66a5e86ce534a1df946b8fa4291ed17c085b252dafbdf30b" - }, - "serialized": "ff02170100000009000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920000000000000000009c1a3815d49e0c9f78b872bfb017e825ea2db708158b70815526a830c85912b4c27f1ce845d8c29eebc9006be932b604fd06755521b1a8b0be4204c65377151a3045022100f4115db125d14edd248b39459ae8a6d112f8d9cdbcf69da03dce597c048d99260220069d4a07229684f91b492979f0050400c323eb4096f586dedc101f0f5a3ac476" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/htlc-lock-secondSign.json b/src/test/resources/transactions/v2-ecdsa/htlc-lock-secondSign.json deleted file mode 100644 index 819f2807..00000000 --- a/src/test/resources/transactions/v2-ecdsa/htlc-lock-secondSign.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1581339432 - } - } - }, - "signature": "3045022100968071560adef123ebc908bb11f46550339c52c997829f597a539e5616f79f8d0220533c0992b991b5d9a670ea1877cd5306bef5963b9a868fadf4122329fd4b2712", - "secondSignature": "304402203c3ef3dfe32837b19460bf8bfc7ec7bd003f773efa09d1966886ff361ef9afb302203a95e56d72c24f2a3313444d1fcd4971dcc67bcb54235a67b964f93201debdda", - "id": "06ab23a6a9355ed3deb4a5ecdb085a77862bf8eb5f270b773009199087890dd1" - }, - "serialized": "ff02170100000008000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454012853415e170995750207ecaf0ccf251c1265b92ad84f5536623045022100968071560adef123ebc908bb11f46550339c52c997829f597a539e5616f79f8d0220533c0992b991b5d9a670ea1877cd5306bef5963b9a868fadf4122329fd4b2712304402203c3ef3dfe32837b19460bf8bfc7ec7bd003f773efa09d1966886ff361ef9afb302203a95e56d72c24f2a3313444d1fcd4971dcc67bcb54235a67b964f93201debdda" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/htlc-lock-sign.json b/src/test/resources/transactions/v2-ecdsa/htlc-lock-sign.json deleted file mode 100644 index ac0e1617..00000000 --- a/src/test/resources/transactions/v2-ecdsa/htlc-lock-sign.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1581339432 - } - } - }, - "signature": "3045022100968071560adef123ebc908bb11f46550339c52c997829f597a539e5616f79f8d0220533c0992b991b5d9a670ea1877cd5306bef5963b9a868fadf4122329fd4b2712", - "id": "cfb37ec05433841cd8d25c3e8d353dc519a6dcb583edd75085b671bff4075b40" - }, - "serialized": "ff02170100000008000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454012853415e170995750207ecaf0ccf251c1265b92ad84f5536623045022100968071560adef123ebc908bb11f46550339c52c997829f597a539e5616f79f8d0220533c0992b991b5d9a670ea1877cd5306bef5963b9a868fadf4122329fd4b2712" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/htlc-lock-with-vendor-field-secondSign.json b/src/test/resources/transactions/v2-ecdsa/htlc-lock-with-vendor-field-secondSign.json deleted file mode 100644 index 49f29658..00000000 --- a/src/test/resources/transactions/v2-ecdsa/htlc-lock-with-vendor-field-secondSign.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "vendorField": "this is a top secret vendor field", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1581339432 - } - } - }, - "signature": "304402206b83b7976c08bbc1f67a17d5481f498bdadd761826379489b9c44390c1c1621002205fe8ab97de3a08305967c9bf66d19a8426bd0d97d744639ab220a03ca8b5ef78", - "secondSignature": "304402202646835437728c73293f3bdba5c3ec8c48e33503b609ae7a12ca6202e42711ac0220448f344f014c69fa6c791972f5ab4cd6561504030b058aa8fe3c16947b6f207e", - "id": "8dd3093cfc16a8c77fcea60ba79515d50ab5d3f6e02864cc5a8f3757c1f00c83" - }, - "serialized": "ff02170100000008000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454012853415e170995750207ecaf0ccf251c1265b92ad84f553662304402206b83b7976c08bbc1f67a17d5481f498bdadd761826379489b9c44390c1c1621002205fe8ab97de3a08305967c9bf66d19a8426bd0d97d744639ab220a03ca8b5ef78304402202646835437728c73293f3bdba5c3ec8c48e33503b609ae7a12ca6202e42711ac0220448f344f014c69fa6c791972f5ab4cd6561504030b058aa8fe3c16947b6f207e" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/htlc-lock-with-vendor-field-sign.json b/src/test/resources/transactions/v2-ecdsa/htlc-lock-with-vendor-field-sign.json deleted file mode 100644 index cea1f04f..00000000 --- a/src/test/resources/transactions/v2-ecdsa/htlc-lock-with-vendor-field-sign.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "vendorField": "this is a top secret vendor field", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1581339432 - } - } - }, - "signature": "304402206b83b7976c08bbc1f67a17d5481f498bdadd761826379489b9c44390c1c1621002205fe8ab97de3a08305967c9bf66d19a8426bd0d97d744639ab220a03ca8b5ef78", - "id": "d0361b035f314a248020f955eff949af0e979a41cc6b420683fc76f9391f598f" - }, - "serialized": "ff02170100000008000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454012853415e170995750207ecaf0ccf251c1265b92ad84f553662304402206b83b7976c08bbc1f67a17d5481f498bdadd761826379489b9c44390c1c1621002205fe8ab97de3a08305967c9bf66d19a8426bd0d97d744639ab220a03ca8b5ef78" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/htlc-refund-secondSign.json b/src/test/resources/transactions/v2-ecdsa/htlc-refund-secondSign.json deleted file mode 100644 index 0da0f345..00000000 --- a/src/test/resources/transactions/v2-ecdsa/htlc-refund-secondSign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 10, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "0", - "amount": "0", - "asset": { - "refund": { - "lockTransactionId": "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4" - } - }, - "signature": "3044022039b189def165ca903805e35f0fa8d0b5820861227d677909acb1650698a63415022020a124f535f92100cd8233f9b5e01eebda72b59c858600934f586fc7ee236574", - "secondSignature": "3044022018cae203467050b6e5c9f095ef8730b51eb8f1f0770be77da45aca6c275c635d02207dd4bd55309f7bac05ad4d3e71a7c3e2182ec4aea4549d443aec6dd3fac831f1", - "id": "6b6f8705c0df33ad0b2491c89788661f7fa834d8414658f836903cc5e4e190de" - }, - "serialized": "ff0217010000000a000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192000000000000000000943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb43044022039b189def165ca903805e35f0fa8d0b5820861227d677909acb1650698a63415022020a124f535f92100cd8233f9b5e01eebda72b59c858600934f586fc7ee2365743044022018cae203467050b6e5c9f095ef8730b51eb8f1f0770be77da45aca6c275c635d02207dd4bd55309f7bac05ad4d3e71a7c3e2182ec4aea4549d443aec6dd3fac831f1" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/htlc-refund-sign.json b/src/test/resources/transactions/v2-ecdsa/htlc-refund-sign.json deleted file mode 100644 index f36eb19c..00000000 --- a/src/test/resources/transactions/v2-ecdsa/htlc-refund-sign.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 10, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "0", - "amount": "0", - "asset": { - "refund": { - "lockTransactionId": "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4" - } - }, - "signature": "3044022039b189def165ca903805e35f0fa8d0b5820861227d677909acb1650698a63415022020a124f535f92100cd8233f9b5e01eebda72b59c858600934f586fc7ee236574", - "id": "c8cf015e1566d9d63236e70c12988f6f13161f90d30ff5120ee62e37484034e3" - }, - "serialized": "ff0217010000000a000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192000000000000000000943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb43044022039b189def165ca903805e35f0fa8d0b5820861227d677909acb1650698a63415022020a124f535f92100cd8233f9b5e01eebda72b59c858600934f586fc7ee236574" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/ipfs-secondSign.json b/src/test/resources/transactions/v2-ecdsa/ipfs-secondSign.json deleted file mode 100644 index a4070c90..00000000 --- a/src/test/resources/transactions/v2-ecdsa/ipfs-secondSign.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 5, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "500000000", - "amount": "0", - "asset": { - "ipfs": "QmR45FmbVVrixReBwJkhEKde2qwHYaQzGxu4ZoDeswuF9w" - }, - "signature": "3045022100e7d20c81b32e7a30fb741ba76fc823b667f38389b0a19d5e0a5779029843b792022050133f52000dc4327548c6f757f6ab2386f080d0fada8902de3d1372a2a9ff92", - "secondSignature": "30450221009a210886183630f56aa2341db8d2fa142a82871290bcd1c95f15c864dbe207ff02206dbaf3ecf954047ab7c507b3a8d12096872f7c43986b26b436df6d01961803b4", - "id": "6ff039ec2ae3a6e48f629ad26d429f0a6d4c888439db4424d417cea7c32fa95a" - }, - "serialized": "ff02170100000005000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920065cd1d000000000012202853f0f11ab91d73b73a2a86606103f45dd469ad2e89ec6f9a25febe8758d3fe3045022100e7d20c81b32e7a30fb741ba76fc823b667f38389b0a19d5e0a5779029843b792022050133f52000dc4327548c6f757f6ab2386f080d0fada8902de3d1372a2a9ff9230450221009a210886183630f56aa2341db8d2fa142a82871290bcd1c95f15c864dbe207ff02206dbaf3ecf954047ab7c507b3a8d12096872f7c43986b26b436df6d01961803b4" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/ipfs-sign.json b/src/test/resources/transactions/v2-ecdsa/ipfs-sign.json deleted file mode 100644 index 27747208..00000000 --- a/src/test/resources/transactions/v2-ecdsa/ipfs-sign.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 5, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "500000000", - "amount": "0", - "asset": { - "ipfs": "QmR45FmbVVrixReBwJkhEKde2qwHYaQzGxu4ZoDeswuF9w" - }, - "signature": "3045022100e7d20c81b32e7a30fb741ba76fc823b667f38389b0a19d5e0a5779029843b792022050133f52000dc4327548c6f757f6ab2386f080d0fada8902de3d1372a2a9ff92", - "id": "b38f24116758b9b2fdb1f80b5ce02044af640f77d552080768942f9a9cfa2a88" - }, - "serialized": "ff02170100000005000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920065cd1d000000000012202853f0f11ab91d73b73a2a86606103f45dd469ad2e89ec6f9a25febe8758d3fe3045022100e7d20c81b32e7a30fb741ba76fc823b667f38389b0a19d5e0a5779029843b792022050133f52000dc4327548c6f757f6ab2386f080d0fada8902de3d1372a2a9ff92" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/multi-payment-secondSign.json b/src/test/resources/transactions/v2-ecdsa/multi-payment-secondSign.json deleted file mode 100644 index 2f55cf1b..00000000 --- a/src/test/resources/transactions/v2-ecdsa/multi-payment-secondSign.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "0", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signature": "3044022068ecfe918717a0890ae0480045d526a7f14f163377e5e6dc4ce3bdd70c20cf750220261eaacb731cf386d5439e651fb2068ab59cb9ea2503d4a522f2da299870b3ae", - "secondSignature": "3045022100c8c77d296b2e9cb0f2af7ac9fa5d4c30d188e580ed888a2e1afc694b206b308d02200c08cdc6cef86418ebcf181efb60a814066ef67413f57069f32d8b563b2b543b", - "id": "3aa197c202b1d7e17bdd21be4b510802f91aab028ff24dafdb8c9514c201e05f" - }, - "serialized": "ff02170100000006000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1928096980000000000000200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f0413044022068ecfe918717a0890ae0480045d526a7f14f163377e5e6dc4ce3bdd70c20cf750220261eaacb731cf386d5439e651fb2068ab59cb9ea2503d4a522f2da299870b3ae3045022100c8c77d296b2e9cb0f2af7ac9fa5d4c30d188e580ed888a2e1afc694b206b308d02200c08cdc6cef86418ebcf181efb60a814066ef67413f57069f32d8b563b2b543b" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/multi-payment-sign.json b/src/test/resources/transactions/v2-ecdsa/multi-payment-sign.json deleted file mode 100644 index 811601d1..00000000 --- a/src/test/resources/transactions/v2-ecdsa/multi-payment-sign.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "0", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signature": "3044022068ecfe918717a0890ae0480045d526a7f14f163377e5e6dc4ce3bdd70c20cf750220261eaacb731cf386d5439e651fb2068ab59cb9ea2503d4a522f2da299870b3ae", - "id": "df4759a599ec78ac1cfb19ded5985312266dd009610eee5e71d55e69076c7d35" - }, - "serialized": "ff02170100000006000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1928096980000000000000200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f0413044022068ecfe918717a0890ae0480045d526a7f14f163377e5e6dc4ce3bdd70c20cf750220261eaacb731cf386d5439e651fb2068ab59cb9ea2503d4a522f2da299870b3ae" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/multi-payment-with-vendor-field-secondSign.json b/src/test/resources/transactions/v2-ecdsa/multi-payment-with-vendor-field-secondSign.json deleted file mode 100644 index 05f2f6ab..00000000 --- a/src/test/resources/transactions/v2-ecdsa/multi-payment-with-vendor-field-secondSign.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "0", - "vendorField": "this is a top secret vendor field", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signature": "304402205d6a667239481f9306f37b35976626a39993b1088ee8ff2dee638905590c9508022040aa06bce7d20146c179d1106f29a821aa7278816e1f77f325e02caec3129565", - "secondSignature": "3044022049d89e8cc29e8febd60b3f2482cf39ee8ed71de07bd3834025067aa80a6ff97b022036d5c300b23806c2d694d2172785f57896312c61a19ddacb4c895f3a44ec1db4", - "id": "64bccef76c16c06e4cb20398b9db02c92e38878dd1afe798b6298d1cbc80d53d" - }, - "serialized": "ff02170100000006000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c640200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f041304402205d6a667239481f9306f37b35976626a39993b1088ee8ff2dee638905590c9508022040aa06bce7d20146c179d1106f29a821aa7278816e1f77f325e02caec31295653044022049d89e8cc29e8febd60b3f2482cf39ee8ed71de07bd3834025067aa80a6ff97b022036d5c300b23806c2d694d2172785f57896312c61a19ddacb4c895f3a44ec1db4" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/multi-payment-with-vendor-field-sign.json b/src/test/resources/transactions/v2-ecdsa/multi-payment-with-vendor-field-sign.json deleted file mode 100644 index a0138200..00000000 --- a/src/test/resources/transactions/v2-ecdsa/multi-payment-with-vendor-field-sign.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "0", - "vendorField": "this is a top secret vendor field", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signature": "304402205d6a667239481f9306f37b35976626a39993b1088ee8ff2dee638905590c9508022040aa06bce7d20146c179d1106f29a821aa7278816e1f77f325e02caec3129565", - "id": "7bd4861b168d903500ecf15503804c9625f0eb0d86d350e3f0b73765f6ce2c7c" - }, - "serialized": "ff02170100000006000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c640200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f041304402205d6a667239481f9306f37b35976626a39993b1088ee8ff2dee638905590c9508022040aa06bce7d20146c179d1106f29a821aa7278816e1f77f325e02caec3129565" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/second-signature-registration.json b/src/test/resources/transactions/v2-ecdsa/second-signature-registration.json deleted file mode 100644 index 359f9fbe..00000000 --- a/src/test/resources/transactions/v2-ecdsa/second-signature-registration.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 1, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "500000000", - "amount": "0", - "asset": { - "signature": { - "publicKey": "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609" - } - }, - "signature": "f9a1e2244c8318e8be85482fc02659e5c1775d246d73d5d0699ae4a1d5e3a3e84f9dcf68ee015f943d2a82eb829f35abd7901279761d96f6b43431520e955c67", - "id": "173a3230159b45d772b2e0348f42af53913bf3e376397f29b8e0bda290badbe4" - }, - "serialized": "ff02170100000001000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920065cd1d000000000003699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609f9a1e2244c8318e8be85482fc02659e5c1775d246d73d5d0699ae4a1d5e3a3e84f9dcf68ee015f943d2a82eb829f35abd7901279761d96f6b43431520e955c67" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/test.json b/src/test/resources/transactions/v2-ecdsa/test.json deleted file mode 100644 index e11d8ef0..00000000 --- a/src/test/resources/transactions/v2-ecdsa/test.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "signSignature": "0220261eaacb731cf386d5439e651fb2068ab59cb9ea2503d4a522f2da299870b3ae", - "signature": "022068ecfe918717a0890ae0480045d526a7f14f163377e5e6dc4ce3bdd70c20cf75", - "id": "93ddabea6c2c7761ecf4ee3ec988e1d971cffedf2363c5b06bc3ba29f3b48931" -} diff --git a/src/test/resources/transactions/v2-ecdsa/transfer-secondSign.json b/src/test/resources/transactions/v2-ecdsa/transfer-secondSign.json deleted file mode 100644 index d385c749..00000000 --- a/src/test/resources/transactions/v2-ecdsa/transfer-secondSign.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signature": "3045022100af4741f03fdc64f0d6ed1dc69ecc77a000532ec1e3e30b9eb72d74eec404b25a0220437850da2e15b672e7ce55277b716770b99b3db995921cd2c69debafbcf22170", - "secondSignature": "3045022100a85e21b1014113abafabd3b04023cb8a2fbb782f76094a34ed1f4e107b2ded67022040bf517fcb5102a214bd6af98bbad126de2103c63b1099e41da30ae239c95d16", - "id": "c12582cfa32281459cb2cf42c7b87e2f2b27eb2e05caceffd40f6c096c8ef792" - }, - "serialized": "ff02170100000000000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f5536623045022100af4741f03fdc64f0d6ed1dc69ecc77a000532ec1e3e30b9eb72d74eec404b25a0220437850da2e15b672e7ce55277b716770b99b3db995921cd2c69debafbcf221703045022100a85e21b1014113abafabd3b04023cb8a2fbb782f76094a34ed1f4e107b2ded67022040bf517fcb5102a214bd6af98bbad126de2103c63b1099e41da30ae239c95d16" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/transfer-sign.json b/src/test/resources/transactions/v2-ecdsa/transfer-sign.json deleted file mode 100644 index 19a6a8bb..00000000 --- a/src/test/resources/transactions/v2-ecdsa/transfer-sign.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signature": "3045022100af4741f03fdc64f0d6ed1dc69ecc77a000532ec1e3e30b9eb72d74eec404b25a0220437850da2e15b672e7ce55277b716770b99b3db995921cd2c69debafbcf22170", - "id": "9b038513f4dd77507da8a71d0204e491324d49f4598fe41f6c6985baae7d3517" - }, - "serialized": "ff02170100000000000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f5536623045022100af4741f03fdc64f0d6ed1dc69ecc77a000532ec1e3e30b9eb72d74eec404b25a0220437850da2e15b672e7ce55277b716770b99b3db995921cd2c69debafbcf22170" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/transfer-with-vendor-field-secondSign.json b/src/test/resources/transactions/v2-ecdsa/transfer-with-vendor-field-secondSign.json deleted file mode 100644 index 7152c7a8..00000000 --- a/src/test/resources/transactions/v2-ecdsa/transfer-with-vendor-field-secondSign.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "vendorField": "this is a top secret vendor field", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signature": "3045022100ef3a6127cfc4336be5f92c6133ea46d180eb90a526d7de2359f1f39ba4624ee30220718f4d2f2edb62a44d14a1c661d08d7454b55ecbe66160d0dfd7dd06e7b343a8", - "secondSignature": "3045022100e3879d1998844ec4a101d9e52bb73d89257fd19142926ff341ce3d8d51925ad302203e26c1413180a6a7a7ebe04c2ec2d2087e7205b18e58bf69c6fe75067939c51a", - "id": "e7268723a7917a421abe00d8731fb1924be7f11e1f4c8f68964b537dcf6b5f37" - }, - "serialized": "ff02170100000000000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f5536623045022100ef3a6127cfc4336be5f92c6133ea46d180eb90a526d7de2359f1f39ba4624ee30220718f4d2f2edb62a44d14a1c661d08d7454b55ecbe66160d0dfd7dd06e7b343a83045022100e3879d1998844ec4a101d9e52bb73d89257fd19142926ff341ce3d8d51925ad302203e26c1413180a6a7a7ebe04c2ec2d2087e7205b18e58bf69c6fe75067939c51a" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/transfer-with-vendor-field-sign.json b/src/test/resources/transactions/v2-ecdsa/transfer-with-vendor-field-sign.json deleted file mode 100644 index 27a9e3ab..00000000 --- a/src/test/resources/transactions/v2-ecdsa/transfer-with-vendor-field-sign.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "vendorField": "this is a top secret vendor field", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signature": "3045022100ef3a6127cfc4336be5f92c6133ea46d180eb90a526d7de2359f1f39ba4624ee30220718f4d2f2edb62a44d14a1c661d08d7454b55ecbe66160d0dfd7dd06e7b343a8", - "id": "0ad296322bfb656490b2d7a5dfc1fd88f840d412c4c8467ddba9890134647659" - }, - "serialized": "ff02170100000000000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f5536623045022100ef3a6127cfc4336be5f92c6133ea46d180eb90a526d7de2359f1f39ba4624ee30220718f4d2f2edb62a44d14a1c661d08d7454b55ecbe66160d0dfd7dd06e7b343a8" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/unvote-secondSign.json b/src/test/resources/transactions/v2-ecdsa/unvote-secondSign.json deleted file mode 100644 index d309512d..00000000 --- a/src/test/resources/transactions/v2-ecdsa/unvote-secondSign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "-022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "3045022100b3d67da287f35bb4f5ae28239cef8b5e82581f8030fe374c0ed86223d66b11bb02200a1ef45b603f70265a7437411565d9d577265452250bf279477f05b09feb5776", - "secondSignature": "3045022100955a00393e7f22397f36e76e39046375dcc9b4e853050a921a904981453a8da8022049175702a8be7de15afcccf3feab568352fe3a2355357495691a1bf6a7a26d13", - "id": "40e0640fe655b1a119051a9ed205a95a32dc95d31354375147e20e57d37161c1" - }, - "serialized": "ff02170100000003000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000100022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d3045022100b3d67da287f35bb4f5ae28239cef8b5e82581f8030fe374c0ed86223d66b11bb02200a1ef45b603f70265a7437411565d9d577265452250bf279477f05b09feb57763045022100955a00393e7f22397f36e76e39046375dcc9b4e853050a921a904981453a8da8022049175702a8be7de15afcccf3feab568352fe3a2355357495691a1bf6a7a26d13" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/unvote-sign.json b/src/test/resources/transactions/v2-ecdsa/unvote-sign.json deleted file mode 100644 index 251ab2af..00000000 --- a/src/test/resources/transactions/v2-ecdsa/unvote-sign.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "-022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "3045022100b3d67da287f35bb4f5ae28239cef8b5e82581f8030fe374c0ed86223d66b11bb02200a1ef45b603f70265a7437411565d9d577265452250bf279477f05b09feb5776", - "id": "cbfcca4f96dece8446c355052eb0aab2af82a526c0e4412140b865bc6336fc0e" - }, - "serialized": "ff02170100000003000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000100022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d3045022100b3d67da287f35bb4f5ae28239cef8b5e82581f8030fe374c0ed86223d66b11bb02200a1ef45b603f70265a7437411565d9d577265452250bf279477f05b09feb5776" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/vote-secondSign.json b/src/test/resources/transactions/v2-ecdsa/vote-secondSign.json deleted file mode 100644 index 43e4a41f..00000000 --- a/src/test/resources/transactions/v2-ecdsa/vote-secondSign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "+022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "304402206a7a9baa573ab08bb4220450ace0d73ac9c768ef38b07a82ca19b2e2f11d0b550220665938431da66ad0b49e2267d65b220c59a35e1fea50083d45560a544f077eb6", - "secondSignature": "30450221009d26b579f96e92f4dde323c380769e94d359b6a6455d959dfae49bf1bdea7b5b02207d433fcf262d6552f7edc22ac9141e15e3a7dc379b84ddb61af458ee14b0f0bb", - "id": "dd5bbb65a9d72609ab7c813e2fc7bc03ec3b0adf803a8ddfb42fd788497fbaa4" - }, - "serialized": "ff02170100000003000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000101022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d304402206a7a9baa573ab08bb4220450ace0d73ac9c768ef38b07a82ca19b2e2f11d0b550220665938431da66ad0b49e2267d65b220c59a35e1fea50083d45560a544f077eb630450221009d26b579f96e92f4dde323c380769e94d359b6a6455d959dfae49bf1bdea7b5b02207d433fcf262d6552f7edc22ac9141e15e3a7dc379b84ddb61af458ee14b0f0bb" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-ecdsa/vote-sign.json b/src/test/resources/transactions/v2-ecdsa/vote-sign.json deleted file mode 100644 index dd68ea89..00000000 --- a/src/test/resources/transactions/v2-ecdsa/vote-sign.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "+022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "304402206a7a9baa573ab08bb4220450ace0d73ac9c768ef38b07a82ca19b2e2f11d0b550220665938431da66ad0b49e2267d65b220c59a35e1fea50083d45560a544f077eb6", - "id": "b8dce941db9d3b04a7afd142fc26e40ecc73f2865fbc84597dca9b907f9791f6" - }, - "serialized": "ff02170100000003000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000101022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d304402206a7a9baa573ab08bb4220450ace0d73ac9c768ef38b07a82ca19b2e2f11d0b550220665938431da66ad0b49e2267d65b220c59a35e1fea50083d45560a544f077eb6" -} \ No newline at end of file diff --git a/src/test/resources/transactions/v2-schnorr/delegate-registration-multiSign.json b/src/test/resources/transactions/v2-schnorr/delegate-registration-multiSign.json deleted file mode 100644 index 98780282..00000000 --- a/src/test/resources/transactions/v2-schnorr/delegate-registration-multiSign.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 2, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "2500000000", - "amount": "0", - "asset": { - "delegate": { - "username": "boldninja" - } - }, - "signatures": [ - "000d72766650302facdd3e872e6272fa963c258c674d332a4d67e0370bc27f4f4772577b39c934760c1677c2307487e626002f8cdfe80ef6ee035e011683367e83", - "0148f538503487c1c09aced2fb3ca6ae615ae64a7692b5bedb770e863532489a23767884ad50a9a23cfcf27b3eee8fa0a889eb59374c14b4f653a3d899e80cfe12", - "0261e089e116826ee92253d7c91787781ba6a0f4d724d7701b14fd28f8fa760a1e2dbfa180cddc2efc1947fd725666c4431966db20a07528a87822a66da7ea2d95" - ], - "id": "2e8d897dad0d6e66b93dab1dcdb874a966b0124edcdc9a49b0b002ce19f7249e" - }, - "serialized": "ff0217010000000200010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01500f90295000000000009626f6c646e696e6a61000d72766650302facdd3e872e6272fa963c258c674d332a4d67e0370bc27f4f4772577b39c934760c1677c2307487e626002f8cdfe80ef6ee035e011683367e830148f538503487c1c09aced2fb3ca6ae615ae64a7692b5bedb770e863532489a23767884ad50a9a23cfcf27b3eee8fa0a889eb59374c14b4f653a3d899e80cfe120261e089e116826ee92253d7c91787781ba6a0f4d724d7701b14fd28f8fa760a1e2dbfa180cddc2efc1947fd725666c4431966db20a07528a87822a66da7ea2d95" -} diff --git a/src/test/resources/transactions/v2-schnorr/delegate-registration-secondSign.json b/src/test/resources/transactions/v2-schnorr/delegate-registration-secondSign.json deleted file mode 100644 index 279086a1..00000000 --- a/src/test/resources/transactions/v2-schnorr/delegate-registration-secondSign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 2, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "2500000000", - "amount": "0", - "asset": { - "delegate": { - "username": "boldninja" - } - }, - "signature": "eaf4b4dfd7903c32cf6c145ddf0744e86536719f5790b4286b08f1a10f0ad183bc601efc8a49a2a7b41758601a1793693afa1781cf0a63a8f72b08d5a1aaba1e", - "secondSignature": "e9b97a33a6a0a759e7e944eb072cf295c9d0ec61a882d3d00cda110cd1acd5bbe46f752e23df89567da1aa9113552e07155896da7e885a71a2001bc0c9d5d315", - "id": "98a40680249d465bbdf3ea4dc2ccf9e0f3c67ec7f0606f8c4b40c513e8ea88af" - }, - "serialized": "ff02170100000002000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f90295000000000009626f6c646e696e6a61eaf4b4dfd7903c32cf6c145ddf0744e86536719f5790b4286b08f1a10f0ad183bc601efc8a49a2a7b41758601a1793693afa1781cf0a63a8f72b08d5a1aaba1ee9b97a33a6a0a759e7e944eb072cf295c9d0ec61a882d3d00cda110cd1acd5bbe46f752e23df89567da1aa9113552e07155896da7e885a71a2001bc0c9d5d315" -} diff --git a/src/test/resources/transactions/v2-schnorr/delegate-registration-sign.json b/src/test/resources/transactions/v2-schnorr/delegate-registration-sign.json deleted file mode 100644 index 348a7918..00000000 --- a/src/test/resources/transactions/v2-schnorr/delegate-registration-sign.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 2, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "2500000000", - "amount": "0", - "asset": { - "delegate": { - "username": "boldninja" - } - }, - "signature": "eaf4b4dfd7903c32cf6c145ddf0744e86536719f5790b4286b08f1a10f0ad183bc601efc8a49a2a7b41758601a1793693afa1781cf0a63a8f72b08d5a1aaba1e", - "id": "cfd113d8cd9fd46b07030c14fac38c1d3fc0eca991e999eab9d0152ea96ab0dc" - }, - "serialized": "ff02170100000002000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f90295000000000009626f6c646e696e6a61eaf4b4dfd7903c32cf6c145ddf0744e86536719f5790b4286b08f1a10f0ad183bc601efc8a49a2a7b41758601a1793693afa1781cf0a63a8f72b08d5a1aaba1e" -} diff --git a/src/test/resources/transactions/v2-schnorr/delegate-resignation-multiSign.json b/src/test/resources/transactions/v2-schnorr/delegate-resignation-multiSign.json deleted file mode 100644 index 4eb950ef..00000000 --- a/src/test/resources/transactions/v2-schnorr/delegate-resignation-multiSign.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 7, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "2500000000", - "amount": "0", - "signatures": [ - "00712291678f0faaa685ec21ff8cae415bf78210db75b7bfd5203ea0140fbddd1c59473a6099bdfa20eeca7313132f5060694d4448726804a8e8a11bdae8b6c324", - "01d09876c0ec2b0622e1ac2ba463797c804d7578aa51b7857a19f6d5ea1218c138e2093d96773023a942999461c7bad445b4434df0fb1e03b64f3ad9e97ac1c378", - "02f868c6d86e0825a6ebf81b399eadd6f5600ec2da27b18f85e86700752fd90b45c49c42c231db009e0834a74badf4f812f33f1ad9342142bf51dcc60bca23c3f1" - ], - "id": "d33b49de1c527c8b37803ed095b9616ac2650defa727d5822017ede25ca8f060" - }, - "serialized": "ff0217010000000700010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01500f90295000000000000712291678f0faaa685ec21ff8cae415bf78210db75b7bfd5203ea0140fbddd1c59473a6099bdfa20eeca7313132f5060694d4448726804a8e8a11bdae8b6c32401d09876c0ec2b0622e1ac2ba463797c804d7578aa51b7857a19f6d5ea1218c138e2093d96773023a942999461c7bad445b4434df0fb1e03b64f3ad9e97ac1c37802f868c6d86e0825a6ebf81b399eadd6f5600ec2da27b18f85e86700752fd90b45c49c42c231db009e0834a74badf4f812f33f1ad9342142bf51dcc60bca23c3f1" -} diff --git a/src/test/resources/transactions/v2-schnorr/delegate-resignation-secondSign.json b/src/test/resources/transactions/v2-schnorr/delegate-resignation-secondSign.json deleted file mode 100644 index 3177b256..00000000 --- a/src/test/resources/transactions/v2-schnorr/delegate-resignation-secondSign.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 7, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "2500000000", - "amount": "0", - "signature": "bdc048ca7eb5688cc01921aecf5914118cfc78eacc23825efa6d75094a683127cc02512dc59e1e0631fa8956f482eabc54933d23011a8337ea9cab99abed504d", - "secondSignature": "6b6692c636d250f95056a6102b3f86b2191a994b99a7171acff849d2170ce605b6a161199037cd6ff762450d92891cb56552ebb2b1fa1d7de789cb6cf9e5137e", - "id": "cae6cc65f93de0b629276d6685139c07e386b243af00a56e2bba8032c6895a9c" - }, - "serialized": "ff02170100000007000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f902950000000000bdc048ca7eb5688cc01921aecf5914118cfc78eacc23825efa6d75094a683127cc02512dc59e1e0631fa8956f482eabc54933d23011a8337ea9cab99abed504d6b6692c636d250f95056a6102b3f86b2191a994b99a7171acff849d2170ce605b6a161199037cd6ff762450d92891cb56552ebb2b1fa1d7de789cb6cf9e5137e" -} diff --git a/src/test/resources/transactions/v2-schnorr/delegate-resignation-sign.json b/src/test/resources/transactions/v2-schnorr/delegate-resignation-sign.json deleted file mode 100644 index 2b0a3e4b..00000000 --- a/src/test/resources/transactions/v2-schnorr/delegate-resignation-sign.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 7, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "2500000000", - "amount": "0", - "signature": "bdc048ca7eb5688cc01921aecf5914118cfc78eacc23825efa6d75094a683127cc02512dc59e1e0631fa8956f482eabc54933d23011a8337ea9cab99abed504d", - "id": "707b4deb339e717dfef44c40db0692015ce9bbab015c007b016b8a46b341e859" - }, - "serialized": "ff02170100000007000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200f902950000000000bdc048ca7eb5688cc01921aecf5914118cfc78eacc23825efa6d75094a683127cc02512dc59e1e0631fa8956f482eabc54933d23011a8337ea9cab99abed504d" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-claim-multiSign.json b/src/test/resources/transactions/v2-schnorr/htlc-claim-multiSign.json deleted file mode 100644 index 291114c2..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-claim-multiSign.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 9, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "0", - "amount": "0", - "asset": { - "claim": { - "lockTransactionId": "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4", - "unlockSecret": "my secret that should be 32bytes" - } - }, - "signatures": [ - "0078149337d8a903cff63fe39063c47a50fa211c53f03b9dec98e8ffaf001149f89aefbbe7a363296ce273744a96d2a09cd2a90563375866d5ba6bbaf4a7fe0de5", - "015cf52ebd07ad63de9670b0d9176aadb1e6bce4fd533141af4bc8ec87d7998e442b7021849b12a043d66bff1bf9b47f5b1970a0468d32c6a9fdec1f0b988ca7c9", - "026d20540724e00ff1e07a905ed9339e6f4e07f0a0fffc2c4bbe4f200fa5c77538ab3b1479e2d4666227bd8f79ba9148597347f916b6ce17af2e23a13da7433978" - ], - "id": "834fc082dc698f2703ad1f1d48111ab52433d4d7ae27b59ff68abf651c706144" - }, - "serialized": "ff0217010000000900010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015000000000000000000943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb46d792073656372657420746861742073686f756c6420626520333262797465730078149337d8a903cff63fe39063c47a50fa211c53f03b9dec98e8ffaf001149f89aefbbe7a363296ce273744a96d2a09cd2a90563375866d5ba6bbaf4a7fe0de5015cf52ebd07ad63de9670b0d9176aadb1e6bce4fd533141af4bc8ec87d7998e442b7021849b12a043d66bff1bf9b47f5b1970a0468d32c6a9fdec1f0b988ca7c9026d20540724e00ff1e07a905ed9339e6f4e07f0a0fffc2c4bbe4f200fa5c77538ab3b1479e2d4666227bd8f79ba9148597347f916b6ce17af2e23a13da7433978" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-claim-secondSign.json b/src/test/resources/transactions/v2-schnorr/htlc-claim-secondSign.json deleted file mode 100644 index e0e45358..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-claim-secondSign.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 9, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "0", - "amount": "0", - "asset": { - "claim": { - "lockTransactionId": "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4", - "unlockSecret": "my secret that should be 32bytes" - } - }, - "signature": "381188e6a3c0da8823ab37cf7562724b3920f4fc8a40cb259ae297bd7237b511cbfdbcb46b7afa319ad1c2d8cc3d8cdc33a437c8b17867777b891d03c036dfb9", - "secondSignature": "e3fba68b18747bc3749adde4bee0472dbdac432e02f5233208cc0e36e1acc5a7a903c8f0140753f1c736160584e07aff74b30dcdbaf66a631a7f84e739198a88", - "id": "c5d6e95a02de4e3ef87acb78bbb64162715e852b805b203f67eee9c31f362f07" - }, - "serialized": "ff02170100000009000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192000000000000000000943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb46d792073656372657420746861742073686f756c642062652033326279746573381188e6a3c0da8823ab37cf7562724b3920f4fc8a40cb259ae297bd7237b511cbfdbcb46b7afa319ad1c2d8cc3d8cdc33a437c8b17867777b891d03c036dfb9e3fba68b18747bc3749adde4bee0472dbdac432e02f5233208cc0e36e1acc5a7a903c8f0140753f1c736160584e07aff74b30dcdbaf66a631a7f84e739198a88" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-claim-sign.json b/src/test/resources/transactions/v2-schnorr/htlc-claim-sign.json deleted file mode 100644 index d3f15010..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-claim-sign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 9, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "0", - "amount": "0", - "asset": { - "claim": { - "lockTransactionId": "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4", - "unlockSecret": "my secret that should be 32bytes" - } - }, - "signature": "381188e6a3c0da8823ab37cf7562724b3920f4fc8a40cb259ae297bd7237b511cbfdbcb46b7afa319ad1c2d8cc3d8cdc33a437c8b17867777b891d03c036dfb9", - "id": "846c5ee8a328376416735da43056d154d41e264564def42fb28b373c0d895c46" - }, - "serialized": "ff02170100000009000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192000000000000000000943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb46d792073656372657420746861742073686f756c642062652033326279746573381188e6a3c0da8823ab37cf7562724b3920f4fc8a40cb259ae297bd7237b511cbfdbcb46b7afa319ad1c2d8cc3d8cdc33a437c8b17867777b891d03c036dfb9" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-lock-multiSign.json b/src/test/resources/transactions/v2-schnorr/htlc-lock-multiSign.json deleted file mode 100644 index 3e419838..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-lock-multiSign.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "10000000", - "amount": "200000000", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1576013417 - } - } - }, - "signatures": [ - "000ac5c8db18c12dfccd043ef19282bc25a8b70a426f90e46de9c0291dff06ee1bbcb21ff0bdc41b9bb43db7182592d87a1441e3a192d79b80c9560fb01de9a69d", - "01671509a3e574eb4d1030f6bca635495d190d3542fa80d78f221e460b29683cda08c177dbf80f6a8cda146221eb86f4b17182d7e5832ce325ce09aeb09c2386b2", - "021cecb71665e99502d7b2cfe7083e3b1ada477bc9fadd2c5b3632c5cfa2666d9b800a2b2127ec6a934e843d2602711bffeb365449e0f2b164f6ff3a372468371a" - ], - "id": "75112f43edb2e9bb43ddb3e9a8cd33e5d245d0f5b11ede76239310b24e413b33" - }, - "serialized": "ff0217010000000800010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01580969800000000000000c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c545401690ef05d170995750207ecaf0ccf251c1265b92ad84f553662000ac5c8db18c12dfccd043ef19282bc25a8b70a426f90e46de9c0291dff06ee1bbcb21ff0bdc41b9bb43db7182592d87a1441e3a192d79b80c9560fb01de9a69d01671509a3e574eb4d1030f6bca635495d190d3542fa80d78f221e460b29683cda08c177dbf80f6a8cda146221eb86f4b17182d7e5832ce325ce09aeb09c2386b2021cecb71665e99502d7b2cfe7083e3b1ada477bc9fadd2c5b3632c5cfa2666d9b800a2b2127ec6a934e843d2602711bffeb365449e0f2b164f6ff3a372468371a" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-lock-secondSign.json b/src/test/resources/transactions/v2-schnorr/htlc-lock-secondSign.json deleted file mode 100644 index aa0ab89f..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-lock-secondSign.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1576013417 - } - } - }, - "signature": "25aaccfdd510e6f75b7ae08b8c12e123bd13aa9a3e0c96f2c937cd323ca578b228b33388c68dac36a785a4f1dfec50e72e71e8f5dd988065df123ad9b338a9af", - "secondSignature": "19bed3897e590331d189c29c583ca7a4de1c3e98f3521e446f56229fb86156c8c2d90277d988faa2ad1af57c5b0b44bdead19cdaea3c2c82576c13745c228745", - "id": "1149a11a651fd95854baf645cd2e22015761db69126bba16f7dbaa8e9eb2a693" - }, - "serialized": "ff02170100000008000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c545401690ef05d170995750207ecaf0ccf251c1265b92ad84f55366225aaccfdd510e6f75b7ae08b8c12e123bd13aa9a3e0c96f2c937cd323ca578b228b33388c68dac36a785a4f1dfec50e72e71e8f5dd988065df123ad9b338a9af19bed3897e590331d189c29c583ca7a4de1c3e98f3521e446f56229fb86156c8c2d90277d988faa2ad1af57c5b0b44bdead19cdaea3c2c82576c13745c228745" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-lock-sign.json b/src/test/resources/transactions/v2-schnorr/htlc-lock-sign.json deleted file mode 100644 index 2494523b..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-lock-sign.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1576013417 - } - } - }, - "signature": "25aaccfdd510e6f75b7ae08b8c12e123bd13aa9a3e0c96f2c937cd323ca578b228b33388c68dac36a785a4f1dfec50e72e71e8f5dd988065df123ad9b338a9af", - "id": "c122a05048c2a385aa3514ce0e704ee22e95512330c28ce37c01c67ab9ad4ad6" - }, - "serialized": "ff02170100000008000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c545401690ef05d170995750207ecaf0ccf251c1265b92ad84f55366225aaccfdd510e6f75b7ae08b8c12e123bd13aa9a3e0c96f2c937cd323ca578b228b33388c68dac36a785a4f1dfec50e72e71e8f5dd988065df123ad9b338a9af" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign.json b/src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign.json deleted file mode 100644 index 05347690..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "10000000", - "amount": "200000000", - "vendorFieldHex": "74686973206973206120746f70207365637265742076656e646f72206669656c64", - "vendorField": "this is a top secret vendor field", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1576013417 - } - } - }, - "signatures": [ - "0042ffe6cdfbcf2de2a1cd47f31ac74a7c04e92246a2bdf625c71d79bc552bdfea69b4f27738f8675d9aec2a77b2e1c27dcd7750523f84e03499d9bf23276a44fe", - "0187653eae1774b5eb2a65a9ca64722c6ec914b780060ec71a38ecc3707e9a970b54605a5b6c59a1c73a3de30a792f7fd821ff3b376c0de553aa946bf41c4ed6f7", - "02e4c1fe7bfca560251b105af65a356f6841ce8d0b74b7121172bce7977aa5f0dc927219ae63c35cb8948eb35ffeefb113deb173d1de66849ab458ed6004c01c06" - ], - "id": "41ee6342c16bcb3b9e24e81b6487830801c75e9dc05eea0053fd219104d7d0c1" - }, - "serialized": "ff0217010000000800010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01580969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c545401690ef05d170995750207ecaf0ccf251c1265b92ad84f5536620042ffe6cdfbcf2de2a1cd47f31ac74a7c04e92246a2bdf625c71d79bc552bdfea69b4f27738f8675d9aec2a77b2e1c27dcd7750523f84e03499d9bf23276a44fe0187653eae1774b5eb2a65a9ca64722c6ec914b780060ec71a38ecc3707e9a970b54605a5b6c59a1c73a3de30a792f7fd821ff3b376c0de553aa946bf41c4ed6f702e4c1fe7bfca560251b105af65a356f6841ce8d0b74b7121172bce7977aa5f0dc927219ae63c35cb8948eb35ffeefb113deb173d1de66849ab458ed6004c01c06" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign.json b/src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign.json deleted file mode 100644 index 9328e2c4..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "vendorFieldHex": "74686973206973206120746f70207365637265742076656e646f72206669656c64", - "vendorField": "this is a top secret vendor field", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1576013417 - } - } - }, - "signature": "60466c0bd6911047b4d450818176a903054ab594622fd37073bc1666ea50ab3f44a5eb304bdfb7b242dba7bf688177752780c0217413c2e231ac11bb7922d558", - "secondSignature": "b92e598e794d58c53fcb79b31c7deb70067eb2d56407eb26d1de31c579db808ae4234c34f35ea590962b72d6bcaddb84cc0dfcc41527917b19323ce2425f6d63", - "id": "1bec3a78ec17a43deece000fee719511c1ab1448e0fdec862bb70e37f12bc711" - }, - "serialized": "ff02170100000008000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c545401690ef05d170995750207ecaf0ccf251c1265b92ad84f55366260466c0bd6911047b4d450818176a903054ab594622fd37073bc1666ea50ab3f44a5eb304bdfb7b242dba7bf688177752780c0217413c2e231ac11bb7922d558b92e598e794d58c53fcb79b31c7deb70067eb2d56407eb26d1de31c579db808ae4234c34f35ea590962b72d6bcaddb84cc0dfcc41527917b19323ce2425f6d63" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-sign.json b/src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-sign.json deleted file mode 100644 index 5620d942..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-lock-with-vendor-field-sign.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 8, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "vendorFieldHex": "74686973206973206120746f70207365637265742076656e646f72206669656c64", - "vendorField": "this is a top secret vendor field", - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "asset": { - "lock": { - "secretHash": "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454", - "expiration": { - "type": 1, - "value": 1576013417 - } - } - }, - "signature": "60466c0bd6911047b4d450818176a903054ab594622fd37073bc1666ea50ab3f44a5eb304bdfb7b242dba7bf688177752780c0217413c2e231ac11bb7922d558", - "id": "cfa6eadb738f4762ad5714558997e978304e69a54a9e226040fbf2989bbc0216" - }, - "serialized": "ff02170100000008000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b000000000f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c545401690ef05d170995750207ecaf0ccf251c1265b92ad84f55366260466c0bd6911047b4d450818176a903054ab594622fd37073bc1666ea50ab3f44a5eb304bdfb7b242dba7bf688177752780c0217413c2e231ac11bb7922d558" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-refund-multiSign.json b/src/test/resources/transactions/v2-schnorr/htlc-refund-multiSign.json deleted file mode 100644 index c5752db9..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-refund-multiSign.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 10, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "0", - "amount": "0", - "asset": { - "refund": { - "lockTransactionId": "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4" - } - }, - "signatures": [ - "0003fbc187eed1d69df28f0583bd1f1252968e5d01e1fe4615e8a146f3b87ca1b60a5fe28973c4756d650f8e878571ca7929747668da76443053d6eb384e3f8480", - "015124b35ac4ba1aacd3842cb51c2d590fca3909dedff016ddeae9f72f0ca4f984d54dc4cd631d7aa0befa67d39e506cba1563bc9cb8b3af5506a08e93f625bca4", - "02309e80689b70901bf1f20aa2b151ec1a1d12da29af829aa0bd59bdb423997f81b6a9479d4211889aee486bb9141dd0cef09433381afc00c9c297115be665c168" - ], - "id": "4971fe722261ca9e6442ae3bba7758a0be3572c80d4fc1607f30ffda629f9dad" - }, - "serialized": "ff0217010000000a00010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015000000000000000000943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb40003fbc187eed1d69df28f0583bd1f1252968e5d01e1fe4615e8a146f3b87ca1b60a5fe28973c4756d650f8e878571ca7929747668da76443053d6eb384e3f8480015124b35ac4ba1aacd3842cb51c2d590fca3909dedff016ddeae9f72f0ca4f984d54dc4cd631d7aa0befa67d39e506cba1563bc9cb8b3af5506a08e93f625bca402309e80689b70901bf1f20aa2b151ec1a1d12da29af829aa0bd59bdb423997f81b6a9479d4211889aee486bb9141dd0cef09433381afc00c9c297115be665c168" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-refund-secondSign.json b/src/test/resources/transactions/v2-schnorr/htlc-refund-secondSign.json deleted file mode 100644 index de3f43d8..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-refund-secondSign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 10, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "0", - "amount": "0", - "asset": { - "refund": { - "lockTransactionId": "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4" - } - }, - "signature": "16d9ef1dceb0cbb105a45af6bdde9439055f07197643f9e2837312463330fd02ec7b13d1242becfe333c1b8ab2ea91c0c8240390d86f0fb0f6cdc22ec6ac64f1", - "secondSignature": "f024e9682bdc8b643c43a963c376fb989c0015fe8ee446d69ff231ccb3b5fe7be7b7566f111a00768c9b001fc4c0f571d2b1c9df61a5a6d3b1918df20438e053", - "id": "2a75087a3e07f73e59e4c7816e082ecb31409c79bff8113544717f600a9defdc" - }, - "serialized": "ff0217010000000a000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192000000000000000000943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb416d9ef1dceb0cbb105a45af6bdde9439055f07197643f9e2837312463330fd02ec7b13d1242becfe333c1b8ab2ea91c0c8240390d86f0fb0f6cdc22ec6ac64f1f024e9682bdc8b643c43a963c376fb989c0015fe8ee446d69ff231ccb3b5fe7be7b7566f111a00768c9b001fc4c0f571d2b1c9df61a5a6d3b1918df20438e053" -} diff --git a/src/test/resources/transactions/v2-schnorr/htlc-refund-sign.json b/src/test/resources/transactions/v2-schnorr/htlc-refund-sign.json deleted file mode 100644 index 58b9530c..00000000 --- a/src/test/resources/transactions/v2-schnorr/htlc-refund-sign.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 10, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "0", - "amount": "0", - "asset": { - "refund": { - "lockTransactionId": "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4" - } - }, - "signature": "16d9ef1dceb0cbb105a45af6bdde9439055f07197643f9e2837312463330fd02ec7b13d1242becfe333c1b8ab2ea91c0c8240390d86f0fb0f6cdc22ec6ac64f1", - "id": "9356aa730990a2ea8e9871ffa65800f34ef1a4bec3215d89c950e72d82a34e91" - }, - "serialized": "ff0217010000000a000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192000000000000000000943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb416d9ef1dceb0cbb105a45af6bdde9439055f07197643f9e2837312463330fd02ec7b13d1242becfe333c1b8ab2ea91c0c8240390d86f0fb0f6cdc22ec6ac64f1" -} diff --git a/src/test/resources/transactions/v2-schnorr/ipfs-multiSign.json b/src/test/resources/transactions/v2-schnorr/ipfs-multiSign.json deleted file mode 100644 index 71d7d50d..00000000 --- a/src/test/resources/transactions/v2-schnorr/ipfs-multiSign.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 5, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "500000000", - "amount": "0", - "asset": { - "ipfs": "QmR45FmbVVrixReBwJkhEKde2qwHYaQzGxu4ZoDeswuF9w" - }, - "signatures": [ - "006323832cc6627fdafef14f6487224947b50fb67ecf39d508cae53a504e38d0616cbe03c814501124236c2812b0a62463d1cfcdaea4db1368732ce9543e94573b", - "015698acde626fe38cd5d374e225ac0b0a8fc60debcf4d389e73f227f13c4768f4168016745619addd5474378de08e3534e1ffdc01b857c1b31abc4c6fa8a85867", - "02da0fe52c86505c6cf17ba7e9a0402d7cfef1574d1938a2c55adfc779f23e7795a4ee81515a1e8150824dededafbb2ecc3a067b697a3aac5b0a4f564304b699be" - ], - "id": "533ad038573215683197ed795f49020efb5a495ce35a87cda2262a891aaa0650" - }, - "serialized": "ff0217010000000500010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f0150065cd1d000000000012202853f0f11ab91d73b73a2a86606103f45dd469ad2e89ec6f9a25febe8758d3fe006323832cc6627fdafef14f6487224947b50fb67ecf39d508cae53a504e38d0616cbe03c814501124236c2812b0a62463d1cfcdaea4db1368732ce9543e94573b015698acde626fe38cd5d374e225ac0b0a8fc60debcf4d389e73f227f13c4768f4168016745619addd5474378de08e3534e1ffdc01b857c1b31abc4c6fa8a8586702da0fe52c86505c6cf17ba7e9a0402d7cfef1574d1938a2c55adfc779f23e7795a4ee81515a1e8150824dededafbb2ecc3a067b697a3aac5b0a4f564304b699be" -} diff --git a/src/test/resources/transactions/v2-schnorr/ipfs-secondSign.json b/src/test/resources/transactions/v2-schnorr/ipfs-secondSign.json deleted file mode 100644 index 2f69882d..00000000 --- a/src/test/resources/transactions/v2-schnorr/ipfs-secondSign.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 5, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "500000000", - "amount": "0", - "asset": { - "ipfs": "QmR45FmbVVrixReBwJkhEKde2qwHYaQzGxu4ZoDeswuF9w" - }, - "signature": "0b6e81b123de99e953d3073a8760d3213ab5f5cf512e65a2dd73aebb410966d8fbc59e775deb4f23c51be0847402b5e1d4ee68732b3e6d8e8914d259d7e373eb", - "secondSignature": "336bcec35df44c82b60b8b7acf1c71bfe554bfc2d1d98aefa3e268eaabcd5fd60288b73d32e1f8b653308df72653cb12631a313de68398b98d7479ae6722dc2e", - "id": "673581d99e94c16766ff971f12332c93c334d684a1e847a9b30c5359c5924ac3" - }, - "serialized": "ff02170100000005000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920065cd1d000000000012202853f0f11ab91d73b73a2a86606103f45dd469ad2e89ec6f9a25febe8758d3fe0b6e81b123de99e953d3073a8760d3213ab5f5cf512e65a2dd73aebb410966d8fbc59e775deb4f23c51be0847402b5e1d4ee68732b3e6d8e8914d259d7e373eb336bcec35df44c82b60b8b7acf1c71bfe554bfc2d1d98aefa3e268eaabcd5fd60288b73d32e1f8b653308df72653cb12631a313de68398b98d7479ae6722dc2e" -} diff --git a/src/test/resources/transactions/v2-schnorr/ipfs-sign.json b/src/test/resources/transactions/v2-schnorr/ipfs-sign.json deleted file mode 100644 index ed807920..00000000 --- a/src/test/resources/transactions/v2-schnorr/ipfs-sign.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 5, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "500000000", - "amount": "0", - "asset": { - "ipfs": "QmR45FmbVVrixReBwJkhEKde2qwHYaQzGxu4ZoDeswuF9w" - }, - "signature": "0b6e81b123de99e953d3073a8760d3213ab5f5cf512e65a2dd73aebb410966d8fbc59e775deb4f23c51be0847402b5e1d4ee68732b3e6d8e8914d259d7e373eb", - "id": "818228ce634b46c488f3b2df8fd02bd50331ebdedb44df5b9b11b97b01e9fb36" - }, - "serialized": "ff02170100000005000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920065cd1d000000000012202853f0f11ab91d73b73a2a86606103f45dd469ad2e89ec6f9a25febe8758d3fe0b6e81b123de99e953d3073a8760d3213ab5f5cf512e65a2dd73aebb410966d8fbc59e775deb4f23c51be0847402b5e1d4ee68732b3e6d8e8914d259d7e373eb" -} diff --git a/src/test/resources/transactions/v2-schnorr/multi-payment-multiSign.json b/src/test/resources/transactions/v2-schnorr/multi-payment-multiSign.json deleted file mode 100644 index 0c804f24..00000000 --- a/src/test/resources/transactions/v2-schnorr/multi-payment-multiSign.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "10000000", - "amount": "0", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signatures": [ - "008aa7cb571fe16e7ccd22f28598f937530f8629faf042a3979e7f7f05099b9bd17bf944c1297e57997c651b5b444457e6647a4a5fd70a74ba6085ff692d1a9cc4", - "0114349859cde10408ff160a13ce746cc0114dc16832d0054dd668819d9ca30876658a680efe06e90ad20bcf9740840fff900d95683313de7d75f5d53f049dcd4d", - "02ea98df8dd3ad2f68b45e9788969de7cb1d405f59ef63e63e93903b9e1436a26e320944f9d4d03dd8246236c978f80478c11861000c98eb211f0945861461aaf1" - ], - "id": "abb2778cd8fa9a689bf87ef4ab303233758e298f135b33a6bb5d50323fed58f2" - }, - "serialized": "ff0217010000000600010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f0158096980000000000000200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f041008aa7cb571fe16e7ccd22f28598f937530f8629faf042a3979e7f7f05099b9bd17bf944c1297e57997c651b5b444457e6647a4a5fd70a74ba6085ff692d1a9cc40114349859cde10408ff160a13ce746cc0114dc16832d0054dd668819d9ca30876658a680efe06e90ad20bcf9740840fff900d95683313de7d75f5d53f049dcd4d02ea98df8dd3ad2f68b45e9788969de7cb1d405f59ef63e63e93903b9e1436a26e320944f9d4d03dd8246236c978f80478c11861000c98eb211f0945861461aaf1" -} diff --git a/src/test/resources/transactions/v2-schnorr/multi-payment-secondSign.json b/src/test/resources/transactions/v2-schnorr/multi-payment-secondSign.json deleted file mode 100644 index 657e801a..00000000 --- a/src/test/resources/transactions/v2-schnorr/multi-payment-secondSign.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "0", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signature": "672e89e66a9c5d7d95c21ccd07a89a111f02823146c06f14689d2cf1efd645fb648258fcf2280486d2cae19f391796d72145d2a8e6f261e887e34cd1998bdb65", - "secondSignature": "cd0411dcb9300b7a56059c54d637f7bd38ce79c65cc7af6629c06d130fa09e6ca1cf1af6080f4e275378376c3ef6d7e853f64b52d29f2a73312ebec0ce5ff782", - "id": "395e9215094a74dc64478f8bb5216277caa2a20555a92947764d92eb0ea1e306" - }, - "serialized": "ff02170100000006000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1928096980000000000000200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f041672e89e66a9c5d7d95c21ccd07a89a111f02823146c06f14689d2cf1efd645fb648258fcf2280486d2cae19f391796d72145d2a8e6f261e887e34cd1998bdb65cd0411dcb9300b7a56059c54d637f7bd38ce79c65cc7af6629c06d130fa09e6ca1cf1af6080f4e275378376c3ef6d7e853f64b52d29f2a73312ebec0ce5ff782" -} diff --git a/src/test/resources/transactions/v2-schnorr/multi-payment-sign.json b/src/test/resources/transactions/v2-schnorr/multi-payment-sign.json deleted file mode 100644 index f19d1ef4..00000000 --- a/src/test/resources/transactions/v2-schnorr/multi-payment-sign.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "0", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signature": "672e89e66a9c5d7d95c21ccd07a89a111f02823146c06f14689d2cf1efd645fb648258fcf2280486d2cae19f391796d72145d2a8e6f261e887e34cd1998bdb65", - "id": "e8c7293d428048f8678dc6c88cb8b32bd49c8ae9b02018297c1889d9bd33ba8d" - }, - "serialized": "ff02170100000006000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1928096980000000000000200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f041672e89e66a9c5d7d95c21ccd07a89a111f02823146c06f14689d2cf1efd645fb648258fcf2280486d2cae19f391796d72145d2a8e6f261e887e34cd1998bdb65" -} diff --git a/src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign.json b/src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign.json deleted file mode 100644 index 46e27522..00000000 --- a/src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "10000000", - "amount": "0", - "vendorFieldHex": "74686973206973206120746f70207365637265742076656e646f72206669656c64", - "vendorField": "this is a top secret vendor field", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signatures": [ - "000557aab4ee58e668cf631fe9755222aaec133726488737b1e321c1322d00f7b5aaf2dff0488e5e10d1804d370dcb1d31c751c6d14d2e61d21187e8b7e2fe451d", - "016151423b2e79d2d87b21dc2c73bfb0cd700c96811a71f89b8474df3862cef847ab9229975175cc4fdae0ef9d3b25ba6190004d3752eb375a54a708b42fd8b518", - "02378ff87ec84f79e14ae044755ba05b403b467d5c4d0b673a03c67ef75fad56223029c9d68959e2add8c33ec8b43c9a99e038dada6d4c4b412a471ee525730a08" - ], - "id": "3534d43c391e0c0f95cbf7dd91a1d2dfe068e65d999f0e29a28dee212619a98a" - }, - "serialized": "ff0217010000000600010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01580969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c640200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f041000557aab4ee58e668cf631fe9755222aaec133726488737b1e321c1322d00f7b5aaf2dff0488e5e10d1804d370dcb1d31c751c6d14d2e61d21187e8b7e2fe451d016151423b2e79d2d87b21dc2c73bfb0cd700c96811a71f89b8474df3862cef847ab9229975175cc4fdae0ef9d3b25ba6190004d3752eb375a54a708b42fd8b51802378ff87ec84f79e14ae044755ba05b403b467d5c4d0b673a03c67ef75fad56223029c9d68959e2add8c33ec8b43c9a99e038dada6d4c4b412a471ee525730a08" -} diff --git a/src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign.json b/src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign.json deleted file mode 100644 index 4abe9790..00000000 --- a/src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "0", - "vendorFieldHex": "74686973206973206120746f70207365637265742076656e646f72206669656c64", - "vendorField": "this is a top secret vendor field", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signature": "db16e5cf3e3fe1334c070518b8a0389df2a8ac04f8604c8d8e5d7427e2c68cac8203db61d03faafaf7077ef2e5b4b0f85e5f400901fb6d367631ee141140e27c", - "secondSignature": "c4b9cb2ceeb0fd3e68e339a4310e89db0481d267d32986b7929344fd2537f13212bea71ab0ec35dc8684a04e93317131280763eeabc1b316c832efdfe414c042", - "id": "95bea3da0b04f043313b7b9b247a6138d61a4af134cf63702310776b6045f325" - }, - "serialized": "ff02170100000006000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c640200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f041db16e5cf3e3fe1334c070518b8a0389df2a8ac04f8604c8d8e5d7427e2c68cac8203db61d03faafaf7077ef2e5b4b0f85e5f400901fb6d367631ee141140e27cc4b9cb2ceeb0fd3e68e339a4310e89db0481d267d32986b7929344fd2537f13212bea71ab0ec35dc8684a04e93317131280763eeabc1b316c832efdfe414c042" -} diff --git a/src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-sign.json b/src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-sign.json deleted file mode 100644 index 180210ac..00000000 --- a/src/test/resources/transactions/v2-schnorr/multi-payment-with-vendor-field-sign.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 6, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "0", - "vendorFieldHex": "74686973206973206120746f70207365637265742076656e646f72206669656c64", - "vendorField": "this is a top secret vendor field", - "asset": { - "payments": [ - { - "amount": "1", - "recipientId": "AHXtmB84sTZ9Zd35h9Y1vfFvPE2Xzqj8ri" - }, - { - "amount": "2", - "recipientId": "AZFEPTWnn2Sn8wDZgCRF8ohwKkrmk2AZi1" - } - ] - }, - "signature": "db16e5cf3e3fe1334c070518b8a0389df2a8ac04f8604c8d8e5d7427e2c68cac8203db61d03faafaf7077ef2e5b4b0f85e5f400901fb6d367631ee141140e27c", - "id": "8ea5a86a2a7847335a11d5f0ed5e2dcd26539e2caf676478b48d74a864229776" - }, - "serialized": "ff02170100000006000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c640200010000000000000017134b5be4b327ddf9c2bb47fec8a1a44189e90f74020000000000000017bfa6aec83cf1bd03a0cab9f35c85ff51a3e9f041db16e5cf3e3fe1334c070518b8a0389df2a8ac04f8604c8d8e5d7427e2c68cac8203db61d03faafaf7077ef2e5b4b0f85e5f400901fb6d367631ee141140e27c" -} diff --git a/src/test/resources/transactions/v2-schnorr/multi-signature-registration.json b/src/test/resources/transactions/v2-schnorr/multi-signature-registration.json deleted file mode 100644 index 1c78d9a9..00000000 --- a/src/test/resources/transactions/v2-schnorr/multi-signature-registration.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 4, - "nonce": "1", - "senderPublicKey": "0205d9bbe71c343ac9a6a83a4344fd404c3534fc7349827097d0835d160bc2b896", - "fee": "2000000000", - "amount": "0", - "asset": { - "multiSignature": { - "publicKeys": [ - "0205d9bbe71c343ac9a6a83a4344fd404c3534fc7349827097d0835d160bc2b896", - "03df0a1eb42d99b5de395cead145ba1ec2ea837be308c7ce3a4e8018b7efc7fdb8", - "03860d76b1df09659ac282cea3da5bd84fc45729f348a4a8e5f802186be72dc17f" - ], - "min": 2 - } - }, - "signature": "f5e9859c955bf8917b308ea21c88daf58661686c2017e476dcf735ad7f00aebf8e6effda3fe99e5f33f6007db7db9c9155796d9b5d31c53bd6156364a6a765d0", - "signatures": [ - "0064900cb2cc3db6ca9c7e3bd363b322cdc4a39e051f655e9867935e1bb856b6dcce52845c031c690808f40340bc827bbaacd7b04bceff866cb0d386ab84715174", - "01dd363ccc101a958bded1a5db1c08f13283fc7cee53da93dfe00785eb406512467ff8e445f8ad843744ac4179f30f942645dfd5bdf5f2bfc344ad02393053880a", - "02d0012f035dc3fd54173c83d40217914653488fe9ce592dca34234163181d255281f2be7033725cfc4a6786509e7fabbaf0be8cf50882fc7b66fe94f259fd004e" - ], - "id": "c868aad20165a336c35e324378f0c12008d18af4c1025291efcb7539c7c917f0" - }, - "serialized": "ff021701000000040001000000000000000205d9bbe71c343ac9a6a83a4344fd404c3534fc7349827097d0835d160bc2b89600943577000000000002030205d9bbe71c343ac9a6a83a4344fd404c3534fc7349827097d0835d160bc2b89603df0a1eb42d99b5de395cead145ba1ec2ea837be308c7ce3a4e8018b7efc7fdb803860d76b1df09659ac282cea3da5bd84fc45729f348a4a8e5f802186be72dc17ff5e9859c955bf8917b308ea21c88daf58661686c2017e476dcf735ad7f00aebf8e6effda3fe99e5f33f6007db7db9c9155796d9b5d31c53bd6156364a6a765d00064900cb2cc3db6ca9c7e3bd363b322cdc4a39e051f655e9867935e1bb856b6dcce52845c031c690808f40340bc827bbaacd7b04bceff866cb0d386ab8471517401dd363ccc101a958bded1a5db1c08f13283fc7cee53da93dfe00785eb406512467ff8e445f8ad843744ac4179f30f942645dfd5bdf5f2bfc344ad02393053880a02d0012f035dc3fd54173c83d40217914653488fe9ce592dca34234163181d255281f2be7033725cfc4a6786509e7fabbaf0be8cf50882fc7b66fe94f259fd004e" -} diff --git a/src/test/resources/transactions/v2-schnorr/second-signature-registration.json b/src/test/resources/transactions/v2-schnorr/second-signature-registration.json deleted file mode 100644 index 907b431c..00000000 --- a/src/test/resources/transactions/v2-schnorr/second-signature-registration.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 1, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "500000000", - "amount": "0", - "asset": { - "signature": { - "publicKey": "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609" - } - }, - "signature": "f9a1e2244c8318e8be85482fc02659e5c1775d246d73d5d0699ae4a1d5e3a3e84f9dcf68ee015f943d2a82eb829f35abd7901279761d96f6b43431520e955c67", - "id": "173a3230159b45d772b2e0348f42af53913bf3e376397f29b8e0bda290badbe4" - }, - "serialized": "ff02170100000001000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed1920065cd1d000000000003699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609f9a1e2244c8318e8be85482fc02659e5c1775d246d73d5d0699ae4a1d5e3a3e84f9dcf68ee015f943d2a82eb829f35abd7901279761d96f6b43431520e955c67" -} diff --git a/src/test/resources/transactions/v2-schnorr/transfer-multiSign.json b/src/test/resources/transactions/v2-schnorr/transfer-multiSign.json deleted file mode 100644 index 819db1f5..00000000 --- a/src/test/resources/transactions/v2-schnorr/transfer-multiSign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "10000000", - "amount": "200000000", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signatures": [ - "00c01c44bf33bea20a74d5acc12c5d6aafe82240f3571121382b77c871f4b33d6da2b62fdc6ca2cc6bc583abb2a69e7975be29e8d80a59c52bcff8d54514cf999e", - "01830a2e319f2070f3519bc22c2d449acdb7691bf9dd25e3649a72ac843e08ce26e0b87e30e65b73f853cf8e375dbc495cc75c6fd199bf4b15327bf8c5ec4bfac5", - "0292c299b739f0cb5e36133d85f51fff2fcc7745e8af4d0778908560c0874e3f2303e0436eabce1c09d88efab0004e61c5d6e47768aa8d2ab0cb9f14d523a38308" - ], - "id": "a7245dcc720d3e133035cff04b4a14dbc0f8ff889c703c89c99f2f03e8f3c59d" - }, - "serialized": "ff0217010000000000010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01580969800000000000000c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f55366200c01c44bf33bea20a74d5acc12c5d6aafe82240f3571121382b77c871f4b33d6da2b62fdc6ca2cc6bc583abb2a69e7975be29e8d80a59c52bcff8d54514cf999e01830a2e319f2070f3519bc22c2d449acdb7691bf9dd25e3649a72ac843e08ce26e0b87e30e65b73f853cf8e375dbc495cc75c6fd199bf4b15327bf8c5ec4bfac50292c299b739f0cb5e36133d85f51fff2fcc7745e8af4d0778908560c0874e3f2303e0436eabce1c09d88efab0004e61c5d6e47768aa8d2ab0cb9f14d523a38308" -} diff --git a/src/test/resources/transactions/v2-schnorr/transfer-secondSign.json b/src/test/resources/transactions/v2-schnorr/transfer-secondSign.json deleted file mode 100644 index 611941c4..00000000 --- a/src/test/resources/transactions/v2-schnorr/transfer-secondSign.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signature": "136c29d921b58ae3194020b82e9808f9cd54f7178cb34678f570f28226b8e56ba0ad318297a3bacbb37ab22ddaa5dbf1901cda3ec2d2bca5ce98d6407839ab9b", - "secondSignature": "02dd94f611e300ad77147d808a34e942b379c5468760d8605adc0304400a2578a2039468b844f30ad1f0515f9cce33855791296117bfe8ef3caa664152644fd6", - "id": "be148ab83b75c199f9778f8963814a641a6ee937b6dd5b294082fbf7def94a45" - }, - "serialized": "ff02170100000000000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f553662136c29d921b58ae3194020b82e9808f9cd54f7178cb34678f570f28226b8e56ba0ad318297a3bacbb37ab22ddaa5dbf1901cda3ec2d2bca5ce98d6407839ab9b02dd94f611e300ad77147d808a34e942b379c5468760d8605adc0304400a2578a2039468b844f30ad1f0515f9cce33855791296117bfe8ef3caa664152644fd6" -} diff --git a/src/test/resources/transactions/v2-schnorr/transfer-sign.json b/src/test/resources/transactions/v2-schnorr/transfer-sign.json deleted file mode 100644 index d972fccc..00000000 --- a/src/test/resources/transactions/v2-schnorr/transfer-sign.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signature": "136c29d921b58ae3194020b82e9808f9cd54f7178cb34678f570f28226b8e56ba0ad318297a3bacbb37ab22ddaa5dbf1901cda3ec2d2bca5ce98d6407839ab9b", - "id": "129517023bd895b682bbb38b1d1f99e9222bd487899c843da22d8572b0fb52a8" - }, - "serialized": "ff02170100000000000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000000000c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f553662136c29d921b58ae3194020b82e9808f9cd54f7178cb34678f570f28226b8e56ba0ad318297a3bacbb37ab22ddaa5dbf1901cda3ec2d2bca5ce98d6407839ab9b" -} diff --git a/src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-multiSign.json b/src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-multiSign.json deleted file mode 100644 index bf23eaa4..00000000 --- a/src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-multiSign.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "10000000", - "amount": "200000000", - "vendorFieldHex": "74686973206973206120746f70207365637265742076656e646f72206669656c64", - "vendorField": "this is a top secret vendor field", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signatures": [ - "0033194adf162a4e3039bf1fbb96d1edd9f0103d54935c1fac56a0382fa6269b715d5d79577a06e334e0836941035954106b1a689d079a69f94462d4df58a8749d", - "015e34212ac4ff97b04510d48e15f10d3e7b7a4f15c739fd07f598720402f3bb69ccf828417ff96cd97a86de6d710d21ad560145d3abdc8739fb7f6f2d48d490c7", - "0287ff743ca6d45c262c89c738dc2271fca2cbab7cbf429b8cbcda6cc31471425d48a2db0c4b4554088e3692e8d442f9d6ca07cd20971ab301e0902c3a4bae4727" - ], - "id": "35d79432c76468deb3ca57f77890c346a92836666aa50fcfa11b3e10c064f8cd" - }, - "serialized": "ff0217010000000000010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01580969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f5536620033194adf162a4e3039bf1fbb96d1edd9f0103d54935c1fac56a0382fa6269b715d5d79577a06e334e0836941035954106b1a689d079a69f94462d4df58a8749d015e34212ac4ff97b04510d48e15f10d3e7b7a4f15c739fd07f598720402f3bb69ccf828417ff96cd97a86de6d710d21ad560145d3abdc8739fb7f6f2d48d490c70287ff743ca6d45c262c89c738dc2271fca2cbab7cbf429b8cbcda6cc31471425d48a2db0c4b4554088e3692e8d442f9d6ca07cd20971ab301e0902c3a4bae4727" -} diff --git a/src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-secondSign.json b/src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-secondSign.json deleted file mode 100644 index ffe18ac0..00000000 --- a/src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-secondSign.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "vendorFieldHex": "74686973206973206120746f70207365637265742076656e646f72206669656c64", - "vendorField": "this is a top secret vendor field", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signature": "b68dd255857f4020ad933f5ae48b9471093255c80e55e59f6fb73884aa835155ba87bf432d0af2826ca20368987dff65adfa723228145a73649a05ae1be58bf4", - "secondSignature": "2afdf98e6830057040688f528f76a564f007839a4344d14c82371a546a506e966196c5f2532934604e5043cbdea34292834550f678749dd090e3977ac8e9e94d", - "id": "c7338d04b372569acd9bfe4660d90c43ebb775079791ba02e10ebdf729230675" - }, - "serialized": "ff02170100000000000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f553662b68dd255857f4020ad933f5ae48b9471093255c80e55e59f6fb73884aa835155ba87bf432d0af2826ca20368987dff65adfa723228145a73649a05ae1be58bf42afdf98e6830057040688f528f76a564f007839a4344d14c82371a546a506e966196c5f2532934604e5043cbdea34292834550f678749dd090e3977ac8e9e94d" -} diff --git a/src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-sign.json b/src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-sign.json deleted file mode 100644 index a03c4a23..00000000 --- a/src/test/resources/transactions/v2-schnorr/transfer-with-vendor-field-sign.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 0, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "10000000", - "amount": "200000000", - "vendorFieldHex": "74686973206973206120746f70207365637265742076656e646f72206669656c64", - "vendorField": "this is a top secret vendor field", - "expiration": 0, - "recipientId": "AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC", - "signature": "b68dd255857f4020ad933f5ae48b9471093255c80e55e59f6fb73884aa835155ba87bf432d0af2826ca20368987dff65adfa723228145a73649a05ae1be58bf4", - "id": "bb5bffa118d389de05ea13d3a4c0948a83ae10320197c8d513963d501217f709" - }, - "serialized": "ff02170100000000000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19280969800000000002174686973206973206120746f70207365637265742076656e646f72206669656c6400c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f553662b68dd255857f4020ad933f5ae48b9471093255c80e55e59f6fb73884aa835155ba87bf432d0af2826ca20368987dff65adfa723228145a73649a05ae1be58bf4" -} diff --git a/src/test/resources/transactions/v2-schnorr/unvote-multiSign.json b/src/test/resources/transactions/v2-schnorr/unvote-multiSign.json deleted file mode 100644 index ec6b9ae4..00000000 --- a/src/test/resources/transactions/v2-schnorr/unvote-multiSign.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "-022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signatures": [ - "0089008266deed566dd482cd6c779eb993a851e2749ccd8ae86802eda6cdd6bde52395096b6015be3d040276db0eab3698a469f6d12ff0de937baf2f8bfad377be", - "019a333d9acf61ce3646fbf1aa043c3c018385db7c72a62ba7416582ee0c63bb4ea80a2aec6e7ecbf3b48d8178559663300b042287b867a7bc3d1ec7d2f61f3fb6", - "0200849267fbdec685a90d9d74fa90387da5c106bb73c0220e73e25b185b5a6382925cd49c140a1b90f33da3a6881d2af27ddf241c5c060e3a09141e2a3d156cc9" - ], - "id": "7ebee4a608a5912a042f5678d38fe6425d466ae74db6b9d86ccb3d18ac47a2b0" - }, - "serialized": "ff0217010000000300010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01500e1f50500000000000100022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d0089008266deed566dd482cd6c779eb993a851e2749ccd8ae86802eda6cdd6bde52395096b6015be3d040276db0eab3698a469f6d12ff0de937baf2f8bfad377be019a333d9acf61ce3646fbf1aa043c3c018385db7c72a62ba7416582ee0c63bb4ea80a2aec6e7ecbf3b48d8178559663300b042287b867a7bc3d1ec7d2f61f3fb60200849267fbdec685a90d9d74fa90387da5c106bb73c0220e73e25b185b5a6382925cd49c140a1b90f33da3a6881d2af27ddf241c5c060e3a09141e2a3d156cc9" -} diff --git a/src/test/resources/transactions/v2-schnorr/unvote-secondSign.json b/src/test/resources/transactions/v2-schnorr/unvote-secondSign.json deleted file mode 100644 index dfeffdfc..00000000 --- a/src/test/resources/transactions/v2-schnorr/unvote-secondSign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "-022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "5975454d700b1f8219b183693e60435a0c57d76017628293f7a6e0ea114ae2eae398b9b2e7c2105d3ac895b6a6d8e15edea00a3cbc1f68aa3236ae3fd7512bb6", - "secondSignature": "c3b4c5df7ef04cda2159b3b7ecb0f018c343a4d7b2147c1c783160f2931fe74875066b7d1f88bd6718da69ca840820c55238f24515522a61ac696df7125f0238", - "id": "2e27ae13501399a36280b2e1627c54a8d2e65c41b5c832d9095c64113c4b190e" - }, - "serialized": "ff02170100000003000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000100022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d5975454d700b1f8219b183693e60435a0c57d76017628293f7a6e0ea114ae2eae398b9b2e7c2105d3ac895b6a6d8e15edea00a3cbc1f68aa3236ae3fd7512bb6c3b4c5df7ef04cda2159b3b7ecb0f018c343a4d7b2147c1c783160f2931fe74875066b7d1f88bd6718da69ca840820c55238f24515522a61ac696df7125f0238" -} diff --git a/src/test/resources/transactions/v2-schnorr/unvote-sign.json b/src/test/resources/transactions/v2-schnorr/unvote-sign.json deleted file mode 100644 index 2a8eae30..00000000 --- a/src/test/resources/transactions/v2-schnorr/unvote-sign.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "-022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "5975454d700b1f8219b183693e60435a0c57d76017628293f7a6e0ea114ae2eae398b9b2e7c2105d3ac895b6a6d8e15edea00a3cbc1f68aa3236ae3fd7512bb6", - "id": "45f3e7d9a921dde539c162672a7b84a2ac6aec1a41889902a1464cd374ea6bac" - }, - "serialized": "ff02170100000003000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000100022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d5975454d700b1f8219b183693e60435a0c57d76017628293f7a6e0ea114ae2eae398b9b2e7c2105d3ac895b6a6d8e15edea00a3cbc1f68aa3236ae3fd7512bb6" -} diff --git a/src/test/resources/transactions/v2-schnorr/vote-multiSign.json b/src/test/resources/transactions/v2-schnorr/vote-multiSign.json deleted file mode 100644 index ed7ebd68..00000000 --- a/src/test/resources/transactions/v2-schnorr/vote-multiSign.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "03fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f015", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "+022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signatures": [ - "003c728aa533024b0d36386652ba80bdccdd70d71f1cfbe63739672975f8562abfe87b5d9ec82a5cb741c58511b08ede21e8c6af640de6c43d4f7bff039c61cb79", - "013c342d6e892ff5d5410b825d5781137a158350e7139cf450b327accacee9d6b32304654679c52f8bfa472a8739f249c427b3ebc8c2cc9f3c1c15a724466797bf", - "0258a19937052d6eb6c76c09dafa711c766a97de7bd897983275b27028133ba816b60a45cae12e00f4a599b9b8dc9530c25a5b134841f8bb60e28cb81b30bc6eed" - ], - "id": "320ec28539f10b06ca02834503ac818fb0a299119aadfa48849707ed5ace56e5" - }, - "serialized": "ff0217010000000300010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01500e1f50500000000000101022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d003c728aa533024b0d36386652ba80bdccdd70d71f1cfbe63739672975f8562abfe87b5d9ec82a5cb741c58511b08ede21e8c6af640de6c43d4f7bff039c61cb79013c342d6e892ff5d5410b825d5781137a158350e7139cf450b327accacee9d6b32304654679c52f8bfa472a8739f249c427b3ebc8c2cc9f3c1c15a724466797bf0258a19937052d6eb6c76c09dafa711c766a97de7bd897983275b27028133ba816b60a45cae12e00f4a599b9b8dc9530c25a5b134841f8bb60e28cb81b30bc6eed" -} diff --git a/src/test/resources/transactions/v2-schnorr/vote-secondSign.json b/src/test/resources/transactions/v2-schnorr/vote-secondSign.json deleted file mode 100644 index e0099cf4..00000000 --- a/src/test/resources/transactions/v2-schnorr/vote-secondSign.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "+022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "86007f8e6a982bc271ec063c20f158734f0bc1e23e0e1abf9edeaa208b4810fa1d466171bba79a5c00b0a4c698728f68aa0748d98613cac247c014ee84a6fc41", - "secondSignature": "3e7a3d285505347bff1628db37cb66054b4ec8ea28a98f6bfa14d25d2450995fac8ecedc1c7d4d7f2bfd6b35f8a466a5328337b1713b1b83a10f2840d9c7543a", - "id": "9ba13df859dbe551798367fbe36945e02f307aa91b51cb779a8669cb1542a1bb" - }, - "serialized": "ff02170100000003000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000101022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d86007f8e6a982bc271ec063c20f158734f0bc1e23e0e1abf9edeaa208b4810fa1d466171bba79a5c00b0a4c698728f68aa0748d98613cac247c014ee84a6fc413e7a3d285505347bff1628db37cb66054b4ec8ea28a98f6bfa14d25d2450995fac8ecedc1c7d4d7f2bfd6b35f8a466a5328337b1713b1b83a10f2840d9c7543a" -} diff --git a/src/test/resources/transactions/v2-schnorr/vote-sign.json b/src/test/resources/transactions/v2-schnorr/vote-sign.json deleted file mode 100644 index 892a5403..00000000 --- a/src/test/resources/transactions/v2-schnorr/vote-sign.json +++ /dev/null @@ -1,21 +0,0 @@ - -{ - "data": { - "version": 2, - "network": 23, - "typeGroup": 1, - "type": 3, - "nonce": "1", - "senderPublicKey": "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192", - "fee": "100000000", - "amount": "0", - "asset": { - "votes": [ - "+022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d" - ] - }, - "signature": "86007f8e6a982bc271ec063c20f158734f0bc1e23e0e1abf9edeaa208b4810fa1d466171bba79a5c00b0a4c698728f68aa0748d98613cac247c014ee84a6fc41", - "id": "2c5d71028607674411c8e37e316a015eccbeb9ba486fddfbd393dc421540a90a" - }, - "serialized": "ff02170100000003000100000000000000034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed19200e1f50500000000000101022cca9529ec97a772156c152a00aad155ee6708243e65c9d211a589cb5d43234d86007f8e6a982bc271ec063c20f158734f0bc1e23e0e1abf9edeaa208b4810fa1d466171bba79a5c00b0a4c698728f68aa0748d98613cac247c014ee84a6fc41" -} diff --git a/src/test/resources/transactions/validator_registration/validator-registration-multi-sign.json b/src/test/resources/transactions/validator_registration/validator-registration-multi-sign.json new file mode 100644 index 00000000..7e7f3fc8 --- /dev/null +++ b/src/test/resources/transactions/validator_registration/validator-registration-multi-sign.json @@ -0,0 +1,23 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 2, + "nonce": "0", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "2500000000", + "amount": "0", + "asset": { + "validatorPublicKey": "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118" + }, + "signature": "0604c8ecb42e1cc125da7e88fbb6e8b3c3cb703890701b91f8277bf84493ac4994417e8c090309f8147316091d879a1a3c1ce15a6476e029c6f0597a5cfd3533", + "signatures": [ + "00ad621bb19f24c785eded7e3953b575e25fca5b26890eda8ac87cb029d8a28d2c2ef084d98d617fddf7677b27488705e3c5c6d6568a2c44753212e3589e93b89c", + "018de3507e97d8e8e88f77c2cac0c4a7b8767b8527b2a53d81a119e2dbf6672fc8595de1c9ddbb1c88fadf7266923b2289dfbd3b266059c77609bdec52e8efeb61", + "021cbf94035e39cf80b4ccb7ee7d9cfac747ab6e1f73ef4a68b5600ee48c1e94861076718d11ab3908ecc6252c0ea515f6586f966e50842846cce5eada78d84453" + ], + "id": "91c5b9e9dd0915a0e2a44edcae3cd0182ffcdcc3921721fc4a88e5b91a3a1d90" + }, + "serialized": "ff011e0100000002000000000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f902950000000000a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d31411180604c8ecb42e1cc125da7e88fbb6e8b3c3cb703890701b91f8277bf84493ac4994417e8c090309f8147316091d879a1a3c1ce15a6476e029c6f0597a5cfd353300ad621bb19f24c785eded7e3953b575e25fca5b26890eda8ac87cb029d8a28d2c2ef084d98d617fddf7677b27488705e3c5c6d6568a2c44753212e3589e93b89c018de3507e97d8e8e88f77c2cac0c4a7b8767b8527b2a53d81a119e2dbf6672fc8595de1c9ddbb1c88fadf7266923b2289dfbd3b266059c77609bdec52e8efeb61021cbf94035e39cf80b4ccb7ee7d9cfac747ab6e1f73ef4a68b5600ee48c1e94861076718d11ab3908ecc6252c0ea515f6586f966e50842846cce5eada78d84453" +} diff --git a/src/test/resources/transactions/validator_registration/validator-registration-sign.json b/src/test/resources/transactions/validator_registration/validator-registration-sign.json new file mode 100644 index 00000000..efbd345d --- /dev/null +++ b/src/test/resources/transactions/validator_registration/validator-registration-sign.json @@ -0,0 +1,18 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 2, + "nonce": "0", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "2500000000", + "amount": "0", + "asset": { + "validatorPublicKey": "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118" + }, + "signature": "449a02672bf54a67ecdbeab20d3fbc16a1358397ebbe28398338f97d9823752f0b3e6c715ce6ad47d8f4df95a7a1ef97b76d159513ba680edecf9e3dd4d76719", + "id": "18659c72ed03091989bf960450ab156d04794ea037357c2f4839d362a1ad576a" + }, + "serialized": "ff011e0100000002000000000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f902950000000000a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118449a02672bf54a67ecdbeab20d3fbc16a1358397ebbe28398338f97d9823752f0b3e6c715ce6ad47d8f4df95a7a1ef97b76d159513ba680edecf9e3dd4d76719" +} diff --git a/src/test/resources/transactions/validator_resignation/validator-resignation-multi-sign.json b/src/test/resources/transactions/validator_resignation/validator-resignation-multi-sign.json new file mode 100644 index 00000000..9ce2df83 --- /dev/null +++ b/src/test/resources/transactions/validator_resignation/validator-resignation-multi-sign.json @@ -0,0 +1,20 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 7, + "nonce": "0", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "2500000000", + "amount": "0", + "signature": "a32aeb2cd0695a71f35953e2bac27b36ba51c6fb3f36b98a5e05072500a96206b3afc95efa47d2bbce291b12307c4bd5e79171930e13844a0bc2036516e26644", + "signatures": [ + "00e78bd07e68978b0bcc911c3b4cce17957a347b3ceda0fe78fca3624c6e9d752c46ba75d31004661d097bc6c2471f86fb6727ac9e385c931d2850fc1ad3eb98c0", + "01706c56c0a5568df17342bb0fffec66cbf948425153f31ee3f16760c372ae4e020f2489695c3f3a80524bbba6fa97aef074259e8dc9305966dfc1a40a632872d0", + "021e218f51b7803c327c092f89af015573371506dd8f27a96dacaf29286d8ecc5d955443cfb1a5d93f359ebef67fdb842fc3e9a8d9691e57a5f627cb11425526e0" + ], + "id": "97ff3cf77125fea2ce33f23ef4ce85d56e207bc47e1595c004a319976fdca64c" + }, + "serialized": "ff011e0100000007000000000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f902950000000000a32aeb2cd0695a71f35953e2bac27b36ba51c6fb3f36b98a5e05072500a96206b3afc95efa47d2bbce291b12307c4bd5e79171930e13844a0bc2036516e2664400e78bd07e68978b0bcc911c3b4cce17957a347b3ceda0fe78fca3624c6e9d752c46ba75d31004661d097bc6c2471f86fb6727ac9e385c931d2850fc1ad3eb98c001706c56c0a5568df17342bb0fffec66cbf948425153f31ee3f16760c372ae4e020f2489695c3f3a80524bbba6fa97aef074259e8dc9305966dfc1a40a632872d0021e218f51b7803c327c092f89af015573371506dd8f27a96dacaf29286d8ecc5d955443cfb1a5d93f359ebef67fdb842fc3e9a8d9691e57a5f627cb11425526e0" +} diff --git a/src/test/resources/transactions/validator_resignation/validator-resignation-sign.json b/src/test/resources/transactions/validator_resignation/validator-resignation-sign.json new file mode 100644 index 00000000..4492199d --- /dev/null +++ b/src/test/resources/transactions/validator_resignation/validator-resignation-sign.json @@ -0,0 +1,15 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 7, + "nonce": "0", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "2500000000", + "amount": "0", + "signature": "f9d93dc161b5351a9e6f89e97bd3a4d1b73349c2339145021dee2654f5a8116aa78c6c3742b5fc39d0c9265735b866954d8c6c8383130d08659b1aff3967d4eb", + "id": "431b779764f51e227eca907706bd339de36c3b23bd46c603283f3a932d12b936" + }, + "serialized": "ff011e0100000007000000000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f902950000000000f9d93dc161b5351a9e6f89e97bd3a4d1b73349c2339145021dee2654f5a8116aa78c6c3742b5fc39d0c9265735b866954d8c6c8383130d08659b1aff3967d4eb" +} diff --git a/src/test/resources/transactions/vote/vote-multi-sign.json b/src/test/resources/transactions/vote/vote-multi-sign.json new file mode 100644 index 00000000..1b9b0a55 --- /dev/null +++ b/src/test/resources/transactions/vote/vote-multi-sign.json @@ -0,0 +1,25 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 3, + "nonce": "1", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "100000000", + "amount": "0", + "asset": { + "votes": [ + "03f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabc" + ] + }, + "signature": "72a097e05983575a69ab7c2c15d80beea988fc02e08124a969b281fa09d1e47ff0b36706f9a9bb6b2e18db929f21b08571c4be36fe2882fecfb990e465bfebde", + "signatures": [ + "0035173f507953f5a7f9da525384b9a1021b553c1089f060e6e77118ab5aa68549ea89d4b63391941e95c0142dd195fd8c032c0a9aca9e1a72943dde8ecd663070", + "010dba0e40f903c7ec76e1f1e7ef3c145e69a878b13e833d132b9f1fa267ba3b2ab049941ede13faee3da9611ac27cb52a6888bbd093a253e7d7bea4c633d4a706", + "02556654e210ed6426d20c0fe246d3270bcdea97d5ab59f5c90888731b079ff83ab53cac3bc80680f093f2e5a78216a0ed894c6985bd89b3802b2d8ff3f6b4c584" + ], + "id": "e344602ba9fe82d035af6c8b759682bab0317ca523212724542217803c093adb" + }, + "serialized": "ff011e0100000003000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300e1f50500000000000103f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabc0072a097e05983575a69ab7c2c15d80beea988fc02e08124a969b281fa09d1e47ff0b36706f9a9bb6b2e18db929f21b08571c4be36fe2882fecfb990e465bfebde0035173f507953f5a7f9da525384b9a1021b553c1089f060e6e77118ab5aa68549ea89d4b63391941e95c0142dd195fd8c032c0a9aca9e1a72943dde8ecd663070010dba0e40f903c7ec76e1f1e7ef3c145e69a878b13e833d132b9f1fa267ba3b2ab049941ede13faee3da9611ac27cb52a6888bbd093a253e7d7bea4c633d4a70602556654e210ed6426d20c0fe246d3270bcdea97d5ab59f5c90888731b079ff83ab53cac3bc80680f093f2e5a78216a0ed894c6985bd89b3802b2d8ff3f6b4c584" +} diff --git a/src/test/resources/transactions/vote/vote-sign.json b/src/test/resources/transactions/vote/vote-sign.json new file mode 100644 index 00000000..0f2b988a --- /dev/null +++ b/src/test/resources/transactions/vote/vote-sign.json @@ -0,0 +1,20 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 3, + "nonce": "1", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "100000000", + "amount": "0", + "asset": { + "votes": [ + "03f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabc" + ] + }, + "signature": "e0a99c2ebd108c6ba1828f4d11e5ce8cdf2e67152575cabea2e86ab59153a1f1493b768af6dfe0a33eec22edf2dd87c25e1531bf285bb4131e4fcdbfce4c8781", + "id": "81bffacc80ae1c3b3f127cbaf5d2867d3209c38610d2cc5a341702fc252cd330" + }, + "serialized": "ff011e0100000003000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300e1f50500000000000103f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabc00e0a99c2ebd108c6ba1828f4d11e5ce8cdf2e67152575cabea2e86ab59153a1f1493b768af6dfe0a33eec22edf2dd87c25e1531bf285bb4131e4fcdbfce4c8781" +} From a415380e875b5bc70ce74ef339fd2f5a0bf267cc Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 11:13:49 -0600 Subject: [PATCH 23/74] use keccak addresses --- .../builder/HtlcLockBuilderTest.java | 4 ++-- .../builder/MultiPaymentBuilderTest.java | 18 +++++++++--------- .../builder/TransferBuilderTest.java | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilderTest.java index 81ea2587..2ac99370 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilderTest.java @@ -13,7 +13,7 @@ void build() { Transaction actual = new HtlcLockBuilder() .amount(1000000) - .recipientId("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25") + .recipientId("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A") .secretHash( "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454") .expirationType(HtlcLockExpirationType.EPOCH_TIMESTAMP, 1) @@ -41,7 +41,7 @@ void buildSecondSignature() { Transaction actual = new HtlcLockBuilder() .amount(1000000) - .recipientId("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25") + .recipientId("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A") .secretHash( "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454") .expirationType(HtlcLockExpirationType.EPOCH_TIMESTAMP, 1) diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java index c78f3bde..4427b45e 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java @@ -12,9 +12,9 @@ class MultiPaymentBuilderTest { void build() { Transaction actual = new MultiPaymentBuilder() - .addPayment("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25", 1) - .addPayment("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25", 2) - .addPayment("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25", 3) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 1) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 2) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 3) .vendorField("This is a transaction from Java") .sign("this is a top secret passphrase") .transaction; @@ -24,7 +24,7 @@ void build() { ArrayList payments = (ArrayList) actualAsset.get("payments"); HashMap payment = (HashMap) payments.get(0); assertEquals(payment.get("amount"), "1"); - assertEquals(payment.get("recipientId"), "AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25"); + assertEquals(payment.get("recipientId"), "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A"); assertTrue(actual.verify()); } @@ -33,9 +33,9 @@ void build() { void buildSecondSignature() { Transaction actual = new MultiPaymentBuilder() - .addPayment("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25", 1) - .addPayment("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25", 2) - .addPayment("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25", 3) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 1) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 2) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 3) .vendorField("This is a transaction from Java") .sign("this is a top secret passphrase") .secondSign("this is a top secret second passphrase") @@ -51,12 +51,12 @@ void buildSecondSignature() { void testMaxPayments() { MultiPaymentBuilder actual = new MultiPaymentBuilder(); for (int i = 0; i < 64; i++) { - actual.addPayment("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25", 1); + actual.addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 1); } Throwable exception = assertThrows( MaximumPaymentCountExceededError.class, - () -> actual.addPayment("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25", 1)); + () -> actual.addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 1)); assertEquals("Expected a maximum of 64 payments", exception.getMessage()); } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java index d28e2d17..26d4745c 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java @@ -14,7 +14,7 @@ class TransferBuilderTest { void build() { Transaction actual = new TransferBuilder() - .recipient("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25") + .recipient("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A") .amount(133380000000L) .expiration(100000) .vendorField("This is a transaction from Java") @@ -28,7 +28,7 @@ void build() { assertTrue(actual.verify()); HashMap actualHashMap = actual.toHashMap(); - assertEquals(actualHashMap.get("recipientId"), "AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25"); + assertEquals(actualHashMap.get("recipientId"), "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A"); assertEquals(actualHashMap.get("amount"), "133380000000"); assertEquals(actualHashMap.get("expiration"), 100000); assertEquals(actualHashMap.get("vendorField"), "This is a transaction from Java"); @@ -43,7 +43,7 @@ void build() { void buildSecondSignature() { Transaction actual = new TransferBuilder() - .recipient("AXoXnFi4z1Z6aFvjEYkDVCtBGW2PaRiM25") + .recipient("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A") .amount(133380000000L) .expiration(100000) .vendorField("This is a transaction from Java") From 2ec53a6ccb2ed554cd15cb52daf0f6d5418b356c Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 12:00:15 -0600 Subject: [PATCH 24/74] votes tests --- .../crypto/transactions/Deserializer.java | 64 +------------------ .../crypto/transactions/TransactionAsset.java | 1 + .../crypto/transactions/types/Vote.java | 31 ++++++--- .../transactions/deserializers/VoteTest.java | 56 +--------------- .../transactions/serializers/VoteTest.java | 28 +------- .../transactions/vote/unvote-sign.json | 26 ++++++++ 6 files changed, 58 insertions(+), 148 deletions(-) create mode 100644 src/test/resources/transactions/vote/unvote-sign.json diff --git a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java index b870703d..052315ab 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java @@ -102,39 +102,6 @@ private void deserializeVendorField() { } private void deserializeSignatures() { - deserializeSchnorrOrEcdsa(); - } - - private void deserializeSchnorrOrEcdsa() { - if (detectSchnorr()) { - deserializeSchnorr(); - } else { - deserializeEcdsa(); - } - } - - private void deserializeEcdsa() { - if (buffer.remaining() != 0) { - int signatureLength = currentSignatureLength(); - byte[] signatureBuffer = new byte[signatureLength]; - this.buffer.get(signatureBuffer); - this.transaction.signature = Hex.encode(signatureBuffer); - } - - if (buffer.remaining() != 0) { - int signatureLength = currentSignatureLength(); - byte[] signatureBuffer = new byte[signatureLength]; - this.buffer.get(signatureBuffer); - this.transaction.secondSignature = Hex.encode(signatureBuffer); - } - } - - private boolean canReadNonMultiSignature() { - return buffer.hasRemaining() - && (buffer.remaining() % 64 == 0 || buffer.remaining() % 65 != 0); - } - - private void deserializeSchnorr() { if (canReadNonMultiSignature()) { byte[] signatureBuffer = new byte[64]; buffer.get(signatureBuffer); @@ -173,34 +140,9 @@ private void deserializeSchnorr() { } } - private boolean detectSchnorr() { - int remaining = buffer.remaining(); - - // `signature` / `secondSignature` - if (remaining == 64 || remaining == 128) { - return true; - } - - // `signatures` of a multi signature transaction (type != 4) - if (remaining % 65 == 0) { - return true; - } - - // only possiblity left is a type 4 transaction with and without a `secondSignature`. - if ((remaining - 64) % 65 == 0 || (remaining - 128) % 65 == 0) { - return true; - } - - return false; - } - - private int currentSignatureLength() { - int mark = this.buffer.position(); - this.buffer.position(mark + 1); - String length = String.valueOf(this.buffer.get()); - int signatureLength = Integer.parseInt(length) + 2; - this.buffer.position(mark); - return signatureLength; + private boolean canReadNonMultiSignature() { + return buffer.hasRemaining() + && (buffer.remaining() % 64 == 0 || buffer.remaining() % 65 != 0); } public void setNewTransactionType(Transaction transaction) { diff --git a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java index 635b6267..165f714e 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java @@ -8,6 +8,7 @@ public class TransactionAsset { public Signature signature = new Signature(); public List votes = new ArrayList<>(); + public List unvotes = new ArrayList<>(); public Delegate delegate = new Delegate(); public MultiSignature multiSignature = new MultiSignature(); public MultiPayment multiPayment = new MultiPayment(); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/Vote.java b/src/main/java/org/arkecosystem/crypto/transactions/types/Vote.java index e4d0c2ed..d33763ff 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/Vote.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/Vote.java @@ -24,34 +24,49 @@ public int getTransactionTypeGroup() { public HashMap assetToHashMap() { HashMap asset = new HashMap<>(); asset.put("votes", this.asset.votes); + asset.put("unvotes", this.asset.unvotes); return asset; } @Override public byte[] serialize() { - ByteBuffer buffer = ByteBuffer.allocate(1 + this.asset.votes.size() * 34); + ByteBuffer buffer = ByteBuffer.allocate( + (1 + this.asset.votes.size() * 33) + + (1 + this.asset.unvotes.size() * 33) + ); + buffer.order(ByteOrder.LITTLE_ENDIAN); List votes = new ArrayList<>(this.asset.votes); - for (int i = 0; i < votes.size(); i++) { - votes.set( - i, (votes.get(i).startsWith("+") ? "01" : "00") + (votes.get(i).substring(1))); - } - + List unvotes = new ArrayList<>(this.asset.unvotes); + buffer.put((byte) votes.size()); buffer.put(Hex.decode(String.join("", votes))); + + buffer.put((byte) unvotes.size()); + buffer.put(Hex.decode(String.join("", unvotes))); + return buffer.array(); } @Override public void deserialize(ByteBuffer buffer) { int voteLength = buffer.get(); + for (int i = 0; i < voteLength; i++) { - byte[] voteBuffer = new byte[34]; + byte[] voteBuffer = new byte[33]; buffer.get(voteBuffer); String vote = Hex.encode(voteBuffer); - vote = (vote.startsWith("01") ? '+' : '-') + vote.substring(2); this.asset.votes.add(vote); } + + int unvoteLength = buffer.get(); + + for (int i = 0; i < unvoteLength; i++) { + byte[] unvoteBuffer = new byte[33]; + buffer.get(unvoteBuffer); + String unvote = Hex.encode(unvoteBuffer); + this.asset.unvotes.add(unvote); + } } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/VoteTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/VoteTest.java index 100c97f9..750fff40 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/VoteTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/VoteTest.java @@ -14,7 +14,7 @@ class VoteTest { @Test void passphraseVote() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/vote-sign"); + FixtureLoader.load("transactions/vote/vote-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -37,7 +37,7 @@ void passphraseVote() { @Test void passphraseUnvote() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/unvote-sign"); + FixtureLoader.load("transactions/vote/unvote-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -54,56 +54,6 @@ void passphraseUnvote() { assertEquals(data.get("id").toString(), actual.id); LinkedTreeMap asset = (LinkedTreeMap) data.get("asset"); - assertEquals((asset.get("votes")), actual.asset.votes); - } - - @Test - void secondPassphraseVote() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/vote-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - - LinkedTreeMap asset = (LinkedTreeMap) data.get("asset"); - assertEquals((asset.get("votes")), actual.asset.votes); - } - - @Test - void secondPassphraseUnvote() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/unvote-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - - LinkedTreeMap asset = (LinkedTreeMap) data.get("asset"); - assertEquals((asset.get("votes")), actual.asset.votes); + assertEquals((asset.get("unvotes")), actual.asset.unvotes); } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/VoteTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/VoteTest.java index 409f1daa..eb7b1224 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/VoteTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/VoteTest.java @@ -14,7 +14,7 @@ class VoteTest { @Test void passphraseVote() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/vote-sign"); + FixtureLoader.load("transactions/vote/vote-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); @@ -26,31 +26,7 @@ void passphraseVote() { @Test void passphraseUnvote() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/unvote-sign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphraseVote() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/vote-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphraseUnvote() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/unvote-secondSign"); + FixtureLoader.load("transactions/vote/unvote-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); diff --git a/src/test/resources/transactions/vote/unvote-sign.json b/src/test/resources/transactions/vote/unvote-sign.json new file mode 100644 index 00000000..14641e6c --- /dev/null +++ b/src/test/resources/transactions/vote/unvote-sign.json @@ -0,0 +1,26 @@ +{ + "data": { + "version": 1, + "network": 30, + "typeGroup": 1, + "type": 3, + "nonce": "1", + "senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3", + "fee": "100000000", + "amount": "0", + "asset": { + "unvotes": [ + "03f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabc" + ], + "votes": [] + }, + "signature": "ce9ab70d7d23b42ce597b000154235a1b895b160f64eb5a71549a2db2befe12c282ac92795595f524f673f901708818508caf8bb819356dde234c015843eda5f", + "signatures": [ + "0093e06e1c463f3f4cfdeefc7b40bea3b93e21a3f652f15ea3e0014292b7c9790c660f5a5cb3b48f7e024b69fcf01bcd7d796cba8f20f21cdb4de60b7ed6420408", + "014c664d9f54189d6db3cd5e4cae11bffee7322107e688d8eae64edc93937c976d5c51125f4d8b123449fc55bc2a38c789d2c36149fbcc3b2ae64bb64d08dbea2c", + "023ac8e92f15afce7c339e5f6575b7a9c88e1f3f89015c7952e216acb307fb35f342a81b94dacc72052c64832268cccc8ae4c5d80cdf1a09817c58c514fe38ee58" + ], + "id": "40c9e1607f73480e1817b04440a9a8a7b4c6f8203417a5533401e782f875ce92" + }, + "serialized": "ff011e0100000003000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300e1f5050000000000000103f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabcce9ab70d7d23b42ce597b000154235a1b895b160f64eb5a71549a2db2befe12c282ac92795595f524f673f901708818508caf8bb819356dde234c015843eda5f0093e06e1c463f3f4cfdeefc7b40bea3b93e21a3f652f15ea3e0014292b7c9790c660f5a5cb3b48f7e024b69fcf01bcd7d796cba8f20f21cdb4de60b7ed6420408014c664d9f54189d6db3cd5e4cae11bffee7322107e688d8eae64edc93937c976d5c51125f4d8b123449fc55bc2a38c789d2c36149fbcc3b2ae64bb64d08dbea2c023ac8e92f15afce7c339e5f6575b7a9c88e1f3f89015c7952e216acb307fb35f342a81b94dacc72052c64832268cccc8ae4c5d80cdf1a09817c58c514fe38ee58" +} From 649babfc17d90321cb8350558c931fcf581dd565 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 12:07:51 -0600 Subject: [PATCH 25/74] vote builder tests & adjustments --- .../transactions/builder/VoteBuilder.java | 10 +++++ .../transactions/builder/VoteBuilderTest.java | 40 +++++++++++-------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java index d0209cf8..f473de64 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java @@ -22,6 +22,16 @@ public VoteBuilder addVote(String vote) { this.transaction.asset.votes.add(vote); return this; } + + public VoteBuilder addUnvotes(List unvotes) { + this.transaction.asset.unvotes = unvotes; + return this; + } + + public VoteBuilder addUnvote(String unvote) { + this.transaction.asset.unvotes.add(unvote); + return this; + } public VoteBuilder sign(String passphrase) { this.transaction.recipientId = Address.fromPassphrase(passphrase); diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java index 957be910..2354977f 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java @@ -15,7 +15,7 @@ void buildVote() { Transaction actual = new VoteBuilder() .addVote( - "+034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192") + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192") .version(2) .nonce(3) .sign("this is a top secret passphrase") @@ -30,7 +30,7 @@ void buildVote() { assertEquals( actualVotes, Arrays.asList( - "+034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")); + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")); } @Test @@ -39,7 +39,7 @@ void buildVotes() { new VoteBuilder() .addVotes( Arrays.asList( - "+034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")) + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")) .version(2) .nonce(3) .sign("this is a top secret passphrase") @@ -54,16 +54,15 @@ void buildVotes() { assertEquals( actualVotes, Arrays.asList( - "+034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")); + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")); } @Test void buildUnvote() { Transaction actual = new VoteBuilder() - .addVote( - "-034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193") - .version(2) + .addUnvote( + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193") .nonce(3) .sign("this is a top secret passphrase") .transaction; @@ -72,12 +71,12 @@ void buildUnvote() { HashMap actualHashMap = actual.toHashMap(); HashMap actualAsset = (HashMap) actualHashMap.get("asset"); - List actualVotes = (List) actualAsset.get("votes"); + List actualUnvotes = (List) actualAsset.get("unvotes"); assertEquals( - actualVotes, + actualUnvotes, Arrays.asList( - "-034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193")); + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193")); } @Test @@ -86,9 +85,14 @@ void buildUnvoteVote() { new VoteBuilder() .addVotes( Arrays.asList( - "-034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193", - "+034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")) - .version(2) + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192" + ) + ) + .addUnvotes( + Arrays.asList( + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193" + ) + ) .nonce(3) .sign("this is a top secret passphrase") .transaction; @@ -98,12 +102,16 @@ void buildUnvoteVote() { HashMap actualHashMap = actual.toHashMap(); HashMap actualAsset = (HashMap) actualHashMap.get("asset"); List actualVotes = (List) actualAsset.get("votes"); + List actualUnvotes = (List) actualAsset.get("unvotes"); assertEquals( actualVotes, Arrays.asList( - "-034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193", - "+034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")); + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")); + + assertEquals( + actualUnvotes, + Arrays.asList("034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193")); } @Test @@ -111,7 +119,7 @@ void buildVoteSecondSignature() { Transaction actual = new VoteBuilder() .addVote( - "+034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192") + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192") .version(2) .nonce(3) .sign("this is a top secret passphrase") From 91c5e14b223cff75a1a538608b591f206af157df Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 12:17:37 -0600 Subject: [PATCH 26/74] remove deprecated --- .../crypto/enums/HtlcLockExpirationType.java | 16 -- .../crypto/transactions/Deserializer.java | 10 +- .../crypto/transactions/TransactionAsset.java | 29 ---- .../builder/HtlcClaimBuilder.java | 29 ---- .../transactions/builder/HtlcLockBuilder.java | 46 ------ .../builder/HtlcRefundBuilder.java | 28 ---- .../transactions/builder/IpfsBuilder.java | 28 ---- .../SecondSignatureRegistrationBuilder.java | 31 ---- .../crypto/transactions/types/HtlcClaim.java | 54 ------ .../crypto/transactions/types/HtlcLock.java | 71 -------- .../crypto/transactions/types/HtlcRefund.java | 47 ------ .../crypto/transactions/types/Ipfs.java | 54 ------ .../builder/HtlcClaimBuilderTest.java | 49 ------ .../builder/HtlcLockBuilderTest.java | 58 ------- .../builder/HtlcRefundBuilderTest.java | 47 ------ .../transactions/builder/IpfsBuilderTest.java | 45 ----- ...econdSignatureRegistrationBuilderTest.java | 31 ---- .../deserializers/HtlcClaimTest.java | 69 -------- .../deserializers/HtlcLockTest.java | 156 ------------------ .../deserializers/HtlcRefundTest.java | 67 -------- .../transactions/deserializers/IpfsTest.java | 59 ------- .../SecondSignatureRegistrationTest.java | 38 ----- .../serializers/HtlcClaimTest.java | 37 ----- .../serializers/HtlcLockTest.java | 61 ------- .../serializers/HtlcRefundTest.java | 38 ----- .../transactions/serializers/IpfsTest.java | 38 ----- .../SecondSignatureRegistrationTest.java | 28 ---- 27 files changed, 1 insertion(+), 1263 deletions(-) delete mode 100644 src/main/java/org/arkecosystem/crypto/enums/HtlcLockExpirationType.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcClaimBuilder.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilder.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcRefundBuilder.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/IpfsBuilder.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/SecondSignatureRegistrationBuilder.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/types/HtlcClaim.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/types/HtlcLock.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/types/HtlcRefund.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/types/Ipfs.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcClaimBuilderTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilderTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcRefundBuilderTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/builder/IpfsBuilderTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/builder/SecondSignatureRegistrationBuilderTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcClaimTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcLockTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcRefundTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/deserializers/IpfsTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/deserializers/SecondSignatureRegistrationTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcClaimTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcLockTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcRefundTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/serializers/IpfsTest.java delete mode 100644 src/test/java/org/arkecosystem/crypto/transactions/serializers/SecondSignatureRegistrationTest.java diff --git a/src/main/java/org/arkecosystem/crypto/enums/HtlcLockExpirationType.java b/src/main/java/org/arkecosystem/crypto/enums/HtlcLockExpirationType.java deleted file mode 100644 index 5d10b8e9..00000000 --- a/src/main/java/org/arkecosystem/crypto/enums/HtlcLockExpirationType.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.arkecosystem.crypto.enums; - -public enum HtlcLockExpirationType { - EPOCH_TIMESTAMP(1), - BLOCK_HEIGHT(2); - - private final int value; - - HtlcLockExpirationType(int value) { - this.value = value; - } - - public int getValue() { - return value; - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java index 052315ab..412e2dd2 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java @@ -12,10 +12,6 @@ import org.arkecosystem.crypto.enums.TransactionTypeGroup; import org.arkecosystem.crypto.transactions.types.DelegateRegistration; import org.arkecosystem.crypto.transactions.types.DelegateResignation; -import org.arkecosystem.crypto.transactions.types.HtlcClaim; -import org.arkecosystem.crypto.transactions.types.HtlcLock; -import org.arkecosystem.crypto.transactions.types.HtlcRefund; -import org.arkecosystem.crypto.transactions.types.Ipfs; import org.arkecosystem.crypto.transactions.types.MultiPayment; import org.arkecosystem.crypto.transactions.types.MultiSignatureRegistration; import org.arkecosystem.crypto.transactions.types.SecondSignatureRegistration; @@ -42,14 +38,10 @@ public Deserializer(String serialized) { coreTransactionTypes.put( CoreTransactionTypes.MULTI_SIGNATURE_REGISTRATION.getValue(), new MultiSignatureRegistration()); - coreTransactionTypes.put(CoreTransactionTypes.IPFS.getValue(), new Ipfs()); coreTransactionTypes.put(CoreTransactionTypes.MULTI_PAYMENT.getValue(), new MultiPayment()); coreTransactionTypes.put( CoreTransactionTypes.DELEGATE_RESIGNATION.getValue(), new DelegateResignation()); - coreTransactionTypes.put(CoreTransactionTypes.HTLC_LOCK.getValue(), new HtlcLock()); - coreTransactionTypes.put(CoreTransactionTypes.HTLC_CLAIM.getValue(), new HtlcClaim()); - coreTransactionTypes.put(CoreTransactionTypes.HTLC_REFUND.getValue(), new HtlcRefund()); - + transactionGroups.put(TransactionTypeGroup.CORE.getValue(), coreTransactionTypes); this.buffer = ByteBuffer.wrap(Hex.decode(serialized)).slice(); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java index 165f714e..d3052f61 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import org.arkecosystem.crypto.enums.HtlcLockExpirationType; public class TransactionAsset { public Signature signature = new Signature(); @@ -12,10 +11,6 @@ public class TransactionAsset { public Delegate delegate = new Delegate(); public MultiSignature multiSignature = new MultiSignature(); public MultiPayment multiPayment = new MultiPayment(); - public String ipfs; - public HtlcLockAsset htlcLockAsset = new HtlcLockAsset(); - public HtlcClaimAsset htlcClaimAsset = new HtlcClaimAsset(); - public HtlcRefundAsset htlcRefundAsset = new HtlcRefundAsset(); public HashMap customAsset = new HashMap<>(); public static class Signature { @@ -44,28 +39,4 @@ public Payment(long amount, String recipientId) { this.recipientId = recipientId; } } - - public static class HtlcLockAsset { - public String secretHash; - public Expiration expiration; - } - - public static class Expiration { - public HtlcLockExpirationType type; - public int value; - - public Expiration(HtlcLockExpirationType type, int value) { - this.type = type; - this.value = value; - } - } - - public static class HtlcClaimAsset { - public String lockTransactionId; - public String unlockSecret; - } - - public static class HtlcRefundAsset { - public String lockTransactionId; - } } diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcClaimBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcClaimBuilder.java deleted file mode 100644 index 01047914..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcClaimBuilder.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import org.arkecosystem.crypto.enums.Fees; -import org.arkecosystem.crypto.transactions.types.HtlcClaim; -import org.arkecosystem.crypto.transactions.types.Transaction; - -public class HtlcClaimBuilder extends AbstractTransactionBuilder { - - public HtlcClaimBuilder() { - super(); - this.transaction.fee = Fees.HTLC_CLAIM.getValue(); - } - - public HtlcClaimBuilder htlcClaimAsset(String lockTransactionId, String unlockSecret) { - this.transaction.asset.htlcClaimAsset.lockTransactionId = lockTransactionId; - this.transaction.asset.htlcClaimAsset.unlockSecret = unlockSecret; - return this; - } - - @Override - public Transaction getTransactionInstance() { - return new HtlcClaim(); - } - - @Override - public HtlcClaimBuilder instance() { - return this; - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilder.java deleted file mode 100644 index 99620356..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilder.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import org.arkecosystem.crypto.enums.Fees; -import org.arkecosystem.crypto.enums.HtlcLockExpirationType; -import org.arkecosystem.crypto.transactions.TransactionAsset; -import org.arkecosystem.crypto.transactions.types.HtlcLock; -import org.arkecosystem.crypto.transactions.types.Transaction; - -public class HtlcLockBuilder extends AbstractTransactionBuilder { - public HtlcLockBuilder() { - super(); - this.transaction.fee = Fees.HTLC_LOCK.getValue(); - } - - public HtlcLockBuilder recipientId(String recipientId) { - this.transaction.recipientId = recipientId; - return this; - } - - public HtlcLockBuilder secretHash(String secretHash) { - this.transaction.asset.htlcLockAsset.secretHash = secretHash; - return this; - } - - public HtlcLockBuilder expirationType( - HtlcLockExpirationType expirationType, int expirationValue) { - this.transaction.asset.htlcLockAsset.expiration = - new TransactionAsset.Expiration(expirationType, expirationValue); - return this; - } - - public HtlcLockBuilder vendorField(String vendorField) { - this.transaction.vendorField = vendorField; - return this; - } - - @Override - public Transaction getTransactionInstance() { - return new HtlcLock(); - } - - @Override - public HtlcLockBuilder instance() { - return this; - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcRefundBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcRefundBuilder.java deleted file mode 100644 index a6634d49..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/HtlcRefundBuilder.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import org.arkecosystem.crypto.enums.Fees; -import org.arkecosystem.crypto.transactions.types.HtlcRefund; -import org.arkecosystem.crypto.transactions.types.Transaction; - -public class HtlcRefundBuilder extends AbstractTransactionBuilder { - - public HtlcRefundBuilder() { - super(); - this.transaction.fee = Fees.HTLC_REFUND.getValue(); - } - - public HtlcRefundBuilder htlcRefundAsset(String lockTransactionId) { - this.transaction.asset.htlcRefundAsset.lockTransactionId = lockTransactionId; - return this; - } - - @Override - public Transaction getTransactionInstance() { - return new HtlcRefund(); - } - - @Override - public HtlcRefundBuilder instance() { - return this; - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/IpfsBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/IpfsBuilder.java deleted file mode 100644 index 06d8f900..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/IpfsBuilder.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import org.arkecosystem.crypto.enums.Fees; -import org.arkecosystem.crypto.transactions.types.Ipfs; -import org.arkecosystem.crypto.transactions.types.Transaction; - -public class IpfsBuilder extends AbstractTransactionBuilder { - - public IpfsBuilder() { - super(); - this.transaction.fee = Fees.IPFS.getValue(); - } - - public IpfsBuilder ipfsAsset(String ipfsAsset) { - this.transaction.asset.ipfs = ipfsAsset; - return this; - } - - @Override - public Transaction getTransactionInstance() { - return new Ipfs(); - } - - @Override - public IpfsBuilder instance() { - return this; - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/SecondSignatureRegistrationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/SecondSignatureRegistrationBuilder.java deleted file mode 100644 index 623535d6..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/SecondSignatureRegistrationBuilder.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import org.arkecosystem.crypto.enums.Fees; -import org.arkecosystem.crypto.identities.PublicKey; -import org.arkecosystem.crypto.transactions.types.SecondSignatureRegistration; -import org.arkecosystem.crypto.transactions.types.Transaction; - -public class SecondSignatureRegistrationBuilder - extends AbstractTransactionBuilder { - - public SecondSignatureRegistrationBuilder() { - super(); - this.transaction.fee = Fees.SECOND_SIGNATURE_REGISTRATION.getValue(); - } - - public SecondSignatureRegistrationBuilder signature(String signature) { - this.transaction.asset.signature.publicKey = PublicKey.fromPassphrase(signature); - - return this; - } - - @Override - public Transaction getTransactionInstance() { - return new SecondSignatureRegistration(); - } - - @Override - public SecondSignatureRegistrationBuilder instance() { - return this; - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/HtlcClaim.java b/src/main/java/org/arkecosystem/crypto/transactions/types/HtlcClaim.java deleted file mode 100644 index 24c6437f..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/HtlcClaim.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.arkecosystem.crypto.transactions.types; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.HashMap; -import org.arkecosystem.crypto.encoding.Hex; -import org.arkecosystem.crypto.enums.CoreTransactionTypes; -import org.arkecosystem.crypto.enums.TransactionTypeGroup; - -public class HtlcClaim extends Transaction { - - @Override - public int getTransactionType() { - return CoreTransactionTypes.HTLC_CLAIM.getValue(); - } - - @Override - public int getTransactionTypeGroup() { - return TransactionTypeGroup.CORE.getValue(); - } - - @Override - public HashMap assetToHashMap() { - HashMap asset = new HashMap<>(); - - HashMap claim = new HashMap<>(); - claim.put("lockTransactionId", this.asset.htlcClaimAsset.lockTransactionId); - claim.put("unlockSecret", this.asset.htlcClaimAsset.unlockSecret); - - asset.put("claim", claim); - return asset; - } - - @Override - public byte[] serialize() { - ByteBuffer buffer = ByteBuffer.allocate(32 + 32); - buffer.order(ByteOrder.LITTLE_ENDIAN); - buffer.put(Hex.decode(this.asset.htlcClaimAsset.lockTransactionId)); - buffer.put(Hex.decode(this.asset.htlcClaimAsset.unlockSecret)); - return buffer.array(); - } - - @Override - public void deserialize(ByteBuffer buffer) { - byte[] lockTransactionIdBuf = new byte[32]; - buffer.get(lockTransactionIdBuf); - - byte[] unlockSecret = new byte[32]; - buffer.get(unlockSecret); - - this.asset.htlcClaimAsset.lockTransactionId = Hex.encode(lockTransactionIdBuf); - this.asset.htlcClaimAsset.unlockSecret = Hex.encode(unlockSecret); - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/HtlcLock.java b/src/main/java/org/arkecosystem/crypto/transactions/types/HtlcLock.java deleted file mode 100644 index c188db12..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/HtlcLock.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.arkecosystem.crypto.transactions.types; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.HashMap; -import org.arkecosystem.crypto.encoding.Base58; -import org.arkecosystem.crypto.encoding.Hex; -import org.arkecosystem.crypto.enums.CoreTransactionTypes; -import org.arkecosystem.crypto.enums.HtlcLockExpirationType; -import org.arkecosystem.crypto.enums.TransactionTypeGroup; -import org.arkecosystem.crypto.transactions.TransactionAsset; - -public class HtlcLock extends Transaction { - - @Override - public int getTransactionType() { - return CoreTransactionTypes.HTLC_LOCK.getValue(); - } - - @Override - public int getTransactionTypeGroup() { - return TransactionTypeGroup.CORE.getValue(); - } - - @Override - public boolean hasVendorField() { - return true; - } - - @Override - public HashMap assetToHashMap() { - HashMap asset = new HashMap<>(); - - HashMap lock = new HashMap<>(); - lock.put("secretHash", this.asset.htlcLockAsset.secretHash); - - HashMap expiration = new HashMap<>(); - expiration.put("type", this.asset.htlcLockAsset.expiration.type.getValue()); - expiration.put("value", this.asset.htlcLockAsset.expiration.value); - lock.put("expiration", expiration); - - asset.put("lock", lock); - return asset; - } - - @Override - public byte[] serialize() { - ByteBuffer buffer = ByteBuffer.allocate(8 + 32 + 1 + 4 + 21); - buffer.order(ByteOrder.LITTLE_ENDIAN); - buffer.putLong(this.amount); - buffer.put(Hex.decode(this.asset.htlcLockAsset.secretHash)); - buffer.put((byte) this.asset.htlcLockAsset.expiration.type.getValue()); - buffer.putInt(this.asset.htlcLockAsset.expiration.value); - buffer.put(Base58.decodeChecked(this.recipientId)); - return buffer.array(); - } - - @Override - public void deserialize(ByteBuffer buffer) { - this.amount = buffer.getLong(); - byte[] secretHash = new byte[32]; - buffer.get(secretHash); - this.asset.htlcLockAsset.secretHash = Hex.encode(secretHash); - this.asset.htlcLockAsset.expiration = - new TransactionAsset.Expiration( - HtlcLockExpirationType.values()[buffer.get() - 1], buffer.getInt()); - byte[] recipientId = new byte[21]; - buffer.get(recipientId); - this.recipientId = Base58.encodeChecked(recipientId); - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/HtlcRefund.java b/src/main/java/org/arkecosystem/crypto/transactions/types/HtlcRefund.java deleted file mode 100644 index 4e82dca7..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/HtlcRefund.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.arkecosystem.crypto.transactions.types; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.HashMap; -import org.arkecosystem.crypto.encoding.Hex; -import org.arkecosystem.crypto.enums.CoreTransactionTypes; -import org.arkecosystem.crypto.enums.TransactionTypeGroup; - -public class HtlcRefund extends Transaction { - - @Override - public int getTransactionType() { - return CoreTransactionTypes.HTLC_REFUND.getValue(); - } - - @Override - public int getTransactionTypeGroup() { - return TransactionTypeGroup.CORE.getValue(); - } - - @Override - public HashMap assetToHashMap() { - HashMap asset = new HashMap<>(); - - HashMap lockTransactionId = new HashMap<>(); - lockTransactionId.put("lockTransactionId", this.asset.htlcRefundAsset.lockTransactionId); - - asset.put("refund", lockTransactionId); - return asset; - } - - @Override - public byte[] serialize() { - ByteBuffer buffer = ByteBuffer.allocate(32); - buffer.order(ByteOrder.LITTLE_ENDIAN); - buffer.put(Hex.decode(this.asset.htlcRefundAsset.lockTransactionId)); - return buffer.array(); - } - - @Override - public void deserialize(ByteBuffer buffer) { - byte[] lockTransactionIdBuffer = new byte[32]; - buffer.get(lockTransactionIdBuffer); - this.asset.htlcRefundAsset.lockTransactionId = Hex.encode(lockTransactionIdBuffer); - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/Ipfs.java b/src/main/java/org/arkecosystem/crypto/transactions/types/Ipfs.java deleted file mode 100644 index 78eb2e99..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/Ipfs.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.arkecosystem.crypto.transactions.types; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.HashMap; -import org.arkecosystem.crypto.encoding.Base58; -import org.arkecosystem.crypto.enums.CoreTransactionTypes; -import org.arkecosystem.crypto.enums.TransactionTypeGroup; - -public class Ipfs extends Transaction { - - @Override - public int getTransactionType() { - return CoreTransactionTypes.IPFS.getValue(); - } - - @Override - public int getTransactionTypeGroup() { - return TransactionTypeGroup.CORE.getValue(); - } - - @Override - public HashMap assetToHashMap() { - HashMap asset = new HashMap<>(); - asset.put("ipfs", this.asset.ipfs); - return asset; - } - - @Override - public byte[] serialize() { - byte[] ipfsBuffer = Base58.decode(this.asset.ipfs); - ByteBuffer buffer = ByteBuffer.allocate(ipfsBuffer.length); - buffer.order(ByteOrder.LITTLE_ENDIAN); - buffer.put(ipfsBuffer); - return buffer.array(); - } - - @Override - public void deserialize(ByteBuffer buffer) { - byte hashFunction = buffer.get(); - byte ipfsHashLength = buffer.get(); - byte[] hashBuffer = new byte[ipfsHashLength]; - buffer.get(hashBuffer); - - byte[] ipfsBuffer = - ByteBuffer.allocate(ipfsHashLength + 2) - .put(hashFunction) - .put(ipfsHashLength) - .put(hashBuffer) - .array(); - - this.asset.ipfs = Base58.encode(ipfsBuffer); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcClaimBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcClaimBuilderTest.java deleted file mode 100644 index 48e2e48e..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcClaimBuilderTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import static org.junit.jupiter.api.Assertions.*; - -import java.util.HashMap; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -class HtlcClaimBuilderTest { - @Test - void build() { - Transaction actual = - new HtlcClaimBuilder() - .htlcClaimAsset( - "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4", - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - .nonce(3) - .sign("this is a top secret passphrase") - .transaction; - - HashMap actualHashMap = actual.toHashMap(); - HashMap actualAsset = (HashMap) actualHashMap.get("asset"); - HashMap claim = (HashMap) actualAsset.get("claim"); - assertEquals( - claim.get("lockTransactionId"), - "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4"); - assertEquals(claim.get("unlockSecret"), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - - assertTrue(actual.verify()); - } - - @Test - void buildSecondSignature() { - Transaction actual = - new HtlcClaimBuilder() - .htlcClaimAsset( - "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4", - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - .nonce(3) - .sign("this is a top secret passphrase") - .secondSign("this is a top secret second passphrase") - .transaction; - - assertTrue(actual.verify()); - assertTrue( - actual.secondVerify( - "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilderTest.java deleted file mode 100644 index 2ac99370..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcLockBuilderTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import static org.junit.jupiter.api.Assertions.*; - -import java.util.HashMap; -import org.arkecosystem.crypto.enums.HtlcLockExpirationType; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -class HtlcLockBuilderTest { - @Test - void build() { - Transaction actual = - new HtlcLockBuilder() - .amount(1000000) - .recipientId("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A") - .secretHash( - "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454") - .expirationType(HtlcLockExpirationType.EPOCH_TIMESTAMP, 1) - .vendorField("This is vendor field java") - .nonce(3) - .sign("this is a top secret passphrase") - .transaction; - - HashMap actualHashMap = actual.toHashMap(); - HashMap actualAsset = (HashMap) actualHashMap.get("asset"); - HashMap lock = (HashMap) actualAsset.get("lock"); - HashMap expiration = (HashMap) lock.get("expiration"); - - assertEquals( - lock.get("secretHash"), - "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454"); - assertEquals(expiration.get("type"), HtlcLockExpirationType.EPOCH_TIMESTAMP.getValue()); - assertEquals(expiration.get("value"), 1); - - assertTrue(actual.verify()); - } - - @Test - void buildSecondSignature() { - Transaction actual = - new HtlcLockBuilder() - .amount(1000000) - .recipientId("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A") - .secretHash( - "0f128d401958b1b30ad0d10406f47f9489321017b4614e6cb993fc63913c5454") - .expirationType(HtlcLockExpirationType.EPOCH_TIMESTAMP, 1) - .nonce(3) - .sign("this is a top secret passphrase") - .secondSign("this is a top secret second passphrase") - .transaction; - - assertTrue(actual.verify()); - assertTrue( - actual.secondVerify( - "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcRefundBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcRefundBuilderTest.java deleted file mode 100644 index 03c759bc..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/HtlcRefundBuilderTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.HashMap; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -class HtlcRefundBuilderTest { - @Test - void build() { - Transaction actual = - new HtlcRefundBuilder() - .htlcRefundAsset( - "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4") - .nonce(3) - .sign("this is a top secret passphrase") - .transaction; - - HashMap actualHashMap = actual.toHashMap(); - HashMap actualAsset = (HashMap) actualHashMap.get("asset"); - HashMap refund = (HashMap) actualAsset.get("refund"); - assertEquals( - refund.get("lockTransactionId"), - "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4"); - - assertTrue(actual.verify()); - } - - @Test - void buildSecondSignature() { - Transaction actual = - new HtlcRefundBuilder() - .htlcRefundAsset( - "943c220691e711c39c79d437ce185748a0018940e1a4144293af9d05627d2eb4") - .nonce(3) - .sign("this is a top secret passphrase") - .secondSign("this is a top secret second passphrase") - .transaction; - - assertTrue(actual.verify()); - assertTrue( - actual.secondVerify( - "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/IpfsBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/IpfsBuilderTest.java deleted file mode 100644 index 8da5bc46..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/IpfsBuilderTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.HashMap; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -class IpfsBuilderTest { - - @Test - void passphrase() { - Transaction actual = - new IpfsBuilder() - .ipfsAsset("QmR45FmbVVrixReBwJkhEKde2qwHYaQzGxu4ZoDeswuF9w") - .version(2) - .nonce(3) - .sign("this is a top secret passphrase") - .transaction; - - HashMap actualHashMap = actual.toHashMap(); - HashMap actualAsset = (HashMap) actualHashMap.get("asset"); - assertEquals(actualAsset.get("ipfs"), "QmR45FmbVVrixReBwJkhEKde2qwHYaQzGxu4ZoDeswuF9w"); - - assertTrue(actual.verify()); - } - - @Test - void buildSecondSignature() { - Transaction actual = - new IpfsBuilder() - .ipfsAsset("QmR45FmbVVrixReBwJkhEKde2qwHYaQzGxu4ZoDeswuF9w") - .version(2) - .nonce(3) - .sign("this is a top secret passphrase") - .secondSign("this is a top secret second passphrase") - .transaction; - - assertTrue(actual.verify()); - assertTrue( - actual.secondVerify( - "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/SecondSignatureRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/SecondSignatureRegistrationBuilderTest.java deleted file mode 100644 index e9fa2243..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/SecondSignatureRegistrationBuilderTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.HashMap; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -class SecondSignatureRegistrationBuilderTest { - - @Test - void passphrase() { - Transaction actual = - new SecondSignatureRegistrationBuilder() - .signature("this is a top secret second passphrase'") - .version(2) - .nonce(3) - .sign("this is a top secret passphrase") - .transaction; - - assertTrue(actual.verify()); - - HashMap actualHashMap = actual.toHashMap(); - HashMap actualAsset = (HashMap) actualHashMap.get("asset"); - HashMap actualSignature = (HashMap) actualAsset.get("signature"); - assertEquals( - actualSignature.get("publicKey"), - "03d8941c0ceb0bc6334a66679e660f7143f5313a0a6e034f3869009970207da847"); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcClaimTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcClaimTest.java deleted file mode 100644 index fe1740d5..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcClaimTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.arkecosystem.crypto.transactions.deserializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.enums.TransactionTypeGroup; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -public class HtlcClaimTest { - - @Test - void passphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-claim-sign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("claim"); - assertEquals( - (asset.get("lockTransactionId")), actual.asset.htlcClaimAsset.lockTransactionId); - assertEquals((asset.get("unlockSecret")), actual.asset.htlcClaimAsset.unlockSecret); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-claim-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("claim"); - assertEquals( - (asset.get("lockTransactionId")), actual.asset.htlcClaimAsset.lockTransactionId); - assertEquals((asset.get("unlockSecret")), actual.asset.htlcClaimAsset.unlockSecret); - - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcLockTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcLockTest.java deleted file mode 100644 index ca3fb658..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcLockTest.java +++ /dev/null @@ -1,156 +0,0 @@ -package org.arkecosystem.crypto.transactions.deserializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.enums.TransactionTypeGroup; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -public class HtlcLockTest { - @Test - void passphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-lock-sign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("lock"); - - assertEquals((asset.get("secretHash")), actual.asset.htlcLockAsset.secretHash); - LinkedTreeMap assetExpiration = - ((LinkedTreeMap) asset.get("expiration")); - assertEquals( - ((Double) assetExpiration.get("type")).intValue(), - actual.asset.htlcLockAsset.expiration.type.getValue()); - assertEquals( - ((Double) assetExpiration.get("value")).intValue(), - actual.asset.htlcLockAsset.expiration.value); - assertEquals((Long.valueOf((String) data.get("amount"))), actual.amount); - } - - @Test - void passphraseVendorField() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-lock-with-vendor-field-sign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("lock"); - - assertEquals((asset.get("secretHash")), actual.asset.htlcLockAsset.secretHash); - LinkedTreeMap assetExpiration = - ((LinkedTreeMap) asset.get("expiration")); - assertEquals( - ((Double) assetExpiration.get("type")).intValue(), - actual.asset.htlcLockAsset.expiration.type.getValue()); - assertEquals( - ((Double) assetExpiration.get("value")).intValue(), - actual.asset.htlcLockAsset.expiration.value); - assertEquals((Long.valueOf((String) data.get("amount"))), actual.amount); - assertEquals(data.get("vendorField").toString(), actual.vendorField); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-lock-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("lock"); - - assertEquals((asset.get("secretHash")), actual.asset.htlcLockAsset.secretHash); - LinkedTreeMap assetExpiration = - ((LinkedTreeMap) asset.get("expiration")); - assertEquals( - ((Double) assetExpiration.get("type")).intValue(), - actual.asset.htlcLockAsset.expiration.type.getValue()); - assertEquals( - ((Double) assetExpiration.get("value")).intValue(), - actual.asset.htlcLockAsset.expiration.value); - assertEquals((Long.valueOf((String) data.get("amount"))), actual.amount); - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - } - - @Test - void secondPassphraseVendorField() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-lock-with-vendor-field-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("lock"); - - assertEquals((asset.get("secretHash")), actual.asset.htlcLockAsset.secretHash); - LinkedTreeMap assetExpiration = - ((LinkedTreeMap) asset.get("expiration")); - assertEquals( - ((Double) assetExpiration.get("type")).intValue(), - actual.asset.htlcLockAsset.expiration.type.getValue()); - assertEquals( - ((Double) assetExpiration.get("value")).intValue(), - actual.asset.htlcLockAsset.expiration.value); - assertEquals((Long.valueOf((String) data.get("amount"))), actual.amount); - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - assertEquals(data.get("vendorField").toString(), actual.vendorField); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcRefundTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcRefundTest.java deleted file mode 100644 index 1db04734..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/HtlcRefundTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.arkecosystem.crypto.transactions.deserializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.enums.TransactionTypeGroup; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -public class HtlcRefundTest { - - @Test - void passphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-refund-sign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("refund"); - assertEquals( - (asset.get("lockTransactionId")), actual.asset.htlcRefundAsset.lockTransactionId); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-refund-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("refund"); - assertEquals( - (asset.get("lockTransactionId")), actual.asset.htlcRefundAsset.lockTransactionId); - - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/IpfsTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/IpfsTest.java deleted file mode 100644 index 8a15ae91..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/IpfsTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.arkecosystem.crypto.transactions.deserializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.enums.TransactionTypeGroup; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -class IpfsTest { - @Test - void passphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/ipfs-sign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = ((LinkedTreeMap) data.get("asset")); - assertEquals((asset.get("ipfs")), actual.asset.ipfs); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/ipfs-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - LinkedTreeMap asset = ((LinkedTreeMap) data.get("asset")); - assertEquals((asset.get("ipfs")), actual.asset.ipfs); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/SecondSignatureRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/SecondSignatureRegistrationTest.java deleted file mode 100644 index 4cf8ddb3..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/SecondSignatureRegistrationTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.arkecosystem.crypto.transactions.deserializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.enums.TransactionTypeGroup; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -public class SecondSignatureRegistrationTest { - - @Test - void passphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/second-signature-registration"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap assetV2 = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("signature"); - assertEquals((assetV2.get("publicKey")), actual.asset.signature.publicKey); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcClaimTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcClaimTest.java deleted file mode 100644 index 6d982268..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcClaimTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.arkecosystem.crypto.transactions.serializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.encoding.Hex; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.Serializer; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -public class HtlcClaimTest { - @Test - void passphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-claim-sign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-claim-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcLockTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcLockTest.java deleted file mode 100644 index 4bcae35c..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcLockTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.arkecosystem.crypto.transactions.serializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.encoding.Hex; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.Serializer; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -class HtlcLockTest { - @Test - void passphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-lock-sign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void passphraseVendorField() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-lock-with-vendor-field-sign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-lock-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphraseVendorField() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-lock-with-vendor-field-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcRefundTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcRefundTest.java deleted file mode 100644 index f395f574..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/HtlcRefundTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.arkecosystem.crypto.transactions.serializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.encoding.Hex; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.Serializer; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -class HtlcRefundTest { - - @Test - void passphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-refund-sign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/htlc-refund-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/IpfsTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/IpfsTest.java deleted file mode 100644 index f6f0513f..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/IpfsTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.arkecosystem.crypto.transactions.serializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.encoding.Hex; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.Serializer; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -class IpfsTest { - - @Test - void passphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/ipfs-sign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/ipfs-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } -} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/SecondSignatureRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/SecondSignatureRegistrationTest.java deleted file mode 100644 index 6afa4324..00000000 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/SecondSignatureRegistrationTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.arkecosystem.crypto.transactions.serializers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.google.gson.internal.LinkedTreeMap; -import org.arkecosystem.crypto.encoding.Hex; -import org.arkecosystem.crypto.transactions.Deserializer; -import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.Serializer; -import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Test; - -public class SecondSignatureRegistrationTest { - - @Test - void passphrase() { - // V2 tests - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/second-signature-registration"); - - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } -} From 4418f280482c1340e668555233ec6a040592165e Mon Sep 17 00:00:00 2001 From: alfonsobries Date: Mon, 5 Aug 2024 18:20:40 +0000 Subject: [PATCH 27/74] style: resolve style guide violations --- .../crypto/transactions/Deserializer.java | 2 +- .../crypto/transactions/builder/VoteBuilder.java | 2 +- .../crypto/transactions/types/Vote.java | 9 ++++----- .../transactions/builder/TransferBuilderTest.java | 3 ++- .../transactions/builder/VoteBuilderTest.java | 13 +++++-------- .../crypto/transactions/deserializers/VoteTest.java | 6 ++---- .../crypto/transactions/serializers/VoteTest.java | 6 ++---- 7 files changed, 17 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java index 412e2dd2..c17a9d32 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java @@ -41,7 +41,7 @@ public Deserializer(String serialized) { coreTransactionTypes.put(CoreTransactionTypes.MULTI_PAYMENT.getValue(), new MultiPayment()); coreTransactionTypes.put( CoreTransactionTypes.DELEGATE_RESIGNATION.getValue(), new DelegateResignation()); - + transactionGroups.put(TransactionTypeGroup.CORE.getValue(), coreTransactionTypes); this.buffer = ByteBuffer.wrap(Hex.decode(serialized)).slice(); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java index f473de64..33423d85 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/VoteBuilder.java @@ -22,7 +22,7 @@ public VoteBuilder addVote(String vote) { this.transaction.asset.votes.add(vote); return this; } - + public VoteBuilder addUnvotes(List unvotes) { this.transaction.asset.unvotes = unvotes; return this; diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/Vote.java b/src/main/java/org/arkecosystem/crypto/transactions/types/Vote.java index d33763ff..3cc5c739 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/Vote.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/Vote.java @@ -30,16 +30,15 @@ public HashMap assetToHashMap() { @Override public byte[] serialize() { - ByteBuffer buffer = ByteBuffer.allocate( - (1 + this.asset.votes.size() * 33) - + (1 + this.asset.unvotes.size() * 33) - ); + ByteBuffer buffer = + ByteBuffer.allocate( + (1 + this.asset.votes.size() * 33) + (1 + this.asset.unvotes.size() * 33)); buffer.order(ByteOrder.LITTLE_ENDIAN); List votes = new ArrayList<>(this.asset.votes); List unvotes = new ArrayList<>(this.asset.unvotes); - + buffer.put((byte) votes.size()); buffer.put(Hex.decode(String.join("", votes))); diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java index 26d4745c..22634cd2 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java @@ -28,7 +28,8 @@ void build() { assertTrue(actual.verify()); HashMap actualHashMap = actual.toHashMap(); - assertEquals(actualHashMap.get("recipientId"), "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A"); + assertEquals( + actualHashMap.get("recipientId"), "0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A"); assertEquals(actualHashMap.get("amount"), "133380000000"); assertEquals(actualHashMap.get("expiration"), 100000); assertEquals(actualHashMap.get("vendorField"), "This is a transaction from Java"); diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java index 2354977f..971773df 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java @@ -85,14 +85,10 @@ void buildUnvoteVote() { new VoteBuilder() .addVotes( Arrays.asList( - "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192" - ) - ) + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")) .addUnvotes( Arrays.asList( - "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193" - ) - ) + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193")) .nonce(3) .sign("this is a top secret passphrase") .transaction; @@ -107,11 +103,12 @@ void buildUnvoteVote() { assertEquals( actualVotes, Arrays.asList( - "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")); + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192")); assertEquals( actualUnvotes, - Arrays.asList("034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193")); + Arrays.asList( + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed193")); } @Test diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/VoteTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/VoteTest.java index 750fff40..d86f2a07 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/VoteTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/VoteTest.java @@ -13,8 +13,7 @@ class VoteTest { @Test void passphraseVote() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/vote/vote-sign"); + LinkedTreeMap fixture = FixtureLoader.load("transactions/vote/vote-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -36,8 +35,7 @@ void passphraseVote() { @Test void passphraseUnvote() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/vote/unvote-sign"); + LinkedTreeMap fixture = FixtureLoader.load("transactions/vote/unvote-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/VoteTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/VoteTest.java index eb7b1224..c136fa66 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/VoteTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/VoteTest.java @@ -13,8 +13,7 @@ class VoteTest { @Test void passphraseVote() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/vote/vote-sign"); + LinkedTreeMap fixture = FixtureLoader.load("transactions/vote/vote-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); @@ -25,8 +24,7 @@ void passphraseVote() { @Test void passphraseUnvote() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/vote/unvote-sign"); + LinkedTreeMap fixture = FixtureLoader.load("transactions/vote/unvote-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); From cb24eb9dce6463c2d412a2861391cce4afde3336 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 12:27:17 -0600 Subject: [PATCH 28/74] wip --- .../crypto/transactions/TransactionAsset.java | 1 + .../crypto/transactions/types/MultiPayment.java | 16 +++++++++++----- .../serializers/MultiPaymentTest.java | 8 ++++---- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java index d3052f61..a82f632d 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java @@ -12,6 +12,7 @@ public class TransactionAsset { public MultiSignature multiSignature = new MultiSignature(); public MultiPayment multiPayment = new MultiPayment(); public HashMap customAsset = new HashMap<>(); + public long amount = 0L; public static class Signature { public String publicKey; diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/MultiPayment.java b/src/main/java/org/arkecosystem/crypto/transactions/types/MultiPayment.java index f15fefb9..e0c61ca6 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/MultiPayment.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/MultiPayment.java @@ -4,10 +4,12 @@ import java.nio.ByteOrder; import java.util.ArrayList; import java.util.HashMap; -import org.arkecosystem.crypto.encoding.Base58; +import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.enums.CoreTransactionTypes; import org.arkecosystem.crypto.enums.TransactionTypeGroup; import org.arkecosystem.crypto.transactions.TransactionAsset; +import org.arkecosystem.crypto.utils.Address; +import org.web3j.crypto.Keys; public class MultiPayment extends Transaction { @@ -42,12 +44,13 @@ public HashMap assetToHashMap() { @Override public byte[] serialize() { - ByteBuffer buffer = ByteBuffer.allocate(2 + this.asset.multiPayment.payments.size() * 29); + ByteBuffer buffer = ByteBuffer.allocate(2 + this.asset.multiPayment.payments.size() * 28); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.putShort((short) this.asset.multiPayment.payments.size()); for (TransactionAsset.Payment current : this.asset.multiPayment.payments) { buffer.putLong(current.amount); - buffer.put(Base58.decodeChecked(current.recipientId)); + byte[] recipientBytes = Hex.decode(Address.toBufferHexString(current.recipientId)); + buffer.put(recipientBytes); } return buffer.array(); } @@ -55,12 +58,15 @@ public byte[] serialize() { @Override public void deserialize(ByteBuffer buffer) { int paymentLength = buffer.getShort() & 0xff; + for (int i = 0; i < paymentLength; i++) { - byte[] recipientId = new byte[21]; + byte[] recipientId = new byte[20]; long amount = buffer.getLong(); buffer.get(recipientId); this.asset.multiPayment.payments.add( - new TransactionAsset.Payment(amount, Base58.encodeChecked(recipientId))); + new TransactionAsset.Payment(amount, Keys.toChecksumAddress("0x" + Hex.encode(recipientId)))); } + + this.asset.amount = this.asset.multiPayment.payments.stream().mapToLong(p -> p.amount).sum(); } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java index c3b56d9f..46f12c7a 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java @@ -14,7 +14,7 @@ class MultiPaymentTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/multi-payment-sign"); + FixtureLoader.load("transactions/multi_payment/multi-payment-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); @@ -26,7 +26,7 @@ void passphrase() { @Test void passphraseVendorField() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/multi-payment-with-vendor-field-sign"); + FixtureLoader.load("transactions/multi_payment/multi-payment-with-vendor-field-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); @@ -38,7 +38,7 @@ void passphraseVendorField() { @Test void secondPassphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/multi-payment-secondSign"); + FixtureLoader.load("transactions/multi_payment/multi-payment-secondSign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); @@ -51,7 +51,7 @@ void secondPassphrase() { void secondPassphraseVendorField() { LinkedTreeMap fixture = FixtureLoader.load( - "transactions/v2-ecdsa/multi-payment-with-vendor-field-secondSign"); + "transactions/multi_payment/multi-payment-with-vendor-field-secondSign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); From 5fb2de64513c35802f4d8861d80a91e3e479479e Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 12:29:26 -0600 Subject: [PATCH 29/74] deserialize multipayment --- .../deserializers/MultiPaymentTest.java | 72 +------------------ .../serializers/MultiPaymentTest.java | 25 ------- 2 files changed, 2 insertions(+), 95 deletions(-) diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/MultiPaymentTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/MultiPaymentTest.java index d5e28006..16e9f3f0 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/MultiPaymentTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/MultiPaymentTest.java @@ -14,7 +14,7 @@ class MultiPaymentTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/multi-payment-sign"); + FixtureLoader.load("transactions/multi_payment/multi-payment-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -45,7 +45,7 @@ void passphrase() { @Test void passphraseVendorField() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/multi-payment-with-vendor-field-sign"); + FixtureLoader.load("transactions/multi_payment/multi-payment-with-vendor-field-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -74,72 +74,4 @@ void passphraseVendorField() { assertEquals(data.get("vendorField").toString(), actual.vendorField); } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/multi-payment-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = (LinkedTreeMap) data.get("asset"); - ArrayList payments = ((ArrayList) asset.get("payments")); - for (int i = 0; i < payments.size(); i++) { - String recipientId = - (String) ((LinkedTreeMap) payments.get(i)).get("recipientId"); - String amount = - ((String) ((LinkedTreeMap) payments.get(i)).get("amount")); - assertEquals(recipientId, actual.asset.multiPayment.payments.get(i).recipientId); - assertEquals(Long.valueOf(amount), actual.asset.multiPayment.payments.get(i).amount); - } - - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - } - - @Test - void secondPassphraseVendorField() { - LinkedTreeMap fixture = - FixtureLoader.load( - "transactions/v2-ecdsa/multi-payment-with-vendor-field-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = (LinkedTreeMap) data.get("asset"); - ArrayList payments = ((ArrayList) asset.get("payments")); - for (int i = 0; i < payments.size(); i++) { - String recipientId = - (String) ((LinkedTreeMap) payments.get(i)).get("recipientId"); - String amount = - ((String) ((LinkedTreeMap) payments.get(i)).get("amount")); - assertEquals(recipientId, actual.asset.multiPayment.payments.get(i).recipientId); - assertEquals(Long.valueOf(amount), actual.asset.multiPayment.payments.get(i).amount); - } - - assertEquals(data.get("vendorField").toString(), actual.vendorField); - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java index 46f12c7a..22ef2700 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java @@ -34,29 +34,4 @@ void passphraseVendorField() { assertEquals(fixture.get("serialized").toString(), actual); } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/multi_payment/multi-payment-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphraseVendorField() { - LinkedTreeMap fixture = - FixtureLoader.load( - "transactions/multi_payment/multi-payment-with-vendor-field-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } } From 802171c214fa9812fbcf4a1276dcb69d341089da Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 12:34:35 -0600 Subject: [PATCH 30/74] rename delegate to validator --- .../crypto/enums/CoreTransactionTypes.java | 4 +-- .../org/arkecosystem/crypto/enums/Fees.java | 4 +-- .../crypto/transactions/Deserializer.java | 8 ++--- .../builder/DelegateRegistrationBuilder.java | 29 ------------------- .../builder/DelegateResignationBuilder.java | 24 --------------- .../builder/ValidatorRegistrationBuilder.java | 29 +++++++++++++++++++ .../builder/ValidatorResignationBuilder.java | 24 +++++++++++++++ ...ration.java => ValidatorRegistration.java} | 4 +-- ...gnation.java => ValidatorResignation.java} | 4 +-- ... => ValidatorRegistrationBuilderTest.java} | 6 ++-- ...a => ValidatorResignationBuilderTest.java} | 6 ++-- ...st.java => ValidatorRegistrationTest.java} | 2 +- ...est.java => ValidatorResignationTest.java} | 2 +- ...st.java => ValidatorRegistrationTest.java} | 2 +- ...est.java => ValidatorResignationTest.java} | 2 +- 15 files changed, 75 insertions(+), 75 deletions(-) delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/DelegateRegistrationBuilder.java delete mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/DelegateResignationBuilder.java create mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java create mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilder.java rename src/main/java/org/arkecosystem/crypto/transactions/types/{DelegateRegistration.java => ValidatorRegistration.java} (91%) rename src/main/java/org/arkecosystem/crypto/transactions/types/{DelegateResignation.java => ValidatorResignation.java} (83%) rename src/test/java/org/arkecosystem/crypto/transactions/builder/{DelegateRegistrationBuilderTest.java => ValidatorRegistrationBuilderTest.java} (90%) rename src/test/java/org/arkecosystem/crypto/transactions/builder/{DelegateResignationBuilderTest.java => ValidatorResignationBuilderTest.java} (88%) rename src/test/java/org/arkecosystem/crypto/transactions/deserializers/{DelegateRegistrationTest.java => ValidatorRegistrationTest.java} (98%) rename src/test/java/org/arkecosystem/crypto/transactions/deserializers/{DelegateResignationTest.java => ValidatorResignationTest.java} (98%) rename src/test/java/org/arkecosystem/crypto/transactions/serializers/{DelegateRegistrationTest.java => ValidatorRegistrationTest.java} (97%) rename src/test/java/org/arkecosystem/crypto/transactions/serializers/{DelegateResignationTest.java => ValidatorResignationTest.java} (97%) diff --git a/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java b/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java index 59ef82da..5ee7d0de 100644 --- a/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java +++ b/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java @@ -3,12 +3,12 @@ public enum CoreTransactionTypes { TRANSFER(0), SECOND_SIGNATURE_REGISTRATION(1), - DELEGATE_REGISTRATION(2), + VALIDATOR_REGISTRATION(2), VOTE(3), MULTI_SIGNATURE_REGISTRATION(4), IPFS(5), MULTI_PAYMENT(6), - DELEGATE_RESIGNATION(7), + VALIDATOR_RESIGNATION(7), HTLC_LOCK(8), HTLC_CLAIM(9), HTLC_REFUND(10); diff --git a/src/main/java/org/arkecosystem/crypto/enums/Fees.java b/src/main/java/org/arkecosystem/crypto/enums/Fees.java index ea2a3103..e5e1321b 100644 --- a/src/main/java/org/arkecosystem/crypto/enums/Fees.java +++ b/src/main/java/org/arkecosystem/crypto/enums/Fees.java @@ -3,12 +3,12 @@ public enum Fees { TRANSFER(10_000_000L), SECOND_SIGNATURE_REGISTRATION(500_000_000L), - DELEGATE_REGISTRATION(2_500_000_000L), + VALIDATOR_REGISTRATION(2_500_000_000L), VOTE(100_000_000L), MULTI_SIGNATURE_REGISTRATION(500_000_000L), IPFS(500_000_000L), MULTI_PAYMENT(10_000_000L), - DELEGATE_RESIGNATION(2_500_000_000L), + VALIDATOR_RESIGNATION(2_500_000_000L), HTLC_LOCK(10_000_000L), HTLC_CLAIM(0L), HTLC_REFUND(0L); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java index 412e2dd2..73c494da 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java @@ -10,8 +10,8 @@ import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.enums.CoreTransactionTypes; import org.arkecosystem.crypto.enums.TransactionTypeGroup; -import org.arkecosystem.crypto.transactions.types.DelegateRegistration; -import org.arkecosystem.crypto.transactions.types.DelegateResignation; +import org.arkecosystem.crypto.transactions.types.ValidatorRegistration; +import org.arkecosystem.crypto.transactions.types.ValidatorResignation; import org.arkecosystem.crypto.transactions.types.MultiPayment; import org.arkecosystem.crypto.transactions.types.MultiSignatureRegistration; import org.arkecosystem.crypto.transactions.types.SecondSignatureRegistration; @@ -33,14 +33,14 @@ public Deserializer(String serialized) { CoreTransactionTypes.SECOND_SIGNATURE_REGISTRATION.getValue(), new SecondSignatureRegistration()); coreTransactionTypes.put( - CoreTransactionTypes.DELEGATE_REGISTRATION.getValue(), new DelegateRegistration()); + CoreTransactionTypes.VALIDATOR_REGISTRATION.getValue(), new ValidatorRegistration()); coreTransactionTypes.put(CoreTransactionTypes.VOTE.getValue(), new Vote()); coreTransactionTypes.put( CoreTransactionTypes.MULTI_SIGNATURE_REGISTRATION.getValue(), new MultiSignatureRegistration()); coreTransactionTypes.put(CoreTransactionTypes.MULTI_PAYMENT.getValue(), new MultiPayment()); coreTransactionTypes.put( - CoreTransactionTypes.DELEGATE_RESIGNATION.getValue(), new DelegateResignation()); + CoreTransactionTypes.VALIDATOR_RESIGNATION.getValue(), new ValidatorResignation()); transactionGroups.put(TransactionTypeGroup.CORE.getValue(), coreTransactionTypes); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/DelegateRegistrationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/DelegateRegistrationBuilder.java deleted file mode 100644 index 2dad6887..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/DelegateRegistrationBuilder.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import org.arkecosystem.crypto.enums.Fees; -import org.arkecosystem.crypto.transactions.types.DelegateRegistration; -import org.arkecosystem.crypto.transactions.types.Transaction; - -public class DelegateRegistrationBuilder - extends AbstractTransactionBuilder { - public DelegateRegistrationBuilder() { - super(); - this.transaction.fee = Fees.DELEGATE_REGISTRATION.getValue(); - } - - public DelegateRegistrationBuilder username(String username) { - this.transaction.asset.delegate.username = username; - - return this; - } - - @Override - public Transaction getTransactionInstance() { - return new DelegateRegistration(); - } - - @Override - public DelegateRegistrationBuilder instance() { - return this; - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/DelegateResignationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/DelegateResignationBuilder.java deleted file mode 100644 index 16205090..00000000 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/DelegateResignationBuilder.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.arkecosystem.crypto.transactions.builder; - -import org.arkecosystem.crypto.enums.Fees; -import org.arkecosystem.crypto.transactions.types.DelegateResignation; -import org.arkecosystem.crypto.transactions.types.Transaction; - -public class DelegateResignationBuilder - extends AbstractTransactionBuilder { - - public DelegateResignationBuilder() { - super(); - this.transaction.fee = Fees.DELEGATE_RESIGNATION.getValue(); - } - - @Override - public Transaction getTransactionInstance() { - return new DelegateResignation(); - } - - @Override - public DelegateResignationBuilder instance() { - return this; - } -} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java new file mode 100644 index 00000000..9918f6b7 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java @@ -0,0 +1,29 @@ +package org.arkecosystem.crypto.transactions.builder; + +import org.arkecosystem.crypto.enums.Fees; +import org.arkecosystem.crypto.transactions.types.ValidatorRegistration; +import org.arkecosystem.crypto.transactions.types.Transaction; + +public class ValidatorRegistrationBuilder + extends AbstractTransactionBuilder { + public ValidatorRegistrationBuilder() { + super(); + this.transaction.fee = Fees.VALIDATOR_REGISTRATION.getValue(); + } + + public ValidatorRegistrationBuilder username(String username) { + this.transaction.asset.delegate.username = username; + + return this; + } + + @Override + public Transaction getTransactionInstance() { + return new ValidatorRegistration(); + } + + @Override + public ValidatorRegistrationBuilder instance() { + return this; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilder.java new file mode 100644 index 00000000..657bf83a --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilder.java @@ -0,0 +1,24 @@ +package org.arkecosystem.crypto.transactions.builder; + +import org.arkecosystem.crypto.enums.Fees; +import org.arkecosystem.crypto.transactions.types.ValidatorResignation; +import org.arkecosystem.crypto.transactions.types.Transaction; + +public class ValidatorResignationBuilder + extends AbstractTransactionBuilder { + + public ValidatorResignationBuilder() { + super(); + this.transaction.fee = Fees.VALIDATOR_RESIGNATION.getValue(); + } + + @Override + public Transaction getTransactionInstance() { + return new ValidatorResignation(); + } + + @Override + public ValidatorResignationBuilder instance() { + return this; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/DelegateRegistration.java b/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java similarity index 91% rename from src/main/java/org/arkecosystem/crypto/transactions/types/DelegateRegistration.java rename to src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java index 13d9ae63..4ded65bd 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/DelegateRegistration.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java @@ -6,10 +6,10 @@ import org.arkecosystem.crypto.enums.CoreTransactionTypes; import org.arkecosystem.crypto.enums.TransactionTypeGroup; -public class DelegateRegistration extends Transaction { +public class ValidatorRegistration extends Transaction { @Override public int getTransactionType() { - return CoreTransactionTypes.DELEGATE_REGISTRATION.getValue(); + return CoreTransactionTypes.VALIDATOR_REGISTRATION.getValue(); } @Override diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/DelegateResignation.java b/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorResignation.java similarity index 83% rename from src/main/java/org/arkecosystem/crypto/transactions/types/DelegateResignation.java rename to src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorResignation.java index ed3821a1..5fda19c3 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/DelegateResignation.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorResignation.java @@ -5,10 +5,10 @@ import org.arkecosystem.crypto.enums.CoreTransactionTypes; import org.arkecosystem.crypto.enums.TransactionTypeGroup; -public class DelegateResignation extends Transaction { +public class ValidatorResignation extends Transaction { @Override public int getTransactionType() { - return CoreTransactionTypes.DELEGATE_RESIGNATION.getValue(); + return CoreTransactionTypes.VALIDATOR_RESIGNATION.getValue(); } @Override diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/DelegateRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java similarity index 90% rename from src/test/java/org/arkecosystem/crypto/transactions/builder/DelegateRegistrationBuilderTest.java rename to src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java index 5626dffc..8b8cd6d6 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/DelegateRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java @@ -6,11 +6,11 @@ import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; -class DelegateRegistrationBuilderTest { +class ValidatorRegistrationBuilderTest { @Test void build() { Transaction actual = - new DelegateRegistrationBuilder() + new ValidatorRegistrationBuilder() .username("java") .version(2) .nonce(3) @@ -28,7 +28,7 @@ void build() { @Test void buildSecondSignature() { Transaction actual = - new DelegateRegistrationBuilder() + new ValidatorRegistrationBuilder() .username("java") .version(2) .nonce(3) diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/DelegateResignationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java similarity index 88% rename from src/test/java/org/arkecosystem/crypto/transactions/builder/DelegateResignationBuilderTest.java rename to src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java index e28451f5..14409dc3 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/DelegateResignationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java @@ -6,11 +6,11 @@ import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; -public class DelegateResignationBuilderTest { +public class ValidatorResignationBuilderTest { @Test void build() { Transaction actual = - new DelegateResignationBuilder() + new ValidatorResignationBuilder() .version(2) .nonce(3) .sign("this is a top secret passphrase") @@ -26,7 +26,7 @@ void build() { @Test void buildSecondSignature() { Transaction actual = - new DelegateResignationBuilder() + new ValidatorResignationBuilder() .version(2) .nonce(3) .sign("this is a top secret passphrase") diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/DelegateRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java similarity index 98% rename from src/test/java/org/arkecosystem/crypto/transactions/deserializers/DelegateRegistrationTest.java rename to src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java index 12953b7d..4c11142d 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/DelegateRegistrationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java @@ -9,7 +9,7 @@ import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; -public class DelegateRegistrationTest { +public class ValidatorRegistrationTest { @Test void passphrase() { diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/DelegateResignationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorResignationTest.java similarity index 98% rename from src/test/java/org/arkecosystem/crypto/transactions/deserializers/DelegateResignationTest.java rename to src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorResignationTest.java index ff8d4b07..ac71587a 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/DelegateResignationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorResignationTest.java @@ -10,7 +10,7 @@ import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; -class DelegateResignationTest { +class ValidatorResignationTest { @Test void passphrase() { diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/DelegateRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java similarity index 97% rename from src/test/java/org/arkecosystem/crypto/transactions/serializers/DelegateRegistrationTest.java rename to src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java index e05723fb..03481d2c 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/DelegateRegistrationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java @@ -10,7 +10,7 @@ import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; -class DelegateRegistrationTest { +class ValidatorRegistrationTest { @Test void passphrase() { LinkedTreeMap fixture = diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/DelegateResignationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorResignationTest.java similarity index 97% rename from src/test/java/org/arkecosystem/crypto/transactions/serializers/DelegateResignationTest.java rename to src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorResignationTest.java index 849c0de1..6ace2e73 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/DelegateResignationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorResignationTest.java @@ -10,7 +10,7 @@ import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; -class DelegateResignationTest { +class ValidatorResignationTest { @Test void passphrase() { From 6def5868d545220e4a753bf95c391446e60d68cb Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 13:16:29 -0600 Subject: [PATCH 31/74] validator registration tests --- .../crypto/transactions/TransactionAsset.java | 6 +--- .../builder/ValidatorRegistrationBuilder.java | 4 +-- .../types/ValidatorRegistration.java | 23 +++++------- .../ValidatorRegistrationBuilderTest.java | 25 +++---------- .../ValidatorRegistrationTest.java | 35 +++---------------- .../ValidatorRegistrationTest.java | 13 +------ 6 files changed, 21 insertions(+), 85 deletions(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java index a82f632d..b69e19bc 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java @@ -8,20 +8,16 @@ public class TransactionAsset { public Signature signature = new Signature(); public List votes = new ArrayList<>(); public List unvotes = new ArrayList<>(); - public Delegate delegate = new Delegate(); public MultiSignature multiSignature = new MultiSignature(); public MultiPayment multiPayment = new MultiPayment(); public HashMap customAsset = new HashMap<>(); public long amount = 0L; + public String validatorPublicKey; public static class Signature { public String publicKey; } - public static class Delegate { - public String username; - } - public static class MultiSignature { public byte min; public List publicKeys = new ArrayList<>(); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java index 9918f6b7..b2db14d6 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java @@ -11,8 +11,8 @@ public ValidatorRegistrationBuilder() { this.transaction.fee = Fees.VALIDATOR_REGISTRATION.getValue(); } - public ValidatorRegistrationBuilder username(String username) { - this.transaction.asset.delegate.username = username; + public ValidatorRegistrationBuilder publicKeyAsset(String publicKey) { + this.transaction.asset.validatorPublicKey = publicKey; return this; } diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java b/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java index 4ded65bd..b473cd67 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java @@ -3,6 +3,8 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.HashMap; + +import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.enums.CoreTransactionTypes; import org.arkecosystem.crypto.enums.TransactionTypeGroup; @@ -21,31 +23,24 @@ public int getTransactionTypeGroup() { public HashMap assetToHashMap() { HashMap asset = new HashMap<>(); - HashMap delegate = new HashMap<>(); - delegate.put("username", this.asset.delegate.username); - asset.put("delegate", delegate); + asset.put("validatorPublicKey", this.asset.validatorPublicKey); return asset; } @Override public byte[] serialize() { - byte[] delegateBytes = this.asset.delegate.username.getBytes(); - - ByteBuffer buffer = ByteBuffer.allocate(1 + delegateBytes.length); + ByteBuffer buffer = ByteBuffer.allocate(48); buffer.order(ByteOrder.LITTLE_ENDIAN); - buffer.put((byte) delegateBytes.length); - buffer.put(delegateBytes); + buffer.put(Hex.decode(this.asset.validatorPublicKey)); + return buffer.array(); } @Override public void deserialize(ByteBuffer buffer) { - int usernameLength = buffer.get(); - - byte[] username = new byte[usernameLength]; - buffer.get(username); - - this.asset.delegate.username = new String(username); + byte[] validatorPublicKey = new byte[48]; + buffer.get(validatorPublicKey); + this.asset.validatorPublicKey = Hex.encode(validatorPublicKey); } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java index 8b8cd6d6..6cd9506a 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java @@ -11,34 +11,17 @@ class ValidatorRegistrationBuilderTest { void build() { Transaction actual = new ValidatorRegistrationBuilder() - .username("java") - .version(2) + .publicKeyAsset("a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118") .nonce(3) .sign("this is a top secret passphrase") .transaction; HashMap actualHashMap = actual.toHashMap(); - HashMap actualAsset = (HashMap) actualHashMap.get("asset"); - HashMap delegate = (HashMap) actualAsset.get("delegate"); - assertEquals(delegate.get("username"), "java"); + + HashMap asset = (HashMap) actualHashMap.get("asset"); - assertTrue(actual.verify()); - } - - @Test - void buildSecondSignature() { - Transaction actual = - new ValidatorRegistrationBuilder() - .username("java") - .version(2) - .nonce(3) - .sign("this is a top secret passphrase") - .secondSign("this is a top secret second passphrase") - .transaction; + assertEquals(asset.get("validatorPublicKey"), "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118"); assertTrue(actual.verify()); - assertTrue( - actual.secondVerify( - "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java index 4c11142d..2b25c6a9 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java @@ -14,7 +14,7 @@ public class ValidatorRegistrationTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/delegate-registration-sign"); + FixtureLoader.load("transactions/validator_registration/validator-registration-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -30,35 +30,8 @@ void passphrase() { assertEquals(data.get("signature").toString(), actual.signature); assertEquals(data.get("id").toString(), actual.id); - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("delegate"); - assertEquals((asset.get("username")), actual.asset.delegate.username); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/delegate-registration-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - LinkedTreeMap asset = - (LinkedTreeMap) - ((LinkedTreeMap) data.get("asset")).get("delegate"); - assertEquals((asset.get("username")), actual.asset.delegate.username); - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); + LinkedTreeMap asset = (LinkedTreeMap) data.get("asset"); + + assertEquals((asset.get("validatorPublicKey")), actual.asset.validatorPublicKey); } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java index 03481d2c..15465519 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java @@ -14,7 +14,7 @@ class ValidatorRegistrationTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/delegate-registration-sign"); + FixtureLoader.load("transactions/validator_registration/validator-registration-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); @@ -23,15 +23,4 @@ void passphrase() { assertEquals(fixture.get("serialized").toString(), actual); } - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/delegate-registration-secondSign"); - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } } From 38050a19b205ae81a390751c1c1a0f8490cc97db Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 13:18:22 -0600 Subject: [PATCH 32/74] adjust validator resignation tests --- .../ValidatorResignationBuilderTest.java | 2 -- .../ValidatorResignationTest.java | 25 +------------------ .../serializers/ValidatorResignationTest.java | 15 +---------- 3 files changed, 2 insertions(+), 40 deletions(-) diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java index 14409dc3..b42b367f 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java @@ -11,7 +11,6 @@ public class ValidatorResignationBuilderTest { void build() { Transaction actual = new ValidatorResignationBuilder() - .version(2) .nonce(3) .sign("this is a top secret passphrase") .transaction; @@ -27,7 +26,6 @@ void build() { void buildSecondSignature() { Transaction actual = new ValidatorResignationBuilder() - .version(2) .nonce(3) .sign("this is a top secret passphrase") .secondSign("this is a top secret second passphrase") diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorResignationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorResignationTest.java index ac71587a..dcfd7407 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorResignationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorResignationTest.java @@ -15,7 +15,7 @@ class ValidatorResignationTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/delegate-resignation-sign"); + FixtureLoader.load("transactions/validator_resignation/validator-resignation-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -33,27 +33,4 @@ void passphrase() { assertNull(data.get("asset")); } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/delegate-resignation-secondSign"); - - LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - assertEquals(((Double) data.get("version")).intValue(), actual.version); - assertEquals(((Double) data.get("network")).intValue(), actual.network); - assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); - assertEquals(((Double) data.get("type")).intValue(), actual.type); - assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); - assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); - assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); - assertEquals(data.get("signature").toString(), actual.signature); - assertEquals(data.get("id").toString(), actual.id); - - assertNull(data.get("asset")); - assertEquals(data.get("secondSignature").toString(), actual.secondSignature); - } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorResignationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorResignationTest.java index 6ace2e73..208e1d11 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorResignationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorResignationTest.java @@ -15,20 +15,7 @@ class ValidatorResignationTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/delegate-resignation-sign"); - - Transaction transaction = - new Deserializer(fixture.get("serialized").toString()).deserialize(); - - String actual = Hex.encode(Serializer.serialize(transaction)); - - assertEquals(fixture.get("serialized").toString(), actual); - } - - @Test - void secondPassphrase() { - LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/delegate-resignation-secondSign"); + FixtureLoader.load("transactions/validator_resignation/validator-resignation-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); From 59ed9f6939db026f7473ee98ca23627ac8b3e143 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 13:26:14 -0600 Subject: [PATCH 33/74] Update MultiSignatureRegistrationBuilderTest.java --- .../builder/MultiSignatureRegistrationBuilderTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java index d377a25a..894ab34c 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java @@ -27,9 +27,7 @@ void build() { Transaction actual = new MultiSignatureRegistrationBuilder() - .version(2) .nonce(3) - .network(23) .fee(Fees.MULTI_SIGNATURE_REGISTRATION.getValue()) .publicKeys(publicKeys) .min(3) @@ -65,7 +63,7 @@ void checkMultiSignaturePassingInvalidMultiSignatureAsset() { () -> { Deserializer deserializer = new Deserializer( - "ff0217010000000000010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01580969800000000000000c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f55366200c01c44bf33bea20a74d5acc12c5d6aafe82240f3571121382b77c871f4b33d6da2b62fdc6ca2cc6bc583abb2a69e7975be29e8d80a59c52bcff8d54514cf999e01830a2e319f2070f3519bc22c2d449acdb7691bf9dd25e3649a72ac843e08ce26e0b87e30e65b73f853cf8e375dbc495cc75c6fd199bf4b15327bf8c5ec4bfac50292c299b739f0cb5e36133d85f51fff2fcc7745e8af4d0778908560c0874e3f2303e0436eabce1c09d88efab0004e61c5d6e47768aa8d2ab0cb9f14d523a38308"); + "ff011e0100000004000200000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d30065cd1d00000000000203029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca9203629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc52b33558cdc62933ff56feb646d1f47a98104bf34b894895d5e816f86e556f87fce8485e55aa32dfa1cd86456a66a58ef7a68dff4af51e2f7fcf75b983540872e000caa6864c71362b369c71107f463f29c43c361e54260cbc54d791b7385dbe76f29d12b9befbe4f98792d7046481afcf0c156408310192a93d8413e5380438f270153a22c5ce2b1894f0a141adc19de567077d2d268f4c7e1476e9558ecb4411d486cd0d7aa3e9c7716739a055a8a1a64a162d0362645d63d13791a9876ef8b5a88021d56997f0c9e21201c59e1b7b6be8d5a609908a4f65bf266144baf5e61e3f14bc2651f62187f4ffa17c8b010fcb0fba94a04df56bc25e5cb20935ec5fb7ad632"); Transaction actual = deserializer.deserialize(); assertTrue(actual.multiVerify(3, Collections.emptyList())); }); @@ -80,7 +78,7 @@ void checkMultiSignaturePassingInvalidMultiSignatureAssets() { Deserializer deserializer = new Deserializer( - "ff0217010000000000010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01580969800000000000000c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f55366200c01c44bf33bea20a74d5acc12c5d6aafe82240f3571121382b77c871f4b33d6da2b62fdc6ca2cc6bc583abb2a69e7975be29e8d80a59c52bcff8d54514cf999e0192c299b739f0cb5e36133d85f51fff2fcc7745e8af4d0778908560c0874e3f2303e0436eabce1c09d88efab0004e61c5d6e47768aa8d2ab0cb9f14d523a3830802830a2e319f2070f3519bc22c2d449acdb7691bf9dd25e3649a72ac843e08ce26e0b87e30e65b73f853cf8e375dbc495cc75c6fd199bf4b15327bf8c5ec4bfac5"); + "ff011e0100000004000200000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d30065cd1d00000000000203029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca9203629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc52b33558cdc62933ff56feb646d1f47a98104bf34b894895d5e816f86e556f87fce8485e55aa32dfa1cd86456a66a58ef7a68dff4af51e2f7fcf75b983540872e000caa6864c71362b369c71107f463f29c43c361e54260cbc54d791b7385dbe76f29d12b9befbe4f98792d7046481afcf0c156408310192a93d8413e5380438f270153a22c5ce2b1894f0a141adc19de567077d2d268f4c7e1476e9558ecb4411d486cd0d7aa3e9c7716739a055a8a1a64a162d0362645d63d13791a9876ef8b5a88021d56997f0c9e21201c59e1b7b6be8d5a609908a4f65bf266144baf5e61e3f14bc2651f62187f4ffa17c8b010fcb0fba94a04df56bc25e5cb20935ec5fb7ad632"); Transaction actual = deserializer.deserialize(); assertFalse(actual.multiVerify(3, Arrays.asList(key1, key2, key3))); } From a7a3ece9323ed24349ff7117e7fb0d26121802db Mon Sep 17 00:00:00 2001 From: alfonsobries Date: Mon, 5 Aug 2024 19:28:02 +0000 Subject: [PATCH 34/74] style: resolve style guide violations --- .../arkecosystem/crypto/transactions/Deserializer.java | 9 +++++---- .../builder/ValidatorRegistrationBuilder.java | 2 +- .../builder/ValidatorResignationBuilder.java | 2 +- .../crypto/transactions/types/MultiPayment.java | 8 +++++--- .../crypto/transactions/types/ValidatorRegistration.java | 3 +-- .../builder/ValidatorRegistrationBuilderTest.java | 9 ++++++--- .../transactions/deserializers/MultiPaymentTest.java | 3 ++- .../deserializers/ValidatorRegistrationTest.java | 5 +++-- .../transactions/serializers/MultiPaymentTest.java | 3 ++- .../serializers/ValidatorRegistrationTest.java | 4 ++-- 10 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java index 73c494da..32730ef9 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java @@ -10,13 +10,13 @@ import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.enums.CoreTransactionTypes; import org.arkecosystem.crypto.enums.TransactionTypeGroup; -import org.arkecosystem.crypto.transactions.types.ValidatorRegistration; -import org.arkecosystem.crypto.transactions.types.ValidatorResignation; import org.arkecosystem.crypto.transactions.types.MultiPayment; import org.arkecosystem.crypto.transactions.types.MultiSignatureRegistration; import org.arkecosystem.crypto.transactions.types.SecondSignatureRegistration; import org.arkecosystem.crypto.transactions.types.Transaction; import org.arkecosystem.crypto.transactions.types.Transfer; +import org.arkecosystem.crypto.transactions.types.ValidatorRegistration; +import org.arkecosystem.crypto.transactions.types.ValidatorResignation; import org.arkecosystem.crypto.transactions.types.Vote; public class Deserializer { @@ -33,7 +33,8 @@ public Deserializer(String serialized) { CoreTransactionTypes.SECOND_SIGNATURE_REGISTRATION.getValue(), new SecondSignatureRegistration()); coreTransactionTypes.put( - CoreTransactionTypes.VALIDATOR_REGISTRATION.getValue(), new ValidatorRegistration()); + CoreTransactionTypes.VALIDATOR_REGISTRATION.getValue(), + new ValidatorRegistration()); coreTransactionTypes.put(CoreTransactionTypes.VOTE.getValue(), new Vote()); coreTransactionTypes.put( CoreTransactionTypes.MULTI_SIGNATURE_REGISTRATION.getValue(), @@ -41,7 +42,7 @@ public Deserializer(String serialized) { coreTransactionTypes.put(CoreTransactionTypes.MULTI_PAYMENT.getValue(), new MultiPayment()); coreTransactionTypes.put( CoreTransactionTypes.VALIDATOR_RESIGNATION.getValue(), new ValidatorResignation()); - + transactionGroups.put(TransactionTypeGroup.CORE.getValue(), coreTransactionTypes); this.buffer = ByteBuffer.wrap(Hex.decode(serialized)).slice(); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java index b2db14d6..37993eee 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilder.java @@ -1,8 +1,8 @@ package org.arkecosystem.crypto.transactions.builder; import org.arkecosystem.crypto.enums.Fees; -import org.arkecosystem.crypto.transactions.types.ValidatorRegistration; import org.arkecosystem.crypto.transactions.types.Transaction; +import org.arkecosystem.crypto.transactions.types.ValidatorRegistration; public class ValidatorRegistrationBuilder extends AbstractTransactionBuilder { diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilder.java index 657bf83a..220f0e44 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilder.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilder.java @@ -1,8 +1,8 @@ package org.arkecosystem.crypto.transactions.builder; import org.arkecosystem.crypto.enums.Fees; -import org.arkecosystem.crypto.transactions.types.ValidatorResignation; import org.arkecosystem.crypto.transactions.types.Transaction; +import org.arkecosystem.crypto.transactions.types.ValidatorResignation; public class ValidatorResignationBuilder extends AbstractTransactionBuilder { diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/MultiPayment.java b/src/main/java/org/arkecosystem/crypto/transactions/types/MultiPayment.java index e0c61ca6..78a0db32 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/MultiPayment.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/MultiPayment.java @@ -58,15 +58,17 @@ public byte[] serialize() { @Override public void deserialize(ByteBuffer buffer) { int paymentLength = buffer.getShort() & 0xff; - + for (int i = 0; i < paymentLength; i++) { byte[] recipientId = new byte[20]; long amount = buffer.getLong(); buffer.get(recipientId); this.asset.multiPayment.payments.add( - new TransactionAsset.Payment(amount, Keys.toChecksumAddress("0x" + Hex.encode(recipientId)))); + new TransactionAsset.Payment( + amount, Keys.toChecksumAddress("0x" + Hex.encode(recipientId)))); } - this.asset.amount = this.asset.multiPayment.payments.stream().mapToLong(p -> p.amount).sum(); + this.asset.amount = + this.asset.multiPayment.payments.stream().mapToLong(p -> p.amount).sum(); } } diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java b/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java index b473cd67..8e085dfb 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/ValidatorRegistration.java @@ -3,7 +3,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.HashMap; - import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.enums.CoreTransactionTypes; import org.arkecosystem.crypto.enums.TransactionTypeGroup; @@ -33,7 +32,7 @@ public byte[] serialize() { ByteBuffer buffer = ByteBuffer.allocate(48); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.put(Hex.decode(this.asset.validatorPublicKey)); - + return buffer.array(); } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java index 6cd9506a..1a28a767 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java @@ -11,16 +11,19 @@ class ValidatorRegistrationBuilderTest { void build() { Transaction actual = new ValidatorRegistrationBuilder() - .publicKeyAsset("a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118") + .publicKeyAsset( + "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118") .nonce(3) .sign("this is a top secret passphrase") .transaction; HashMap actualHashMap = actual.toHashMap(); - + HashMap asset = (HashMap) actualHashMap.get("asset"); - assertEquals(asset.get("validatorPublicKey"), "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118"); + assertEquals( + asset.get("validatorPublicKey"), + "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118"); assertTrue(actual.verify()); } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/MultiPaymentTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/MultiPaymentTest.java index 16e9f3f0..1c58f300 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/MultiPaymentTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/MultiPaymentTest.java @@ -45,7 +45,8 @@ void passphrase() { @Test void passphraseVendorField() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/multi_payment/multi-payment-with-vendor-field-sign"); + FixtureLoader.load( + "transactions/multi_payment/multi-payment-with-vendor-field-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java index 2b25c6a9..c0b1edda 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/ValidatorRegistrationTest.java @@ -14,7 +14,8 @@ public class ValidatorRegistrationTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/validator_registration/validator-registration-sign"); + FixtureLoader.load( + "transactions/validator_registration/validator-registration-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); @@ -31,7 +32,7 @@ void passphrase() { assertEquals(data.get("id").toString(), actual.id); LinkedTreeMap asset = (LinkedTreeMap) data.get("asset"); - + assertEquals((asset.get("validatorPublicKey")), actual.asset.validatorPublicKey); } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java index 22ef2700..017d047b 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/MultiPaymentTest.java @@ -26,7 +26,8 @@ void passphrase() { @Test void passphraseVendorField() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/multi_payment/multi-payment-with-vendor-field-sign"); + FixtureLoader.load( + "transactions/multi_payment/multi-payment-with-vendor-field-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java index 15465519..ec1d8cb6 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/ValidatorRegistrationTest.java @@ -14,7 +14,8 @@ class ValidatorRegistrationTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/validator_registration/validator-registration-sign"); + FixtureLoader.load( + "transactions/validator_registration/validator-registration-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); @@ -22,5 +23,4 @@ void passphrase() { assertEquals(fixture.get("serialized").toString(), actual); } - } From 3c2ea6d59ca4d16d94195e28e358d11f39bd2071 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 14:00:47 -0600 Subject: [PATCH 35/74] fixture sign verification adjustments --- .../FixtureSignVerificationTest.java | 188 ++++++------------ .../transactions/vote/unvote-sign.json | 11 +- 2 files changed, 67 insertions(+), 132 deletions(-) diff --git a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java index 7d5099f8..c9be3f6e 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java @@ -17,102 +17,49 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; + public class FixtureSignVerificationTest { - private final String passphrase = "this is a top secret passphrase"; + private final String passphrase = "my super secret passphrase"; private final String secondPassphrase = "this is a top secret second passphrase"; - private final String musigPassphrase1 = "this is a top secret passphrase 1"; - private final String musigPassphrase2 = "this is a top secret passphrase 2"; - private final String musigPassphrase3 = "this is a top secret passphrase 3"; + private final String musigPassphrase1 = "album pony urban cheap small blade cannon silent run reveal luxury glad predict excess fire beauty hollow reward solar egg exclude leaf sight degree"; + private final String musigPassphrase2 = "hen slogan retire boss upset blame rocket slender area arch broom bring elder few milk bounce execute page evoke once inmate pear marine deliver"; + private final String musigPassphrase3 = "top visa use bacon sun infant shrimp eye bridge fantasy chair sadness stable simple salad canoe raw hill target connect avoid promote spider category"; @ParameterizedTest @ValueSource( strings = { - "transactions/v2-ecdsa/second-signature-registration", - "transactions/v2-ecdsa/transfer-with-vendor-field-secondSign", - "transactions/v2-ecdsa/transfer-secondSign", - "transactions/v2-ecdsa/transfer-sign", - "transactions/v2-ecdsa/multi-payment-secondSign", - "transactions/v2-ecdsa/delegate-resignation-secondSign", - "transactions/v2-ecdsa/htlc-claim-sign", - "transactions/v2-ecdsa/htlc-claim-secondSign", - "transactions/v2-ecdsa/htlc-lock-sign", - "transactions/v2-ecdsa/htlc-refund-secondSign", - "transactions/v2-ecdsa/delegate-registration-sign", - "transactions/v2-ecdsa/vote-sign", - "transactions/v2-ecdsa/multi-payment-sign", - "transactions/v2-ecdsa/multi-payment-with-vendor-field-sign", - "transactions/v2-ecdsa/delegate-registration-secondSign", - "transactions/v2-ecdsa/ipfs-secondSign", - "transactions/v2-ecdsa/htlc-lock-secondSign", - "transactions/v2-ecdsa/unvote-sign", - "transactions/v2-ecdsa/vote-secondSign", - "transactions/v2-ecdsa/delegate-resignation-sign", - "transactions/v2-ecdsa/htlc-lock-with-vendor-field-sign", - "transactions/v2-ecdsa/ipfs-sign", - "transactions/v2-ecdsa/htlc-lock-with-vendor-field-secondSign", - "transactions/v2-ecdsa/unvote-secondSign", - "transactions/v2-ecdsa/transfer-with-vendor-field-sign", - "transactions/v2-ecdsa/multi-payment-with-vendor-field-secondSign", - "transactions/v2-ecdsa/htlc-refund-sign", - }) - void checkEcdsa(String file) { - LinkedTreeMap fixture = FixtureLoader.load(file); + "transactions/transfer/transfer-sign", + "transactions/transfer/transfer-with-vendor-field-sign", + // "transactions/transfer/transfer-multi-sign", + + "transactions/vote/vote-sign", + "transactions/vote/unvote-sign", + // "transactions/vote/vote-multi-sign", - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); + "transactions/validator_registration/validator-registration-sign", + // "transactions/validator_registration/validator-registration-multi-sign", - assertTrue(actual.verify()); - } + "transactions/validator_resignation/validator-resignation-sign", + // "transactions/validator_resignation/validator-resignation-multi-sign", - @ParameterizedTest - @ValueSource( - strings = { - "transactions/v2-schnorr/second-signature-registration", - "transactions/v2-schnorr/transfer-with-vendor-field-secondSign", - "transactions/v2-schnorr/transfer-secondSign", - "transactions/v2-schnorr/multi-signature-registration", - "transactions/v2-schnorr/transfer-sign", - "transactions/v2-schnorr/multi-payment-secondSign", - "transactions/v2-schnorr/delegate-resignation-secondSign", - "transactions/v2-schnorr/htlc-claim-sign", - "transactions/v2-schnorr/htlc-claim-secondSign", - "transactions/v2-schnorr/htlc-lock-sign", - "transactions/v2-schnorr/htlc-refund-secondSign", - "transactions/v2-schnorr/delegate-registration-sign", - "transactions/v2-schnorr/vote-sign", - "transactions/v2-schnorr/multi-payment-sign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-sign", - "transactions/v2-schnorr/delegate-registration-secondSign", - "transactions/v2-schnorr/ipfs-secondSign", - "transactions/v2-schnorr/htlc-lock-secondSign", - "transactions/v2-schnorr/unvote-sign", - "transactions/v2-schnorr/vote-secondSign", - "transactions/v2-schnorr/delegate-resignation-sign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-sign", - "transactions/v2-schnorr/ipfs-sign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign", - "transactions/v2-schnorr/unvote-secondSign", - "transactions/v2-schnorr/transfer-with-vendor-field-sign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign", - "transactions/v2-schnorr/htlc-refund-sign", - "transactions/v2-schnorr/htlc-lock-multiSign", - "transactions/v2-schnorr/htlc-claim-multiSign", - "transactions/v2-schnorr/htlc-refund-multiSign", - "transactions/v2-schnorr/ipfs-multiSign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign", - "transactions/v2-schnorr/vote-multiSign", - "transactions/v2-schnorr/multi-payment-multiSign", - "transactions/v2-schnorr/transfer-with-vendor-field-multiSign", - "transactions/v2-schnorr/unvote-multiSign", - "transactions/v2-schnorr/delegate-registration-multiSign", - "transactions/v2-schnorr/transfer-multiSign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign", - "transactions/v2-schnorr/delegate-resignation-multiSign", + "transactions/multi_payment/multi-payment-sign", + "transactions/multi_payment/multi-payment-with-vendor-field-sign", + // "transactions/multi_payment/multi-payment-multi-sign", + + // "transactions/username_resignation/username-resignation-sign", + // "transactions/username_resignation/username-resignation-multi-sign", + + // "transactions/username_registration/username-registration-multi-sign", + // "transactions/username_registration/username-registration-sign", + + "transactions/multi_signature_registration/multi-signature-registration-sign", }) void checkSchnorrSignature(String file) { LinkedTreeMap fixture = FixtureLoader.load(file); Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); + if (actual.signature != null) assertTrue(actual.verify()); @@ -128,47 +75,31 @@ void checkSchnorrSignature(String file) { @ParameterizedTest @ValueSource( strings = { - "transactions/v2-schnorr/second-signature-registration", - "transactions/v2-schnorr/transfer-with-vendor-field-secondSign", - "transactions/v2-schnorr/transfer-secondSign", - "transactions/v2-schnorr/multi-signature-registration", - "transactions/v2-schnorr/transfer-sign", - "transactions/v2-schnorr/multi-payment-secondSign", - "transactions/v2-schnorr/delegate-resignation-secondSign", - "transactions/v2-schnorr/htlc-claim-sign", - "transactions/v2-schnorr/htlc-claim-secondSign", - "transactions/v2-schnorr/htlc-lock-sign", - "transactions/v2-schnorr/htlc-refund-secondSign", - "transactions/v2-schnorr/delegate-registration-sign", - "transactions/v2-schnorr/vote-sign", - "transactions/v2-schnorr/multi-payment-sign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-sign", - "transactions/v2-schnorr/delegate-registration-secondSign", - "transactions/v2-schnorr/ipfs-secondSign", - "transactions/v2-schnorr/htlc-lock-secondSign", - "transactions/v2-schnorr/unvote-sign", - "transactions/v2-schnorr/vote-secondSign", - "transactions/v2-schnorr/delegate-resignation-sign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-sign", - "transactions/v2-schnorr/ipfs-sign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-secondSign", - "transactions/v2-schnorr/unvote-secondSign", - "transactions/v2-schnorr/transfer-with-vendor-field-sign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-secondSign", - "transactions/v2-schnorr/htlc-refund-sign", - "transactions/v2-schnorr/htlc-lock-multiSign", - "transactions/v2-schnorr/htlc-claim-multiSign", - "transactions/v2-schnorr/htlc-refund-multiSign", - "transactions/v2-schnorr/ipfs-multiSign", - "transactions/v2-schnorr/htlc-lock-with-vendor-field-multiSign", - "transactions/v2-schnorr/vote-multiSign", - "transactions/v2-schnorr/multi-payment-multiSign", - "transactions/v2-schnorr/transfer-with-vendor-field-multiSign", - "transactions/v2-schnorr/unvote-multiSign", - "transactions/v2-schnorr/delegate-registration-multiSign", - "transactions/v2-schnorr/transfer-multiSign", - "transactions/v2-schnorr/multi-payment-with-vendor-field-multiSign", - "transactions/v2-schnorr/delegate-resignation-multiSign", + "transactions/transfer/transfer-sign", + "transactions/transfer/transfer-with-vendor-field-sign", + // "transactions/transfer/transfer-multi-sign", + + "transactions/vote/vote-sign", + "transactions/vote/unvote-sign", + // "transactions/vote/vote-multi-sign", + + "transactions/validator_registration/validator-registration-sign", + // "transactions/validator_registration/validator-registration-multi-sign", + + "transactions/validator_resignation/validator-resignation-sign", + // "transactions/validator_resignation/validator-resignation-multi-sign", + + "transactions/multi_payment/multi-payment-sign", + "transactions/multi_payment/multi-payment-with-vendor-field-sign", + // "transactions/multi_payment/multi-payment-multi-sign", + + // "transactions/username_resignation/username-resignation-sign", + // "transactions/username_resignation/username-resignation-multi-sign", + + // "transactions/username_registration/username-registration-multi-sign", + // "transactions/username_registration/username-registration-sign", + + // "transactions/multi_signature_registration/multi-signature-registration-sign", }) void checkSigningAgainProducesSameSignature(String file) { LinkedTreeMap fixture = FixtureLoader.load(file); @@ -194,14 +125,23 @@ void checkSigningAgainProducesSameSignature(String file) { if (withoutSignatures.secondSignature != null) { checkSecondSignature(withoutSignatures); } + + int signatureLength = 128; if (withoutSignatures.signatures != null) { checkMultiSignature(withoutSignatures); + + signatureLength = 128 + (withoutSignatures.signatures.size() * 130); } + String serializedWithoutSignatures = Hex.encode(Serializer.serialize(withoutSignatures)); + String serializedFixture = fixture.get("serialized").toString(); + + // Exclude the last 128 characters (signature) for final comparison assertThat( - Hex.encode(Serializer.serialize(withoutSignatures)), - is(fixture.get("serialized").toString())); + serializedWithoutSignatures.substring(0, serializedWithoutSignatures.length() - signatureLength), + is(serializedFixture.substring(0, serializedFixture.length() - signatureLength))); + } private void reSignUnsigned(Transaction actual, Transaction withoutSignatures) { diff --git a/src/test/resources/transactions/vote/unvote-sign.json b/src/test/resources/transactions/vote/unvote-sign.json index 14641e6c..e169bdf6 100644 --- a/src/test/resources/transactions/vote/unvote-sign.json +++ b/src/test/resources/transactions/vote/unvote-sign.json @@ -14,13 +14,8 @@ ], "votes": [] }, - "signature": "ce9ab70d7d23b42ce597b000154235a1b895b160f64eb5a71549a2db2befe12c282ac92795595f524f673f901708818508caf8bb819356dde234c015843eda5f", - "signatures": [ - "0093e06e1c463f3f4cfdeefc7b40bea3b93e21a3f652f15ea3e0014292b7c9790c660f5a5cb3b48f7e024b69fcf01bcd7d796cba8f20f21cdb4de60b7ed6420408", - "014c664d9f54189d6db3cd5e4cae11bffee7322107e688d8eae64edc93937c976d5c51125f4d8b123449fc55bc2a38c789d2c36149fbcc3b2ae64bb64d08dbea2c", - "023ac8e92f15afce7c339e5f6575b7a9c88e1f3f89015c7952e216acb307fb35f342a81b94dacc72052c64832268cccc8ae4c5d80cdf1a09817c58c514fe38ee58" - ], - "id": "40c9e1607f73480e1817b04440a9a8a7b4c6f8203417a5533401e782f875ce92" + "signature": "b7c16d70bd8503d3228d57dcb32468601e687849ebbbfe18b9ef2404ecf907f362a4e0a3326b6149d21256a77c7ba8ccbafddacc5bcb07c5f209e861a7f4cc66", + "id": "110a8a1bf940068cb555261f6715402623360bac6aebcdfde8c649d2a03b00db" }, - "serialized": "ff011e0100000003000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300e1f5050000000000000103f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabcce9ab70d7d23b42ce597b000154235a1b895b160f64eb5a71549a2db2befe12c282ac92795595f524f673f901708818508caf8bb819356dde234c015843eda5f0093e06e1c463f3f4cfdeefc7b40bea3b93e21a3f652f15ea3e0014292b7c9790c660f5a5cb3b48f7e024b69fcf01bcd7d796cba8f20f21cdb4de60b7ed6420408014c664d9f54189d6db3cd5e4cae11bffee7322107e688d8eae64edc93937c976d5c51125f4d8b123449fc55bc2a38c789d2c36149fbcc3b2ae64bb64d08dbea2c023ac8e92f15afce7c339e5f6575b7a9c88e1f3f89015c7952e216acb307fb35f342a81b94dacc72052c64832268cccc8ae4c5d80cdf1a09817c58c514fe38ee58" + "serialized": "ff011e0100000003000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300e1f5050000000000000103f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabcb7c16d70bd8503d3228d57dcb32468601e687849ebbbfe18b9ef2404ecf907f362a4e0a3326b6149d21256a77c7ba8ccbafddacc5bcb07c5f209e861a7f4cc66" } From 08e83a74ace363cfc9290f87150daad3f31669b0 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 14:12:53 -0600 Subject: [PATCH 36/74] schnorr tests --- .../java/org/arkecosystem/crypto/Schnorr.java | 180 ------------------ .../crypto/signature/SchnorrSigner.java | 19 +- .../org/arkecosystem/crypto/SchnorrTest.java | 138 +------------- .../crypto/signature/SchnorrSignerTest.java | 13 +- src/test/resources/utils/test-vectors.csv | 17 -- 5 files changed, 16 insertions(+), 351 deletions(-) delete mode 100644 src/test/resources/utils/test-vectors.csv diff --git a/src/main/java/org/arkecosystem/crypto/Schnorr.java b/src/main/java/org/arkecosystem/crypto/Schnorr.java index 2b91b775..23d13508 100644 --- a/src/main/java/org/arkecosystem/crypto/Schnorr.java +++ b/src/main/java/org/arkecosystem/crypto/Schnorr.java @@ -1,166 +1,6 @@ package org.arkecosystem.crypto; -import java.math.BigInteger; -import org.bitcoinj.core.Sha256Hash; - -/** Heavily inspired in https://github.com/miketwk/bip-schnorr-java/blob/master/Schnorr.java */ public class Schnorr { - public static final BigInteger p = - new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16); - public static final BigInteger n = - new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16); - public static final BigInteger[] G = { - new BigInteger("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16), - new BigInteger("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16) - }; - - public static final BigInteger TWO = BigInteger.valueOf(2); - public static final BigInteger THREE = BigInteger.valueOf(3); - - private static final char[] hexArray = "0123456789ABCDEF".toCharArray(); - - public static BigInteger[] addPoint(BigInteger[] p1, BigInteger[] p2) { - if (p1 == null || p1.length != 2) return p2; - - if (p2 == null || p2.length != 2) return p1; - - if (p1[0].compareTo(p2[0]) == 0 && p1[1].compareTo(p2[1]) != 0) return null; - - BigInteger lam; - if (p1[0].compareTo(p2[0]) == 0 && p1[1].compareTo(p2[1]) == 0) - lam = - (THREE.multiply(p1[0]) - .multiply(p1[0]) - .multiply(TWO.multiply(p1[1]).modPow(p.subtract(TWO), p))) - .mod(p); - else - lam = - (p2[1].subtract(p1[1]) - .multiply(p2[0].subtract(p1[0]).modPow(p.subtract(TWO), p))) - .mod(p); - - BigInteger x3 = (lam.multiply(lam).subtract(p1[0]).subtract(p2[0])).mod(p); - - return new BigInteger[] {x3, lam.multiply(p1[0].subtract(x3)).subtract(p1[1]).mod(p)}; - } - - public static BigInteger[] multiplyPoint(BigInteger[] P, BigInteger n) { - BigInteger[] R = null; - for (int i = 0; i < 256; i++) { - if (BigInteger.ONE.compareTo(n.shiftRight(i).and(BigInteger.ONE)) == 0) - R = addPoint(R, P); - P = addPoint(P, P); - } - return R; - } - - public static BigInteger jacobi(BigInteger x) { - return x.modPow(p.subtract(BigInteger.ONE).divide(TWO), p); - } - - public static BigInteger[] bytesToPoint(byte[] b) { - if (b[0] != 2 && b[0] != 3) return null; - - BigInteger odd = b[0] == 3 ? BigInteger.ONE : BigInteger.ZERO; - BigInteger x = toBigInteger(b, 1, 32); - BigInteger y_sq = x.modPow(THREE, p).add(BigInteger.valueOf(7)).mod(p); - BigInteger y0 = y_sq.modPow(p.add(BigInteger.ONE).divide(BigInteger.valueOf(4)), p); - if (y_sq.compareTo(y0.modPow(TWO, p)) != 0) return null; - - BigInteger y = y0.and(BigInteger.ONE).compareTo(odd) != 0 ? p.subtract(y0) : y0; - - return new BigInteger[] {x, y}; - } - - public static byte[] to32BytesData(BigInteger num) { - String hexNum = num.toString(16); - if (hexNum.length() < 64) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 64 - hexNum.length(); i++) sb.append("0"); - - hexNum = sb.append(hexNum).toString(); - } - return hexStringToByteArray(hexNum); - } - - public static BigInteger toBigInteger(byte[] data, int startPos, int len) { - return new BigInteger(bytesToHex(data, startPos, len), 16); - } - - public static BigInteger toBigInteger(byte[] data) { - return new BigInteger(bytesToHex(data), 16); - } - - public static byte[] pointToBytes(BigInteger[] point) { - byte[] res = new byte[33]; - res[0] = - BigInteger.ONE.compareTo(point[1].and(BigInteger.ONE)) == 0 - ? (byte) 0x03 - : (byte) 0x02; - System.arraycopy(to32BytesData(point[0]), 0, res, 1, 32); - return res; - } - - public static byte[] schnorrSign(byte[] msg, BigInteger seckey) { - if (msg.length != 32) throw new RuntimeException("The message must be a 32-byte array."); - - if (BigInteger.ZERO.compareTo(seckey) > 0 - || seckey.compareTo(n.subtract(BigInteger.ONE)) > 0) - throw new RuntimeException("The secret key must be an integer in the range 1..n-1."); - - byte[] resultData = new byte[32 + msg.length]; - System.arraycopy(to32BytesData(seckey), 0, resultData, 0, 32); - System.arraycopy(msg, 0, resultData, 32, msg.length); - - BigInteger k0 = toBigInteger(Sha256Hash.hash(resultData)).mod(n); - if (BigInteger.ZERO.compareTo(k0) == 0) - throw new RuntimeException("Failure. This happens only with negligible probability."); - - BigInteger[] R = multiplyPoint(G, k0); - - BigInteger k = BigInteger.ONE.compareTo(jacobi(R[1])) != 0 ? n.subtract(k0) : k0; - byte[] R0Bytes = to32BytesData(R[0]); - byte[] eData = new byte[32 + 33 + 32]; - System.arraycopy(R0Bytes, 0, eData, 0, 32); - System.arraycopy(pointToBytes(multiplyPoint(G, seckey)), 0, eData, 32, 33); - System.arraycopy(msg, 0, eData, 65, 32); - eData = Sha256Hash.hash(eData); - BigInteger e = toBigInteger(eData).mod(n); - - byte[] finalData = new byte[64]; - System.arraycopy(R0Bytes, 0, finalData, 0, 32); - System.arraycopy(to32BytesData(e.multiply(seckey).add(k).mod(n)), 0, finalData, 32, 32); - - return finalData; - } - - public static boolean schnorrVerify(byte[] msg, byte[] pubkey, byte[] sig) { - if (msg.length != 32) throw new RuntimeException("The message must be a 32-byte array."); - - if (pubkey.length != 33) - throw new RuntimeException("The public key must be a 33-byte array."); - - if (sig.length != 64) throw new RuntimeException("The signature must be a 64-byte array."); - - BigInteger[] P = bytesToPoint(pubkey); - if (P == null) return false; - - BigInteger r = toBigInteger(sig, 0, 32); - BigInteger s = toBigInteger(sig, 32, 32); - - if (r.compareTo(p) >= 0 || s.compareTo(n) >= 0) return false; - - byte[] eData = new byte[32 + 33 + 32]; - System.arraycopy(sig, 0, eData, 0, 32); - System.arraycopy(pointToBytes(P), 0, eData, 32, 33); - System.arraycopy(msg, 0, eData, 65, 32); - eData = Sha256Hash.hash(eData); - BigInteger e = toBigInteger(eData).mod(n); - - BigInteger[] R = addPoint(multiplyPoint(G, s), multiplyPoint(P, n.subtract(e))); - - return R != null && BigInteger.ONE.compareTo(jacobi(R[1])) == 0 && r.compareTo(R[0]) == 0; - } public static byte[] hexStringToByteArray(String s) { int len = s.length(); @@ -173,24 +13,4 @@ public static byte[] hexStringToByteArray(String s) { } return data; } - - public static String bytesToHex(byte[] bytes) { - char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - - public static String bytesToHex(byte[] bytes, int startPos, int len) { - char[] hexChars = new char[len * 2]; - for (int j = 0, i = startPos; j < len; j++, i++) { - int v = bytes[i] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } } diff --git a/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java b/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java index ab96ff4c..40beaf36 100644 --- a/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java +++ b/src/main/java/org/arkecosystem/crypto/signature/SchnorrSigner.java @@ -1,5 +1,6 @@ package org.arkecosystem.crypto.signature; +import org.arkecosystem.crypto.Schnorr; import org.bitcoinj.core.ECKey; import org.bitcoinj.secp256k1.api.P256K1KeyPair; import org.bitcoinj.secp256k1.api.P256k1PrivKey; @@ -11,10 +12,7 @@ public byte[] sign(byte[] message, ECKey privateKey) { Secp256k1 secp = Secp256k1.get(); - // @TODO: check if this is the correct way to get the private key - // String privateKeyHex = privateKey.getPrivateKeyAsHex(); - - byte[] privKeyBytes = hexStringToByteArray(privateKey.getPrivateKeyAsHex()); + byte[] privKeyBytes = Schnorr.hexStringToByteArray(privateKey.getPrivateKeyAsHex()); P256k1PrivKey privKey = new P256k1PrivKeyImpl(privKeyBytes); @@ -22,17 +20,4 @@ public byte[] sign(byte[] message, ECKey privateKey) { return secp.schnorrSigSign32(message, keyPair); } - - // Helper method to convert hex string to byte array - private static byte[] hexStringToByteArray(String s) { - int len = s.length(); - byte[] data = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { - data[i / 2] = - (byte) - ((Character.digit(s.charAt(i), 16) << 4) - + Character.digit(s.charAt(i + 1), 16)); - } - return data; - } } diff --git a/src/test/java/org/arkecosystem/crypto/SchnorrTest.java b/src/test/java/org/arkecosystem/crypto/SchnorrTest.java index b0bc8787..f61e5c82 100644 --- a/src/test/java/org/arkecosystem/crypto/SchnorrTest.java +++ b/src/test/java/org/arkecosystem/crypto/SchnorrTest.java @@ -1,142 +1,16 @@ package org.arkecosystem.crypto; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import java.math.BigInteger; -import org.junit.jupiter.api.Assertions; +import org.arkecosystem.crypto.encoding.Hex; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvFileSource; class SchnorrTest { - - @ParameterizedTest - @CsvFileSource(resources = "/utils/test-vectors.csv", numLinesToSkip = 1) - void schnorrSignAndVerify( - String secretKey, - String publickey, - String message, - String signature, - boolean expected, - String comment) { - - byte[] pubkey = Schnorr.hexStringToByteArray(publickey); - byte[] msg = Schnorr.hexStringToByteArray(message); - - if (secretKey != null) { - BigInteger seckeyNum = new BigInteger(secretKey, 16); - String sig_actual = Schnorr.bytesToHex(Schnorr.schnorrSign(msg, seckeyNum)); - assertEquals(signature, sig_actual); - } - boolean result_actual = - Schnorr.schnorrVerify(msg, pubkey, Schnorr.hexStringToByteArray(signature)); - assertEquals(expected, result_actual, comment); - } - - @Test - public void addPointNoP1() { - BigInteger[] p2 = { - new BigInteger("1"), new BigInteger("2"), - }; - - assertEquals(p2, Schnorr.addPoint(null, p2)); - } - - @Test - public void addPointNoP2() { - BigInteger[] p1 = { - new BigInteger("1"), new BigInteger("2"), - }; - - assertEquals(p1, Schnorr.addPoint(p1, null)); - } - - @Test - public void bytesToPointInvalidBytes() { - byte[] bytes = new byte[] {1}; - - assertNull(Schnorr.bytesToPoint(bytes)); - } - @Test - public void cannotSignMessageIfNot32BytesLong() { - Assertions.assertThrows( - RuntimeException.class, - () -> { - byte[] bytes = new byte[] {1}; - - Schnorr.schnorrSign(bytes, new BigInteger("1")); - }); - } - - @Test - public void cannotSignMessageIfSecKeyZero() { - Assertions.assertThrows( - RuntimeException.class, - () -> { - byte[] bytes = - Schnorr.hexStringToByteArray( - "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); - - Schnorr.schnorrSign(bytes, new BigInteger("-1")); - }); - } - - @Test - public void cannotVerifyIfMessageNot32BytesLong() { - Exception thrown = - Assertions.assertThrows( - RuntimeException.class, - () -> { - byte[] message = Schnorr.hexStringToByteArray("01"); - byte[] publicKey = - Schnorr.hexStringToByteArray( - "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"); - byte[] signature = - Schnorr.hexStringToByteArray( - "787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF67031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05"); - - Schnorr.schnorrVerify(message, publicKey, signature); - }); - assertEquals("The message must be a 32-byte array.", thrown.getMessage()); - } - - @Test - public void cannotVerifyIfPublicKeyNot33BytesLong() { - Exception thrown = - Assertions.assertThrows( - RuntimeException.class, - () -> { - byte[] message = - Schnorr.hexStringToByteArray( - "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); - byte[] publicKey = Schnorr.hexStringToByteArray("00"); - byte[] signature = - Schnorr.hexStringToByteArray( - "787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF67031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05"); - - Schnorr.schnorrVerify(message, publicKey, signature); - }); - assertEquals("The public key must be a 33-byte array.", thrown.getMessage()); - } - - @Test - public void cannotVerifyIfSignatureNot64BytesLong() { - Exception thrown = - Assertions.assertThrows( - RuntimeException.class, - () -> { - byte[] message = - Schnorr.hexStringToByteArray( - "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); - byte[] publicKey = - Schnorr.hexStringToByteArray( - "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"); - byte[] signature = Schnorr.hexStringToByteArray("00"); - - Schnorr.schnorrVerify(message, publicKey, signature); - }); - assertEquals("The signature must be a 64-byte array.", thrown.getMessage()); + public void convertHexStringToByteArray() { + assertEquals( + Hex.encode(Schnorr.hexStringToByteArray("b693449AdDa7EFc015D87944EAE8b7C37EB1690A")), + "b693449adda7efc015d87944eae8b7c37eb1690a" + ); } } diff --git a/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java b/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java index bbb38cfd..2d2a9f1b 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java @@ -1,8 +1,10 @@ package org.arkecosystem.crypto.signature; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.arkecosystem.crypto.Schnorr; +import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.identities.PrivateKey; import org.bitcoinj.core.ECKey; import org.junit.jupiter.api.BeforeEach; @@ -21,11 +23,12 @@ void setUp() { void sign() { String message = "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"; ECKey privateKey = PrivateKey.fromPassphrase("some passphrase"); - String signature = - "BCB684D8166A3BCC86BBABA0DF77CC6C5E86769DFF2D6377F71EC25B6AF2C983C57BEA0FE27D1F712CD0CCA0A5B09BFF15D64842DCE0EABA23834F705E73011A"; + String otherValidSignature = + "d39f6c989c185699c2f3a8674dcdd86944f9e11debc57e179bf51de3f3604546c565a37302417ab0914aa45b46f66154fbd845f883942a4cdd8654d1aaecb5c3"; - assertEquals( - signature, - Schnorr.bytesToHex(signer.sign(Schnorr.hexStringToByteArray(message), privateKey))); + String result = Hex.encode(signer.sign(Schnorr.hexStringToByteArray(message), privateKey)); + + // Since the signature is non-deterministic, we can only check the length + assertEquals(otherValidSignature.length(), result.length()); } } diff --git a/src/test/resources/utils/test-vectors.csv b/src/test/resources/utils/test-vectors.csv deleted file mode 100644 index 48ffb8db..00000000 --- a/src/test/resources/utils/test-vectors.csv +++ /dev/null @@ -1,17 +0,0 @@ -secretKey,publickey,message,signature,expected,comment -0000000000000000000000000000000000000000000000000000000000000001,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF67031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05,TRUE, -B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,TRUE, -C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380,TRUE, -,03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,TRUE, -,031B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0000000000000000000000000000000000000000000000000000000000000000,52818579ACA59767E3291D91B76B637BEF062083284992F2D95F564CA6CB4E3530B1DA849C8E8304ADC0CFE870660334B3CFC18E825EF1DB34CFAE3DFC5D8187,TRUE,"test fails if jacobi symbol of x(R) instead of y(R) is used" -,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DCE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD,TRUE,"test fails if msg is reduced modulo p or n" -,03EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,FALSE,"public key not on the curve" -,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7,FALSE,"incorrect R residuosity" -,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C, 00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC,FALSE,"negated message" -,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C,FALSE,"negated s value" -,03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"negated public key" -,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000009E9D01AF988B5CEDCE47221BFA9B222721F3FA408915444A4B489021DB55775F,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0" -,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000001D37DDF0254351836D84B1BD6A795FD5D523048F298C4214D187FE4892947F728,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1" -,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is not an X coordinate on the curve" -,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2F1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is equal to field size" -,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,"sig[32:64] is equal to curve order" From 7b6ec804f24a37441d022e9be53dffca89bac8a5 Mon Sep 17 00:00:00 2001 From: alfonsobries Date: Mon, 5 Aug 2024 20:13:45 +0000 Subject: [PATCH 37/74] style: resolve style guide violations --- .../org/arkecosystem/crypto/SchnorrTest.java | 6 ++--- .../FixtureSignVerificationTest.java | 25 ++++++++++--------- .../crypto/signature/SchnorrSignerTest.java | 1 - 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/test/java/org/arkecosystem/crypto/SchnorrTest.java b/src/test/java/org/arkecosystem/crypto/SchnorrTest.java index f61e5c82..008fe682 100644 --- a/src/test/java/org/arkecosystem/crypto/SchnorrTest.java +++ b/src/test/java/org/arkecosystem/crypto/SchnorrTest.java @@ -9,8 +9,8 @@ class SchnorrTest { @Test public void convertHexStringToByteArray() { assertEquals( - Hex.encode(Schnorr.hexStringToByteArray("b693449AdDa7EFc015D87944EAE8b7C37EB1690A")), - "b693449adda7efc015d87944eae8b7c37eb1690a" - ); + Hex.encode( + Schnorr.hexStringToByteArray("b693449AdDa7EFc015D87944EAE8b7C37EB1690A")), + "b693449adda7efc015d87944eae8b7c37eb1690a"); } } diff --git a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java index c9be3f6e..73294eda 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java @@ -17,14 +17,16 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; - public class FixtureSignVerificationTest { private final String passphrase = "my super secret passphrase"; private final String secondPassphrase = "this is a top secret second passphrase"; - private final String musigPassphrase1 = "album pony urban cheap small blade cannon silent run reveal luxury glad predict excess fire beauty hollow reward solar egg exclude leaf sight degree"; - private final String musigPassphrase2 = "hen slogan retire boss upset blame rocket slender area arch broom bring elder few milk bounce execute page evoke once inmate pear marine deliver"; - private final String musigPassphrase3 = "top visa use bacon sun infant shrimp eye bridge fantasy chair sadness stable simple salad canoe raw hill target connect avoid promote spider category"; + private final String musigPassphrase1 = + "album pony urban cheap small blade cannon silent run reveal luxury glad predict excess fire beauty hollow reward solar egg exclude leaf sight degree"; + private final String musigPassphrase2 = + "hen slogan retire boss upset blame rocket slender area arch broom bring elder few milk bounce execute page evoke once inmate pear marine deliver"; + private final String musigPassphrase3 = + "top visa use bacon sun infant shrimp eye bridge fantasy chair sadness stable simple salad canoe raw hill target connect avoid promote spider category"; @ParameterizedTest @ValueSource( @@ -32,7 +34,7 @@ public class FixtureSignVerificationTest { "transactions/transfer/transfer-sign", "transactions/transfer/transfer-with-vendor-field-sign", // "transactions/transfer/transfer-multi-sign", - + "transactions/vote/vote-sign", "transactions/vote/unvote-sign", // "transactions/vote/vote-multi-sign", @@ -59,7 +61,6 @@ void checkSchnorrSignature(String file) { LinkedTreeMap fixture = FixtureLoader.load(file); Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - if (actual.signature != null) assertTrue(actual.verify()); @@ -78,7 +79,7 @@ void checkSchnorrSignature(String file) { "transactions/transfer/transfer-sign", "transactions/transfer/transfer-with-vendor-field-sign", // "transactions/transfer/transfer-multi-sign", - + "transactions/vote/vote-sign", "transactions/vote/unvote-sign", // "transactions/vote/vote-multi-sign", @@ -125,7 +126,7 @@ void checkSigningAgainProducesSameSignature(String file) { if (withoutSignatures.secondSignature != null) { checkSecondSignature(withoutSignatures); } - + int signatureLength = 128; if (withoutSignatures.signatures != null) { @@ -137,11 +138,11 @@ void checkSigningAgainProducesSameSignature(String file) { String serializedWithoutSignatures = Hex.encode(Serializer.serialize(withoutSignatures)); String serializedFixture = fixture.get("serialized").toString(); - // Exclude the last 128 characters (signature) for final comparison + // Exclude the last 128 characters (signature) for final comparison assertThat( - serializedWithoutSignatures.substring(0, serializedWithoutSignatures.length() - signatureLength), - is(serializedFixture.substring(0, serializedFixture.length() - signatureLength))); - + serializedWithoutSignatures.substring( + 0, serializedWithoutSignatures.length() - signatureLength), + is(serializedFixture.substring(0, serializedFixture.length() - signatureLength))); } private void reSignUnsigned(Transaction actual, Transaction withoutSignatures) { diff --git a/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java b/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java index 2d2a9f1b..858c5c5f 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/SchnorrSignerTest.java @@ -1,7 +1,6 @@ package org.arkecosystem.crypto.signature; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; import org.arkecosystem.crypto.Schnorr; import org.arkecosystem.crypto.encoding.Hex; From 78459f6807c4537104723a8d9e73cc66cabcadff Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 14:15:23 -0600 Subject: [PATCH 38/74] wip --- .../crypto/transactions/deserializers/DeserializerTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/DeserializerTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/DeserializerTest.java index a821e057..32a5509a 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/DeserializerTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/DeserializerTest.java @@ -15,7 +15,7 @@ class DeserializerTest { @Test void checkNewTransactionType() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-sign"); + FixtureLoader.load("transactions/transfer/transfer-sign"); Deserializer deserializer = new Deserializer(fixture.get("serialized").toString()); deserializer.setNewTransactionType( @@ -52,7 +52,7 @@ public HashMap assetToHashMap() { @Test void checkNewTransactionToCoreGroup() { LinkedTreeMap fixture = - FixtureLoader.load("transactions/v2-ecdsa/transfer-sign"); + FixtureLoader.load("transactions/transfer/transfer-sign"); Deserializer deserializer = new Deserializer(fixture.get("serialized").toString()); deserializer.setNewTransactionType( @@ -86,7 +86,7 @@ public HashMap assetToHashMap() { @Test void duplicateParticipantInMultiSignature() { String serialized = - "ff0217010000000000010000000000000003fb92a2c3efaa177d8a51fc0cdf41905098d8b2cd900cbac94617492827e5f01580969800000000000000c2eb0b0000000000000000170995750207ecaf0ccf251c1265b92ad84f55366200c01c44bf33bea20a74d5acc12c5d6aafe82240f3571121382b77c871f4b33d6da2b62fdc6ca2cc6bc583abb2a69e7975be29e8d80a59c52bcff8d54514cf999e00c01c44bf33bea20a74d5acc12c5d6aafe82240f3571121382b77c871f4b33d6da2b62fdc6ca2cc6bc583abb2a69e7975be29e8d80a59c52bcff8d54514cf999e0292c299b739f0cb5e36133d85f51fff2fcc7745e8af4d0778908560c0874e3f2303e0436eabce1c09d88efab0004e61c5d6e47768aa8d2ab0cb9f14d523a38308"; + "ff011e0100000000000100000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3809698000000000000010000000000000000000000b693449adda7efc015d87944eae8b7c37eb1690af25db2b781b79f671b7848284de63f3cb898f9938c0b6203a11cace4aaa4b962eabe9c4a67c207a3f8baea3b4f4cef90a0b67a2bfd84cd61dcc771597f52656d005afa0050c85a2ac9b34accb0f47c6a9cc9eee831ac713e62e846898d1b75d6a33034680bce95f638c6dfabf8056f8afa9ef73a3c35741234faf01d0a346e3e7d005afa0050c85a2ac9b34accb0f47c6a9cc9eee831ac713e62e846898d1b75d6a33034680bce95f638c6dfabf8056f8afa9ef73a3c35741234faf01d0a346e3e7d02d6af0f5a85a7967d677b2f1f86e00b8ca37facb714467e12810a692d5bcbdfcac4e4c2d4b79a70c7366405339bf84a854308d20cb48652816a9cf37fb3e86e00"; Exception thrown = Assertions.assertThrows( From 772dc85a9097ae7af26ae6025dd750f2efbf781e Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 14:15:57 -0600 Subject: [PATCH 39/74] Update SchnorrVerifierTest.java --- .../org/arkecosystem/crypto/signature/SchnorrVerifierTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/arkecosystem/crypto/signature/SchnorrVerifierTest.java b/src/test/java/org/arkecosystem/crypto/signature/SchnorrVerifierTest.java index ac34ab0e..7f09c61c 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/SchnorrVerifierTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/SchnorrVerifierTest.java @@ -24,7 +24,7 @@ void verify() { "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); ECKey privateKey = PrivateKey.fromPassphrase("some passphrase"); String signature = - "BCB684D8166A3BCC86BBABA0DF77CC6C5E86769DFF2D6377F71EC25B6AF2C983C57BEA0FE27D1F712CD0CCA0A5B09BFF15D64842DCE0EABA23834F705E73011A"; + "d39f6c989c185699c2f3a8674dcdd86944f9e11debc57e179bf51de3f3604546c565a37302417ab0914aa45b46f66154fbd845f883942a4cdd8654d1aaecb5c3"; assertTrue(verifier.verify(message, privateKey, Schnorr.hexStringToByteArray(signature))); } From 2bfd4103928ffe96f63c4c6da4aa5c5845ff9958 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 14:27:04 -0600 Subject: [PATCH 40/74] install libsecp256k1 --- .github/workflows/test.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 79d867a2..5a17f685 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -59,6 +59,14 @@ jobs: java-version: ${{ matrix.java }} cache: "gradle" + - name: Install libsecp256k1 + run: | + nix profile install nixpkgs#secp256k1 + echo "$HOME/.nix-profile/lib" >> $GITHUB_ENV + + - name: Set LD_LIBRARY_PATH + run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.nix-profile/lib" >> $GITHUB_ENV + - name: Install run: gradle dependencies From 333be4301497cf36cffcf7d694649d9c586fa82a Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 14:30:12 -0600 Subject: [PATCH 41/74] add nix --- .github/workflows/test.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5a17f685..31c2e028 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -52,21 +52,27 @@ jobs: - name: Merge Conflict finder uses: olivernybroe/action-conflict-finder@v1.1 - - name: Use Java Version ${{ matrix.java }} - uses: actions/setup-java@v2 - with: - distribution: "zulu" - java-version: ${{ matrix.java }} - cache: "gradle" + - name: Install Nix + run: | + curl -L https://nixos.org/nix/install | sh + . $HOME/.nix-profile/etc/profile.d/nix.sh - name: Install libsecp256k1 run: | nix profile install nixpkgs#secp256k1 - echo "$HOME/.nix-profile/lib" >> $GITHUB_ENV + env: + NIX_PATH: $HOME/.nix-profile/bin - name: Set LD_LIBRARY_PATH run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.nix-profile/lib" >> $GITHUB_ENV + - name: Use Java Version ${{ matrix.java }} + uses: actions/setup-java@v2 + with: + distribution: "zulu" + java-version: ${{ matrix.java }} + cache: "gradle" + - name: Install run: gradle dependencies From c083f07edaf1069e66eb26e07d283c56606f8e86 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 14:34:12 -0600 Subject: [PATCH 42/74] Update test.yml --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 31c2e028..99f68664 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -56,6 +56,10 @@ jobs: run: | curl -L https://nixos.org/nix/install | sh . $HOME/.nix-profile/etc/profile.d/nix.sh + echo ". $HOME/.nix-profile/etc/profile.d/nix.sh" >> $GITHUB_ENV + + - name: Verify Nix installation + run: nix --version - name: Install libsecp256k1 run: | From 39b825e32d47531155295ef1fc9b0ca2b779d930 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 14:35:18 -0600 Subject: [PATCH 43/74] Update test.yml --- .github/workflows/test.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 99f68664..aa050751 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,13 +53,7 @@ jobs: uses: olivernybroe/action-conflict-finder@v1.1 - name: Install Nix - run: | - curl -L https://nixos.org/nix/install | sh - . $HOME/.nix-profile/etc/profile.d/nix.sh - echo ". $HOME/.nix-profile/etc/profile.d/nix.sh" >> $GITHUB_ENV - - - name: Verify Nix installation - run: nix --version + uses: cachix/install-nix-action@v27 - name: Install libsecp256k1 run: | From 249f8c7aabaf9f275ae08b665125859fc5371a46 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 14:39:31 -0600 Subject: [PATCH 44/74] Update test.yml --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aa050751..744eafa7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,11 +21,11 @@ jobs: - name: Merge Conflict finder uses: olivernybroe/action-conflict-finder@v1.1 - - name: Use Java Version ${{ matrix.java }} + - name: Use Java Version 17 uses: actions/setup-java@v2 with: distribution: "adopt" - java-version: "22" + java-version: "17" cache: "gradle" - name: Format code @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [11, 15, 16, 17, 18, 19, 20, 21, 22] + java: [17, 18, 19, 20, 21, 22] steps: - name: Checkout code From 3c65e8ca55e831addb9ca5490cf25116e0caa881 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 16:50:05 -0600 Subject: [PATCH 45/74] test with java 22 only --- .github/workflows/test.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 744eafa7..981df822 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,11 +21,11 @@ jobs: - name: Merge Conflict finder uses: olivernybroe/action-conflict-finder@v1.1 - - name: Use Java Version 17 + - name: Use Java Version ${{ matrix.java }} uses: actions/setup-java@v2 with: distribution: "adopt" - java-version: "17" + java-version: "22" cache: "gradle" - name: Format code @@ -41,7 +41,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [17, 18, 19, 20, 21, 22] + # java: [11, 15, 16, 17, 18, 19, 20, 21, 22] + java: [22] steps: - name: Checkout code From d81bc09d90031870e149ba82144e36dd3e5c7f92 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 16:52:12 -0600 Subject: [PATCH 46/74] add java 21 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 981df822..31439a85 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,7 @@ jobs: strategy: matrix: # java: [11, 15, 16, 17, 18, 19, 20, 21, 22] - java: [22] + java: [21, 22] steps: - name: Checkout code From f0d60f63f294acb5b85dbcdec56fd2bb7b11affb Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 16:55:16 -0600 Subject: [PATCH 47/74] Update test.yml --- .github/workflows/test.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 31439a85..260cad8b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -65,6 +65,15 @@ jobs: - name: Set LD_LIBRARY_PATH run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.nix-profile/lib" >> $GITHUB_ENV + - name: Dowload and compile libsecp256k1 + run: | + git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git + cd secp256k1-jdk + gradle build + cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib + cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib + rm -rf secp256k1-jdk + - name: Use Java Version ${{ matrix.java }} uses: actions/setup-java@v2 with: From 3f705ab8e1cf4b31c0c6e2d7d6a15e77cc844b88 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 16:58:54 -0600 Subject: [PATCH 48/74] Update test.yml --- .github/workflows/test.yml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 260cad8b..e189634e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: - name: Merge Conflict finder uses: olivernybroe/action-conflict-finder@v1.1 - - name: Use Java Version ${{ matrix.java }} + - name: Use Java Version 22 uses: actions/setup-java@v2 with: distribution: "adopt" @@ -41,7 +41,6 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # java: [11, 15, 16, 17, 18, 19, 20, 21, 22] java: [21, 22] steps: @@ -65,22 +64,22 @@ jobs: - name: Set LD_LIBRARY_PATH run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.nix-profile/lib" >> $GITHUB_ENV + - name: Use Java Version ${{ matrix.java }} + uses: actions/setup-java@v2 + with: + distribution: "zulu" + java-version: ${{ matrix.java }} + cache: "gradle" + - name: Dowload and compile libsecp256k1 run: | git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git cd secp256k1-jdk - gradle build + ./gradlew build cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib rm -rf secp256k1-jdk - - name: Use Java Version ${{ matrix.java }} - uses: actions/setup-java@v2 - with: - distribution: "zulu" - java-version: ${{ matrix.java }} - cache: "gradle" - - name: Install run: gradle dependencies From 58ca8d73750ed6712c044798154818c670d6acd8 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:04:47 -0600 Subject: [PATCH 49/74] Update test.yml --- .github/workflows/test.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e189634e..2086bca9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [21, 22] + java: [17, 22] steps: - name: Checkout code @@ -67,15 +67,19 @@ jobs: - name: Use Java Version ${{ matrix.java }} uses: actions/setup-java@v2 with: - distribution: "zulu" + distribution: "adopt" java-version: ${{ matrix.java }} cache: "gradle" - - name: Dowload and compile libsecp256k1 + - name: Download and compile secp256k1-jdk run: | git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git cd secp256k1-jdk - ./gradlew build + if [ ${{ matrix.java }} -ge 22 ]; then + ./gradlew -PjavaPath=$JAVA_HOME/lib build + else + ./gradlew build + fi cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib rm -rf secp256k1-jdk From 6278a7afae47bf512597bf484c195f7c3a83059e Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:09:18 -0600 Subject: [PATCH 50/74] Update test.yml --- .github/workflows/test.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2086bca9..fb49dcf3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -75,11 +75,7 @@ jobs: run: | git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git cd secp256k1-jdk - if [ ${{ matrix.java }} -ge 22 ]; then - ./gradlew -PjavaPath=$JAVA_HOME/lib build - else - ./gradlew build - fi + gradle build cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib rm -rf secp256k1-jdk From 14a806b77178821c3129db767ebd80efbe6fbb13 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:12:33 -0600 Subject: [PATCH 51/74] Update test.yml --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fb49dcf3..4ed356bc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [17, 22] + java: [22] steps: - name: Checkout code @@ -75,7 +75,7 @@ jobs: run: | git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git cd secp256k1-jdk - gradle build + gradle build -x test cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib rm -rf secp256k1-jdk From a5b3b7807543ba86df99ad50631be0ee25f2e70c Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:15:37 -0600 Subject: [PATCH 52/74] java 21 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4ed356bc..226d96dd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -75,7 +75,7 @@ jobs: run: | git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git cd secp256k1-jdk - gradle build -x test + /gradlew build -x test cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib rm -rf secp256k1-jdk From 906676176f3d1f438898bb3062f978e843b35d67 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:17:34 -0600 Subject: [PATCH 53/74] Update test.yml --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 226d96dd..07a6bdae 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -75,7 +75,7 @@ jobs: run: | git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git cd secp256k1-jdk - /gradlew build -x test + ./gradlew build -x test cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib rm -rf secp256k1-jdk From a9eb999bb04c9ad1549e954825fc6424b9576440 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:19:56 -0600 Subject: [PATCH 54/74] Update test.yml --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 07a6bdae..37f729ab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [22] + java: [21, 22] steps: - name: Checkout code From 49a33cb3e706026f1ce1bc880ce76b13c0c56952 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:23:47 -0600 Subject: [PATCH 55/74] cache dowload --- .github/workflows/test.yml | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 37f729ab..b7da6a89 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,6 @@ on: jobs: format: runs-on: ubuntu-latest - steps: - name: Checkout code uses: actions/checkout@v2 @@ -41,7 +40,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [21, 22] + java: [22] steps: - name: Checkout code @@ -64,6 +63,15 @@ jobs: - name: Set LD_LIBRARY_PATH run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.nix-profile/lib" >> $GITHUB_ENV + - name: Setup Cache for secp256k1-jdk + uses: actions/cache@v2 + with: + path: | + ~/secp256k1-jdk + key: ${{ runner.os }}-secp256k1-jdk-${{ hashFiles('**/build.gradle') }} + restore-keys: | + ${{ runner.os }}-secp256k1-jdk- + - name: Use Java Version ${{ matrix.java }} uses: actions/setup-java@v2 with: @@ -73,12 +81,13 @@ jobs: - name: Download and compile secp256k1-jdk run: | - git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git - cd secp256k1-jdk - ./gradlew build -x test - cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib - cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib - rm -rf secp256k1-jdk + if [ ! -d "$HOME/secp256k1-jdk" ]; then + git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git $HOME/secp256k1-jdk + cd $HOME/secp256k1-jdk + ./gradlew build -x test + fi + cp $HOME/secp256k1-jdk/secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib + cp $HOME/secp256k1-jdk/secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib - name: Install run: gradle dependencies From b1ea6a424e32fa836ffd0cfd778fa24bfb4a937a Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:26:42 -0600 Subject: [PATCH 56/74] add 21 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b7da6a89..2a403d03 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [22] + java: [21, 22] steps: - name: Checkout code From 1c405f5e920e9d168394372522701c7633293c65 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:34:53 -0600 Subject: [PATCH 57/74] test --- .github/workflows/test.yml | 27 +++++++++++++++------------ libs/secp256k1-api-0.0.1.jar | Bin 12671 -> 0 bytes libs/secp256k1-foreign-0.0.1.jar | Bin 94605 -> 0 bytes 3 files changed, 15 insertions(+), 12 deletions(-) delete mode 100644 libs/secp256k1-api-0.0.1.jar delete mode 100644 libs/secp256k1-foreign-0.0.1.jar diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2a403d03..3ebbb10c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [21, 22] + java: [22] steps: - name: Checkout code @@ -63,14 +63,20 @@ jobs: - name: Set LD_LIBRARY_PATH run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.nix-profile/lib" >> $GITHUB_ENV - - name: Setup Cache for secp256k1-jdk + - name: Setup Cache for secp256k1-jdk repo uses: actions/cache@v2 with: path: | ~/secp256k1-jdk - key: ${{ runner.os }}-secp256k1-jdk-${{ hashFiles('**/build.gradle') }} + key: ${{ runner.os }}-secp256k1-jdk-repo restore-keys: | - ${{ runner.os }}-secp256k1-jdk- + ${{ runner.os }}-secp256k1-jdk-repo + + - name: Clone secp256k1-jdk if not cached + run: | + if [ ! -d "$HOME/secp256k1-jdk" ]; then + git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git $HOME/secp256k1-jdk + fi - name: Use Java Version ${{ matrix.java }} uses: actions/setup-java@v2 @@ -79,15 +85,12 @@ jobs: java-version: ${{ matrix.java }} cache: "gradle" - - name: Download and compile secp256k1-jdk + - name: Build secp256k1-jdk run: | - if [ ! -d "$HOME/secp256k1-jdk" ]; then - git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git $HOME/secp256k1-jdk - cd $HOME/secp256k1-jdk - ./gradlew build -x test - fi - cp $HOME/secp256k1-jdk/secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ../lib - cp $HOME/secp256k1-jdk/secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ../lib + cd $HOME/secp256k1-jdk + ./gradlew build -x test + cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ${{ github.workspace }}/lib + cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ${{ github.workspace }}/lib - name: Install run: gradle dependencies diff --git a/libs/secp256k1-api-0.0.1.jar b/libs/secp256k1-api-0.0.1.jar deleted file mode 100644 index 2795c7fb661dbae252828d37f0fa41155f4d2455..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12671 zcmbVz1yr0(vNrCnLvWbj5IkrI?(XjHt`Tf-8{FO9B|va@2<{Rrfnb54Ke^v`H#h8V zcF*7E^vrwabUiI^S9jG@H44(uFgOqp2nZ0(R*;$yj|J-I$74Z!tg@mif{c=KVlSW} z6n<-1DG;h9@z_B3u|A6bYA7oxCn+YXtimKKb|yPAEF;axG>IzBNH;bzUaQ1B!?wP2 zI>I<0IVw9!FUbIjbO16**v`|Ug(;-M2PCJM64G(Oc^J|7r5a?JXPFNS_YT88>G`p< ze+&`k@!8(V{GUemf7_t`-Nwk$#n|4`&gzei@t-z!HZ^u&<>0ht`J))&zZWxfu>2>{ zG1uwKqsL_?f`@>h`?IK$sk5t%3sByg$=Jrw**QJlRvAkXr~d&zK-Uo&NIJ}p9T5bs ztHa8RE0`ouq9)LvFNHnoKsw4_=}m4|e&JM5K%jpPd95I8PO5;TQh-0)<~`2+@yubI zu7SPyo{oKP>K3rPFX2ade?rcGWy^u1Q^R8*J@fnPKfka7!sk4{D9OI z%sh}V--sex$y(Nnd{@O5f|g@_h>?qQWEc?4@u_S_G>{E={oHQpJqzqsQr5(e#Dqm= z0@gPv?&e8caSoY=-_@K!oo~uZO4Ww5JnnjpK!)tA&>kJk>r}W*7CdW~#EDIcD$=NS zi5hXA`h2Y{zJGA%GWf(kWSIRC2hhhP+|Id_rJ^6e5ST$JvrXA(l~Ysr?0}`QNst_7 z3s{Q{2)S(HDI9F59K4S94Jid>M3ZC4bHOeRQomndKLkKxlh`0r6ZQz4!&;@$fQ~U|%3;-N z$tQMxVK5Hn$(aGMq`9eyPRom=7wYyhs#dZ$5zr$j+H^M1NF30AO=Oq!a(8cG2E22HY=Nl=JF1YUV(GnF8bpmPjR3C$+JZh_P zYAw=KhEs$V(KSf9^-QgOkKg>Y(&SXwpjRHSSnw zo@th@nQyiUH94z8S4f@MOl# zp99`n9Dg`o_8uGjP`UQ*?H$}Yq7y3+w90>0ZmBZ*Eh46t9`@xn?h(B~aIu9ryl{W( z*ToGeSS>^9Li;{PL`QA(I*?bqY3E&0L*MB}=gd)__S@s-bIN5UR=dirB! z`ty!gwludhba8bu6)|)%{A;)KUf9pQf`fz8hLdxHqY{IQxXp37%Nqf2-;T60+-=Tm zLs2T%+6dqE_{rR@kDRymfTwa)5_`ZRZg6;FaK2?dH6nLuJ*_Tp9`ed&wz0(EX7h%? zGe%-?c&MWm)M9WI>$g)m+bWGCX)0oHl_l>`N! zO-DZ5{oaIQNmHQdWaee^45K;)?ypm0I(& zv$=hA2>EXek*`E>&aHzf`l9)mBO`QHs!E&PmvQ6*$rBoFhL=o&^Vn{n6boevxXfCU}lvuMIZ*dND#C7|Ih7+;fcW;g` z0Mofdv|$|ADeWRklZ0(P>>F3Ys(n%E)`PSgowCo2^AKy&!Q(s=UF>#{_cA$?OL@(o4+m>C!HxOoB}iDp zGnt?F6nGXXXg|e$p{;<>Z}CEmj++>kSsE)t=L-M9^j^4Q_W_2eKOMt?S|%_>m#=qk z4Z~lg$UH=$`n`)b#SDh_=Pc3ho)VlXcSt*|C6j0+lNd}Ol!!M2Mw5xsO^3sX3^#I` z9v_=0oZ@|on#4K2X>httsYtr}ze>MXmuER4{Qa5}p~sDS@zbzHf`Fj@Z?xlY%}~=; zUJ?WFTNA>FEvLbRO8UoQ*f@tkTiU(0#Dag;2sf1ko~o0@_v}X?9HcB~8x^ozy`ELi z5K0+2KV7^pl=~QO;#^H@$8UUmRG3@4%e$s`ySsM$7WNxU69}Wb>1!P8QUSZo^x|k! zSJBu?i*Cl~w~}N}x@9fV$jZcAgW$cr*VMwhIhM&zAsa$;ABXi%WdgPHN3OqDFmDTa zDGTFw*VjrW5>q3gD)uf4e<{}Ss)cXco1UmNhVVy895*pUSTF_gmd9<6`*;hEy36%@ z>KGs(_ZudW5!klQ2O5IVq&nSj`hz36#6og`d7E501!Tn2bTKJZzC+XKt~y-+&jXnK zH2M11R!t+!Zh$dWx||+**ui{_`%Vm1%f$rNvywS^Tbm?J=#j!j}5^N~P zCp80$37tD^%0~+0@ylQ);hMm0ofd99Q7GjSqiO0PeR=0v8_F23=)hz9FS~z4~yhV2za|_!YH~|RE{1P zO+k8E=whDn>d^2c=~Q1nJ|~Ldr7DjuwY8L}A76@*@_wGeb%V?E9wEsFT7p+;p_y7I zF;T88*&u{frk=xCch|*xdUm6`+$}KCqQsS7tNg&Cvw|C>!JK`aG&xwG6?X&wgn~%Qc((VOmdRsUG&$ zvy^y3BxWaGsx!{-%an7%^E4a&y9pj$M8lF0ko`WLm2^D_A0_dgSgOAcy+FDOpP)z{ zzU7l{AcmP`T{tuG!Rt%!s`5eTfJ;k^KB7A}FLb6&s=I?%!IAe-MQyGOPN|E$=cpS@ z5&LFHMfN00*4ih~F2~+k!UsJp2i{5c7>pAhF-P8+MH05bi=7_Z)FOqeLJtI5w~R)i z%uWH!`!&G{* zG3|1{Klagbf47*DW|S9u)_qu z>g;T4@-Ivd*AW&pKW0Gh$tAgh>nQ}uYkWdU7iYz-gN{9w1AHYBsYRpBPegq0gIK#D zeYyqguivy+zI;zi1%*joTM-wCxR_D^&Tvh&ZD_1lDUX5owkP%;pIeTLKuX`rMUo<; z8lk&Ts8N%p9e*@fF~FMy^Vplcr!~|v&P&{*)XHpz_x)O^GE!vW%;8=5;&p58gbAZmZ%rrlZ^l*RYftcKS;5*{%lmDl4K!>QWDw( zG6TYlaoKS<8hCYdo`T?!f;#&z%&h6*k<)rW!wMt$Nv& zTRm&;>Oo=i_yNOSS8^pJObCV&zjViyVBVUa0;{rQA`lht>V9h5S#DCzDDf~`a5=+r z_yF?XGvH7&NOK*_B-Fng;W&z3vnac?*&(iPc zSiTu$Qy@weIIw4x}#vXs16p_MaVj%EqJS|=PbE8$awlW=u0lm z$|rT%aTjTw-RIK!R!tOx)+a;@_bdxkxSqZlUqLbp4VtrG!G+#t8}Wu}{KLgPjh!e|@h$>3Gc9EU%x`|Phn}+omYVm`Ty&kC zbjdx&+H1qE?EINAdWg9jbs?TSN|1eFmTd>QYJ$pX)$LBOpy|xw(=0fBa9P{CHEo9= zvydLFz2%!E%<&Rc#L8+w_MA-()<>)P>?4Z(5h7%IZjL!-YDURBUopKPlSP2BBRbUd z?J+oXv!AT<2lU9dAGqq~+(?lzZYLmNY?4!gGg;cWs~Nw!q+ZHMC}-~gF}I+MRkk>H zZNN2K&MmYU{9AFAtfV(#371^VqbC^sH-pvaCyM#fAw{+RF-)S81*=;Fnq%O$`#R}` z)oOIdS3y~)W%Y(h>emR7XN&vYo_hZH4$10KBF^OVEF!t5Uyb?5GdN97aLz{D0MsYp zwFp~LTh?PZ?GJEkpd!~uSt8!ZHjvmhH4Nv(h-795;YX#A!gR%T)jWqvwe25{Et|({ z1U;ae;RR=({_vKlg5vrtBj4c}Jjr7Ot}aI|Ann2p`73@v43X&S=DBrIH7d>ILUikZ z!RzUD&Nyrtl;!m^s#F#+#PHfG#PfAL#MD#6d_VpMi@|`p0r^SiOgu#9u!1O*h@#-) z3E&jfs~+*@PYsL|wn{i~c-<6CK@^s#q2IF2+=oqD1ewYqvF`ac>@oB?sS>(Ogbi7D z)Wg4wofMG=VW~|syd!|A-h{g|$?x@TY|#wBa@a)Z(kqLg(*2!$8a2%*Z`DjeL;f8=Jv21xW2GD zCgfF^dapbnd2K|ZGncQk)}SEo2C)u^EWhHx!V@q^x*7huzgn$^mtL}Sg61wopwn3vkmgsKWK5$^ z=3&2;WtiNpaB)f?UqAPfV4fGWytj3G%|O!xI#iLy(T>w zPCtorK{@)P`Z?Q3rh0`Mm%_}Iq}F$C#FxF^Zzb&Ftt7jv?a_(+kC7gzn%Qz@-!KTb zjOiW+ew|{cRUO`x>z&b^v!D4g;JuC~tBisYc5ZSPl9NdzcmuSXxS`T?y(Y=!(7r-a z)3`$m*+8ZeF#b&GX)FRU>XEjZ8rLl9e2>#OI25SagXo2^mT)&*L9KFl2N6>eLm2KImp(nY(hQ=)*7xsi{Q z<3m*dETLn_9Ma!4vXq*k#n4U+t&bG;hY>W^m9in<>n3xz^euNJbE zt%4QFHm${|j2VL;7NSUu7Oy0TnG5K`+G%91ZTs~@y+Hn_`p|^>Yv}9T7O&4#Jqp4S z3>BZdm$~Phzc1`|rhDHW9t+&VIN*JBF+gAZQq?>W*@ogTJyfzeXbmfGrpOXnvM-q; z^{N!0Seg8@Ywjremzhg3s@lKscUiCC5R;)#;%3wmP#XGe_TT6R^yLvH=w3EZE^VBkJzt ziHShZPXqK+<=>zQzZ2cj&l3w$BA%fm!EeoivqUZo01myJ^fHt)5DC~=c?l{*&RzUk6&6~9N6`Rk5gMh0tJq5;zU>7Gle>H8n zlA8<0-3t{j$r4C9aB8$yL&;OpLX+WmNpe?ooG{UgvPShCx~a5D&E<5BOz|$Dd^4YT z%B2EB?O~aGn82O7gu;!=)#yE4Cw`4b|A;Skqqjyl13ql?`$6y3d8xtBXOR^GNeL1L$t})rKA8Dce6L z&}~uE-Q768G*fxoUt)hFt}VnYtu)Uw1pm207d*7NEkH)(0JB66T# z1)XOGk$ZZnTY9yTUKVeq#(X-ElI52@Ze$#2U_EyliT7(WH)h zPBUZ>6-CM?hN4}c=~2(*Ymq@r3w4&-q!$1<(;=zZ;I(JnZgMlV=#1!jaHh5N6{nL9 z=4sZ-o^Q(Y!G|y4JwJFgn3s7I&9^vVA7R9fa-qEiufMM(WnCH3zIz3cbwTxNyVTFcbo3hs za(pH7z= zW!l?-*DomK9n6S#Nhlj2L)2V(^qJ?ekN0KiW94|Pe=zHQ5et90-2Xn1arf^78E6%(|dig5;8}u#ZJ*@g>vgPyl5;`NT-p3zym(Pwq9N$z{_CsWB zgoH-Feu%6#-*fF=nmto!S+?syz_zqS5~w# zGJVuqrNNw{GP4`5Z++9Y5M9vTqQtI~%f!E*u=k><>G=d9a2Dl5$w!7`iD_jPDrQF# zJH@1%F=o?g>J3d)dANR6H4i1<3_sIh{BkeNmdXgHh?sUi<7f4<-Ss{nv2je_diqLu zuEomwPT-|mOqVQ{^SIB#wn%3f9@zmRAhL~w$Oa>s=1R~4ZP-fn57`-`bxw7LE0`35 z8*O7)l&{uGDX8Q=bM%{Dh7^vrqgp*Qf!*9D1QL>OW8GZ+VP`^Zyehio0_)GI`g6DI zbd)PJ1*66ghpq#NJ^{tJnsU?Za2?;-?5z~IL%=FlM0JHFM-*@6JIG1W=E4I~q-dR+ zCFo8eSxiqbPA)^a_ZFJcvQ(*COz!)RL=04+ z{VbK5wg}n+Kez8#7Pl1aH!oE%@99x#Tn=oN`HmETtojqrzY)y6VCCoUj^n~*@n1j_ zZs^YP5jmi6+ecC3R%PigdDZU|oqmJ*yMbsA4tX8*XdnX6|6@G<9|od=lf9dziRs@q zalQJXJGLm!gDmX==RyOE5UxTIfSGn)AwY`OkKGm$H6IHGQa{#Y%I?DgYN~8@JFd@1 zT-?lezNEJS3gahN3tMa3Cu2ucE9~gc##l&eYTb`+kB(QHFUP*DJup2Wt|Q)JWs3)e zy6&0m)rk(8%@azGo{45mG_#~iEG3wYME2?`F3g^bwA+~2je8#Y>wQn99_b8r~HQp8%=T)m@2?ncy`!P*~M3O8l4;x=S)+2x>onXfr@)vjSJ z{g$FI)CqiOjLBR?=QS~0Wv7NQ@=fcFL}HkzF7~VjhT(E9S}z@&e4MC1CpENL6`tP1G&4heD?s?hXvNzi6q9ABgV|`KUG1%pPaj&bCzTCu@l(xw%O0M5RHScbQPg5Xo@z@fTiCi7h?S49jEzvpv$A}igbJlix3 zPrcc%zET`$fCB#Lm&0OqG{KHU%8o?T1DoWd6JNSZ8Pt#tZD0;h>Oyhkre<-k{3KG~ zM32(U#wUwRoV%$ScvJE7_4C$MBIYXeQCLD3wVojdvP5g9xKZ%0PMGk14VmDHHH)me zR!Si+7!C}t8v7P52bLHbak^t@WdEUuJF5vqSl9%7FPntTJSi_%j`jJ}wzxV|=STa} zI++QV-lkByi_|LWt6_~x4nf$5jsrRCTDZnxJj}M$7O^EUdzDgm!D{MVyotCusXYY? zWXiX`*`*r%NI{FTQ6%a3tlT8=KXCIi@X9TPBIq*{Ep*5P&7jo-jac!AIz+V^QEa3 za}1KMiY0n#EMd*er$7%;Bt6y6nC!;6oh3p#m{Y^n`jQY;Ej#FSyH@NjRUPGT6?{Ek zQzCVg0h6K9hOOfcJhNr*bLclLU!>?>ML%<|?`G4FqJ|eh+r;)MS!ct|+(HI@rEjXp4pxBqiw3qetiYt@j8?oHr8@U(N*Uq%mi=KrCV^;u0Dn>p7N7sL zi>dtd6_;)Z0sjqr;?5b~>@*q7vdEe~!Y$QDIS0_a_dX{IN;W#8P2O(pc|i+3;$4}) z7uvXI(Tzp?t*r)?DPl|b&0W$+5Vuqr+Eo6#IE=l+KsBiV>+?7ObW8`MjpWyskf4NW z=%xq{csP5?Nx|-Z0C159-j>Z11-SptPeTs8K?^3%CHxW4-LTf1Te|D%1!r*t#e@~R zYyDZTXsk`b`33j=N13uB0?+mc4@~8dUIg8jXsbQh`lXIYT+VFmS49I9@B#icfu4XR z;&I<~Qh)$y@)fZ%y`m!~8u*o~i2MV@zO-fKOd+Zl(zn^Gaw;D+?-gBg9IH-}AJ%}N75loppIj_g>%Mw z+-83ib%@#lrHc*M`Km+~FQhuWG1TA(owRUuTnyRyTZ)EVZt5BJz?}{tib{*IFJF*U zpSK&9A#3s&8p&3O%LI^J9|8GF@*``jCu#Z1t%UF!Q=QSIJq)o2=eZY^t|d;*nES9~ zamHCnU+Ao~f{O5&va_`l)NZCJ>wKvdq#>bjp#OcY>*E|B3kJkj!Jps%$b5Y&_B8YL zXXBqG&zJV`^B-dWClB^1!q3)^*5dz^pMn0r%Fm8}(n~*0?AE`^Pto(o$KOPM(X4+0`I+nbSNRD-|F}E;4aom+wNKXkY3A$yLgo3I{Tb*< z9_-TrKFtmMh5M6G{?h>eb*A7`{HK{%zwjd;b9n!N|1W~1PqCk-L;b=wMffB3)8we9 zz)v$tegXR<{};f2Y57yor=j9spqGz!;2&1vmw)$PtjW_b?XO-oF#g!fPv-UapzYHM zJdHH`g7(DwkI=s*mHsL2@U+*by0Kg{xf{i>fj z@4s*r$o`1?>s3E><)04ysptHw3r_MscJcRn{=a_oQ|zby$uDdM;2*L7u`IuPD^KyC kUXZ`=ksp)#|LM9^kcNHCcl`Np2^@%bk531WjUXWYAL$~RhyVZp diff --git a/libs/secp256k1-foreign-0.0.1.jar b/libs/secp256k1-foreign-0.0.1.jar deleted file mode 100644 index 38414c6a768aa8b3ff5140322aad08f8ad96e987..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94605 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 Date: Mon, 5 Aug 2024 17:38:57 -0600 Subject: [PATCH 58/74] Update test.yml --- .github/workflows/test.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3ebbb10c..48d988b8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -87,10 +87,9 @@ jobs: - name: Build secp256k1-jdk run: | - cd $HOME/secp256k1-jdk - ./gradlew build -x test - cp secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ${{ github.workspace }}/lib - cp secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ${{ github.workspace }}/lib + $HOME/secp256k1-jdk/gradlew build -x test + cp $HOME/secp256k1-jdk/secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ./lib + cp $HOME/secp256k1-jdk/secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ./lib - name: Install run: gradle dependencies From a281c338fd68ab5eedc7c24bcf7923b2097ba763 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:42:32 -0600 Subject: [PATCH 59/74] Update test.yml --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 48d988b8..cebf854c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -87,7 +87,7 @@ jobs: - name: Build secp256k1-jdk run: | - $HOME/secp256k1-jdk/gradlew build -x test + $HOME/secp256k1-jdk/gradlew -p $HOME/secp256k1-jdk build -x test cp $HOME/secp256k1-jdk/secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ./lib cp $HOME/secp256k1-jdk/secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ./lib From 4398b7fc0185586600ebcfac08bfbd12d743fc45 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:45:51 -0600 Subject: [PATCH 60/74] wip --- libs/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 libs/.gitkeep diff --git a/libs/.gitkeep b/libs/.gitkeep new file mode 100644 index 00000000..e69de29b From 58ed071a62c55cc8a4e60574ea2428301346a10c Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:48:48 -0600 Subject: [PATCH 61/74] Update test.yml --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cebf854c..f628c363 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -88,8 +88,8 @@ jobs: - name: Build secp256k1-jdk run: | $HOME/secp256k1-jdk/gradlew -p $HOME/secp256k1-jdk build -x test - cp $HOME/secp256k1-jdk/secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ./lib - cp $HOME/secp256k1-jdk/secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ./lib + cp $HOME/secp256k1-jdk/secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ./libs + cp $HOME/secp256k1-jdk/secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ./libs - name: Install run: gradle dependencies From 829d1d2079e4fc5d2314805828fde55f65ecdef6 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:53:14 -0600 Subject: [PATCH 62/74] add java 21 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f628c363..42bb4884 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [22] + java: [21, 22] steps: - name: Checkout code From be561c3329ff067468a2e70c3334ca737116d2cb Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 17:54:35 -0600 Subject: [PATCH 63/74] add default 22 libs again --- libs/.gitkeep | 0 libs/secp256k1-api-0.0.1.jar | Bin 0 -> 12671 bytes libs/secp256k1-foreign-0.0.1.jar | Bin 0 -> 94605 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 libs/.gitkeep create mode 100644 libs/secp256k1-api-0.0.1.jar create mode 100644 libs/secp256k1-foreign-0.0.1.jar diff --git a/libs/.gitkeep b/libs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/libs/secp256k1-api-0.0.1.jar b/libs/secp256k1-api-0.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..2795c7fb661dbae252828d37f0fa41155f4d2455 GIT binary patch literal 12671 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 literal 0 HcmV?d00001 diff --git a/libs/secp256k1-foreign-0.0.1.jar b/libs/secp256k1-foreign-0.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..38414c6a768aa8b3ff5140322aad08f8ad96e987 GIT binary patch literal 94605 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 Date: Mon, 5 Aug 2024 17:58:03 -0600 Subject: [PATCH 64/74] gradle java version issue --- .github/workflows/test.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 42bb4884..0585fef2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [21, 22] + java: [21] steps: - name: Checkout code @@ -85,6 +85,15 @@ jobs: java-version: ${{ matrix.java }} cache: "gradle" + - name: Set JAVA_HOME + run: echo "JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV + + - name: Add JAVA_HOME to PATH + run: echo "$JAVA_HOME/bin" >> $GITHUB_PATH + + - name: Print java version + run: java -version + - name: Build secp256k1-jdk run: | $HOME/secp256k1-jdk/gradlew -p $HOME/secp256k1-jdk build -x test From 0a42b1e40b702c60c5f87a4322c28ff79c944aef Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 18:05:06 -0600 Subject: [PATCH 65/74] worth a try --- .github/workflows/test.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0585fef2..ec38d83f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -85,18 +85,12 @@ jobs: java-version: ${{ matrix.java }} cache: "gradle" - - name: Set JAVA_HOME - run: echo "JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV - - - name: Add JAVA_HOME to PATH - run: echo "$JAVA_HOME/bin" >> $GITHUB_PATH - - - name: Print java version - run: java -version - - name: Build secp256k1-jdk run: | - $HOME/secp256k1-jdk/gradlew -p $HOME/secp256k1-jdk build -x test + $HOME/secp256k1-jdk/gradlew -p $HOME/secp256k1-jdk build -x test \ + -Dorg.gradle.java.installations.fromEnv=JAVA_HOME \ + -Dorg.gradle.java.installations.auto-detect=false \ + -DjavaToolchainVersion=21 cp $HOME/secp256k1-jdk/secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ./libs cp $HOME/secp256k1-jdk/secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ./libs From e9629c579343905cc5f9637523d596a28b8dc63f Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 18:06:41 -0600 Subject: [PATCH 66/74] last try --- .github/workflows/test.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ec38d83f..b4f698a2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -88,9 +88,11 @@ jobs: - name: Build secp256k1-jdk run: | $HOME/secp256k1-jdk/gradlew -p $HOME/secp256k1-jdk build -x test \ - -Dorg.gradle.java.installations.fromEnv=JAVA_HOME \ - -Dorg.gradle.java.installations.auto-detect=false \ - -DjavaToolchainVersion=21 + -PjavaToolchainVersion=21 + -PsourceCompatibility=21 + -PtargetCompatibility=21 + -PoptionsRelease=21 + cp $HOME/secp256k1-jdk/secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ./libs cp $HOME/secp256k1-jdk/secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ./libs From e39b8bf48e0e8bb9ef8d55c47e83ab4438f28a10 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 5 Aug 2024 18:08:07 -0600 Subject: [PATCH 67/74] drop compatibility with old versions of java --- .github/workflows/test.yml | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b4f698a2..106a49c7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,10 +38,6 @@ jobs: unit: runs-on: ubuntu-latest - strategy: - matrix: - java: [21] - steps: - name: Checkout code uses: actions/checkout@v2 @@ -63,39 +59,13 @@ jobs: - name: Set LD_LIBRARY_PATH run: echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.nix-profile/lib" >> $GITHUB_ENV - - name: Setup Cache for secp256k1-jdk repo - uses: actions/cache@v2 - with: - path: | - ~/secp256k1-jdk - key: ${{ runner.os }}-secp256k1-jdk-repo - restore-keys: | - ${{ runner.os }}-secp256k1-jdk-repo - - - name: Clone secp256k1-jdk if not cached - run: | - if [ ! -d "$HOME/secp256k1-jdk" ]; then - git clone https://gitlab.com/bitcoinj/secp256k1-jdk.git $HOME/secp256k1-jdk - fi - - - name: Use Java Version ${{ matrix.java }} + - name: Use Java Version 22 uses: actions/setup-java@v2 with: distribution: "adopt" - java-version: ${{ matrix.java }} + java-version: "22" cache: "gradle" - - name: Build secp256k1-jdk - run: | - $HOME/secp256k1-jdk/gradlew -p $HOME/secp256k1-jdk build -x test \ - -PjavaToolchainVersion=21 - -PsourceCompatibility=21 - -PtargetCompatibility=21 - -PoptionsRelease=21 - - cp $HOME/secp256k1-jdk/secp256k1-api/build/libs/secp256k1-api-0.0.1.jar ./libs - cp $HOME/secp256k1-jdk/secp256k1-foreign/build/libs/secp256k1-foreign-0.0.1.jar ./libs - - name: Install run: gradle dependencies From 32b047ac550ace3ddc4ccb9b512ac605f72a5313 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Tue, 6 Aug 2024 12:15:50 -0600 Subject: [PATCH 68/74] add username transactions wip --- .../crypto/enums/CoreTransactionTypes.java | 6 +-- .../org/arkecosystem/crypto/enums/Fees.java | 6 +-- .../crypto/transactions/Deserializer.java | 6 +++ .../crypto/transactions/TransactionAsset.java | 1 + .../builder/UsernameRegistrationBuilder.java | 29 ++++++++++ .../builder/UsernameResignationBuilder.java | 24 +++++++++ .../types/UsernameRegistration.java | 54 +++++++++++++++++++ .../types/UsernameResignation.java | 31 +++++++++++ .../UsernameRegistrationBuilderTest.java | 30 +++++++++++ .../UsernameResignationBuilderTest.java | 39 ++++++++++++++ .../UsernameRegistrationTest.java | 38 +++++++++++++ .../UsernameResignationTest.java | 36 +++++++++++++ .../serializers/UsernameRegistrationTest.java | 26 +++++++++ .../serializers/UsernameResignationTest.java | 26 +++++++++ 14 files changed, 344 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilder.java create mode 100644 src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java create mode 100644 src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java create mode 100644 src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java create mode 100644 src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java create mode 100644 src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java create mode 100644 src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java create mode 100644 src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameResignationTest.java create mode 100644 src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java create mode 100644 src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameResignationTest.java diff --git a/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java b/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java index 5ee7d0de..a977cb48 100644 --- a/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java +++ b/src/main/java/org/arkecosystem/crypto/enums/CoreTransactionTypes.java @@ -6,12 +6,10 @@ public enum CoreTransactionTypes { VALIDATOR_REGISTRATION(2), VOTE(3), MULTI_SIGNATURE_REGISTRATION(4), - IPFS(5), MULTI_PAYMENT(6), VALIDATOR_RESIGNATION(7), - HTLC_LOCK(8), - HTLC_CLAIM(9), - HTLC_REFUND(10); + USERNAME_REGISTRATION(8), + USERNAME_RESIGNATION(9); private final int value; diff --git a/src/main/java/org/arkecosystem/crypto/enums/Fees.java b/src/main/java/org/arkecosystem/crypto/enums/Fees.java index e5e1321b..8a5cf991 100644 --- a/src/main/java/org/arkecosystem/crypto/enums/Fees.java +++ b/src/main/java/org/arkecosystem/crypto/enums/Fees.java @@ -6,12 +6,10 @@ public enum Fees { VALIDATOR_REGISTRATION(2_500_000_000L), VOTE(100_000_000L), MULTI_SIGNATURE_REGISTRATION(500_000_000L), - IPFS(500_000_000L), MULTI_PAYMENT(10_000_000L), VALIDATOR_RESIGNATION(2_500_000_000L), - HTLC_LOCK(10_000_000L), - HTLC_CLAIM(0L), - HTLC_REFUND(0L); + USERNAME_REGISTRATION(2_500_000_000L), + USERNAME_RESIGNATION(2_500_000_000L); private final Long value; diff --git a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java index 32730ef9..66c45891 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java @@ -15,6 +15,8 @@ import org.arkecosystem.crypto.transactions.types.SecondSignatureRegistration; import org.arkecosystem.crypto.transactions.types.Transaction; import org.arkecosystem.crypto.transactions.types.Transfer; +import org.arkecosystem.crypto.transactions.types.UsernameRegistration; +import org.arkecosystem.crypto.transactions.types.UsernameResignation; import org.arkecosystem.crypto.transactions.types.ValidatorRegistration; import org.arkecosystem.crypto.transactions.types.ValidatorResignation; import org.arkecosystem.crypto.transactions.types.Vote; @@ -42,6 +44,10 @@ public Deserializer(String serialized) { coreTransactionTypes.put(CoreTransactionTypes.MULTI_PAYMENT.getValue(), new MultiPayment()); coreTransactionTypes.put( CoreTransactionTypes.VALIDATOR_RESIGNATION.getValue(), new ValidatorResignation()); + coreTransactionTypes.put( + CoreTransactionTypes.USERNAME_RESIGNATION.getValue(), new UsernameResignation()); + coreTransactionTypes.put( + CoreTransactionTypes.USERNAME_REGISTRATION.getValue(), new UsernameRegistration()); transactionGroups.put(TransactionTypeGroup.CORE.getValue(), coreTransactionTypes); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java index b69e19bc..5d0fef1d 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/TransactionAsset.java @@ -13,6 +13,7 @@ public class TransactionAsset { public HashMap customAsset = new HashMap<>(); public long amount = 0L; public String validatorPublicKey; + public String username; public static class Signature { public String publicKey; diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilder.java new file mode 100644 index 00000000..19592102 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilder.java @@ -0,0 +1,29 @@ +package org.arkecosystem.crypto.transactions.builder; + +import org.arkecosystem.crypto.enums.Fees; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.arkecosystem.crypto.transactions.types.UsernameRegistration; + +public class UsernameRegistrationBuilder + extends AbstractTransactionBuilder { + public UsernameRegistrationBuilder() { + super(); + this.transaction.fee = Fees.VALIDATOR_REGISTRATION.getValue(); + } + + public UsernameRegistrationBuilder usernameAsset(String username) { + this.transaction.asset.username = username; + + return this; + } + + @Override + public Transaction getTransactionInstance() { + return new UsernameRegistration(); + } + + @Override + public UsernameRegistrationBuilder instance() { + return this; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java new file mode 100644 index 00000000..7fee046d --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java @@ -0,0 +1,24 @@ +package org.arkecosystem.crypto.transactions.builder; + +import org.arkecosystem.crypto.enums.Fees; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.arkecosystem.crypto.transactions.types.UsernameResignation; + +public class UsernameResignationBuilder + extends AbstractTransactionBuilder { + + public UsernameResignationBuilder() { + super(); + this.transaction.fee = Fees.USERNAME_RESIGNATION.getValue(); + } + + @Override + public Transaction getTransactionInstance() { + return new UsernameResignation(); + } + + @Override + public UsernameResignationBuilder instance() { + return this; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java new file mode 100644 index 00000000..55ce81ae --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java @@ -0,0 +1,54 @@ +package org.arkecosystem.crypto.transactions.types; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.HashMap; +import org.arkecosystem.crypto.encoding.Hex; +import org.arkecosystem.crypto.enums.CoreTransactionTypes; +import org.arkecosystem.crypto.enums.TransactionTypeGroup; + +public class UsernameRegistration extends Transaction { + @Override + public int getTransactionType() { + return CoreTransactionTypes.USERNAME_REGISTRATION.getValue(); + } + + @Override + public int getTransactionTypeGroup() { + return TransactionTypeGroup.CORE.getValue(); + } + + @Override + public HashMap assetToHashMap() { + HashMap asset = new HashMap<>(); + + asset.put("username", this.asset.username); + + return asset; + } + + @Override + public byte[] serialize() { + byte[] username = this.asset.username.getBytes(); + + ByteBuffer buffer = ByteBuffer.allocate(username.length + 1); + + buffer.order(ByteOrder.LITTLE_ENDIAN); + + buffer.put((byte) username.length); + buffer.put(username); + + return buffer.array(); + } + + @Override + public void deserialize(ByteBuffer buffer) { + int usernameLength = buffer.get() & 0xff; + + byte[] username = new byte[usernameLength]; + buffer.get(username); + + String utf8Username = new String(username); + this.asset.username = utf8Username; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java new file mode 100644 index 00000000..8f1b70b2 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java @@ -0,0 +1,31 @@ +package org.arkecosystem.crypto.transactions.types; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import org.arkecosystem.crypto.enums.CoreTransactionTypes; +import org.arkecosystem.crypto.enums.TransactionTypeGroup; + +public class UsernameResignation extends Transaction { + @Override + public int getTransactionType() { + return CoreTransactionTypes.USERNAME_RESIGNATION.getValue(); + } + + @Override + public int getTransactionTypeGroup() { + return TransactionTypeGroup.CORE.getValue(); + } + + @Override + public HashMap assetToHashMap() { + return null; + } + + @Override + public byte[] serialize() { + return new byte[0]; + } + + @Override + public void deserialize(ByteBuffer buffer) {} +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java new file mode 100644 index 00000000..55bb1a0f --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java @@ -0,0 +1,30 @@ +package org.arkecosystem.crypto.transactions.builder; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.HashMap; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +class UsernameRegistrationBuilderTest { + @Test + void build() { + Transaction actual = + new UsernameRegistrationBuilder() + .usernameAsset( + "alfonsobries") + .nonce(3) + .sign("this is a top secret passphrase") + .transaction; + + HashMap actualHashMap = actual.toHashMap(); + + HashMap asset = (HashMap) actualHashMap.get("asset"); + + assertEquals( + asset.get("validatorPublicKey"), + "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118"); + + assertTrue(actual.verify()); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java new file mode 100644 index 00000000..4975815c --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java @@ -0,0 +1,39 @@ +package org.arkecosystem.crypto.transactions.builder; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.HashMap; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +public class UsernameResignationBuilderTest { + @Test + void build() { + Transaction actual = + new UsernameResignationBuilder() + .nonce(3) + .sign("this is a top secret passphrase") + .transaction; + + HashMap actualHashMap = actual.toHashMap(); + HashMap actualAsset = (HashMap) actualHashMap.get("asset"); + assertNull(actualAsset); + + assertTrue(actual.verify()); + } + + @Test + void buildSecondSignature() { + Transaction actual = + new UsernameResignationBuilder() + .nonce(3) + .sign("this is a top secret passphrase") + .secondSign("this is a top secret second passphrase") + .transaction; + + assertTrue(actual.verify()); + assertTrue( + actual.secondVerify( + "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java new file mode 100644 index 00000000..a4a8be8f --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java @@ -0,0 +1,38 @@ +package org.arkecosystem.crypto.transactions.deserializers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.internal.LinkedTreeMap; +import org.arkecosystem.crypto.enums.TransactionTypeGroup; +import org.arkecosystem.crypto.transactions.Deserializer; +import org.arkecosystem.crypto.transactions.FixtureLoader; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +public class UsernameRegistrationTest { + + @Test + void passphrase() { + LinkedTreeMap fixture = + FixtureLoader.load( + "transactions/username_registration/username-registration-sign"); + + LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); + + Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); + + assertEquals(((Double) data.get("version")).intValue(), actual.version); + assertEquals(((Double) data.get("network")).intValue(), actual.network); + assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); + assertEquals(((Double) data.get("type")).intValue(), actual.type); + assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); + assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); + assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); + assertEquals(data.get("signature").toString(), actual.signature); + assertEquals(data.get("id").toString(), actual.id); + + LinkedTreeMap asset = (LinkedTreeMap) data.get("asset"); + + assertEquals((asset.get("username")), actual.asset.username); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameResignationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameResignationTest.java new file mode 100644 index 00000000..6dfa1ff7 --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameResignationTest.java @@ -0,0 +1,36 @@ +package org.arkecosystem.crypto.transactions.deserializers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import com.google.gson.internal.LinkedTreeMap; +import org.arkecosystem.crypto.enums.TransactionTypeGroup; +import org.arkecosystem.crypto.transactions.Deserializer; +import org.arkecosystem.crypto.transactions.FixtureLoader; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +class UsernameResignationTest { + + @Test + void passphrase() { + LinkedTreeMap fixture = + FixtureLoader.load("transactions/username_resignation/username-resignation-sign"); + + LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); + + Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); + + assertEquals(((Double) data.get("version")).intValue(), actual.version); + assertEquals(((Double) data.get("network")).intValue(), actual.network); + assertEquals(TransactionTypeGroup.CORE.getValue(), actual.typeGroup); + assertEquals(((Double) data.get("type")).intValue(), actual.type); + assertEquals((Long.valueOf((String) data.get("nonce"))), actual.nonce); + assertEquals(data.get("senderPublicKey").toString(), actual.senderPublicKey); + assertEquals((Long.valueOf((String) data.get("fee"))), actual.fee); + assertEquals(data.get("signature").toString(), actual.signature); + assertEquals(data.get("id").toString(), actual.id); + + assertNull(data.get("asset")); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java new file mode 100644 index 00000000..ca727b7e --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java @@ -0,0 +1,26 @@ +package org.arkecosystem.crypto.transactions.serializers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.internal.LinkedTreeMap; +import org.arkecosystem.crypto.encoding.Hex; +import org.arkecosystem.crypto.transactions.Deserializer; +import org.arkecosystem.crypto.transactions.FixtureLoader; +import org.arkecosystem.crypto.transactions.Serializer; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +class UsernameRegistrationTest { + @Test + void passphrase() { + LinkedTreeMap fixture = + FixtureLoader.load( + "transactions/username_registration/username-registration-sign"); + Transaction transaction = + new Deserializer(fixture.get("serialized").toString()).deserialize(); + + String actual = Hex.encode(Serializer.serialize(transaction)); + + assertEquals(fixture.get("serialized").toString(), actual); + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameResignationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameResignationTest.java new file mode 100644 index 00000000..ec77bef7 --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameResignationTest.java @@ -0,0 +1,26 @@ +package org.arkecosystem.crypto.transactions.serializers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.internal.LinkedTreeMap; +import org.arkecosystem.crypto.encoding.Hex; +import org.arkecosystem.crypto.transactions.Deserializer; +import org.arkecosystem.crypto.transactions.FixtureLoader; +import org.arkecosystem.crypto.transactions.Serializer; +import org.arkecosystem.crypto.transactions.types.Transaction; +import org.junit.jupiter.api.Test; + +class UsernameResignationTest { + @Test + void passphrase() { + LinkedTreeMap fixture = + FixtureLoader.load("transactions/username_resignation/username-resignation-sign"); + + Transaction transaction = + new Deserializer(fixture.get("serialized").toString()).deserialize(); + + String actual = Hex.encode(Serializer.serialize(transaction)); + + assertEquals(fixture.get("serialized").toString(), actual); + } +} From ad9191ea01109e80f30a3f29459486c37a763e05 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Tue, 6 Aug 2024 12:18:49 -0600 Subject: [PATCH 69/74] wip --- .../crypto/transactions/types/UsernameRegistration.java | 1 - .../transactions/builder/UsernameRegistrationBuilderTest.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java index 55ce81ae..d7d16db7 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java @@ -3,7 +3,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.HashMap; -import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.enums.CoreTransactionTypes; import org.arkecosystem.crypto.enums.TransactionTypeGroup; diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java index 55bb1a0f..6daeccb9 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java @@ -22,8 +22,8 @@ void build() { HashMap asset = (HashMap) actualHashMap.get("asset"); assertEquals( - asset.get("validatorPublicKey"), - "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118"); + asset.get("username"), + "alfonsobries"); assertTrue(actual.verify()); } From b64d5d5f5022976ea34a74e1e0f2e589ba206fc7 Mon Sep 17 00:00:00 2001 From: alfonsobries Date: Tue, 6 Aug 2024 18:20:48 +0000 Subject: [PATCH 70/74] style: resolve style guide violations --- .../crypto/transactions/types/UsernameRegistration.java | 8 ++++---- .../builder/UsernameRegistrationBuilderTest.java | 7 ++----- .../deserializers/UsernameRegistrationTest.java | 3 +-- .../serializers/UsernameRegistrationTest.java | 3 +-- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java index d7d16db7..f4bbe80d 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java @@ -31,9 +31,9 @@ public byte[] serialize() { byte[] username = this.asset.username.getBytes(); ByteBuffer buffer = ByteBuffer.allocate(username.length + 1); - + buffer.order(ByteOrder.LITTLE_ENDIAN); - + buffer.put((byte) username.length); buffer.put(username); @@ -43,10 +43,10 @@ public byte[] serialize() { @Override public void deserialize(ByteBuffer buffer) { int usernameLength = buffer.get() & 0xff; - + byte[] username = new byte[usernameLength]; buffer.get(username); - + String utf8Username = new String(username); this.asset.username = utf8Username; } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java index 6daeccb9..36769fea 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java @@ -11,8 +11,7 @@ class UsernameRegistrationBuilderTest { void build() { Transaction actual = new UsernameRegistrationBuilder() - .usernameAsset( - "alfonsobries") + .usernameAsset("alfonsobries") .nonce(3) .sign("this is a top secret passphrase") .transaction; @@ -21,9 +20,7 @@ void build() { HashMap asset = (HashMap) actualHashMap.get("asset"); - assertEquals( - asset.get("username"), - "alfonsobries"); + assertEquals(asset.get("username"), "alfonsobries"); assertTrue(actual.verify()); } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java index a4a8be8f..0853ed71 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/deserializers/UsernameRegistrationTest.java @@ -14,8 +14,7 @@ public class UsernameRegistrationTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load( - "transactions/username_registration/username-registration-sign"); + FixtureLoader.load("transactions/username_registration/username-registration-sign"); LinkedTreeMap data = (LinkedTreeMap) fixture.get("data"); diff --git a/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java index ca727b7e..c07191d6 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/serializers/UsernameRegistrationTest.java @@ -14,8 +14,7 @@ class UsernameRegistrationTest { @Test void passphrase() { LinkedTreeMap fixture = - FixtureLoader.load( - "transactions/username_registration/username-registration-sign"); + FixtureLoader.load("transactions/username_registration/username-registration-sign"); Transaction transaction = new Deserializer(fixture.get("serialized").toString()).deserialize(); From 7fc228c8f699135a70e1818df29dbe5791275fa2 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Tue, 6 Aug 2024 12:25:25 -0600 Subject: [PATCH 71/74] add fixtures for usernames --- .../crypto/signature/FixtureSignVerificationTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java index 73294eda..02c18f9a 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java @@ -49,11 +49,11 @@ public class FixtureSignVerificationTest { "transactions/multi_payment/multi-payment-with-vendor-field-sign", // "transactions/multi_payment/multi-payment-multi-sign", - // "transactions/username_resignation/username-resignation-sign", + "transactions/username_resignation/username-resignation-sign", // "transactions/username_resignation/username-resignation-multi-sign", + "transactions/username_registration/username-registration-sign", // "transactions/username_registration/username-registration-multi-sign", - // "transactions/username_registration/username-registration-sign", "transactions/multi_signature_registration/multi-signature-registration-sign", }) @@ -94,11 +94,11 @@ void checkSchnorrSignature(String file) { "transactions/multi_payment/multi-payment-with-vendor-field-sign", // "transactions/multi_payment/multi-payment-multi-sign", - // "transactions/username_resignation/username-resignation-sign", + "transactions/username_resignation/username-resignation-sign", // "transactions/username_resignation/username-resignation-multi-sign", + "transactions/username_registration/username-registration-sign", // "transactions/username_registration/username-registration-multi-sign", - // "transactions/username_registration/username-registration-sign", // "transactions/multi_signature_registration/multi-signature-registration-sign", }) From 42400b093c354518946f6f1d36e5e6befd5fd685 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Mon, 12 Aug 2024 10:26:43 -0600 Subject: [PATCH 72/74] merge conflicts --- .../types/UsernameRegistration.java | 53 +++++++++++++++++++ .../crypto/{ => utils}/Schnorr.java | 0 2 files changed, 53 insertions(+) create mode 100644 src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java rename src/main/java/org/arkecosystem/crypto/{ => utils}/Schnorr.java (100%) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java new file mode 100644 index 00000000..0948d0ad --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java @@ -0,0 +1,53 @@ +package org.arkecosystem.crypto.transactions.types; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.HashMap; +import org.arkecosystem.crypto.enums.CoreTransactionTypes; +import org.arkecosystem.crypto.enums.TransactionTypeGroup; + +public class UsernameRegistration extends Transaction { + @Override + public int getTransactionType() { + return CoreTransactionTypes.USERNAME_REGISTRATION.getValue(); + } + + @Override + public int getTransactionTypeGroup() { + return TransactionTypeGroup.CORE.getValue(); + } + + @Override + public HashMap assetToHashMap() { + HashMap asset = new HashMap<>(); + + asset.put("username", this.asset.username); + + return asset; + } + + @Override + public byte[] serialize() { + byte[] username = this.asset.username.getBytes(); + + ByteBuffer buffer = ByteBuffer.allocate(username.length + 1); + + buffer.order(ByteOrder.LITTLE_ENDIAN); + + buffer.put((byte) username.length); + buffer.put(username); + + return buffer.array(); + } + + @Override + public void deserialize(ByteBuffer buffer) { + int usernameLength = buffer.get() & 0xff; + + byte[] username = new byte[usernameLength]; + buffer.get(username); + + String utf8Username = new String(username); + this.asset.username = utf8Username; + } +} \ No newline at end of file diff --git a/src/main/java/org/arkecosystem/crypto/Schnorr.java b/src/main/java/org/arkecosystem/crypto/utils/Schnorr.java similarity index 100% rename from src/main/java/org/arkecosystem/crypto/Schnorr.java rename to src/main/java/org/arkecosystem/crypto/utils/Schnorr.java From 912dad40b71578a34d1e6b1831b004b001cfd7cf Mon Sep 17 00:00:00 2001 From: alfonsobries Date: Mon, 12 Aug 2024 16:27:27 +0000 Subject: [PATCH 73/74] style: resolve style guide violations --- .../crypto/transactions/types/UsernameRegistration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java index 0948d0ad..f4bbe80d 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameRegistration.java @@ -50,4 +50,4 @@ public void deserialize(ByteBuffer buffer) { String utf8Username = new String(username); this.asset.username = utf8Username; } -} \ No newline at end of file +} From 3782075e6ab0a340afae0e7ab46ca32a990ddf50 Mon Sep 17 00:00:00 2001 From: Alfonso Bribiesca Date: Wed, 14 Aug 2024 06:01:51 -0600 Subject: [PATCH 74/74] feat: multisignature tests (#182) --- .../transactions/types/Transaction.java | 49 +------ .../FixtureSignVerificationTest.java | 136 ------------------ .../builder/MultiPaymentBuilderTest.java | 26 ++++ ...MultiSignatureRegistrationBuilderTest.java | 32 ----- .../builder/TransferBuilderTest.java | 29 ++++ .../UsernameRegistrationBuilderTest.java | 24 ++++ .../UsernameResignationBuilderTest.java | 23 +++ .../ValidatorRegistrationBuilderTest.java | 25 ++++ .../ValidatorResignationBuilderTest.java | 23 +++ .../transactions/builder/VoteBuilderTest.java | 26 ++++ 10 files changed, 179 insertions(+), 214 deletions(-) diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java b/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java index 0530eca3..0e61dfe0 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/Transaction.java @@ -4,9 +4,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.identities.PrivateKey; import org.arkecosystem.crypto.signature.SchnorrSigner; @@ -93,7 +91,7 @@ public boolean verify() { byte[] signature = Hex.decode(this.signature); byte[] hash = Sha256Hash.hash(Serializer.serialize(this, true, true, false)); - return verifier(this.signature).verify(hash, keys, signature); + return verifier().verify(hash, keys, signature); } public boolean secondVerify(String secondPublicKey) { @@ -102,48 +100,7 @@ public boolean secondVerify(String secondPublicKey) { byte[] signature = Hex.decode(this.secondSignature); byte[] hash = Sha256Hash.hash(Serializer.serialize(this, false, true, false)); - return verifier(this.secondSignature).verify(hash, keys, signature); - } - - public boolean multiVerify(int min, List publicKeys) { - if (publicKeys.isEmpty()) { - throw new RuntimeException("The multi signature asset is invalid."); - } - - byte[] hash = Sha256Hash.hash(Serializer.serialize(this, true, true, true)); - - Set publicKeyIndexes = new HashSet<>(); - int verifiedSignatures = 0; - boolean verified = false; - for (int i = 0; i < this.signatures.size(); i++) { - String signature = this.signatures.get(i); - int publicKeyIndex = Integer.parseInt(signature.substring(0, 2), 16); - - if (!publicKeyIndexes.contains(publicKeyIndex)) { - publicKeyIndexes.add(publicKeyIndex); - } else { - throw new RuntimeException("Duplicate participant in multi signature"); - } - - String partialSignature = signature.substring(2); - String publicKey = publicKeys.get(publicKeyIndex); - - if (verifier(partialSignature) - .verify( - hash, - ECKey.fromPublicOnly(Hex.decode(publicKey)), - Hex.decode(partialSignature))) { - verifiedSignatures++; - } - - if (verifiedSignatures == min) { - verified = true; - break; - } else if (signatures.size() - (i + 1 - verifiedSignatures) < min) { - break; - } - } - return verified; + return verifier().verify(hash, keys, signature); } public String toJson() { @@ -206,7 +163,7 @@ private Signer signer() { return new SchnorrSigner(); } - private Verifier verifier(String signature) { + private Verifier verifier() { return new SchnorrVerifier(); } } diff --git a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java index 02c18f9a..c338e6ec 100644 --- a/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java +++ b/src/test/java/org/arkecosystem/crypto/signature/FixtureSignVerificationTest.java @@ -1,60 +1,31 @@ package org.arkecosystem.crypto.signature; -import static org.hamcrest.CoreMatchers.startsWith; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.gson.internal.LinkedTreeMap; -import java.util.Arrays; -import java.util.List; -import org.arkecosystem.crypto.encoding.Hex; import org.arkecosystem.crypto.identities.PublicKey; import org.arkecosystem.crypto.transactions.Deserializer; import org.arkecosystem.crypto.transactions.FixtureLoader; -import org.arkecosystem.crypto.transactions.Serializer; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; public class FixtureSignVerificationTest { - private final String passphrase = "my super secret passphrase"; private final String secondPassphrase = "this is a top secret second passphrase"; - private final String musigPassphrase1 = - "album pony urban cheap small blade cannon silent run reveal luxury glad predict excess fire beauty hollow reward solar egg exclude leaf sight degree"; - private final String musigPassphrase2 = - "hen slogan retire boss upset blame rocket slender area arch broom bring elder few milk bounce execute page evoke once inmate pear marine deliver"; - private final String musigPassphrase3 = - "top visa use bacon sun infant shrimp eye bridge fantasy chair sadness stable simple salad canoe raw hill target connect avoid promote spider category"; @ParameterizedTest @ValueSource( strings = { "transactions/transfer/transfer-sign", - "transactions/transfer/transfer-with-vendor-field-sign", - // "transactions/transfer/transfer-multi-sign", - "transactions/vote/vote-sign", "transactions/vote/unvote-sign", - // "transactions/vote/vote-multi-sign", - "transactions/validator_registration/validator-registration-sign", - // "transactions/validator_registration/validator-registration-multi-sign", - "transactions/validator_resignation/validator-resignation-sign", - // "transactions/validator_resignation/validator-resignation-multi-sign", - "transactions/multi_payment/multi-payment-sign", "transactions/multi_payment/multi-payment-with-vendor-field-sign", - // "transactions/multi_payment/multi-payment-multi-sign", - "transactions/username_resignation/username-resignation-sign", - // "transactions/username_resignation/username-resignation-multi-sign", - "transactions/username_registration/username-registration-sign", - // "transactions/username_registration/username-registration-multi-sign", - "transactions/multi_signature_registration/multi-signature-registration-sign", }) void checkSchnorrSignature(String file) { @@ -67,117 +38,10 @@ void checkSchnorrSignature(String file) { if (actual.secondSignature != null) { checkSecondSignature(actual); } - - if (actual.signatures != null) { - checkMultiSignature(actual); - } - } - - @ParameterizedTest - @ValueSource( - strings = { - "transactions/transfer/transfer-sign", - "transactions/transfer/transfer-with-vendor-field-sign", - // "transactions/transfer/transfer-multi-sign", - - "transactions/vote/vote-sign", - "transactions/vote/unvote-sign", - // "transactions/vote/vote-multi-sign", - - "transactions/validator_registration/validator-registration-sign", - // "transactions/validator_registration/validator-registration-multi-sign", - - "transactions/validator_resignation/validator-resignation-sign", - // "transactions/validator_resignation/validator-resignation-multi-sign", - - "transactions/multi_payment/multi-payment-sign", - "transactions/multi_payment/multi-payment-with-vendor-field-sign", - // "transactions/multi_payment/multi-payment-multi-sign", - - "transactions/username_resignation/username-resignation-sign", - // "transactions/username_resignation/username-resignation-multi-sign", - - "transactions/username_registration/username-registration-sign", - // "transactions/username_registration/username-registration-multi-sign", - - // "transactions/multi_signature_registration/multi-signature-registration-sign", - }) - void checkSigningAgainProducesSameSignature(String file) { - LinkedTreeMap fixture = FixtureLoader.load(file); - - Transaction actual = new Deserializer(fixture.get("serialized").toString()).deserialize(); - - // Remove the signatures from original transaction - Transaction withoutSignatures = - new Deserializer(Hex.encode(Serializer.serialize(actual, true, true, true))) - .deserialize(); - - // Ensure only the signatures were removed - assertThat( - fixture.get("serialized").toString(), - startsWith(Hex.encode(Serializer.serialize(withoutSignatures)))); - - reSignUnsigned(actual, withoutSignatures); - - if (withoutSignatures.signature != null) { - assertTrue(withoutSignatures.verify()); - } - - if (withoutSignatures.secondSignature != null) { - checkSecondSignature(withoutSignatures); - } - - int signatureLength = 128; - - if (withoutSignatures.signatures != null) { - checkMultiSignature(withoutSignatures); - - signatureLength = 128 + (withoutSignatures.signatures.size() * 130); - } - - String serializedWithoutSignatures = Hex.encode(Serializer.serialize(withoutSignatures)); - String serializedFixture = fixture.get("serialized").toString(); - - // Exclude the last 128 characters (signature) for final comparison - assertThat( - serializedWithoutSignatures.substring( - 0, serializedWithoutSignatures.length() - signatureLength), - is(serializedFixture.substring(0, serializedFixture.length() - signatureLength))); - } - - private void reSignUnsigned(Transaction actual, Transaction withoutSignatures) { - if (actual.signatures != null) { - int i = 0; - for (String passphrase : - Arrays.asList(musigPassphrase1, musigPassphrase2, musigPassphrase3)) { - withoutSignatures.multiSign(passphrase, i++); - } - if (actual.signature != null) { - withoutSignatures.sign(musigPassphrase1); - } - if (actual.secondSignature != null) { - withoutSignatures.secondSign(secondPassphrase); - } - } else if (actual.secondSignature != null) { - withoutSignatures.sign(passphrase); - withoutSignatures.secondSign(secondPassphrase); - } else if (actual.signature != null) { - withoutSignatures.sign(passphrase); - } } private void checkSecondSignature(Transaction actual) { String secondPublicKey = PublicKey.fromPassphrase(secondPassphrase); assertTrue(actual.secondVerify(secondPublicKey)); } - - private void checkMultiSignature(Transaction actual) { - String key1 = PublicKey.fromPassphrase(musigPassphrase1); - String key2 = PublicKey.fromPassphrase(musigPassphrase2); - String key3 = PublicKey.fromPassphrase(musigPassphrase3); - - List publicKeys = Arrays.asList(key1, key2, key3); - - assertTrue(actual.multiVerify(2, publicKeys)); - } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java index 4427b45e..ab66bd60 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiPaymentBuilderTest.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -59,4 +60,29 @@ void testMaxPayments() { () -> actual.addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 1)); assertEquals("Expected a maximum of 64 payments", exception.getMessage()); } + + @Test + void buildMultiSignature() { + Transaction actual = + new MultiPaymentBuilder() + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 1) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 2) + .addPayment("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A", 3) + .vendorField("This is a transaction from Java") + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java index 894ab34c..3751034f 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/MultiSignatureRegistrationBuilderTest.java @@ -3,14 +3,11 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import org.arkecosystem.crypto.enums.Fees; import org.arkecosystem.crypto.identities.PublicKey; -import org.arkecosystem.crypto.transactions.Deserializer; import org.arkecosystem.crypto.transactions.types.Transaction; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class MultiSignatureRegistrationBuilderTest { @@ -38,7 +35,6 @@ void build() { .transaction; assertTrue(actual.verify()); - assertTrue(actual.multiVerify(3, publicKeys)); HashMap actualHashMap = actual.toHashMap(); @@ -54,32 +50,4 @@ void build() { assertEquals(publicKeys, actualPublicKeys); assertEquals(3, actualMin); } - - @Test - void checkMultiSignaturePassingInvalidMultiSignatureAsset() { - Exception thrown = - Assertions.assertThrows( - RuntimeException.class, - () -> { - Deserializer deserializer = - new Deserializer( - "ff011e0100000004000200000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d30065cd1d00000000000203029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca9203629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc52b33558cdc62933ff56feb646d1f47a98104bf34b894895d5e816f86e556f87fce8485e55aa32dfa1cd86456a66a58ef7a68dff4af51e2f7fcf75b983540872e000caa6864c71362b369c71107f463f29c43c361e54260cbc54d791b7385dbe76f29d12b9befbe4f98792d7046481afcf0c156408310192a93d8413e5380438f270153a22c5ce2b1894f0a141adc19de567077d2d268f4c7e1476e9558ecb4411d486cd0d7aa3e9c7716739a055a8a1a64a162d0362645d63d13791a9876ef8b5a88021d56997f0c9e21201c59e1b7b6be8d5a609908a4f65bf266144baf5e61e3f14bc2651f62187f4ffa17c8b010fcb0fba94a04df56bc25e5cb20935ec5fb7ad632"); - Transaction actual = deserializer.deserialize(); - assertTrue(actual.multiVerify(3, Collections.emptyList())); - }); - assertEquals("The multi signature asset is invalid.", thrown.getMessage()); - } - - @Test - void checkMultiSignaturePassingInvalidMultiSignatureAssets() { - String key1 = PublicKey.fromPassphrase("this is a top secret passphrase 1"); - String key2 = PublicKey.fromPassphrase("this is a top secret passphrase 2"); - String key3 = PublicKey.fromPassphrase("this is a top secret passphrase 3"); - - Deserializer deserializer = - new Deserializer( - "ff011e0100000004000200000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d30065cd1d00000000000203029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca9203629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc52b33558cdc62933ff56feb646d1f47a98104bf34b894895d5e816f86e556f87fce8485e55aa32dfa1cd86456a66a58ef7a68dff4af51e2f7fcf75b983540872e000caa6864c71362b369c71107f463f29c43c361e54260cbc54d791b7385dbe76f29d12b9befbe4f98792d7046481afcf0c156408310192a93d8413e5380438f270153a22c5ce2b1894f0a141adc19de567077d2d268f4c7e1476e9558ecb4411d486cd0d7aa3e9c7716739a055a8a1a64a162d0362645d63d13791a9876ef8b5a88021d56997f0c9e21201c59e1b7b6be8d5a609908a4f65bf266144baf5e61e3f14bc2651f62187f4ffa17c8b010fcb0fba94a04df56bc25e5cb20935ec5fb7ad632"); - Transaction actual = deserializer.deserialize(); - assertFalse(actual.multiVerify(3, Arrays.asList(key1, key2, key3))); - } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java index 22634cd2..00e061af 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/TransferBuilderTest.java @@ -1,9 +1,11 @@ package org.arkecosystem.crypto.transactions.builder; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.enums.Fees; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -62,4 +64,31 @@ void buildSecondSignature() { HashMap actualHashMap = actual.toHashMap(); assertEquals(actualHashMap.get("secondSignature"), actual.secondSignature); } + + @Test + void buildMultiSignature() { + Transaction actual = + new TransferBuilder() + .recipient("0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A") + .amount(133380000000L) + .expiration(100000) + .vendorField("This is a transaction from Java") + .nonce(3) + .fee(Fees.TRANSFER.getValue()) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("secret 1") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java index 36769fea..d373b3f5 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameRegistrationBuilderTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -24,4 +25,27 @@ void build() { assertTrue(actual.verify()); } + + @Test + void buildMultiSignature() { + Transaction actual = + new UsernameRegistrationBuilder() + .usernameAsset("alfonsobries") + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java index 4975815c..e96e39ed 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -36,4 +37,26 @@ void buildSecondSignature() { actual.secondVerify( "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); } + + @Test + void buildMultiSignature() { + Transaction actual = + new UsernameResignationBuilder() + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java index 1a28a767..65ffa8f8 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorRegistrationBuilderTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -27,4 +28,28 @@ void build() { assertTrue(actual.verify()); } + + @Test + void buildMultiSignature() { + Transaction actual = + new ValidatorRegistrationBuilder() + .publicKeyAsset( + "a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118") + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java index b42b367f..960a93fa 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/ValidatorResignationBuilderTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.HashMap; +import java.util.List; import org.arkecosystem.crypto.transactions.types.Transaction; import org.junit.jupiter.api.Test; @@ -36,4 +37,26 @@ void buildSecondSignature() { actual.secondVerify( "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); } + + @Test + void buildMultiSignature() { + Transaction actual = + new ValidatorResignationBuilder() + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } } diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java index 971773df..8aca1456 100644 --- a/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/VoteBuilderTest.java @@ -1,6 +1,7 @@ package org.arkecosystem.crypto.transactions.builder; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; @@ -128,4 +129,29 @@ void buildVoteSecondSignature() { actual.secondVerify( "03699e966b2525f9088a6941d8d94f7869964a000efe65783d78ac82e1199fe609")); } + + @Test + void buildMultiSignature() { + Transaction actual = + new VoteBuilder() + .addVote( + "034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192") + .version(2) + .nonce(3) + .multiSign("secret 1", 0) + .multiSign("secret 2", 1) + .multiSign("secret 3", 2) + .sign("this is a top secret passphrase") + .transaction; + + assertTrue(actual.verify()); + + HashMap actualHashMap = actual.toHashMap(); + + assertNotNull(actualHashMap.get("signatures")); + + List actualSignatures = (List) actualHashMap.get("signatures"); + + assertEquals(3, actualSignatures.size()); + } }