Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
30d4e9a
Add Result type to scale
Feb 27, 2023
abaef5b
Add Junit test for result type
Feb 27, 2023
4ee1b05
chore: add lib files for different architectures
Oct 12, 2023
55a3140
chore: add windows lib as well
Oct 12, 2023
99f71ea
Merge pull request #1 from LimeChain/#165
Oct 16, 2023
3327211
Add VRF proof verification / generation to the Schnorrkel wrapper (#2)
David-Petrov Mar 12, 2024
181141c
feat: added bridge to make_bytes function
Grigorov-Georgi Oct 24, 2024
8f2e16e
chore: refactoring
Grigorov-Georgi Oct 25, 2024
8bfd062
chore: renaming variables
Grigorov-Georgi Oct 28, 2024
8c77c93
chore: reformated rust code with rustfmt
Grigorov-Georgi Oct 28, 2024
74cf470
chore: fixed rust clippy warnings
Grigorov-Georgi Oct 28, 2024
830af6f
feat: incremented polkaj-schnorrkel version
Grigorov-Georgi Oct 28, 2024
9765d6c
feat: cross compile for all chip architectures
Grigorov-Georgi Oct 28, 2024
49b7718
Merge pull request #3 from LimeChain/feat/schnorrkel-make-bytes
Grigorov-Georgi Oct 29, 2024
ab2d1c6
feat: changed makeBytes signature to accept PublicKey instead KeyPair
Grigorov-Georgi Nov 25, 2024
72ae2ff
feat: generated rust binaries
Grigorov-Georgi Nov 25, 2024
e588769
Merge pull request #4 from LimeChain/adjust-schnorkel-make-bytes
Grigorov-Georgi Nov 25, 2024
21a68a8
feat: add custom serialization and deserialization for Hash256 and Ha…
Zurcusa Jan 27, 2025
b06c8ef
feat: add custom serialization and deserialization for Hash256 and Ha…
Zurcusa Jan 27, 2025
2403d33
Merge pull request #5 from LimeChain/717-hash-custom-serialization
Zurcusa Jan 27, 2025
5a1ec93
feat: add Hash264 object with 33 bytes length
Mar 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
buildscript {

repositories {
maven { url "https://repo.grails.org/grails/core/" }
}

dependencies {
classpath 'com.netflix.nebula:gradle-aggregate-javadocs-plugin:3.0.1'
}
Expand All @@ -15,7 +19,7 @@ apply plugin: 'jacoco'

allprojects {
group = 'io.emeraldpay.polkaj'
version = "0.5.0-SNAPSHOT"
version = "0.5.5-SNAPSHOT"

repositories {
mavenLocal()
Expand Down Expand Up @@ -50,9 +54,9 @@ task syncJars(type: Sync) {

// Skip Bintray for the root module
bintray {
dryRun=true
publish=false
override=true
dryRun = true
publish = false
override = true
publications = []
configurations = []
pkg {
Expand All @@ -62,4 +66,4 @@ bintray {
name = 'none'
}
}
}
}
1 change: 1 addition & 0 deletions polkaj-adapter-tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ dependencies {
api 'org.codehaus.groovy:groovy-all:3.0.3'
api 'commons-codec:commons-codec:1.14'
api 'cglib:cglib-nodep:3.3.0'
api 'org.junit.jupiter:junit-jupiter-api:5.9.2'
}
1 change: 1 addition & 0 deletions polkaj-api-base/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ apply from: '../common_java_app.gradle'

dependencies {
api project(":polkaj-json-types")
api 'org.junit.jupiter:junit-jupiter-api:5.9.2'
}
1 change: 1 addition & 0 deletions polkaj-api-http/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ compileJava {
dependencies {
api project(":polkaj-json-types")
api project(":polkaj-api-base")
api 'org.junit.jupiter:junit-jupiter-api:5.9.2'

testImplementation 'org.mock-server:mockserver-netty:5.10'
testImplementation project(":polkaj-adapter-tests")
Expand Down
1 change: 1 addition & 0 deletions polkaj-api-ws/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ compileJava {
dependencies {
api project(":polkaj-json-types")
api project(":polkaj-api-base")
api 'org.junit.jupiter:junit-jupiter-api:5.9.2'

testImplementation 'org.java-websocket:Java-WebSocket:1.5.1'
testImplementation project(":polkaj-adapter-tests")
Expand Down
1 change: 1 addition & 0 deletions polkaj-common-types/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ apply from: '../common_java_app.gradle'

dependencies {
api project(":polkaj-ss58")
api 'org.junit.jupiter:junit-jupiter-api:5.9.2'
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

abstract public class FixedBytes extends ByteData {

/**
* Needed for serialization/deserialization.
*/
public FixedBytes() {
super(new byte[0]);
}

protected FixedBytes(byte[] value, int expectedSize) {
super(value);
if (value.length != expectedSize) {
Expand Down Expand Up @@ -34,7 +41,7 @@ protected static byte[] parseHex(String hex) {
}
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = Integer.valueOf(hex.substring(i, i+2), 16).byteValue();
data[i / 2] = Integer.valueOf(hex.substring(i, i + 2), 16).byteValue();
}
return data;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package io.emeraldpay.polkaj.types;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
* A 256 bit value, commonly used as a hash
*/
public class Hash256 extends FixedBytes implements Comparable<Hash256> {
public class Hash256 extends FixedBytes implements Comparable<Hash256>, Serializable {

/**
* Length in bytes (32 byte)
Expand All @@ -14,7 +19,7 @@ public class Hash256 extends FixedBytes implements Comparable<Hash256> {
* Create a new value. Makes sure the input is correct, if not throws an exception
*
* @param value 32 byte value
* @throws NullPointerException if value is null
* @throws NullPointerException if value is null
* @throws IllegalArgumentException is size is not 32 bytes
*/
public Hash256(byte[] value) {
Expand All @@ -36,7 +41,7 @@ public static Hash256 empty() {
* @param hex hex value, may optionally start with 0x prefix
* @return hash instance
* @throws IllegalArgumentException if value has invalid length
* @throws NumberFormatException if value has invalid format (non-hex characters, etc)
* @throws NumberFormatException if value has invalid format (non-hex characters, etc)
*/
public static Hash256 from(String hex) {
byte[] parsed = parseHex(hex, SIZE_BYTES);
Expand All @@ -47,4 +52,38 @@ public static Hash256 from(String hex) {
public int compareTo(Hash256 o) {
return super.compareTo(o);
}

/**
* Custom serialization logic. Writes the length and value of the underlying byte array for the hash.
*
* @param out the {@link ObjectOutputStream} to write this object to
* @throws IOException if an I/O error occurs while writing to the stream
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeInt(value.length);
out.write(value);
}

/**
* Custom deserialization logic. Validates the required length and sets the underlying byte array using reflection.
*
* @param in the {@link ObjectInputStream} to read this object from
* @throws IOException if the length of the serialized data is invalid or if an I/O error occurs
* @throws ClassNotFoundException if the class of a serialized object cannot be found
*/
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
int length = in.readInt();
if (length != SIZE_BYTES) {
throw new IOException("Invalid Hash256 length: " + length);
}
byte[] value = new byte[length];
in.readFully(value);
try {
java.lang.reflect.Field valueField = ByteData.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.set(this, value.clone());
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new IOException("Failed to initialize Hash256", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package io.emeraldpay.polkaj.types;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
* A 264 bit value, commonly used as a hash
*/
public class Hash264 extends FixedBytes implements Comparable<Hash264>, Serializable {

/**
* Length in bytes (33 byte)
*/
public static final int SIZE_BYTES = 33;

/**
* Create a new value. Makes sure the input is correct, if not throws an exception
*
* @param value 33 byte value
* @throws NullPointerException if value is null
* @throws IllegalArgumentException is size is not 33 bytes
*/
public Hash264(byte[] value) {
super(value, SIZE_BYTES);
}

/**
* Creates an empty zeroed instance
*
* @return empty hash
*/
public static Hash264 empty() {
return new Hash264(new byte[SIZE_BYTES]);
}

/**
* Parse hex value and create a new instance
*
* @param hex hex value, may optionally start with 0x prefix
* @return hash instance
* @throws IllegalArgumentException if value has invalid length
* @throws NumberFormatException if value has invalid format (non-hex characters, etc)
*/
public static Hash264 from(String hex) {
byte[] parsed = parseHex(hex, SIZE_BYTES);
return new Hash264(parsed);
}

@Override
public int compareTo(Hash264 o) {
return super.compareTo(o);
}

/**
* Custom serialization logic. Writes the length and value of the underlying byte array for the hash.
*
* @param out the {@link ObjectOutputStream} to write this object to
* @throws IOException if an I/O error occurs while writing to the stream
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeInt(value.length);
out.write(value);
}

/**
* Custom deserialization logic. Validates the required length and sets the underlying byte array using reflection.
*
* @param in the {@link ObjectInputStream} to read this object from
* @throws IOException if the length of the serialized data is invalid or if an I/O error occurs
* @throws ClassNotFoundException if the class of a serialized object cannot be found
*/
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
int length = in.readInt();
if (length != SIZE_BYTES) {
throw new IOException("Invalid Hash264 length: " + length);
}
byte[] value = new byte[length];
in.readFully(value);
try {
java.lang.reflect.Field valueField = ByteData.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.set(this, value.clone());
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new IOException("Failed to initialize Hash264", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package io.emeraldpay.polkaj.types;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
* A 512 bit value, commonly used as a hash
*/
public class Hash512 extends FixedBytes implements Comparable<Hash512> {
public class Hash512 extends FixedBytes implements Comparable<Hash512>, Serializable {

/**
* Length in bytes (64 byte)
Expand All @@ -14,7 +19,7 @@ public class Hash512 extends FixedBytes implements Comparable<Hash512> {
* Create a new value. Makes sure the input is correct, if not throws an exception
*
* @param value 64 byte value
* @throws NullPointerException if value is null
* @throws NullPointerException if value is null
* @throws IllegalArgumentException is size is not 64 bytes
*/
public Hash512(byte[] value) {
Expand All @@ -36,7 +41,7 @@ public static Hash512 empty() {
* @param hex hex value, may optionally start with 0x prefix
* @return hash instance
* @throws IllegalArgumentException if value has invalid length
* @throws NumberFormatException if value has invalid format (non-hex characters, etc)
* @throws NumberFormatException if value has invalid format (non-hex characters, etc)
*/
public static Hash512 from(String hex) {
byte[] parsed = parseHex(hex, SIZE_BYTES);
Expand All @@ -47,4 +52,38 @@ public static Hash512 from(String hex) {
public int compareTo(Hash512 o) {
return super.compareTo(o);
}

/**
* Custom serialization logic. Writes the length and value of the underlying byte array for the hash.
*
* @param out the {@link ObjectOutputStream} to write this object to
* @throws IOException if an I/O error occurs while writing to the stream
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeInt(value.length);
out.write(value);
}

/**
* Custom deserialization logic. Validates the required length and sets the underlying byte array using reflection.
*
* @param in the {@link ObjectInputStream} to read this object from
* @throws IOException if the length of the serialized data is invalid or if an I/O error occurs
* @throws ClassNotFoundException if the class of a serialized object cannot be found
*/
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
int length = in.readInt();
if (length != SIZE_BYTES) {
throw new IOException("Invalid Hash512 length: " + length);
}
byte[] value = new byte[length];
in.readFully(value);
try {
java.lang.reflect.Field valueField = ByteData.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.set(this, value.clone());
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new IOException("Failed to initialize Hash512", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@ class FixedBytesSpec extends Specification {
def t = thrown(IllegalStateException)
t.message.contains("Different size")
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,24 @@ class Hash256Spec extends Specification {
then:
hash1.hashCode() != hash2.hashCode()
}

def "Deserialization produces expected Hash256"() {
setup:
def hash = Hash256.from("0x63c2499de640b43c924bc2bfc9ea89730e7c4790e24d126906e7af6c99cb506b")
def serialized = SerializationUtil.serialize(hash)
when:
def deserialized = SerializationUtil.deserialize(serialized)
then:
deserialized instanceof Hash256
deserialized.toString() == "0x63c2499de640b43c924bc2bfc9ea89730e7c4790e24d126906e7af6c99cb506b"
}

def "Cannot deserialize invalid length bytes"() {
setup:
def serialized = new byte[]{1, 2, 3, 4}
when:
SerializationUtil.deserialize(serialized)
then:
thrown(IllegalArgumentException)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,18 @@ class Hash512Spec extends Specification {
then:
hash1.hashCode() != hash2.hashCode()
}

def "Deserialization produces expected Hash512"() {
setup:
def hash = Hash512.from(
"0x63c2499de640b43c924bc2bfc9ea89730e7c4790e24d126906e7af6c99cb506b" +
"63c2499de640b43c924bc2bfc9ea89730e7c4790e24d126906e7af6c99cb506b")
def serialized = SerializationUtil.serialize(hash)
when:
def deserialized = SerializationUtil.deserialize(serialized)
then:
deserialized instanceof Hash512
deserialized.toString() == "0x63c2499de640b43c924bc2bfc9ea89730e7c4790e24d126906e7af6c99cb506b" +
"63c2499de640b43c924bc2bfc9ea89730e7c4790e24d126906e7af6c99cb506b"
}
}
Loading