Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
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