Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
371 changes: 217 additions & 154 deletions README.md

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ configurations {

dependencies {
// Core dependencies that work on both platforms
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.19.2")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.19.2")
implementation("com.fasterxml.jackson.core:jackson-databind:2.19.2")
implementation(platform("com.fasterxml.jackson:jackson-bom:2.20.0"))
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8")
implementation("com.fasterxml.jackson.core:jackson-databind")
implementation("org.bouncycastle:bcprov-jdk18on:1.81")
implementation("org.slf4j:slf4j-api:2.0.13")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
Expand Down
7 changes: 0 additions & 7 deletions src/main/java/org/unicitylabs/sdk/Hashable.java

This file was deleted.

98 changes: 81 additions & 17 deletions src/main/java/org/unicitylabs/sdk/StateTransitionClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,65 @@
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import org.unicitylabs.sdk.api.IAggregatorClient;
import org.unicitylabs.sdk.api.AggregatorClient;
import org.unicitylabs.sdk.api.InclusionProofResponse;
import org.unicitylabs.sdk.api.RequestId;
import org.unicitylabs.sdk.api.SubmitCommitmentResponse;
import org.unicitylabs.sdk.bft.RootTrustBase;
import org.unicitylabs.sdk.predicate.PredicateEngineService;
import org.unicitylabs.sdk.token.Token;
import org.unicitylabs.sdk.token.TokenState;
import org.unicitylabs.sdk.verification.VerificationException;
import org.unicitylabs.sdk.transaction.Commitment;
import org.unicitylabs.sdk.transaction.InclusionProofVerificationStatus;
import org.unicitylabs.sdk.transaction.MintCommitment;
import org.unicitylabs.sdk.transaction.MintTransactionData;
import org.unicitylabs.sdk.transaction.Transaction;
import org.unicitylabs.sdk.transaction.MintTransactionReason;
import org.unicitylabs.sdk.transaction.TransferCommitment;
import org.unicitylabs.sdk.transaction.TransferTransactionData;
import org.unicitylabs.sdk.transaction.TransferTransaction;
import org.unicitylabs.sdk.verification.VerificationException;

/**
* Client for handling state transitions of tokens, including submitting commitments and finalizing
* transactions.
*/
public class StateTransitionClient {

protected final IAggregatorClient client;
/**
* The aggregator client used for submitting commitments and retrieving inclusion proofs.
*/
protected final AggregatorClient client;

public StateTransitionClient(IAggregatorClient client) {
/**
* Creates a new StateTransitionClient with the specified aggregator client.
*
* @param client The aggregator client to use for communication.
*/
public StateTransitionClient(AggregatorClient client) {
this.client = client;
}

public <T extends MintTransactionData<?>> CompletableFuture<SubmitCommitmentResponse> submitCommitment(
MintCommitment<T> commitment
) {
/**
* Submits a mint commitment to the aggregator.
*
* @param commitment The mint commitment to submit.
* @param <R> The type of mint transaction data.
* @return A CompletableFuture that resolves to the response from the aggregator.
*/
public <R extends MintTransactionReason>
CompletableFuture<SubmitCommitmentResponse> submitCommitment(MintCommitment<R> commitment) {
return this.client.submitCommitment(
commitment.getRequestId(),
commitment.getTransactionData().calculateHash(),
commitment.getAuthenticator()
);
}

/**
* Submits a transfer commitment to the aggregator after verifying ownership.
*
* @param commitment The transfer commitment to submit.
* @return A CompletableFuture that resolves to the response from the aggregator.
* @throws IllegalArgumentException if ownership verification fails.
*/
public CompletableFuture<SubmitCommitmentResponse> submitCommitment(
TransferCommitment commitment
) {
Expand All @@ -55,29 +79,63 @@ public CompletableFuture<SubmitCommitmentResponse> submitCommitment(
.calculateHash(), commitment.getAuthenticator());
}

public <T extends MintTransactionData<?>> Token<T> finalizeTransaction(
/**
* Finalizes a transaction by updating the token state based on the provided transaction data
* without nametags.
*
* @param trustBase The root trust base for inclusion proof verification.
* @param token The token to be updated.
* @param state The current state of the token.
* @param transaction The transaction containing transfer data.
* @param <R> The type of mint transaction data.
* @return The updated token after applying the transaction.
* @throws VerificationException if verification fails during the update process.
*/
public <R extends MintTransactionReason> Token<R> finalizeTransaction(
RootTrustBase trustBase,
Token<T> token,
Token<R> token,
TokenState state,
Transaction<TransferTransactionData> transaction
TransferTransaction transaction
) throws VerificationException {
return this.finalizeTransaction(trustBase, token, state, transaction, List.of());
}

public <T extends MintTransactionData<?>> Token<T> finalizeTransaction(
/**
* Finalizes a transaction by updating the token state based on the provided transaction data and
* nametags.
*
* @param trustBase The root trust base for inclusion proof verification.
* @param token The token to be updated.
* @param state The current state of the token.
* @param transaction The transaction containing transfer data.
* @param nametags A list of tokens used as nametags in the transaction.
* @param <R> The type of mint transaction data of token.
* @return The updated token after applying the transaction.
* @throws VerificationException if verification fails during the update process.
*/
public <R extends MintTransactionReason> Token<R> finalizeTransaction(
RootTrustBase trustBase,
Token<T> token,
Token<R> token,
TokenState state,
Transaction<TransferTransactionData> transaction,
TransferTransaction transaction,
List<Token<?>> nametags
) throws VerificationException {
Objects.requireNonNull(token, "Token is null");

return token.update(trustBase, state, transaction, nametags);
}

/**
* Retrieves the inclusion proof for a token and verifies its status against the provided public
* key and trust base.
*
* @param token The token for which to retrieve the inclusion proof.
* @param publicKey The public key associated with the token.
* @param trustBase The root trust base for verification.
* @return A CompletableFuture that resolves to the inclusion proof verification status.
*/
public CompletableFuture<InclusionProofVerificationStatus> getTokenStatus(
Token<? extends MintTransactionData<?>> token,
Token<?> token,
byte[] publicKey,
RootTrustBase trustBase
) {
Expand All @@ -86,6 +144,12 @@ public CompletableFuture<InclusionProofVerificationStatus> getTokenStatus(
.thenApply(response -> response.getInclusionProof().verify(requestId, trustBase));
}

/**
* Retrieves the inclusion proof for a given commitment.
*
* @param commitment The commitment for which to retrieve the inclusion proof.
* @return A CompletableFuture that resolves to the inclusion proof response from the aggregator.
*/
public CompletableFuture<InclusionProofResponse> getInclusionProof(Commitment<?> commitment) {
return this.client.getInclusionProof(commitment.getRequestId());
}
Expand Down
24 changes: 22 additions & 2 deletions src/main/java/org/unicitylabs/sdk/address/Address.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@

package org.unicitylabs.sdk.address;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

/**
* Address interface.
*/
@JsonSerialize(using = AddressJson.Serializer.class)
@JsonDeserialize(using = AddressJson.Deserializer.class)
public interface Address {
AddressScheme getScheme();
String getAddress();

/**
* Get the address scheme.
*
* @return address scheme
*/
AddressScheme getScheme();

/**
* Get the address as a string.
*
* @return address string
*/
String getAddress();
}
16 changes: 14 additions & 2 deletions src/main/java/org/unicitylabs/sdk/address/AddressFactory.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
package org.unicitylabs.sdk.address;

import java.util.Arrays;
import java.util.Objects;
import org.unicitylabs.sdk.hash.DataHash;
import org.unicitylabs.sdk.token.TokenId;
import org.unicitylabs.sdk.util.HexConverter;
import java.util.Arrays;
import java.util.Objects;

/**
* Factory for creating Address instances from string representations.
*/
public class AddressFactory {

/**
* Create an Address from its string representation.
*
* @param address The address string.
* @return The corresponding Address instance.
* @throws IllegalArgumentException if the address format is invalid or does not match the
* expected format.
* @throws NullPointerException if the address is null.
*/
public static Address createAddress(String address) {
Objects.requireNonNull(address, "Address cannot be null");

Expand Down
90 changes: 90 additions & 0 deletions src/main/java/org/unicitylabs/sdk/address/AddressJson.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.unicitylabs.sdk.address;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import org.unicitylabs.sdk.predicate.EncodedPredicate;

/**
* Address serializer and deserializer implementation.
*/
public class AddressJson {

private AddressJson() {
}

/**
* Address serializer.
*/
public static class Serializer extends StdSerializer<Address> {

/**
* Create serializer.
*/
public Serializer() {
super(Address.class);
}

/**
* Serialize address.
*
* @param value addess
* @param gen json generator
* @param serializers serializer provider
* @throws IOException on serialization failure
*/
@Override
public void serialize(Address value, JsonGenerator gen,
SerializerProvider serializers)
throws IOException {
gen.writeObject(value.toString());
}
}

/**
* Address deserializer.
*/
public static class Deserializer extends StdDeserializer<Address> {

/**
* Create deserializer.
*/
public Deserializer() {
super(Address.class);
}

/**
* Deserialize address.
*
* @param p Parser used for reading JSON content
* @param ctx Context that can be used to access information about this deserialization
* activity.
* @return address
* @throws IOException on deserialization failure
*/
@Override
public Address deserialize(JsonParser p, DeserializationContext ctx)
throws IOException {
if (p.getCurrentToken() != JsonToken.VALUE_STRING) {
throw MismatchedInputException.from(
p,
EncodedPredicate.class,
"Expected string value"
);
}

try {
return AddressFactory.createAddress(p.readValueAs(String.class));
} catch (Exception e) {
throw MismatchedInputException.from(p, EncodedPredicate.class, "Expected bytes");
}
}
}
}

3 changes: 3 additions & 0 deletions src/main/java/org/unicitylabs/sdk/address/AddressScheme.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@

package org.unicitylabs.sdk.address;

/**
* Address scheme.
*/
public enum AddressScheme {
DIRECT,
PROXY
Expand Down
13 changes: 9 additions & 4 deletions src/main/java/org/unicitylabs/sdk/address/DirectAddress.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package org.unicitylabs.sdk.address;

import java.util.Arrays;
import java.util.Objects;
import org.unicitylabs.sdk.hash.DataHash;
import org.unicitylabs.sdk.hash.DataHasher;
import org.unicitylabs.sdk.hash.HashAlgorithm;
import org.unicitylabs.sdk.util.HexConverter;

import java.util.Arrays;
import java.util.Objects;

/**
* Direct address implementation
* Direct address implementation.
*/
public class DirectAddress implements Address {

Expand All @@ -21,6 +20,12 @@ private DirectAddress(DataHash data, byte[] checksum) {
this.checksum = Arrays.copyOf(checksum, checksum.length);
}

/**
* Create a direct address from a predicate reference.
*
* @param reference the data hash to create the address from
* @return the direct address
*/
public static DirectAddress create(DataHash reference) {
DataHash checksum = new DataHasher(HashAlgorithm.SHA256).update(reference.getImprint())
.digest();
Expand Down
Loading
Loading