diff --git a/README.md b/README.md index e40e019..2db8c16 100644 --- a/README.md +++ b/README.md @@ -127,18 +127,18 @@ MintCommitment commitment = MintCommitment.create( ); // Submit mint transaction using StateTransitionClient -SubmitCommitmentResponse response = client +CertificationResponse response = client .submitCommitment(commitment) .get(); -if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new Exception( - String.format( - "Failed to submit mint commitment: %s", - response.getStatus() - ) - ); -} + String.format( + "Failed to submit mint commitment: %s", + response.getStatus() + ) + ); + } // Wait for inclusion proof InclusionProof inclusionProof = InclusionProofUtils.waitInclusionProof( @@ -187,8 +187,8 @@ TransferCommitment transferCommitment = TransferCommitment.create( SigningService.createFromMaskedSecret(senderSecret, senderNonce) ); -SubmitCommitmentResponse transferResponse = this.client.submitCommitment(transferCommitment).get(); -if (transferResponse.getStatus() != SubmitCommitmentStatus.SUCCESS) { +CertificationResponse transferResponse = this.client.submitCommitment(transferCommitment).get(); +if (transferResponse.getStatus() != CertificationStatus.SUCCESS) { throw new Exception( String.format( "Failed to submit transfer commitment: %s", @@ -245,8 +245,8 @@ MintCommitment nametagMintCommitment = MintCommitment.create( ); // Submit nametag mint transaction using StateTransitionClient -SubmitCommitmentResponse nametagMintResponse = client.submitCommitment(nametagMintCommitment).get(); -if (nametagMintResponse.getStatus() != SubmitCommitmentStatus.SUCCESS) { +CertificationResponse nametagMintResponse = client.submitCommitment(nametagMintCommitment).get(); +if (nametagMintResponse.getStatus() != CertificationStatus.SUCCESS) { throw new Exception( String.format( "Failed to submit nametag mint commitment: %s", @@ -294,7 +294,6 @@ Token finalizedToken = client.finalizeTransaction( transaction, List.of(nametagToken) ); - ``` ## Building from Source @@ -410,7 +409,7 @@ Located in `src/test/java/org/unicitylabs/sdk/`: ./gradlew integrationTest # Specific test class -./gradlew test --tests "org.unicitylabs.sdk.api.RequestIdTest" +./gradlew test --tests "org.unicitylabs.sdk.api.StateIdTest" ``` ## License diff --git a/src/main/java/org/unicitylabs/sdk/StateTransitionClient.java b/src/main/java/org/unicitylabs/sdk/StateTransitionClient.java index 5bba9b8..6949a26 100644 --- a/src/main/java/org/unicitylabs/sdk/StateTransitionClient.java +++ b/src/main/java/org/unicitylabs/sdk/StateTransitionClient.java @@ -6,8 +6,8 @@ import java.util.concurrent.CompletableFuture; 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.api.StateId; +import org.unicitylabs.sdk.api.CertificationResponse; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.predicate.Predicate; import org.unicitylabs.sdk.predicate.PredicateEngineService; @@ -50,12 +50,8 @@ public StateTransitionClient(AggregatorClient client) { * @return A CompletableFuture that resolves to the response from the aggregator. */ public - CompletableFuture submitCommitment(MintCommitment commitment) { - return this.client.submitCommitment( - commitment.getRequestId(), - commitment.getTransactionData().calculateHash(), - commitment.getAuthenticator() - ); + CompletableFuture submitCommitment(MintCommitment commitment) { + return this.client.submitCertificationRequest(commitment.getCertificationData(), false); } /** @@ -65,20 +61,17 @@ CompletableFuture submitCommitment(MintCommitment c * @return A CompletableFuture that resolves to the response from the aggregator. * @throws IllegalArgumentException if ownership verification fails. */ - public CompletableFuture submitCommitment( - TransferCommitment commitment - ) { + public CompletableFuture submitCommitment(TransferCommitment commitment) { if ( !PredicateEngineService.createPredicate( commitment.getTransactionData().getSourceState().getPredicate() - ).isOwner(commitment.getAuthenticator().getPublicKey()) + ).isOwner(commitment.getCertificationData().getPublicKey()) ) { throw new IllegalArgumentException( "Ownership verification failed: Authenticator does not match source state predicate."); } - return this.client.submitCommitment(commitment.getRequestId(), commitment.getTransactionData() - .calculateHash(), commitment.getAuthenticator()); + return this.client.submitCertificationRequest(commitment.getCertificationData(), false); } /** @@ -126,26 +119,26 @@ public Token finalizeTransaction( } /** - * Retrieves the inclusion proof for a given request id. + * Retrieves the inclusion proof for a given state id. * - * @param requestId The request ID of inclusion proof to retrieve. + * @param stateId The state ID of inclusion proof to retrieve. * @return A CompletableFuture that resolves to the inclusion proof response from the aggregator. */ - public CompletableFuture getInclusionProof(RequestId requestId) { - return this.client.getInclusionProof(requestId); + public CompletableFuture getInclusionProof(StateId stateId) { + return this.client.getInclusionProof(stateId); } /** - * Check if state is already spent for given request id. + * Check if state is already spent for given state id. * - * @param requestId request id + * @param stateId state id * @param trustBase root trust base * @return A CompletableFuture that resolves to true if state is spent, false otherwise. */ - public CompletableFuture isStateSpent(RequestId requestId, RootTrustBase trustBase) { - return this.getInclusionProof(requestId) + public CompletableFuture isStateSpent(StateId stateId, RootTrustBase trustBase) { + return this.getInclusionProof(stateId) .thenApply(inclusionProof -> { - InclusionProofVerificationStatus result = inclusionProof.getInclusionProof().verify(requestId, trustBase); + InclusionProofVerificationStatus result = inclusionProof.getInclusionProof().verify(trustBase, stateId); switch (result) { case OK: return true; @@ -178,7 +171,7 @@ public CompletableFuture isStateSpent( throw new IllegalArgumentException("Given key is not owner of the token."); } - return this.isStateSpent(RequestId.create(publicKey, token.getState()), trustBase); + return this.isStateSpent(StateId.create(publicKey, token.getState()), trustBase); } /** @@ -190,7 +183,7 @@ public CompletableFuture isStateSpent( */ public CompletableFuture isMinted(TokenId tokenId, RootTrustBase trustBase) { return this.isStateSpent( - RequestId.create( + StateId.create( MintSigningService.create(tokenId).getPublicKey(), MintTransactionState.create(tokenId) ), diff --git a/src/main/java/org/unicitylabs/sdk/api/AggregatorClient.java b/src/main/java/org/unicitylabs/sdk/api/AggregatorClient.java index 8808cdb..8669b07 100644 --- a/src/main/java/org/unicitylabs/sdk/api/AggregatorClient.java +++ b/src/main/java/org/unicitylabs/sdk/api/AggregatorClient.java @@ -2,7 +2,6 @@ package org.unicitylabs.sdk.api; import java.util.concurrent.CompletableFuture; -import org.unicitylabs.sdk.hash.DataHash; /** * Aggregator client structure. @@ -10,25 +9,24 @@ public interface AggregatorClient { /** - * Submit commitment. + * Submit certification request. * - * @param requestId request id - * @param transactionHash transaction hash - * @param authenticator authenticator - * @return submit commitment response + * @param certificationData certification data + * @param receipt whether to request a receipt + * @return certification response */ - CompletableFuture submitCommitment( - RequestId requestId, - DataHash transactionHash, - Authenticator authenticator); + CompletableFuture submitCertificationRequest( + CertificationData certificationData, + boolean receipt + ); /** - * Get inclusion proof for request id. + * Get inclusion proof for state id. * - * @param requestId request id + * @param stateId state id * @return inclusion / non inclusion proof */ - CompletableFuture getInclusionProof(RequestId requestId); + CompletableFuture getInclusionProof(StateId stateId); /** * Get block height. diff --git a/src/main/java/org/unicitylabs/sdk/api/Authenticator.java b/src/main/java/org/unicitylabs/sdk/api/Authenticator.java deleted file mode 100644 index 97d106c..0000000 --- a/src/main/java/org/unicitylabs/sdk/api/Authenticator.java +++ /dev/null @@ -1,189 +0,0 @@ -package org.unicitylabs.sdk.api; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import org.unicitylabs.sdk.hash.DataHash; -import org.unicitylabs.sdk.serializer.UnicityObjectMapper; -import org.unicitylabs.sdk.serializer.cbor.CborDeserializer; -import org.unicitylabs.sdk.serializer.cbor.CborSerializer; -import org.unicitylabs.sdk.serializer.json.JsonSerializationException; -import org.unicitylabs.sdk.signing.Signature; -import org.unicitylabs.sdk.signing.SigningService; -import org.unicitylabs.sdk.util.HexConverter; - -/** - * Authenticator for transaction submission. - */ -public class Authenticator { - - private final String algorithm; - private final Signature signature; - private final DataHash stateHash; - private final byte[] publicKey; - - @JsonCreator - private Authenticator( - @JsonProperty("algorithm") String algorithm, - @JsonProperty("publicKey") byte[] publicKey, - @JsonProperty("signature") Signature signature, - @JsonProperty("stateHash") DataHash stateHash - ) { - this.algorithm = algorithm; - this.publicKey = Arrays.copyOf(publicKey, publicKey.length); - this.signature = signature; - this.stateHash = stateHash; - } - - /** - * Create authenticator from signing service. - * - * @param signingService signing service - * @param transactionHash transaction hash - * @param stateHash state hash - * @return authenticator - */ - public static Authenticator create( - SigningService signingService, - DataHash transactionHash, - DataHash stateHash - ) { - return new Authenticator( - signingService.getAlgorithm(), - signingService.getPublicKey(), - signingService.sign(transactionHash), - stateHash - ); - } - - /** - * Get signature. - * - * @return signature - */ - public Signature getSignature() { - return this.signature; - } - - /** - * Get algorithm. - * - * @return algorithm - */ - public String getAlgorithm() { - return this.algorithm; - } - - /** - * Get state hash. - * - * @return state hash - */ - public DataHash getStateHash() { - return this.stateHash; - } - - /** - * Get public key. - * - * @return public key - */ - public byte[] getPublicKey() { - return Arrays.copyOf(this.publicKey, this.publicKey.length); - } - - /** - * Verify if signature and data are correct. - * - * @param hash data hash - * @return true if successful - */ - public boolean verify(DataHash hash) { - return SigningService.verifyWithPublicKey(hash, this.signature.getBytes(), this.publicKey); - } - - /** - * Create authenticator from CBOR bytes. - * - * @param bytes CBOR bytes - * @return authenticator - */ - public static Authenticator fromCbor(byte[] bytes) { - List data = CborDeserializer.readArray(bytes); - - return new Authenticator( - CborDeserializer.readTextString(data.get(0)), - CborDeserializer.readByteString(data.get(1)), - Signature.decode(CborDeserializer.readByteString(data.get(2))), - DataHash.fromCbor(data.get(3)) - ); - } - - /** - * Convert authenticator to CBOR bytes. - * - * @return CBOR bytes - */ - public byte[] toCbor() { - return CborSerializer.encodeArray( - CborSerializer.encodeTextString(this.algorithm), - CborSerializer.encodeByteString(this.publicKey), - CborSerializer.encodeByteString(this.signature.encode()), - this.stateHash.toCbor() - ); - } - - /** - * Create authenticator from JSON string. - * - * @param input JSON string - * @return authenticator - */ - public static Authenticator fromJson(String input) { - try { - return UnicityObjectMapper.JSON.readValue(input, Authenticator.class); - } catch (JsonProcessingException e) { - throw new JsonSerializationException(Authenticator.class, e); - } - } - - /** - * Convert authenticator to JSON string. - * - * @return JSON string - */ - public String toJson() { - try { - return UnicityObjectMapper.JSON.writeValueAsString(this); - } catch (JsonProcessingException e) { - throw new JsonSerializationException(Authenticator.class, e); - } - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Authenticator)) { - return false; - } - Authenticator that = (Authenticator) o; - return Objects.equals(this.algorithm, that.algorithm) - && Objects.equals(this.signature, that.signature) - && Objects.equals(this.stateHash, that.stateHash) - && Objects.deepEquals(this.publicKey, that.publicKey); - } - - @Override - public int hashCode() { - return Objects.hash(this.algorithm, this.signature, this.stateHash, - Arrays.hashCode(this.publicKey)); - } - - @Override - public String toString() { - return String.format("Authenticator{algorithm=%s, signature=%s, stateHash=%s, publicKey=%s}", - this.algorithm, this.signature, this.stateHash, HexConverter.encode(this.publicKey)); - } -} \ No newline at end of file diff --git a/src/main/java/org/unicitylabs/sdk/api/CertificationData.java b/src/main/java/org/unicitylabs/sdk/api/CertificationData.java new file mode 100644 index 0000000..cadcb37 --- /dev/null +++ b/src/main/java/org/unicitylabs/sdk/api/CertificationData.java @@ -0,0 +1,202 @@ +package org.unicitylabs.sdk.api; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Arrays; +import java.util.List; +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.serializer.cbor.CborDeserializer; +import org.unicitylabs.sdk.serializer.cbor.CborSerializer; +import org.unicitylabs.sdk.signing.Signature; +import org.unicitylabs.sdk.signing.SigningService; +import org.unicitylabs.sdk.util.HexConverter; + +/** + * Certification data. + */ +public class CertificationData { + + private final byte[] publicKey; + private final DataHash sourceStateHash; + private final DataHash transactionHash; + private final Signature signature; + + /** + * Certification data. + * + * @param publicKey public key. + * @param sourceStateHash source state hash. + * @param transactionHash transaction hash. + * @param signature signature. + */ + @JsonCreator + private CertificationData( + @JsonProperty("publicKey") byte[] publicKey, + @JsonProperty("sourceStateHash") DataHash sourceStateHash, + @JsonProperty("transactionHash") DataHash transactionHash, + @JsonProperty("signature") Signature signature + ) { + this.publicKey = publicKey; + this.sourceStateHash = sourceStateHash; + this.transactionHash = transactionHash; + this.signature = signature; + } + + /** + * Get copy of public key. + * + * @return public key + */ + public byte[] getPublicKey() { + return Arrays.copyOf(this.publicKey, this.publicKey.length); + } + + /** + * Get source state hash. + * + * @return source state hash + */ + public DataHash getSourceStateHash() { + return this.sourceStateHash; + } + + /** + * Get transaction hash. + * + * @return transaction hash + */ + public DataHash getTransactionHash() { + return this.transactionHash; + } + + /** + * Get signature. + * + * @return signature + */ + public Signature getSignature() { + return this.signature; + } + + /** + * Create CertificationData from signing service. + * + * @param sourceStateHash source state hash + * @param transactionHash transaction hash + * @param signingService signing service + * @return CertificationData + */ + public static CertificationData create( + DataHash sourceStateHash, + DataHash transactionHash, + SigningService signingService + ) { + Objects.requireNonNull(sourceStateHash, "Source state hash cannot be null"); + Objects.requireNonNull(transactionHash, "Transaction hash cannot be null"); + + return new CertificationData( + signingService.getPublicKey(), + sourceStateHash, + transactionHash, + signingService.sign( + new DataHasher(HashAlgorithm.SHA256) + .update( + CborSerializer.encodeArray(sourceStateHash.toCbor(), transactionHash.toCbor()) + ) + .digest() + )); + } + + + /** + * Create CertificationData from CBOR bytes. + * + * @param bytes CBOR bytes + * @return CertificationData + */ + public static CertificationData fromCbor(byte[] bytes) { + List data = CborDeserializer.readArray(bytes); + + return new CertificationData( + CborDeserializer.readByteString(data.get(0)), + DataHash.fromCbor(data.get(1)), + DataHash.fromCbor(data.get(2)), + Signature.fromCbor(data.get(3)) + ); + } + + /** + * Calculate state ID. + * + * @return state ID + */ + public StateId calculateStateId() { + return StateId.create(this.publicKey, this.sourceStateHash); + } + + /** + * Calculate leaf value for Merkle tree. + * + * @return leaf value + */ + public DataHash calculateLeafValue() { + return new DataHasher(HashAlgorithm.SHA256) + .update(this.toCbor()) + .digest(); + } + + /** + * Verifies current certification data. + * + * @return true if valid, false otherwise + */ + public boolean verify() { + return SigningService.verifyWithPublicKey( + new DataHasher(HashAlgorithm.SHA256) + .update(CborSerializer.encodeArray(this.sourceStateHash.toCbor(), this.transactionHash.toCbor())) + .digest(), + this.signature.getBytes(), + this.publicKey + ); + } + + /** + * Convert the certification data to CBOR bytes. + * + * @return CBOR bytes + */ + public byte[] toCbor() { + return CborSerializer.encodeArray( + CborSerializer.encodeByteString(this.publicKey), + this.sourceStateHash.toCbor(), + this.transactionHash.toCbor(), + this.signature.toCbor() + ); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof CertificationData)) { + return false; + } + CertificationData that = (CertificationData) o; + return Arrays.equals(this.publicKey, that.publicKey) + && Objects.equals(this.sourceStateHash, that.sourceStateHash) + && Objects.equals(this.transactionHash, that.transactionHash) + && Objects.equals(this.signature, that.signature); + } + + @Override + public int hashCode() { + return Objects.hash(Arrays.hashCode(this.publicKey), this.sourceStateHash, this.transactionHash, this.signature); + } + + @Override + public String toString() { + return String.format("Commitment{publicKey=%s, sourceStateHash=%s, transactionHash=%s, signature=%s}", + HexConverter.encode(this.publicKey), this.sourceStateHash, this.transactionHash, this.signature); + } +} diff --git a/src/main/java/org/unicitylabs/sdk/api/CertificationRequest.java b/src/main/java/org/unicitylabs/sdk/api/CertificationRequest.java new file mode 100644 index 0000000..e9da630 --- /dev/null +++ b/src/main/java/org/unicitylabs/sdk/api/CertificationRequest.java @@ -0,0 +1,85 @@ +package org.unicitylabs.sdk.api; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.unicitylabs.sdk.serializer.UnicityObjectMapper; +import org.unicitylabs.sdk.serializer.json.JsonSerializationException; + +/** + * Submit certification request. + */ +public class CertificationRequest { + + private final StateId stateId; + private final CertificationData certificationData; + private final Boolean receipt; + + /** + * Create certification request. + * + * @param stateId state id + * @param certificationData certification data + * @param receipt get receipt + */ + @JsonCreator + private CertificationRequest( + @JsonProperty("stateId") StateId stateId, + @JsonProperty("certificationData") CertificationData certificationData, + @JsonProperty("receipt") Boolean receipt) { + this.stateId = stateId; + this.certificationData = certificationData; + this.receipt = receipt; + } + + /** + * Get state id. + * + * @return state id + */ + public StateId getStateId() { + return this.stateId; + } + + /** + * Get certification data. + * + * @return certification data + */ + public CertificationData getCertificationData() { + return this.certificationData; + } + + /** + * Is getting receipt from unicity service. + * + * @return true if receipt unicity service should return receipt + */ + public Boolean getReceipt() { + return this.receipt; + } + + /** + * Create certification request. + * + * @param certificationData certification data + * @param receipt get receipt + * @return certification request + */ + public static CertificationRequest create(CertificationData certificationData, boolean receipt) { + return new CertificationRequest(certificationData.calculateStateId(), certificationData, receipt); + } + + /** + * Convert certification request to JSON string. + * + * @return JSON string + */ + public String toJson() { + try { + return UnicityObjectMapper.JSON.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new JsonSerializationException(CertificationRequest.class, e); + } + } +} diff --git a/src/main/java/org/unicitylabs/sdk/api/CertificationResponse.java b/src/main/java/org/unicitylabs/sdk/api/CertificationResponse.java new file mode 100644 index 0000000..44dcd40 --- /dev/null +++ b/src/main/java/org/unicitylabs/sdk/api/CertificationResponse.java @@ -0,0 +1,193 @@ +package org.unicitylabs.sdk.api; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import org.unicitylabs.sdk.hash.DataHasher; +import org.unicitylabs.sdk.hash.HashAlgorithm; +import org.unicitylabs.sdk.serializer.UnicityObjectMapper; +import org.unicitylabs.sdk.serializer.cbor.CborDeserializer; +import org.unicitylabs.sdk.serializer.cbor.CborSerializer; +import org.unicitylabs.sdk.serializer.json.JsonSerializationException; +import org.unicitylabs.sdk.signing.Signature; +import org.unicitylabs.sdk.signing.SigningService; + +/** + * Submit commitment response. + */ +public class CertificationResponse { + + private final CertificationStatus status; + private final Receipt receipt; + + /** + * Create submit commitment response. + * + * @param status status + * @param receipt receipt + */ + @JsonCreator + CertificationResponse( + @JsonProperty("status") CertificationStatus status, + @JsonProperty("receipt") Receipt receipt + ) { + this.status = status; + this.receipt = receipt; + } + + /** + * Get status. + * + * @return status + */ + public CertificationStatus getStatus() { + return this.status; + } + + /** + * Get receipt. + * + * @return receipt + */ + public Optional getReceipt() { + return Optional.ofNullable(this.receipt); + } + + /** + * Create a new certification response. + * + * @param signingService Aggregator signing service + * @param certificationData Certification data + * @param status Certification response status + * @return Created certification response + */ + public static CertificationResponse createWithReceipt( + SigningService signingService, + CertificationData certificationData, + CertificationStatus status + ) { + Signature signature = signingService.sign( + new DataHasher(HashAlgorithm.SHA256).update(certificationData.toCbor()).digest() + ); + + return new CertificationResponse(status, new Receipt(signingService.getPublicKey(), signature)); + } + + /** + * Create a new certification response. + * + * @param status Certification response status + * @return certification response + */ + public static CertificationResponse create(CertificationStatus status) { + return new CertificationResponse(status, null); + } + + /** + * Create submit commitment response from JSON string. + * + * @param input JSON string + * @return submit commitment response + */ + public static CertificationResponse fromJson(String input) { + try { + return UnicityObjectMapper.JSON.readValue(input, CertificationResponse.class); + } catch (JsonProcessingException e) { + throw new JsonSerializationException(CertificationResponse.class, e); + } + } + + /** + * Convert submit commitment response to JSON string. + * + * @return JSON string + */ + public String toJson() { + try { + return UnicityObjectMapper.JSON.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new JsonSerializationException(CertificationResponse.class, e); + } + } + + @Override + public String toString() { + return String.format("CertificationResponse{status=%s}", this.status); + } + + /** + * Certification receipt to confirm certification. + */ + public static class Receipt { + + private final byte[] publicKey; + private final Signature signature; + + @JsonCreator + private Receipt( + @JsonProperty("publicKey") byte[] publicKey, + @JsonProperty("signature") Signature signature + ) { + this.publicKey = publicKey; + this.signature = signature; + } + + /** + * Get copy of public key. + * + * @return public key + */ + public byte[] getPublicKey() { + return Arrays.copyOf(this.publicKey, this.publicKey.length); + } + + /** + * Get signature. + * + * @return signature + */ + public Signature getSignature() { + return this.signature; + } + + /** + * Verify receipt for certification data. + * + * @param certificationData certification data + * @return true if receipt is valid + */ + public boolean verify(CertificationData certificationData) { + return SigningService.verifyWithPublicKey( + certificationData.calculateLeafValue(), + this.signature.getBytes(), + this.publicKey + ); + } + + /** + * Serialize receipt to CBOR bytes. + * + * @return CBOR bytes + */ + public byte[] toCbor() { + return CborSerializer.encodeArray(CborSerializer.encodeByteString(this.publicKey), this.signature.toCbor()); + } + + /** + * Create receipt from CBOR bytes. + * + * @param bytes CBOR bytes + * @return receipt + */ + public static Receipt fromCbor(byte[] bytes) { + List data = CborDeserializer.readArray(bytes); + return new Receipt( + CborDeserializer.readByteString(data.get(0)), + Signature.fromCbor(data.get(1)) + ); + } + } +} diff --git a/src/main/java/org/unicitylabs/sdk/api/CertificationStatus.java b/src/main/java/org/unicitylabs/sdk/api/CertificationStatus.java new file mode 100644 index 0000000..bc917e1 --- /dev/null +++ b/src/main/java/org/unicitylabs/sdk/api/CertificationStatus.java @@ -0,0 +1,78 @@ +package org.unicitylabs.sdk.api; + +/** + * Status codes for certification. + */ +public enum CertificationStatus { + /** + * The certification request was accepted and stored. + */ + SUCCESS("SUCCESS"), + + /** + * The certification request failed because the state ID already exists. + */ + STATE_ID_EXISTS("STATE_ID_EXISTS"), + /** + * The certification request failed because the state ID does not match the expected format. + */ + STATE_ID_MISMATCH("STATE_ID_MISMATCH"), + /** + * The certification request failed because the signature verification failed. + */ + SIGNATURE_VERIFICATION_FAILED("SIGNATURE_VERIFICATION_FAILED"), + /** + * The certification request failed because signature has invalid format. + */ + INVALID_SIGNATURE_FORMAT("INVALID_SIGNATURE_FORMAT"), + /** + * The certification request failed because the public key has invalid format. + */ + INVALID_PUBLIC_KEY_FORMAT("INVALID_PUBLIC_KEY_FORMAT"), + /** + * The certification request failed because the source state hash has invalid format. + */ + INVALID_SOURCE_STATE_HASH_FORMAT("INVALID_SOURCE_STATE_HASH_FORMAT"), + /** + * The certification request failed because the transaction hash has invalid format. + */ + INVALID_TRANSACTION_HASH_FORMAT("INVALID_TRANSACTION_HASH_FORMAT"), + /** + * The certification request failed because the algorithm is not supported. + */ + UNSUPPORTED_ALGORITHM("UNSUPPORTED_ALGORITHM"), + /** + * The certification request failed because request was sent to invalid shard. + */ + INVALID_SHARD("INVALID_SHARD"); + + private final String value; + + CertificationStatus(String value) { + this.value = value; + } + + /** + * Get string value of the status. + * + * @return string value + */ + public String getValue() { + return value; + } + + /** + * Create status from string value. + * + * @param value string value + * @return status + */ + public static CertificationStatus fromString(String value) { + for (CertificationStatus status : CertificationStatus.values()) { + if (status.value.equalsIgnoreCase(value)) { + return status; + } + } + throw new IllegalArgumentException("Unknown status: " + value); + } +} \ No newline at end of file diff --git a/src/main/java/org/unicitylabs/sdk/api/InclusionProofRequest.java b/src/main/java/org/unicitylabs/sdk/api/InclusionProofRequest.java index 663ac20..1ebf325 100644 --- a/src/main/java/org/unicitylabs/sdk/api/InclusionProofRequest.java +++ b/src/main/java/org/unicitylabs/sdk/api/InclusionProofRequest.java @@ -11,27 +11,27 @@ */ public class InclusionProofRequest { - private final RequestId requestId; + private final StateId stateId; /** * Create inclusion proof request. * - * @param requestId request id + * @param stateId state id */ @JsonCreator public InclusionProofRequest( - @JsonProperty("requestId") RequestId requestId + @JsonProperty("stateId") StateId stateId ) { - this.requestId = requestId; + this.stateId = stateId; } /** - * Get request id. + * Get state id. * - * @return request id + * @return state id */ - public RequestId getRequestId() { - return this.requestId; + public StateId getStateId() { + return this.stateId; } /** diff --git a/src/main/java/org/unicitylabs/sdk/api/JsonRpcAggregatorClient.java b/src/main/java/org/unicitylabs/sdk/api/JsonRpcAggregatorClient.java index 8606632..82f7f3f 100644 --- a/src/main/java/org/unicitylabs/sdk/api/JsonRpcAggregatorClient.java +++ b/src/main/java/org/unicitylabs/sdk/api/JsonRpcAggregatorClient.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; -import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.jsonrpc.JsonRpcHttpTransport; /** @@ -38,46 +37,32 @@ public JsonRpcAggregatorClient(String url, String apiKey) { this.apiKey = apiKey; } - /** - * Submit commitment. - * - * @param requestId request id - * @param transactionHash transaction hash - * @param authenticator authenticator - * @return submit commitment response - */ - public CompletableFuture submitCommitment( - RequestId requestId, - DataHash transactionHash, - Authenticator authenticator + public CompletableFuture submitCertificationRequest( + CertificationData certificationData, + boolean receipt ) { - SubmitCommitmentRequest request = new SubmitCommitmentRequest( - requestId, - transactionHash, - authenticator, - false - ); + CertificationRequest request = CertificationRequest.create(certificationData,receipt); Map> headers = this.apiKey == null ? Map.of() : Map.of(AUTHORIZATION, List.of(String.format("Bearer %s", this.apiKey))); return this.transport.request( - "submit_commitment", + "certification_request", request, - SubmitCommitmentResponse.class, + CertificationResponse.class, headers ); } /** - * Get inclusion proof for request id. + * Get inclusion proof for state id. * - * @param requestId request id + * @param stateId state id * @return inclusion / non inclusion proof */ - public CompletableFuture getInclusionProof(RequestId requestId) { - InclusionProofRequest request = new InclusionProofRequest(requestId); + public CompletableFuture getInclusionProof(StateId stateId) { + InclusionProofRequest request = new InclusionProofRequest(stateId); return this.transport.request("get_inclusion_proof", request, InclusionProofResponse.class); } diff --git a/src/main/java/org/unicitylabs/sdk/api/LeafValue.java b/src/main/java/org/unicitylabs/sdk/api/LeafValue.java deleted file mode 100644 index 8c2966b..0000000 --- a/src/main/java/org/unicitylabs/sdk/api/LeafValue.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.unicitylabs.sdk.api; - -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; - -/** - * Leaf value for merkle tree. - */ -public class LeafValue { - - private final byte[] bytes; - - private LeafValue(byte[] bytes) { - this.bytes = Arrays.copyOf(bytes, bytes.length); - } - - /** - * Create leaf value from authenticator and transaction hash. - * - * @param authenticator authenticator - * @param transactionHash transaction hash - * @return leaf value - */ - public static LeafValue create(Authenticator authenticator, DataHash transactionHash) { - DataHash hash = new DataHasher(HashAlgorithm.SHA256) - .update(authenticator.toCbor()) - .update(transactionHash.getImprint()) - .digest(); - - return new LeafValue(hash.getImprint()); - } - - /** - * Get leaf value as bytes. - * - * @return bytes - */ - public byte[] getBytes() { - return Arrays.copyOf(this.bytes, this.bytes.length); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof LeafValue)) { - return false; - } - LeafValue leafValue = (LeafValue) o; - return Objects.deepEquals(this.bytes, leafValue.bytes); - } - - @Override - public int hashCode() { - return Arrays.hashCode(this.bytes); - } - - @Override - public String toString() { - return String.format("LeafValue{%s}", HexConverter.encode(this.bytes)); - } -} \ No newline at end of file diff --git a/src/main/java/org/unicitylabs/sdk/api/RequestId.java b/src/main/java/org/unicitylabs/sdk/api/RequestId.java deleted file mode 100644 index fabe147..0000000 --- a/src/main/java/org/unicitylabs/sdk/api/RequestId.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.unicitylabs.sdk.api; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import org.unicitylabs.sdk.hash.DataHash; -import org.unicitylabs.sdk.hash.DataHasher; -import org.unicitylabs.sdk.hash.HashAlgorithm; -import org.unicitylabs.sdk.serializer.UnicityObjectMapper; -import org.unicitylabs.sdk.serializer.json.JsonSerializationException; -import org.unicitylabs.sdk.token.TokenState; -import org.unicitylabs.sdk.transaction.MintTransaction; -import org.unicitylabs.sdk.util.BitString; -import org.unicitylabs.sdk.util.HexConverter; - -/** - * Represents a unique request identifier derived from a public key and state hash. - */ -@JsonDeserialize(using = RequestIdJson.Deserializer.class) -public class RequestId extends DataHash { - - /** - * Constructs a RequestId instance. - * - * @param hash The DataHash representing the request ID. - */ - protected RequestId(DataHash hash) { - super(hash.getAlgorithm(), hash.getData()); - } - - /** - * Creates a RequestId from public key and state. - * - * @param publicKey public key as a byte array. - * @param state token state. - * @return request id - */ - public static RequestId create(byte[] publicKey, TokenState state) { - return RequestId.create(publicKey, state.calculateHash()); - } - - /** - * Creates a RequestId from public key and hash. - * - * @param publicKey public key as a byte array. - * @param hash hash. - * @return request id - */ - public static RequestId create(byte[] publicKey, DataHash hash) { - return RequestId.create(publicKey, hash.getImprint()); - } - - /** - * Creates a RequestId from identifier bytes and hash imprint. - * - * @param id id bytes. - * @param stateBytes state bytes. - * @return request id. - */ - public static RequestId create(byte[] id, byte[] stateBytes) { - DataHasher hasher = new DataHasher(HashAlgorithm.SHA256); - hasher.update(id); - hasher.update(stateBytes); - - return new RequestId(hasher.digest()); - } - - /** - * Create a request id from JSON string. - * - * @param input JSON string - * @return request id - */ - public static RequestId fromJson(String input) { - try { - return UnicityObjectMapper.JSON.readValue(input, RequestId.class); - } catch (JsonProcessingException e) { - throw new JsonSerializationException(RequestId.class, e); - } - } - - /** - * Converts the request id to a JSON string. - * - * @return JSON string - */ - public String toJson() { - try { - return UnicityObjectMapper.JSON.writeValueAsString(this); - } catch (JsonProcessingException e) { - throw new JsonSerializationException(RequestId.class, e); - } - } - - /** - * Converts the RequestId to a BitString. - * - * @return The BitString representation of the RequestId. - */ - public BitString toBitString() { - return BitString.fromDataHash(this); - } - - /** - * Returns a string representation of the RequestId. - * - * @return The string representation. - */ - @Override - public String toString() { - return String.format("RequestId[%s]", HexConverter.encode(this.getImprint())); - } -} \ No newline at end of file diff --git a/src/main/java/org/unicitylabs/sdk/api/StateId.java b/src/main/java/org/unicitylabs/sdk/api/StateId.java new file mode 100644 index 0000000..156ab00 --- /dev/null +++ b/src/main/java/org/unicitylabs/sdk/api/StateId.java @@ -0,0 +1,117 @@ +package org.unicitylabs.sdk.api; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.unicitylabs.sdk.hash.DataHash; +import org.unicitylabs.sdk.hash.DataHasher; +import org.unicitylabs.sdk.hash.HashAlgorithm; +import org.unicitylabs.sdk.serializer.UnicityObjectMapper; +import org.unicitylabs.sdk.serializer.cbor.CborSerializer; +import org.unicitylabs.sdk.serializer.json.JsonSerializationException; +import org.unicitylabs.sdk.token.TokenState; +import org.unicitylabs.sdk.util.BitString; +import org.unicitylabs.sdk.util.HexConverter; + +/** + * Represents a unique state identifier derived from a public key and state hash. + */ +@JsonDeserialize(using = StateIdJson.Deserializer.class) +public class StateId extends DataHash { + + /** + * Constructs a StateId instance. + * + * @param hash The DataHash representing the state ID. + */ + protected StateId(DataHash hash) { + super(hash.getAlgorithm(), hash.getData()); + } + + /** + * Creates a StateId from public key and state. + * + * @param publicKey public key as a byte array. + * @param state token state. + * @return state id + */ + public static StateId create(byte[] publicKey, TokenState state) { + return StateId.create(publicKey, state.calculateHash()); + } + + /** + * Creates a StateId from public key and hash. + * + * @param publicKey public key as a byte array. + * @param hash hash. + * @return state id + */ + public static StateId create(byte[] publicKey, DataHash hash) { + return StateId.create(publicKey, hash.getImprint()); + } + + /** + * Creates a StateId from identifier bytes and hash imprint. + * + * @param publicKey public key bytes. + * @param hashImprint state bytes. + * @return state id. + */ + public static StateId create(byte[] publicKey, byte[] hashImprint) { + return new StateId( + new DataHasher(HashAlgorithm.SHA256) + .update( + CborSerializer.encodeArray( + CborSerializer.encodeByteString(hashImprint), + CborSerializer.encodeByteString(publicKey) + ) + ) + .digest() + ); + } + + /** + * Create a state id from JSON string. + * + * @param input JSON string + * @return state id + */ + public static StateId fromJson(String input) { + try { + return UnicityObjectMapper.JSON.readValue(input, StateId.class); + } catch (JsonProcessingException e) { + throw new JsonSerializationException(StateId.class, e); + } + } + + /** + * Converts the state id to a JSON string. + * + * @return JSON string + */ + public String toJson() { + try { + return UnicityObjectMapper.JSON.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new JsonSerializationException(StateId.class, e); + } + } + + /** + * Converts the StateId to a BitString. + * + * @return The BitString representation of the StateId. + */ + public BitString toBitString() { + return BitString.fromDataHash(this); + } + + /** + * Returns a string representation of the StateId. + * + * @return The string representation. + */ + @Override + public String toString() { + return String.format("StateId[%s]", HexConverter.encode(this.getImprint())); + } +} \ No newline at end of file diff --git a/src/main/java/org/unicitylabs/sdk/api/RequestIdJson.java b/src/main/java/org/unicitylabs/sdk/api/StateIdJson.java similarity index 59% rename from src/main/java/org/unicitylabs/sdk/api/RequestIdJson.java rename to src/main/java/org/unicitylabs/sdk/api/StateIdJson.java index 2ee0bf5..2068373 100644 --- a/src/main/java/org/unicitylabs/sdk/api/RequestIdJson.java +++ b/src/main/java/org/unicitylabs/sdk/api/StateIdJson.java @@ -7,37 +7,37 @@ import org.unicitylabs.sdk.hash.DataHash; /** - * Request ID deserializer implementation. + * State ID deserializer implementation. */ -public class RequestIdJson { +public class StateIdJson { - private RequestIdJson() { + private StateIdJson() { } /** - * Request ID deserializer. + * State ID deserializer. */ - public static class Deserializer extends StdDeserializer { + public static class Deserializer extends StdDeserializer { /** * Create deserializer. */ public Deserializer() { - super(RequestId.class); + super(StateId.class); } /** - * Deserialize request id. + * Deserialize state id. * * @param p Parser used for reading JSON content * @param ctx Context that can be used to access information about this deserialization * activity. - * @return request id + * @return state id * @throws IOException on deserialization failure */ @Override - public RequestId deserialize(JsonParser p, DeserializationContext ctx) throws IOException { - return new RequestId(p.readValueAs(DataHash.class)); + public StateId deserialize(JsonParser p, DeserializationContext ctx) throws IOException { + return new StateId(p.readValueAs(DataHash.class)); } } } diff --git a/src/main/java/org/unicitylabs/sdk/api/SubmitCommitmentRequest.java b/src/main/java/org/unicitylabs/sdk/api/SubmitCommitmentRequest.java deleted file mode 100644 index 957a45d..0000000 --- a/src/main/java/org/unicitylabs/sdk/api/SubmitCommitmentRequest.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.unicitylabs.sdk.api; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import org.unicitylabs.sdk.hash.DataHash; -import org.unicitylabs.sdk.serializer.UnicityObjectMapper; -import org.unicitylabs.sdk.serializer.json.JsonSerializationException; - -/** - * Submit commitment request. - */ -public class SubmitCommitmentRequest { - - private final RequestId requestId; - private final DataHash transactionHash; - private final Authenticator authenticator; - private final Boolean receipt; - - /** - * Create submit commitment request. - * - * @param requestId request id - * @param transactionHash transaction hash - * @param authenticator authenticator - * @param receipt get receipt - */ - @JsonCreator - public SubmitCommitmentRequest( - @JsonProperty("requestId") RequestId requestId, - @JsonProperty("transactionHash") DataHash transactionHash, - @JsonProperty("authenticator") Authenticator authenticator, - @JsonProperty("receipt") Boolean receipt) { - this.requestId = requestId; - this.transactionHash = transactionHash; - this.authenticator = authenticator; - this.receipt = receipt; - } - - /** - * Get request id. - * - * @return request id - */ - public RequestId getRequestId() { - return this.requestId; - } - - /** - * Get transaction hash. - * - * @return transaction hash - */ - public DataHash getTransactionHash() { - return this.transactionHash; - } - - /** - * Get authenticator. - * - * @return authenticator - */ - public Authenticator getAuthenticator() { - return this.authenticator; - } - - /** - * Is getting receipt from unicity service. - * - * @return true if receipt unicity service should return receipt - */ - public Boolean getReceipt() { - return this.receipt; - } - - /** - * Create submit commitment request from JSON string. - * - * @param input JSON string - * @return submit commitment request - */ - public static SubmitCommitmentRequest fromJson(String input) { - try { - return UnicityObjectMapper.JSON.readValue(input, SubmitCommitmentRequest.class); - } catch (JsonProcessingException e) { - throw new JsonSerializationException(SubmitCommitmentRequest.class, e); - } - } - - /** - * Convert submit commitment request to JSON string. - * - * @return JSON string - */ - public String toJson() { - try { - return UnicityObjectMapper.JSON.writeValueAsString(this); - } catch (JsonProcessingException e) { - throw new JsonSerializationException(SubmitCommitmentRequest.class, e); - } - } -} diff --git a/src/main/java/org/unicitylabs/sdk/api/SubmitCommitmentResponse.java b/src/main/java/org/unicitylabs/sdk/api/SubmitCommitmentResponse.java deleted file mode 100644 index 39d88c8..0000000 --- a/src/main/java/org/unicitylabs/sdk/api/SubmitCommitmentResponse.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.unicitylabs.sdk.api; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import org.unicitylabs.sdk.serializer.UnicityObjectMapper; -import org.unicitylabs.sdk.serializer.json.JsonSerializationException; - -/** - * Submit commitment response. - */ -public class SubmitCommitmentResponse { - - private final SubmitCommitmentStatus status; - - /** - * Create submit commitment response. - * - * @param status status - */ - @JsonCreator - public SubmitCommitmentResponse( - @JsonProperty("status") SubmitCommitmentStatus status - ) { - this.status = status; - } - - /** - * Get status. - * - * @return status - */ - public SubmitCommitmentStatus getStatus() { - return this.status; - } - - /** - * Create submit commitment response from JSON string. - * - * @param input JSON string - * @return submit commitment response - */ - public static SubmitCommitmentResponse fromJson(String input) { - try { - return UnicityObjectMapper.JSON.readValue(input, SubmitCommitmentResponse.class); - } catch (JsonProcessingException e) { - throw new JsonSerializationException(SubmitCommitmentResponse.class, e); - } - } - - /** - * Convert submit commitment response to JSON string. - * - * @return JSON string - */ - public String toJson() { - try { - return UnicityObjectMapper.JSON.writeValueAsString(this); - } catch (JsonProcessingException e) { - throw new JsonSerializationException(SubmitCommitmentResponse.class, e); - } - } - - @Override - public String toString() { - return String.format("SubmitCommitmentResponse{status=%s}", this.status); - } -} diff --git a/src/main/java/org/unicitylabs/sdk/api/SubmitCommitmentStatus.java b/src/main/java/org/unicitylabs/sdk/api/SubmitCommitmentStatus.java deleted file mode 100644 index f0f926c..0000000 --- a/src/main/java/org/unicitylabs/sdk/api/SubmitCommitmentStatus.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.unicitylabs.sdk.api; - -/** - * Status codes for submit commitment response. - */ -public enum SubmitCommitmentStatus { - /** - * The commitment was accepted and stored. - */ - SUCCESS("SUCCESS"), - /** - * Signature verification failed. - */ - AUTHENTICATOR_VERIFICATION_FAILED("AUTHENTICATOR_VERIFICATION_FAILED"), - /** - * Request identifier did not match the payload. - */ - REQUEST_ID_MISMATCH("REQUEST_ID_MISMATCH"), - /** - * A commitment with the same request id already exists. - */ - REQUEST_ID_EXISTS("REQUEST_ID_EXISTS"); - - private final String value; - - SubmitCommitmentStatus(String value) { - this.value = value; - } - - /** - * Get string value of the status. - * - * @return string value - */ - public String getValue() { - return value; - } - - /** - * Create status from string value. - * - * @param value string value - * @return status - */ - public static SubmitCommitmentStatus fromString(String value) { - for (SubmitCommitmentStatus status : SubmitCommitmentStatus.values()) { - if (status.value.equalsIgnoreCase(value)) { - return status; - } - } - throw new IllegalArgumentException("Unknown status: " + value); - } -} \ No newline at end of file diff --git a/src/main/java/org/unicitylabs/sdk/bft/InputRecord.java b/src/main/java/org/unicitylabs/sdk/bft/InputRecord.java index 6c35aa3..574d0ec 100644 --- a/src/main/java/org/unicitylabs/sdk/bft/InputRecord.java +++ b/src/main/java/org/unicitylabs/sdk/bft/InputRecord.java @@ -1,6 +1,5 @@ package org.unicitylabs.sdk.bft; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Arrays; import java.util.List; import java.util.Objects; diff --git a/src/main/java/org/unicitylabs/sdk/bft/ShardTreeCertificate.java b/src/main/java/org/unicitylabs/sdk/bft/ShardTreeCertificate.java index fbc2cb3..040f5db 100644 --- a/src/main/java/org/unicitylabs/sdk/bft/ShardTreeCertificate.java +++ b/src/main/java/org/unicitylabs/sdk/bft/ShardTreeCertificate.java @@ -1,7 +1,5 @@ package org.unicitylabs.sdk.bft; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Arrays; import java.util.List; import java.util.Objects; diff --git a/src/main/java/org/unicitylabs/sdk/mtree/plain/SparseMerkleTreePath.java b/src/main/java/org/unicitylabs/sdk/mtree/plain/SparseMerkleTreePath.java index 53b9012..63d3fe2 100644 --- a/src/main/java/org/unicitylabs/sdk/mtree/plain/SparseMerkleTreePath.java +++ b/src/main/java/org/unicitylabs/sdk/mtree/plain/SparseMerkleTreePath.java @@ -61,10 +61,10 @@ public List getSteps() { /** * Verify merkle tree path against given path. * - * @param requestId path + * @param stateId path * @return MerkleTreePathVerificationResult */ - public MerkleTreePathVerificationResult verify(BigInteger requestId) { + public MerkleTreePathVerificationResult verify(BigInteger stateId) { if (this.steps.isEmpty()) { return new MerkleTreePathVerificationResult(false, false); } @@ -122,7 +122,7 @@ public MerkleTreePathVerificationResult verify(BigInteger requestId) { boolean pathValid = currentData != null && this.rootHash.equals(new DataHash(this.rootHash.getAlgorithm(), currentData)); - boolean pathIncluded = currentPath.compareTo(requestId) == 0; + boolean pathIncluded = currentPath.compareTo(stateId) == 0; return new MerkleTreePathVerificationResult(pathValid, pathIncluded); } diff --git a/src/main/java/org/unicitylabs/sdk/predicate/embedded/DefaultPredicate.java b/src/main/java/org/unicitylabs/sdk/predicate/embedded/DefaultPredicate.java index 8d732e0..b9e7c02 100644 --- a/src/main/java/org/unicitylabs/sdk/predicate/embedded/DefaultPredicate.java +++ b/src/main/java/org/unicitylabs/sdk/predicate/embedded/DefaultPredicate.java @@ -2,8 +2,8 @@ import java.util.Arrays; import java.util.Objects; -import org.unicitylabs.sdk.api.Authenticator; -import org.unicitylabs.sdk.api.RequestId; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.DataHasher; @@ -162,26 +162,27 @@ public boolean verify(Token token, TransferTransaction transaction, RootTrust return false; } - Authenticator authenticator = transaction.getInclusionProof().getAuthenticator().orElse(null); + CertificationData certificationData = transaction.getInclusionProof().getCertificationData().orElse(null); - if (authenticator == null) { + if (certificationData == null) { return false; } - if (!Arrays.equals(authenticator.getPublicKey(), this.publicKey)) { + if (!Arrays.equals(certificationData.getPublicKey(), this.publicKey)) { return false; } DataHash transactionHash = transaction.getData().calculateHash(); - if (!authenticator.verify(transactionHash)) { + if (!certificationData.getTransactionHash().equals(transactionHash)) { return false; } - RequestId requestId = RequestId.create(this.publicKey, transaction.getData().getSourceState()); - return transaction.getInclusionProof().verify( - requestId, - trustBase - ) == InclusionProofVerificationStatus.OK; + if (!certificationData.verify()) { + return false; + } + + StateId stateId = StateId.create(this.publicKey, transaction.getData().getSourceState()); + return transaction.getInclusionProof().verify(trustBase, stateId) == InclusionProofVerificationStatus.OK; } @Override diff --git a/src/main/java/org/unicitylabs/sdk/signing/Signature.java b/src/main/java/org/unicitylabs/sdk/signing/Signature.java index 677d767..c5b0d88 100644 --- a/src/main/java/org/unicitylabs/sdk/signing/Signature.java +++ b/src/main/java/org/unicitylabs/sdk/signing/Signature.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.Arrays; import java.util.Objects; +import org.unicitylabs.sdk.serializer.cbor.CborDeserializer; +import org.unicitylabs.sdk.serializer.cbor.CborSerializer; import org.unicitylabs.sdk.util.HexConverter; /** @@ -51,6 +53,15 @@ public byte[] encode() { return signature; } + /** + * Serialize Signature to CBOR bytes. + * + * @return CBOR bytes + */ + public byte[] toCbor() { + return CborSerializer.encodeByteString(this.encode()); + } + /** * Decodes a byte array into a Signature object. * @@ -67,6 +78,16 @@ public static Signature decode(byte[] input) { return new Signature(bytes, recovery); } + /** + * Create Signature from CBOR bytes. + * + * @param bytes CBOR bytes + * @return signature + */ + public static Signature fromCbor(byte[] bytes) { + return Signature.decode(CborDeserializer.readByteString(bytes)); + } + @Override public boolean equals(Object o) { if (!(o instanceof Signature)) { diff --git a/src/main/java/org/unicitylabs/sdk/signing/SigningService.java b/src/main/java/org/unicitylabs/sdk/signing/SigningService.java index eb0eae4..5b75dc9 100644 --- a/src/main/java/org/unicitylabs/sdk/signing/SigningService.java +++ b/src/main/java/org/unicitylabs/sdk/signing/SigningService.java @@ -65,7 +65,7 @@ public SigningService(byte[] privateKey) { * @return public key bytes */ public byte[] getPublicKey() { - return Arrays.copyOf(publicKey, publicKey.length); + return Arrays.copyOf(this.publicKey, this.publicKey.length); } /** diff --git a/src/main/java/org/unicitylabs/sdk/token/fungible/CoinIdJson.java b/src/main/java/org/unicitylabs/sdk/token/fungible/CoinIdJson.java index c6d9b4c..c487751 100644 --- a/src/main/java/org/unicitylabs/sdk/token/fungible/CoinIdJson.java +++ b/src/main/java/org/unicitylabs/sdk/token/fungible/CoinIdJson.java @@ -9,12 +9,7 @@ import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; -import java.math.BigInteger; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; import org.unicitylabs.sdk.token.TokenId; -import org.unicitylabs.sdk.util.HexConverter; /** * Token coin json serializer and deserializer. diff --git a/src/main/java/org/unicitylabs/sdk/transaction/Commitment.java b/src/main/java/org/unicitylabs/sdk/transaction/Commitment.java index 8a14bef..fa451d4 100644 --- a/src/main/java/org/unicitylabs/sdk/transaction/Commitment.java +++ b/src/main/java/org/unicitylabs/sdk/transaction/Commitment.java @@ -1,9 +1,11 @@ package org.unicitylabs.sdk.transaction; +import com.fasterxml.jackson.core.JsonProcessingException; import java.util.Objects; -import org.unicitylabs.sdk.api.Authenticator; -import org.unicitylabs.sdk.api.RequestId; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.serializer.UnicityObjectMapper; +import org.unicitylabs.sdk.serializer.json.JsonSerializationException; /** * Commitment representing a submitted transaction. @@ -12,30 +14,18 @@ */ public abstract class Commitment> { - private final RequestId requestId; private final T transactionData; - private final Authenticator authenticator; + private final CertificationData certificationData; /** * Create commitment. * - * @param requestId request id * @param transactionData transaction data - * @param authenticator authenticator + * @param certificationData certification data */ - protected Commitment(RequestId requestId, T transactionData, Authenticator authenticator) { - this.requestId = requestId; + protected Commitment(T transactionData, CertificationData certificationData) { this.transactionData = transactionData; - this.authenticator = authenticator; - } - - /** - * Returns the request ID associated with this commitment. - * - * @return request ID - */ - public RequestId getRequestId() { - return requestId; + this.certificationData = certificationData; } /** @@ -44,7 +34,7 @@ public RequestId getRequestId() { * @return transaction data */ public T getTransactionData() { - return transactionData; + return this.transactionData; } /** @@ -52,8 +42,8 @@ public T getTransactionData() { * * @return authenticator */ - public Authenticator getAuthenticator() { - return authenticator; + public CertificationData getCertificationData() { + return this.certificationData; } /** @@ -64,25 +54,37 @@ public Authenticator getAuthenticator() { */ public abstract Transaction toTransaction(InclusionProof inclusionProof); + /** + * Convert commitment to JSON string. + * + * @return JSON string + */ + public String toJson() { + try { + return UnicityObjectMapper.JSON.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new JsonSerializationException(InclusionProof.class, e); + } + } + @Override public boolean equals(Object o) { if (!(o instanceof Commitment)) { return false; } Commitment that = (Commitment) o; - return Objects.equals(this.requestId, that.requestId) - && Objects.equals(this.transactionData, that.transactionData) - && Objects.equals(this.authenticator, that.authenticator); + return Objects.equals(this.transactionData, that.transactionData) + && Objects.equals(this.certificationData, that.certificationData); } @Override public int hashCode() { - return Objects.hash(this.requestId, this.transactionData, authenticator); + return Objects.hash(this.transactionData, this.certificationData); } @Override public String toString() { - return String.format("Commitment{requestId=%s, transactionData=%s, authenticator=%s}", - this.requestId, this.transactionData, this.authenticator); + return String.format("Commitment{transactionData=%s, certificationData=%s}", + this.transactionData, this.certificationData); } } diff --git a/src/main/java/org/unicitylabs/sdk/transaction/InclusionProof.java b/src/main/java/org/unicitylabs/sdk/transaction/InclusionProof.java index 9538978..dd377ba 100644 --- a/src/main/java/org/unicitylabs/sdk/transaction/InclusionProof.java +++ b/src/main/java/org/unicitylabs/sdk/transaction/InclusionProof.java @@ -3,13 +3,11 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; -import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; -import org.unicitylabs.sdk.api.Authenticator; -import org.unicitylabs.sdk.api.LeafValue; -import org.unicitylabs.sdk.api.RequestId; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.bft.UnicityCertificate; import org.unicitylabs.sdk.bft.verification.UnicityCertificateVerificationContext; @@ -30,27 +28,20 @@ public class InclusionProof { private final SparseMerkleTreePath merkleTreePath; - private final Authenticator authenticator; - private final DataHash transactionHash; + private final CertificationData certificationData; private final UnicityCertificate unicityCertificate; @JsonCreator InclusionProof( @JsonProperty("merkleTreePath") SparseMerkleTreePath merkleTreePath, - @JsonProperty("authenticator") Authenticator authenticator, - @JsonProperty("transactionHash") DataHash transactionHash, + @JsonProperty("certificationData") CertificationData certificationData, @JsonProperty("unicityCertificate") UnicityCertificate unicityCertificate ) { Objects.requireNonNull(merkleTreePath, "Merkle tree path cannot be null."); Objects.requireNonNull(unicityCertificate, "Unicity certificate cannot be null."); - if ((authenticator == null) != (transactionHash == null)) { - throw new IllegalArgumentException( - "Authenticator and transaction hash must be both set or both null."); - } this.merkleTreePath = merkleTreePath; - this.authenticator = authenticator; - this.transactionHash = transactionHash; + this.certificationData = certificationData; this.unicityCertificate = unicityCertificate; } @@ -73,31 +64,23 @@ public UnicityCertificate getUnicityCertificate() { } /** - * Get authenticator on inclusion proof, null on non inclusion proof. + * Get certification data on inclusion proof, null on non inclusion proof. * * @return authenticator */ - public Optional getAuthenticator() { - return Optional.ofNullable(this.authenticator); - } - - /** - * Get authenticator on inclusion proof, null on non inclusion proof. - * - * @return inclusion proof - */ - public Optional getTransactionHash() { - return Optional.ofNullable(this.transactionHash); + public Optional getCertificationData() { + return Optional.ofNullable(this.certificationData); } /** * Verify inclusion proof. * - * @param requestId request id * @param trustBase trust base for unicity certificate anchor verification + * @param stateId state id + * * @return inclusion proof verification status */ - public InclusionProofVerificationStatus verify(RequestId requestId, RootTrustBase trustBase) { + public InclusionProofVerificationStatus verify(RootTrustBase trustBase, StateId stateId) { // Check if path is valid and signed by a trusted authority if (!new UnicityCertificateVerificationRule().verify( new UnicityCertificateVerificationContext( @@ -106,30 +89,30 @@ public InclusionProofVerificationStatus verify(RequestId requestId, RootTrustBas trustBase ) ).isSuccessful()) { - return InclusionProofVerificationStatus.NOT_AUTHENTICATED; + return InclusionProofVerificationStatus.INVALID_TRUST_BASE; } - MerkleTreePathVerificationResult result = this.merkleTreePath.verify( - requestId.toBitString().toBigInteger()); + MerkleTreePathVerificationResult result = this.merkleTreePath.verify(stateId.toBitString().toBigInteger()); if (!result.isPathValid()) { return InclusionProofVerificationStatus.PATH_INVALID; } - if (this.authenticator != null && this.transactionHash != null) { - if (!this.authenticator.verify(this.transactionHash)) { + if (this.certificationData != null) { + if (!this.certificationData.verify()) { return InclusionProofVerificationStatus.NOT_AUTHENTICATED; } try { - LeafValue leafValue = LeafValue.create(this.authenticator, this.transactionHash); if (this.merkleTreePath.getSteps().size() == 0) { return InclusionProofVerificationStatus.PATH_NOT_INCLUDED; } + DataHash leafValue = this.certificationData.calculateLeafValue(); SparseMerkleTreePathStep step = this.merkleTreePath.getSteps().get(0); - if (!Arrays.equals(leafValue.getBytes(), step.getData().orElse(null))) { + if (!leafValue.equals(step.getData().map(DataHash::fromImprint).orElse(null))) { return InclusionProofVerificationStatus.PATH_NOT_INCLUDED; } + } catch (CborSerializationException e) { return InclusionProofVerificationStatus.NOT_AUTHENTICATED; } @@ -153,9 +136,8 @@ public static InclusionProof fromCbor(byte[] bytes) { return new InclusionProof( SparseMerkleTreePath.fromCbor(data.get(0)), - CborDeserializer.readOptional(data.get(1), Authenticator::fromCbor), - CborDeserializer.readOptional(data.get(2), DataHash::fromCbor), - UnicityCertificate.fromCbor(data.get(3)) + CborDeserializer.readOptional(data.get(1), CertificationData::fromCbor), + UnicityCertificate.fromCbor(data.get(2)) ); } @@ -167,8 +149,7 @@ public static InclusionProof fromCbor(byte[] bytes) { public byte[] toCbor() { return CborSerializer.encodeArray( this.merkleTreePath.toCbor(), - CborSerializer.encodeOptional(this.authenticator, Authenticator::toCbor), - CborSerializer.encodeOptional(this.transactionHash, DataHash::toCbor), + CborSerializer.encodeOptional(this.certificationData, CertificationData::toCbor), this.unicityCertificate.toCbor() ); } @@ -206,18 +187,18 @@ public boolean equals(Object o) { return false; } InclusionProof that = (InclusionProof) o; - return Objects.equals(merkleTreePath, that.merkleTreePath) && Objects.equals(authenticator, - that.authenticator) && Objects.equals(transactionHash, that.transactionHash); + return Objects.equals(this.merkleTreePath, that.merkleTreePath) && Objects.equals(this.certificationData, + that.certificationData); } @Override public int hashCode() { - return Objects.hash(merkleTreePath, authenticator, transactionHash); + return Objects.hash(this.merkleTreePath, this.certificationData); } @Override public String toString() { - return String.format("InclusionProof{merkleTreePath=%s, authenticator=%s, transactionHash=%s}", - merkleTreePath, authenticator, transactionHash); + return String.format("InclusionProof{merkleTreePath=%s, certificationData=%s}", this.merkleTreePath, + this.certificationData); } } diff --git a/src/main/java/org/unicitylabs/sdk/transaction/InclusionProofVerificationStatus.java b/src/main/java/org/unicitylabs/sdk/transaction/InclusionProofVerificationStatus.java index d67bdb8..caf6fb1 100644 --- a/src/main/java/org/unicitylabs/sdk/transaction/InclusionProofVerificationStatus.java +++ b/src/main/java/org/unicitylabs/sdk/transaction/InclusionProofVerificationStatus.java @@ -4,6 +4,10 @@ * Status codes for verifying an InclusionProof. */ public enum InclusionProofVerificationStatus { + /** + * Inclusion proof verification failed because the trust base is invalid. + */ + INVALID_TRUST_BASE("INVALID_TRUST_BASE"), /** * Inclusion proof verification failed because the proof could not be authenticated. */ diff --git a/src/main/java/org/unicitylabs/sdk/transaction/MintCommitment.java b/src/main/java/org/unicitylabs/sdk/transaction/MintCommitment.java index 03e9297..db2c66b 100644 --- a/src/main/java/org/unicitylabs/sdk/transaction/MintCommitment.java +++ b/src/main/java/org/unicitylabs/sdk/transaction/MintCommitment.java @@ -3,9 +3,12 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; import java.util.Objects; -import org.unicitylabs.sdk.api.Authenticator; -import org.unicitylabs.sdk.api.RequestId; +import org.unicitylabs.sdk.api.BlockHeightResponse; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.serializer.UnicityObjectMapper; +import org.unicitylabs.sdk.serializer.json.JsonSerializationException; import org.unicitylabs.sdk.signing.MintSigningService; import org.unicitylabs.sdk.signing.SigningService; @@ -18,14 +21,12 @@ public class MintCommitment extends Commitment> { @JsonCreator private MintCommitment( - @JsonProperty("requestId") - RequestId requestId, @JsonProperty("transactionData") MintTransaction.Data transactionData, @JsonProperty("authenticator") - Authenticator authenticator + CertificationData certificationData ) { - super(requestId, transactionData, authenticator); + super(transactionData, certificationData); } /** @@ -39,27 +40,39 @@ public MintTransaction toTransaction(InclusionProof inclusionProof) { return new MintTransaction<>(this.getTransactionData(), inclusionProof); } + /** + * Create mint commitment from JSON string. + * + * @param input JSON string + * @return mint commitment data + */ + public static MintCommitment fromJson(String input) { + try { + return UnicityObjectMapper.JSON.readValue(input, MintCommitment.class); + } catch (JsonProcessingException e) { + throw new JsonSerializationException(BlockHeightResponse.class, e); + } + } + /** * Create mint commitment from transaction data. * - * @param data mint transaction data + * @param transactionData mint transaction data * @param mint reason * @return mint commitment */ public static MintCommitment create( - MintTransaction.Data data + MintTransaction.Data transactionData ) { - Objects.requireNonNull(data, "Transaction data cannot be null"); + Objects.requireNonNull(transactionData, "Transaction data cannot be null"); - SigningService signingService = MintSigningService.create(data.getTokenId()); - return new MintCommitment<>( - RequestId.create(signingService.getPublicKey(), data.getSourceState()), - data, - Authenticator.create( - signingService, - data.calculateHash(), - data.getSourceState() - ) + SigningService signingService = MintSigningService.create(transactionData.getTokenId()); + CertificationData certificationData = CertificationData.create( + transactionData.getSourceState(), + transactionData.calculateHash(), + signingService ); + + return new MintCommitment<>(transactionData, certificationData); } } diff --git a/src/main/java/org/unicitylabs/sdk/transaction/MintTransaction.java b/src/main/java/org/unicitylabs/sdk/transaction/MintTransaction.java index e80e9ed..95d7768 100644 --- a/src/main/java/org/unicitylabs/sdk/transaction/MintTransaction.java +++ b/src/main/java/org/unicitylabs/sdk/transaction/MintTransaction.java @@ -13,7 +13,8 @@ import java.util.Optional; import org.unicitylabs.sdk.address.Address; import org.unicitylabs.sdk.address.AddressFactory; -import org.unicitylabs.sdk.api.RequestId; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.DataHasher; @@ -85,12 +86,9 @@ public static MintTransaction fromJson(String input) { * @return verification result */ public VerificationResult verify(RootTrustBase trustBase) { - if (!this.getInclusionProof().getAuthenticator().isPresent()) { - return VerificationResult.fail("Missing authenticator"); - } - - if (!this.getInclusionProof().getTransactionHash().isPresent()) { - return VerificationResult.fail("Missing transaction hash"); + CertificationData certificationData = this.getInclusionProof().getCertificationData().orElse(null); + if (certificationData == null) { + return VerificationResult.fail("Missing certification data"); } if (!this.getData().getSourceState() @@ -99,13 +97,11 @@ public VerificationResult verify(RootTrustBase trustBase) { } SigningService signingService = MintSigningService.create(this.getData().getTokenId()); - if (!Arrays.equals(signingService.getPublicKey(), - this.getInclusionProof().getAuthenticator().get().getPublicKey())) { - return VerificationResult.fail("Authenticator public key mismatch"); + if (!Arrays.equals(signingService.getPublicKey(), certificationData.getPublicKey())) { + return VerificationResult.fail("Certification data public key mismatch"); } - if (!this.getInclusionProof().getAuthenticator().get() - .verify(this.getInclusionProof().getTransactionHash().get())) { + if (!certificationData.verify()) { return VerificationResult.fail("Authenticator verification failed"); } @@ -118,11 +114,8 @@ public VerificationResult verify(RootTrustBase trustBase) { } InclusionProofVerificationStatus inclusionProofStatus = this.getInclusionProof().verify( - RequestId.create( - MintSigningService.create(this.getData().getTokenId()).getPublicKey(), - this.getData().getSourceState() - ), - trustBase + trustBase, + StateId.create(signingService.getPublicKey(), this.getData().getSourceState()) ); if (inclusionProofStatus != InclusionProofVerificationStatus.OK) { diff --git a/src/main/java/org/unicitylabs/sdk/transaction/MintTransactionState.java b/src/main/java/org/unicitylabs/sdk/transaction/MintTransactionState.java index cb11459..b491389 100644 --- a/src/main/java/org/unicitylabs/sdk/transaction/MintTransactionState.java +++ b/src/main/java/org/unicitylabs/sdk/transaction/MintTransactionState.java @@ -1,6 +1,6 @@ package org.unicitylabs.sdk.transaction; -import org.unicitylabs.sdk.api.RequestId; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.token.TokenId; import org.unicitylabs.sdk.util.HexConverter; @@ -24,6 +24,6 @@ private MintTransactionState(DataHash hash) { * @return mint state */ public static MintTransactionState create(TokenId tokenId) { - return new MintTransactionState(RequestId.create(tokenId.getBytes(), MINT_SUFFIX)); + return new MintTransactionState(StateId.create(tokenId.getBytes(), MINT_SUFFIX)); } } diff --git a/src/main/java/org/unicitylabs/sdk/transaction/TransferCommitment.java b/src/main/java/org/unicitylabs/sdk/transaction/TransferCommitment.java index 5e9396f..f42f01f 100644 --- a/src/main/java/org/unicitylabs/sdk/transaction/TransferCommitment.java +++ b/src/main/java/org/unicitylabs/sdk/transaction/TransferCommitment.java @@ -3,11 +3,14 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; import java.util.Objects; import org.unicitylabs.sdk.address.Address; -import org.unicitylabs.sdk.api.Authenticator; -import org.unicitylabs.sdk.api.RequestId; +import org.unicitylabs.sdk.api.BlockHeightResponse; +import org.unicitylabs.sdk.api.CertificationData; import org.unicitylabs.sdk.hash.DataHash; +import org.unicitylabs.sdk.serializer.UnicityObjectMapper; +import org.unicitylabs.sdk.serializer.json.JsonSerializationException; import org.unicitylabs.sdk.signing.SigningService; import org.unicitylabs.sdk.token.Token; @@ -18,14 +21,12 @@ public class TransferCommitment extends Commitment { @JsonCreator private TransferCommitment( - @JsonProperty("requestId") - RequestId requestId, @JsonProperty("transactionData") TransferTransaction.Data transactionData, - @JsonProperty("authenticator") - Authenticator authenticator + @JsonProperty("certificationData") + CertificationData certificationData ) { - super(requestId, transactionData, authenticator); + super(transactionData, certificationData); } /** @@ -39,6 +40,20 @@ public TransferTransaction toTransaction(InclusionProof inclusionProof) { return new TransferTransaction(this.getTransactionData(), inclusionProof); } + /** + * Create transfer commitment from JSON string. + * + * @param input JSON string + * @return transfer commitment data + */ + public static TransferCommitment fromJson(String input) { + try { + return UnicityObjectMapper.JSON.readValue(input, TransferCommitment.class); + } catch (JsonProcessingException e) { + throw new JsonSerializationException(BlockHeightResponse.class, e); + } + } + /** * Create transfer commitment. * @@ -63,7 +78,7 @@ public static TransferCommitment create( Objects.requireNonNull(salt, "Salt cannot be null"); Objects.requireNonNull(signingService, "SigningService cannot be null"); - TransferTransaction.Data data = new TransferTransaction.Data( + TransferTransaction.Data transactionData = new TransferTransaction.Data( token.getState(), recipient, salt, @@ -71,13 +86,13 @@ public static TransferCommitment create( message, token.getNametags() ); - RequestId requestId = RequestId.create(signingService.getPublicKey(), data.getSourceState()); - Authenticator authenticator = Authenticator.create( - signingService, - data.calculateHash(), - data.getSourceState().calculateHash() + + CertificationData certificationData = CertificationData.create( + transactionData.getSourceState().calculateHash(), + transactionData.calculateHash(), + signingService ); - return new TransferCommitment(requestId, data, authenticator); + return new TransferCommitment(transactionData, certificationData); } } diff --git a/src/main/java/org/unicitylabs/sdk/transaction/split/SplitMintReason.java b/src/main/java/org/unicitylabs/sdk/transaction/split/SplitMintReason.java index 89b5f39..2a637a9 100644 --- a/src/main/java/org/unicitylabs/sdk/transaction/split/SplitMintReason.java +++ b/src/main/java/org/unicitylabs/sdk/transaction/split/SplitMintReason.java @@ -2,7 +2,6 @@ package org.unicitylabs.sdk.transaction.split; import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import java.math.BigInteger; @@ -10,7 +9,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.stream.Collectors; import org.unicitylabs.sdk.mtree.plain.SparseMerkleTreePathStep; import org.unicitylabs.sdk.predicate.Predicate; diff --git a/src/main/java/org/unicitylabs/sdk/util/InclusionProofUtils.java b/src/main/java/org/unicitylabs/sdk/util/InclusionProofUtils.java index fb40735..892ea0d 100644 --- a/src/main/java/org/unicitylabs/sdk/util/InclusionProofUtils.java +++ b/src/main/java/org/unicitylabs/sdk/util/InclusionProofUtils.java @@ -7,6 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.unicitylabs.sdk.StateTransitionClient; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.transaction.Commitment; import org.unicitylabs.sdk.transaction.InclusionProof; @@ -78,14 +79,13 @@ private static void checkInclusionProof( long startTime, long timeoutMillis, long intervalMillis) { - if (System.currentTimeMillis() - startTime > timeoutMillis) { future.completeExceptionally(new TimeoutException("Timeout waiting for inclusion proof")); } - client.getInclusionProof(commitment.getRequestId()).thenAccept(response -> { - InclusionProofVerificationStatus status = response.getInclusionProof() - .verify(commitment.getRequestId(), trustBase); + StateId stateId = commitment.getCertificationData().calculateStateId(); + client.getInclusionProof(stateId).thenAccept(response -> { + InclusionProofVerificationStatus status = response.getInclusionProof().verify(trustBase, stateId); switch (status) { case OK: future.complete(response.getInclusionProof()); diff --git a/src/test/java/org/unicitylabs/sdk/MockAggregatorServer.java b/src/test/java/org/unicitylabs/sdk/MockAggregatorServer.java index fc63d44..83dbefe 100644 --- a/src/test/java/org/unicitylabs/sdk/MockAggregatorServer.java +++ b/src/test/java/org/unicitylabs/sdk/MockAggregatorServer.java @@ -27,7 +27,7 @@ public MockAggregatorServer() { this.server = new MockWebServer(); this.objectMapper = new ObjectMapper(); this.protectedMethods = new HashSet<>(); - this.protectedMethods.add("submit_commitment"); + this.protectedMethods.add("certification_request"); server.setDispatcher(new Dispatcher() { @Override @@ -117,7 +117,7 @@ private MockResponse generateSuccessResponse(String method) { String id = UUID.randomUUID().toString(); switch (method != null ? method : "") { - case "submit_commitment": + case "certification_request": responseBody = String.format( "{\n" + " \"jsonrpc\": \"2.0\",\n" + diff --git a/src/test/java/org/unicitylabs/sdk/TestAggregatorClient.java b/src/test/java/org/unicitylabs/sdk/TestAggregatorClient.java index 3fca876..608aa92 100644 --- a/src/test/java/org/unicitylabs/sdk/TestAggregatorClient.java +++ b/src/test/java/org/unicitylabs/sdk/TestAggregatorClient.java @@ -1,20 +1,15 @@ package org.unicitylabs.sdk; -import java.util.AbstractMap; import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; import java.util.concurrent.CompletableFuture; -import org.unicitylabs.sdk.api.Authenticator; import org.unicitylabs.sdk.api.AggregatorClient; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; import org.unicitylabs.sdk.api.InclusionProofResponse; -import org.unicitylabs.sdk.api.LeafValue; -import org.unicitylabs.sdk.api.RequestId; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.bft.UnicityCertificateUtils; -import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.HashAlgorithm; import org.unicitylabs.sdk.mtree.plain.SparseMerkleTree; import org.unicitylabs.sdk.mtree.plain.SparseMerkleTreeRootNode; @@ -24,7 +19,7 @@ public class TestAggregatorClient implements AggregatorClient { private final SparseMerkleTree tree = new SparseMerkleTree(HashAlgorithm.SHA256); - private final HashMap> requests = new HashMap<>(); + private final HashMap requests = new HashMap<>(); private final SigningService signingService; public TestAggregatorClient(SigningService signingService) { @@ -34,37 +29,36 @@ public TestAggregatorClient(SigningService signingService) { @Override - public CompletableFuture submitCommitment( - RequestId requestId, - DataHash transactionHash, - Authenticator authenticator + public CompletableFuture submitCertificationRequest( + CertificationData certificationData, + boolean receipt ) { + // TODO: Add checks if everything is valid try { + StateId stateId = certificationData.calculateStateId(); + tree.addLeaf( - requestId.toBitString().toBigInteger(), - LeafValue.create(authenticator, transactionHash).getBytes() + stateId.toBitString().toBigInteger(), + certificationData.calculateLeafValue().getImprint() ); - requests.put(requestId, new AbstractMap.SimpleEntry<>(authenticator, transactionHash)); + requests.put(stateId, certificationData); - return CompletableFuture.completedFuture( - new SubmitCommitmentResponse(SubmitCommitmentStatus.SUCCESS) - ); + return CompletableFuture.completedFuture(CertificationResponse.create(CertificationStatus.SUCCESS)); } catch (Exception e) { throw new RuntimeException("Aggregator commitment failed", e); } } @Override - public CompletableFuture getInclusionProof(RequestId requestId) { - Entry entry = requests.get(requestId); + public CompletableFuture getInclusionProof(StateId stateId) { + CertificationData certificationData = requests.get(stateId); SparseMerkleTreeRootNode root = tree.calculateRoot(); return CompletableFuture.completedFuture( new InclusionProofResponse( InclusionProofFixture.create( - root.getPath(requestId.toBitString().toBigInteger()), - entry != null ? entry.getKey() : null, - entry != null ? entry.getValue() : null, + root.getPath(stateId.toBitString().toBigInteger()), + certificationData, UnicityCertificateUtils.generateCertificate(signingService, root.getRootHash()) ) ) diff --git a/src/test/java/org/unicitylabs/sdk/TestApiKeyIntegration.java b/src/test/java/org/unicitylabs/sdk/TestApiKeyIntegration.java index e254820..5c3c2d0 100644 --- a/src/test/java/org/unicitylabs/sdk/TestApiKeyIntegration.java +++ b/src/test/java/org/unicitylabs/sdk/TestApiKeyIntegration.java @@ -1,146 +1,158 @@ package org.unicitylabs.sdk; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import okhttp3.mockwebserver.RecordedRequest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.unicitylabs.sdk.api.AggregatorClient; -import org.unicitylabs.sdk.api.Authenticator; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; import org.unicitylabs.sdk.api.JsonRpcAggregatorClient; -import org.unicitylabs.sdk.api.RequestId; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.HashAlgorithm; import org.unicitylabs.sdk.jsonrpc.JsonRpcNetworkException; import org.unicitylabs.sdk.signing.SigningService; import org.unicitylabs.sdk.util.HexConverter; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; +public class TestApiKeyIntegration { -import static org.junit.jupiter.api.Assertions.*; + private static final String TEST_API_KEY = "test-api-key-12345"; -public class TestApiKeyIntegration { + private MockAggregatorServer mockServer; + private AggregatorClient clientWithApiKey; + private AggregatorClient clientWithoutApiKey; - private static final String TEST_API_KEY = "test-api-key-12345"; - - private MockAggregatorServer mockServer; - private AggregatorClient clientWithApiKey; - private AggregatorClient clientWithoutApiKey; - - private DataHash transactionHash; - private RequestId requestId; - private Authenticator authenticator; - - @BeforeEach - void setUp() throws Exception { - mockServer = new MockAggregatorServer(); - mockServer.setExpectedApiKey(TEST_API_KEY); - mockServer.start(); - - clientWithApiKey = new JsonRpcAggregatorClient( - mockServer.getUrl(), TEST_API_KEY); - clientWithoutApiKey = new JsonRpcAggregatorClient(mockServer.getUrl()); - - SigningService signingService = new SigningService( - HexConverter.decode("0000000000000000000000000000000000000000000000000000000000000001")); - - DataHash stateHash = new DataHash(HashAlgorithm.SHA256, HexConverter.decode("fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321")); - requestId = RequestId.create(signingService.getPublicKey(), stateHash); - transactionHash = new DataHash(HashAlgorithm.SHA256, HexConverter.decode("abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890")); - - authenticator = Authenticator.create(signingService, transactionHash, stateHash); - } - - @AfterEach - void tearDown() throws Exception { - mockServer.shutdown(); - } - - @Test - public void testSubmitCommitmentWithApiKey() throws Exception { - CompletableFuture future = - clientWithApiKey.submitCommitment(requestId, transactionHash, authenticator); - - SubmitCommitmentResponse response = future.get(5, TimeUnit.SECONDS); - assertEquals(SubmitCommitmentStatus.SUCCESS, response.getStatus()); - - RecordedRequest request = mockServer.takeRequest(); - assertEquals("Bearer " + TEST_API_KEY, request.getHeader("Authorization")); - } - - @Test - public void testSubmitCommitmentWithoutApiKeyThrowsUnauthorized() throws Exception { - CompletableFuture future = - clientWithoutApiKey.submitCommitment(requestId, transactionHash, authenticator); - - try { - future.get(5, TimeUnit.SECONDS); - fail("Expected UnauthorizedException to be thrown"); - } catch (Exception e) { - assertInstanceOf(ExecutionException.class, e); - assertInstanceOf(JsonRpcNetworkException.class, e.getCause()); - assertEquals("Network error [401] occurred: Unauthorized", e.getCause().getMessage()); - } - - RecordedRequest request = mockServer.takeRequest(); - assertNull(request.getHeader("Authorization")); - } - - @Test - public void testSubmitCommitmentWithWrongApiKeyThrowsUnauthorized() throws Exception { - mockServer.setExpectedApiKey("different-api-key"); - - CompletableFuture future = - clientWithApiKey.submitCommitment(requestId, transactionHash, authenticator); - - try { - future.get(5, TimeUnit.SECONDS); - fail("Expected UnauthorizedException to be thrown"); - } catch (Exception e) { - assertInstanceOf(ExecutionException.class, e); - assertInstanceOf(JsonRpcNetworkException.class, e.getCause()); - assertEquals("Network error [401] occurred: Unauthorized", e.getCause().getMessage()); - } - - RecordedRequest request = mockServer.takeRequest(); - assertEquals("Bearer " + TEST_API_KEY, request.getHeader("Authorization")); - } - - @Test - public void testRateLimitExceeded() throws Exception { - mockServer.simulateRateLimitForNextRequest(30); - - CompletableFuture future = - clientWithApiKey.submitCommitment(requestId, transactionHash, authenticator); - - try { - future.get(5, TimeUnit.SECONDS); - fail("Expected RateLimitExceededException to be thrown"); - } catch (Exception e) { - assertInstanceOf(ExecutionException.class, e); - assertInstanceOf(JsonRpcNetworkException.class, e.getCause()); - assertTrue(e.getCause().getMessage().contains("Network error [429] occurred: Too Many Requests"), e.getCause().getMessage()); - } + private CertificationData certificationData; + + @BeforeEach + void setUp() throws Exception { + mockServer = new MockAggregatorServer(); + mockServer.setExpectedApiKey(TEST_API_KEY); + mockServer.start(); + + clientWithApiKey = new JsonRpcAggregatorClient( + mockServer.getUrl(), TEST_API_KEY); + clientWithoutApiKey = new JsonRpcAggregatorClient(mockServer.getUrl()); + + SigningService signingService = new SigningService( + HexConverter.decode("0000000000000000000000000000000000000000000000000000000000000001")); + + certificationData = CertificationData.create( + new DataHash(HashAlgorithm.SHA256, + HexConverter.decode("fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321")), + new DataHash(HashAlgorithm.SHA256, + HexConverter.decode("abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890")), + signingService + ); + } + + @AfterEach + void tearDown() throws Exception { + mockServer.shutdown(); + } + + @Test + public void testSubmitCommitmentWithApiKey() throws Exception { + CompletableFuture future = clientWithApiKey.submitCertificationRequest( + certificationData, + false + ); + + CertificationResponse response = future.get(5, TimeUnit.SECONDS); + assertEquals(CertificationStatus.SUCCESS, response.getStatus()); + + RecordedRequest request = mockServer.takeRequest(); + assertEquals("Bearer " + TEST_API_KEY, request.getHeader("Authorization")); + } + + @Test + public void testSubmitCommitmentWithoutApiKeyThrowsUnauthorized() throws Exception { + CompletableFuture future = clientWithoutApiKey.submitCertificationRequest( + certificationData, + false + ); + + try { + future.get(5, TimeUnit.SECONDS); + fail("Expected UnauthorizedException to be thrown"); + } catch (Exception e) { + assertInstanceOf(ExecutionException.class, e); + assertInstanceOf(JsonRpcNetworkException.class, e.getCause()); + assertEquals("Network error [401] occurred: Unauthorized", e.getCause().getMessage()); } - - @Test - public void testGetBlockHeightWorksWithoutApiKey() throws Exception { - CompletableFuture future = clientWithoutApiKey.getBlockHeight(); - - Long blockHeight = future.get(5, TimeUnit.SECONDS); - assertNotNull(blockHeight); - assertEquals(67890L, blockHeight); + + RecordedRequest request = mockServer.takeRequest(); + assertNull(request.getHeader("Authorization")); + } + + @Test + public void testSubmitCommitmentWithWrongApiKeyThrowsUnauthorized() throws Exception { + mockServer.setExpectedApiKey("different-api-key"); + + CompletableFuture future = clientWithApiKey.submitCertificationRequest( + certificationData, + false + ); + + try { + future.get(5, TimeUnit.SECONDS); + fail("Expected UnauthorizedException to be thrown"); + } catch (Exception e) { + assertInstanceOf(ExecutionException.class, e); + assertInstanceOf(JsonRpcNetworkException.class, e.getCause()); + assertEquals("Network error [401] occurred: Unauthorized", e.getCause().getMessage()); } - - @Test - public void testGetBlockHeightAlsoWorksWithApiKey() throws Exception { - CompletableFuture future = clientWithApiKey.getBlockHeight(); - - Long blockHeight = future.get(5, TimeUnit.SECONDS); - assertNotNull(blockHeight); - assertEquals(67890L, blockHeight); + + RecordedRequest request = mockServer.takeRequest(); + assertEquals("Bearer " + TEST_API_KEY, request.getHeader("Authorization")); + } + + @Test + public void testRateLimitExceeded() { + mockServer.simulateRateLimitForNextRequest(30); + + CompletableFuture future = clientWithApiKey.submitCertificationRequest( + certificationData, + false + ); + + try { + future.get(5, TimeUnit.SECONDS); + fail("Expected RateLimitExceededException to be thrown"); + } catch (Exception e) { + assertInstanceOf(ExecutionException.class, e); + assertInstanceOf(JsonRpcNetworkException.class, e.getCause()); + assertTrue(e.getCause().getMessage().contains("Network error [429] occurred: Too Many Requests"), + e.getCause().getMessage()); } + } + + @Test + public void testGetBlockHeightWorksWithoutApiKey() throws Exception { + CompletableFuture future = clientWithoutApiKey.getBlockHeight(); + + Long blockHeight = future.get(5, TimeUnit.SECONDS); + assertNotNull(blockHeight); + assertEquals(67890L, blockHeight); + } + + @Test + public void testGetBlockHeightAlsoWorksWithApiKey() throws Exception { + CompletableFuture future = clientWithApiKey.getBlockHeight(); + + Long blockHeight = future.get(5, TimeUnit.SECONDS); + assertNotNull(blockHeight); + assertEquals(67890L, blockHeight); + } } \ No newline at end of file diff --git a/src/test/java/org/unicitylabs/sdk/api/AuthenticatorTest.java b/src/test/java/org/unicitylabs/sdk/api/AuthenticatorTest.java deleted file mode 100644 index 2aaed3a..0000000 --- a/src/test/java/org/unicitylabs/sdk/api/AuthenticatorTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.unicitylabs.sdk.api; - -import com.fasterxml.jackson.core.JsonProcessingException; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.unicitylabs.sdk.hash.DataHash; -import org.unicitylabs.sdk.signing.SigningService; -import org.unicitylabs.sdk.util.HexConverter; - -public class AuthenticatorTest { - - @Test - public void testJsonSerialization() throws JsonProcessingException { - SigningService signingService = new SigningService( - HexConverter.decode("0000000000000000000000000000000000000000000000000000000000000001")); - Authenticator authenticator = Authenticator.create( - signingService, - DataHash.fromImprint(new byte[34]), - DataHash.fromImprint(new byte[34]) - ); - - Assertions.assertEquals( - "8469736563703235366b3158210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817985841a0b37f8fba683cc68f6574cd43b39f0343a50008bf6ccea9d13231d9e7e2e1e411edc8d307254296264aebfc3dc76cd8b668373a072fd64665b50000e9fcce5201582200000000000000000000000000000000000000000000000000000000000000000000", - HexConverter.encode(authenticator.toCbor())); - - Authenticator.fromJson("{\"algorithm\":\"secp256k1\",\"publicKey\":\"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\",\"signature\":\"a0b37f8fba683cc68f6574cd43b39f0343a50008bf6ccea9d13231d9e7e2e1e411edc8d307254296264aebfc3dc76cd8b668373a072fd64665b50000e9fcce5201\",\"stateHash\":\"00000000000000000000000000000000000000000000000000000000000000000000\"}"); - } -} diff --git a/src/test/java/org/unicitylabs/sdk/api/RequestIdTest.java b/src/test/java/org/unicitylabs/sdk/api/StateIdTest.java similarity index 59% rename from src/test/java/org/unicitylabs/sdk/api/RequestIdTest.java rename to src/test/java/org/unicitylabs/sdk/api/StateIdTest.java index 993484d..b9fa620 100644 --- a/src/test/java/org/unicitylabs/sdk/api/RequestIdTest.java +++ b/src/test/java/org/unicitylabs/sdk/api/StateIdTest.java @@ -7,29 +7,29 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class RequestIdTest { +public class StateIdTest { @Test public void shouldResolveToBigInteger() { - RequestId requestId = RequestId.create(new byte[5], + StateId stateId = StateId.create(new byte[5], new DataHash(HashAlgorithm.SHA256, new byte[32])); Assertions.assertEquals( new BigInteger( - "7588617643772589565921291111125869131233840654380505021472016115258380142349673042" + "7588640947079736950651543599112501467726489700903461286985351382586976462842180672" ), - requestId.toBitString().toBigInteger()); + stateId.toBitString().toBigInteger()); } @Test - public void testJsonSerialization() throws JsonProcessingException { - RequestId requestId = RequestId.create( + public void testJsonSerialization() { + StateId stateId = StateId.create( new byte[5], new DataHash(HashAlgorithm.SHA256, new byte[32]) ); Assertions.assertEquals( - requestId, - RequestId.fromJson(requestId.toJson()) + stateId, + StateId.fromJson(stateId.toJson()) ); } } diff --git a/src/test/java/org/unicitylabs/sdk/bft/RootTrustBaseTest.java b/src/test/java/org/unicitylabs/sdk/bft/RootTrustBaseTest.java index 6c856f4..919cfb3 100644 --- a/src/test/java/org/unicitylabs/sdk/bft/RootTrustBaseTest.java +++ b/src/test/java/org/unicitylabs/sdk/bft/RootTrustBaseTest.java @@ -7,7 +7,7 @@ public class RootTrustBaseTest { @Test - public void testRootTrustBaseDeserializationFromJson() throws IOException { + public void testRootTrustBaseDeserializationFromJson() { RootTrustBase trustBase = RootTrustBase.fromJson( "{\"version\":1,\"networkId\":3,\"epoch\":1,\"epochStartRound\":1,\"rootNodes\":[{\"nodeId\":\"16Uiu2HAm3PaA9z8jonZzfvuT1WJgTxCpbFkV4Wq4PSSBk7VctkmG\",\"sigKey\":\"0x03982564bf661da9c048397114fab9dcfbfedb0ad7c1b1c83e13c0f9fa633f7aa6\",\"stake\":1},{\"nodeId\":\"16Uiu2HAm8918Ds2nPiVLXg55kypyoXoiweokpQxtnguZjgxz3pNE\",\"sigKey\":\"0x039a2f7f41c5583d339f31490757152b947ccb19944634a40a16a762a32a4855d4\",\"stake\":1},{\"nodeId\":\"16Uiu2HAmEEEGyvYZno7hm2Gs8FwfPejWdpvWC3HLivQD5hXFbNUh\",\"sigKey\":\"0x038cabc84fa86076277879554c277f9a0a19955fa4c3b37871fca81d5f709777f1\",\"stake\":1},{\"nodeId\":\"16Uiu2HAmNwgru7QSsVRacGqXdtfeaf1oqtznvXA6rSzKU1822kuW\",\"sigKey\":\"0x03044c0309fd0a713440da958f8c510a40a4347aa82622481655d162c227d771e3\",\"stake\":1}],\"quorumThreshold\":3,\"stateHash\":\"\",\"changeRecordHash\":\"\",\"previousEntryHash\":\"\",\"signatures\":{\"16Uiu2HAm3PaA9z8jonZzfvuT1WJgTxCpbFkV4Wq4PSSBk7VctkmG\":\"0xfe672d56ddd60e4b028b52999b4e43bcbdac9413d9e8da6f969d46c249da8f492cd719017510af8b199b94c7605b79707da56950a4888320f8cf7e07329e92da01\",\"16Uiu2HAm8918Ds2nPiVLXg55kypyoXoiweokpQxtnguZjgxz3pNE\":\"0x8d1b178f6617a6aff9e9d4a71febac6837bd2a5088f3e3b81c766065e6c7a7ad718d1e0a1c7f7e12954514e663b888337cbaa6e7c8bd5e721f4ae5520ca6f09e00\",\"16Uiu2HAmEEEGyvYZno7hm2Gs8FwfPejWdpvWC3HLivQD5hXFbNUh\":\"0x28ef1e0279fb2962149011177c173aabb7e1fad102f07c898b9de4fe71b424390dd0cbc59f75453a7573c4853218eab800431e42fd0d4a6000ef73d50170d03101\",\"16Uiu2HAmNwgru7QSsVRacGqXdtfeaf1oqtznvXA6rSzKU1822kuW\":\"0xf563d04beb3eb5bd5967cb53e6cc1d1b331cd37c03d7a34ba7f11bc0d2c4994818168e1f5caf88956b34384dd3d3685c432d7a487b5c0bee2da012fd70891bab01\"}}" ); diff --git a/src/test/java/org/unicitylabs/sdk/bft/UnicityCertificateTest.java b/src/test/java/org/unicitylabs/sdk/bft/UnicityCertificateTest.java index 3f2e5a1..ad03b92 100644 --- a/src/test/java/org/unicitylabs/sdk/bft/UnicityCertificateTest.java +++ b/src/test/java/org/unicitylabs/sdk/bft/UnicityCertificateTest.java @@ -8,7 +8,7 @@ public class UnicityCertificateTest { @Test - public void testUnicityCertificateDeserializationFromCbor() throws IOException { + public void testUnicityCertificateDeserializationFromCbor() { byte[] data = HexConverter.decode( "d903ef8701d903f08a0118f70058220000ea2fc549e86b1f8666bd7a6d5dd0721b446856ad80c67ea958c4045dfb0b627c58220000ea2fc549e86b1f8666bd7a6d5dd0721b446856ad80c67ea958c4045dfb0b627c401a68d27af6f600f6582024bf5304778618efe3303e1ac36a5c23b7d9d64bbd2c2ae92ea1488ad59e9cfa58206a362e77353752942e9c8101511861ee7fac83ba0873ee88f34416535ae17c5c82418080d903f68301078182055820b206f60d312bf4422815c861e9330ddc3a29b0c744864d7bea41f94d1d34c669d903e988010319073b001a68d27af958204b3f7f036452271a1245ca79f6c2e35adc0b192e6eeb001dff35d70d1be3b2d55820380451b471673eb68cf750ceedb09755c08e3b0b7dea32d0101465970ca3a661a4783531365569753248416d33506141397a386a6f6e5a7a6676755431574a675478437062466b5634577134505353426b375663746b6d475841c5103160b79e7691cec53448949bbd93a870a38c89ad4c929aa1c8e77f2a1d9053d3f8f04e96bcb38ba234bf3dee52baad4b1df94be0b8a5e569918fb94e18ec00783531365569753248416d383931384473326e5069564c586735356b7970796f586f6977656f6b705178746e67755a6a67787a33704e455841fa3736ebdc729b31d6e3c964787dfcefcbd39286a1619665eac1313e6d35049b4385156f652ad9ac87a769d3bf7b8cc819bb5a6f838e595d2e2092df2592849400783531365569753248416d454545477976595a6e6f37686d3247733846776650656a57647076574333484c6976514435685846624e55685841e49ea9e0ca1bb21a37a203fef7bc64efc660ff208f4e572ad3d58ae1d5f1e86e7af1c030c66b3325f99886b1a1d0836487c16112c43c07248b490121d473287701783531365569753248416d4e776772753751537356526163477158647466656166316f71747a6e7658413672537a4b55313832326b75575841ecb36e24df58876277643117344d5329fc1bb22b51e9e6835ac587c894db06a11110e966fd97acd91659c778494d9b4dcdc1bd22ffb47a90e3bec38db8a7310f01"); UnicityCertificate unicityCertificate = UnicityCertificate.fromCbor(data); diff --git a/src/test/java/org/unicitylabs/sdk/common/BaseEscrowSwapTest.java b/src/test/java/org/unicitylabs/sdk/common/BaseEscrowSwapTest.java index 62fd818..770f352 100644 --- a/src/test/java/org/unicitylabs/sdk/common/BaseEscrowSwapTest.java +++ b/src/test/java/org/unicitylabs/sdk/common/BaseEscrowSwapTest.java @@ -8,8 +8,8 @@ import org.junit.jupiter.api.Test; import org.unicitylabs.sdk.StateTransitionClient; import org.unicitylabs.sdk.address.ProxyAddress; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.hash.HashAlgorithm; import org.unicitylabs.sdk.predicate.embedded.MaskedPredicate; @@ -61,8 +61,8 @@ private String[] transferToken(Token token, SigningService signingService, St signingService ); - SubmitCommitmentResponse response = this.client.submitCommitment(commitment).get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + CertificationResponse response = this.client.submitCommitment(commitment).get(); + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new RuntimeException("Failed to submit transfer commitment: " + response); } diff --git a/src/test/java/org/unicitylabs/sdk/common/CommonTestFlow.java b/src/test/java/org/unicitylabs/sdk/common/CommonTestFlow.java index 56c2b2b..a5c8c49 100644 --- a/src/test/java/org/unicitylabs/sdk/common/CommonTestFlow.java +++ b/src/test/java/org/unicitylabs/sdk/common/CommonTestFlow.java @@ -15,9 +15,8 @@ import org.unicitylabs.sdk.StateTransitionClient; import org.unicitylabs.sdk.address.DirectAddress; import org.unicitylabs.sdk.address.ProxyAddress; -import org.unicitylabs.sdk.api.RequestId; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.DataHasher; @@ -27,7 +26,6 @@ import org.unicitylabs.sdk.predicate.embedded.MaskedPredicateReference; import org.unicitylabs.sdk.predicate.embedded.UnmaskedPredicate; import org.unicitylabs.sdk.predicate.embedded.UnmaskedPredicateReference; -import org.unicitylabs.sdk.signing.MintSigningService; import org.unicitylabs.sdk.signing.SigningService; import org.unicitylabs.sdk.token.Token; import org.unicitylabs.sdk.token.TokenId; @@ -36,7 +34,6 @@ import org.unicitylabs.sdk.token.fungible.CoinId; import org.unicitylabs.sdk.token.fungible.TokenCoinData; import org.unicitylabs.sdk.transaction.InclusionProof; -import org.unicitylabs.sdk.transaction.InclusionProofVerificationStatus; import org.unicitylabs.sdk.transaction.MintCommitment; import org.unicitylabs.sdk.transaction.MintTransaction; import org.unicitylabs.sdk.transaction.TransferCommitment; @@ -93,11 +90,11 @@ public void testTransferFlow() throws Exception { null, aliceSigningService ); - SubmitCommitmentResponse aliceToBobTransferSubmitResponse = this.client.submitCommitment( + CertificationResponse aliceToBobTransferSubmitResponse = this.client.submitCommitment( aliceToBobTransferCommitment ).get(); - if (aliceToBobTransferSubmitResponse.getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (aliceToBobTransferSubmitResponse.getStatus() != CertificationStatus.SUCCESS) { throw new Exception(String.format("Failed to submit transaction commitment: %s", aliceToBobTransferSubmitResponse.getStatus())); } @@ -176,11 +173,11 @@ public void testTransferFlow() throws Exception { null, SigningService.createFromSecret(BOB_SECRET) ); - SubmitCommitmentResponse bobToCarolTransferSubmitResponse = client.submitCommitment( + CertificationResponse bobToCarolTransferSubmitResponse = client.submitCommitment( bobToCarolTransferCommitment ).get(); - if (bobToCarolTransferSubmitResponse.getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (bobToCarolTransferSubmitResponse.getStatus() != CertificationStatus.SUCCESS) { throw new Exception(String.format("Failed to submit transaction commitment: %s", bobToCarolTransferSubmitResponse.getStatus())); } @@ -222,11 +219,11 @@ public void testTransferFlow() throws Exception { null, SigningService.createFromSecret(CAROL_SECRET) ); - SubmitCommitmentResponse carolToBobTransferSubmitResponse = this.client.submitCommitment( + CertificationResponse carolToBobTransferSubmitResponse = this.client.submitCommitment( carolToBobTransferCommitment ).get(); - if (carolToBobTransferSubmitResponse.getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (carolToBobTransferSubmitResponse.getStatus() != CertificationStatus.SUCCESS) { throw new Exception(String.format("Failed to submit transaction commitment: %s", carolToBobTransferSubmitResponse.getStatus())); } @@ -305,7 +302,7 @@ public void testTransferFlow() throws Exception { ); if (client.submitCommitment(burnCommitment).get().getStatus() - != SubmitCommitmentStatus.SUCCESS) { + != CertificationStatus.SUCCESS) { throw new Exception("Failed to submit burn commitment"); } @@ -322,7 +319,7 @@ public void testTransferFlow() throws Exception { List> splitTransactions = new ArrayList<>(); for (MintCommitment commitment : splitCommitments) { - if (client.submitCommitment(commitment).get().getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (client.submitCommitment(commitment).get().getStatus() != CertificationStatus.SUCCESS) { throw new Exception("Failed to submit split mint commitment"); } diff --git a/src/test/java/org/unicitylabs/sdk/common/split/BaseTokenSplitTest.java b/src/test/java/org/unicitylabs/sdk/common/split/BaseTokenSplitTest.java index fa0d29d..b33ff2c 100644 --- a/src/test/java/org/unicitylabs/sdk/common/split/BaseTokenSplitTest.java +++ b/src/test/java/org/unicitylabs/sdk/common/split/BaseTokenSplitTest.java @@ -11,8 +11,8 @@ import org.junit.jupiter.api.Test; import org.unicitylabs.sdk.StateTransitionClient; import org.unicitylabs.sdk.address.ProxyAddress; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.hash.HashAlgorithm; import org.unicitylabs.sdk.predicate.embedded.MaskedPredicate; @@ -115,11 +115,11 @@ void testTokenSplitFullAmounts() throws Exception { ) ); - SubmitCommitmentResponse burnCommitmentResponse = this.client + CertificationResponse burnCommitmentResponse = this.client .submitCommitment(burnCommitment) .get(); - if (burnCommitmentResponse.getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (burnCommitmentResponse.getStatus() != CertificationStatus.SUCCESS) { throw new Exception(String.format("Failed to submit burn commitment: %s", burnCommitmentResponse.getStatus())); } @@ -136,11 +136,11 @@ void testTokenSplitFullAmounts() throws Exception { ); for (MintCommitment commitment : mintCommitments) { - SubmitCommitmentResponse response = this.client + CertificationResponse response = this.client .submitCommitment(commitment) .get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new Exception(String.format("Failed to submit burn commitment: %s", response.getStatus())); } diff --git a/src/test/java/org/unicitylabs/sdk/e2e/BasicE2ETest.java b/src/test/java/org/unicitylabs/sdk/e2e/BasicE2ETest.java index 2469706..88485f8 100644 --- a/src/test/java/org/unicitylabs/sdk/e2e/BasicE2ETest.java +++ b/src/test/java/org/unicitylabs/sdk/e2e/BasicE2ETest.java @@ -1,23 +1,24 @@ package org.unicitylabs.sdk.e2e; +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.security.SecureRandom; +import java.util.concurrent.ExecutorService; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; import org.unicitylabs.sdk.api.JsonRpcAggregatorClient; -import org.unicitylabs.sdk.api.Authenticator; -import org.unicitylabs.sdk.api.RequestId; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.DataHasher; import org.unicitylabs.sdk.hash.HashAlgorithm; import org.unicitylabs.sdk.signing.SigningService; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; - -import java.security.SecureRandom; -import java.util.concurrent.ExecutorService; - -import static org.junit.jupiter.api.Assertions.*; /** * Basic end-to-end test to verify connectivity with aggregator. @@ -43,11 +44,10 @@ void testCommitmentPerformance() throws Exception { DataHash stateHash = new DataHasher(HashAlgorithm.SHA256).update(stateBytes).digest(); DataHash txDataHash = new DataHasher(HashAlgorithm.SHA256).update("test commitment performance".getBytes()).digest(); SigningService signingService = SigningService.createFromSecret(randomSecret); - RequestId requestId = RequestId.create(signingService.getPublicKey(), stateHash.getImprint()); - Authenticator auth = Authenticator.create(signingService, txDataHash, stateHash); - SubmitCommitmentResponse response = aggregatorClient.submitCommitment(requestId, txDataHash, auth).get(); + CertificationData certificationData = CertificationData.create(stateHash, txDataHash, signingService); + CertificationResponse response = aggregatorClient.submitCertificationRequest(certificationData, false).get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (response.getStatus() != CertificationStatus.SUCCESS) { System.err.println("Commitment submission failed with status: " + response.getStatus()); } long endTime = System.currentTimeMillis(); @@ -88,10 +88,10 @@ void testCommitmentPerformanceMultiThreaded() throws Exception { DataHash stateHash = new DataHasher(HashAlgorithm.SHA256).update(stateBytes).digest(); DataHash txDataHash = new DataHasher(HashAlgorithm.SHA256).update(txData).digest(); SigningService signingService = SigningService.createFromSecret(randomSecret); - RequestId requestId = RequestId.create(signingService.getPublicKey(), stateHash.getImprint()); - Authenticator auth = Authenticator.create(signingService, txDataHash, stateHash); - SubmitCommitmentResponse response = aggregatorClient.submitCommitment(requestId, txDataHash, auth).get(); - return response.getStatus() == SubmitCommitmentStatus.SUCCESS; + StateId stateId = StateId.create(signingService.getPublicKey(), stateHash.getImprint()); + CertificationData certificationData = CertificationData.create(stateId, txDataHash, signingService); + CertificationResponse response = aggregatorClient.submitCertificationRequest(certificationData, false).get(); + return response.getStatus() == CertificationStatus.SUCCESS; } finally { latch.countDown(); } diff --git a/src/test/java/org/unicitylabs/sdk/e2e/context/TestContext.java b/src/test/java/org/unicitylabs/sdk/e2e/context/TestContext.java index e5500f2..d57e105 100644 --- a/src/test/java/org/unicitylabs/sdk/e2e/context/TestContext.java +++ b/src/test/java/org/unicitylabs/sdk/e2e/context/TestContext.java @@ -3,14 +3,13 @@ import org.unicitylabs.sdk.StateTransitionClient; import org.unicitylabs.sdk.TestAggregatorClient; import org.unicitylabs.sdk.api.AggregatorClient; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; +import org.unicitylabs.sdk.api.CertificationResponse; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.predicate.Predicate; import org.unicitylabs.sdk.signing.SigningService; import org.unicitylabs.sdk.token.Token; import org.unicitylabs.sdk.token.TokenId; -import org.unicitylabs.sdk.transaction.Transaction; import org.unicitylabs.sdk.transaction.TransferTransaction; import org.unicitylabs.sdk.utils.TestUtils; import org.unicitylabs.sdk.utils.helpers.CommitmentResult; @@ -51,7 +50,7 @@ public class TestContext { private byte[] stateBytes; private DataHash stateHash; private DataHash txDataHash; - private SubmitCommitmentResponse commitmentResponse; + private CertificationResponse commitmentResponse; private long submissionDuration; private Exception lastError; private boolean operationSucceeded; @@ -137,8 +136,8 @@ public void setAggregatorClients(List aggregatorClients) { public DataHash getTxDataHash() { return txDataHash; } public void setTxDataHash(DataHash txDataHash) { this.txDataHash = txDataHash; } - public SubmitCommitmentResponse getCommitmentResponse() { return commitmentResponse; } - public void setCommitmentResponse(SubmitCommitmentResponse commitmentResponse) { this.commitmentResponse = commitmentResponse; } + public CertificationResponse getCommitmentResponse() { return commitmentResponse; } + public void setCommitmentResponse(CertificationResponse commitmentResponse) { this.commitmentResponse = commitmentResponse; } public long getSubmissionDuration() { return submissionDuration; } public void setSubmissionDuration(long submissionDuration) { this.submissionDuration = submissionDuration; } diff --git a/src/test/java/org/unicitylabs/sdk/e2e/steps/shared/SharedStepDefinitions.java b/src/test/java/org/unicitylabs/sdk/e2e/steps/shared/SharedStepDefinitions.java index 3e336d6..890ad2b 100644 --- a/src/test/java/org/unicitylabs/sdk/e2e/steps/shared/SharedStepDefinitions.java +++ b/src/test/java/org/unicitylabs/sdk/e2e/steps/shared/SharedStepDefinitions.java @@ -10,7 +10,6 @@ import org.unicitylabs.sdk.predicate.PredicateEngineService; import org.unicitylabs.sdk.predicate.embedded.UnmaskedPredicate; import org.unicitylabs.sdk.serializer.UnicityObjectMapper; -import org.unicitylabs.sdk.transaction.*; import org.unicitylabs.sdk.utils.TestUtils; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.HashAlgorithm; @@ -31,7 +30,6 @@ import java.util.concurrent.*; import java.util.stream.Collectors; -import static org.unicitylabs.sdk.utils.TestUtils.randomCoinData; import static org.junit.jupiter.api.Assertions.*; import org.unicitylabs.sdk.utils.helpers.CommitmentResult; @@ -130,11 +128,10 @@ public void iSubmitACommitmentWithTheGeneratedData() throws Exception { long startTime = System.currentTimeMillis(); SigningService signingService = SigningService.createFromSecret(context.getRandomSecret()); - var requestId = TestUtils.createRequestId(signingService, context.getStateHash()); - var authenticator = TestUtils.createAuthenticator(signingService, context.getTxDataHash(), context.getStateHash()); + CertificationData certificationData = TestUtils.createCertificationData(signingService, context.getTxDataHash(), context.getStateHash()); - SubmitCommitmentResponse response = context.getAggregatorClient() - .submitCommitment(requestId, context.getTxDataHash(), authenticator).get(); + CertificationResponse response = context.getAggregatorClient() + .submitCertificationRequest(certificationData, false).get(); context.setCommitmentResponse(response); long endTime = System.currentTimeMillis(); @@ -144,7 +141,7 @@ public void iSubmitACommitmentWithTheGeneratedData() throws Exception { @Then("the commitment should be submitted successfully") public void theCommitmentShouldBeSubmittedSuccessfully() { assertNotNull(context.getCommitmentResponse(), "Commitment response should not be null"); - assertEquals(SubmitCommitmentStatus.SUCCESS, context.getCommitmentResponse().getStatus(), + assertEquals(CertificationStatus.SUCCESS, context.getCommitmentResponse().getStatus(), "Commitment should be submitted successfully"); } @@ -194,23 +191,23 @@ public void iSubmitAllMintCommitmentsConcurrently() throws Exception { DataHash stateHash = TestUtils.hashData(stateBytes); DataHash txDataHash = TestUtils.hashData(txData); - RequestId requestId = TestUtils.createRequestId(signingService, stateHash); + StateId stateId = TestUtils.createStateId(signingService, stateHash); try { - Authenticator authenticator = TestUtils.createAuthenticator(signingService, txDataHash, stateHash); + CertificationData certificationData = TestUtils.createCertificationData(signingService, txDataHash, stateHash); - SubmitCommitmentResponse response = context.getAggregatorClient() - .submitCommitment(requestId, txDataHash, authenticator).get(); + CertificationResponse response = context.getAggregatorClient() + .submitCertificationRequest(certificationData, false).get(); - boolean success = response.getStatus() == SubmitCommitmentStatus.SUCCESS; + boolean success = response.getStatus() == CertificationStatus.SUCCESS; long end = System.nanoTime(); return new CommitmentResult(userName, Thread.currentThread().getName(), - requestId, success, start, end); + stateId, success, start, end); } catch (Exception e) { long end = System.nanoTime(); return new CommitmentResult(userName, Thread.currentThread().getName(), - requestId, false, start, end); + stateId, false, start, end); } }, executor); @@ -303,7 +300,7 @@ public void allMintCommitmentsShouldReceiveInclusionProofs(int timeoutSeconds) t results.stream() .filter(r -> !r.isVerified()) .forEach(r -> System.out.println( - "❌ Commitment failed: requestId=" + r.getRequestId().toString() + ", status=" + r.getStatus() + "❌ Commitment failed: stateId=" + r.getStateId().toString() + ", status=" + r.getStatus() )); assertEquals(results.size(), verifiedCount, "All commitments should be verified"); @@ -374,7 +371,7 @@ public void iSubmitAllMintCommitmentsConcurrentlyToAllAggregators() { byte[] txData = TestUtils.generateRandomBytes(32); DataHash stateHash = TestUtils.hashData(stateBytes); DataHash txDataHash = TestUtils.hashData(txData); - RequestId requestId = TestUtils.createRequestId(signingService, stateHash); + StateId stateId = TestUtils.createStateId(signingService, stateHash); // Submit the same commitment to all aggregators concurrently for (int aggIndex = 0; aggIndex < aggregatorClients.size(); aggIndex++) { @@ -385,22 +382,22 @@ public void iSubmitAllMintCommitmentsConcurrentlyToAllAggregators() { long start = System.nanoTime(); try { - Authenticator authenticator = TestUtils.createAuthenticator(signingService, txDataHash, stateHash); + CertificationData certificationData = TestUtils.createCertificationData(signingService, txDataHash, stateHash); - SubmitCommitmentResponse response = aggregatorClient - .submitCommitment(requestId, txDataHash, authenticator).get(); + CertificationResponse response = aggregatorClient + .submitCertificationRequest(certificationData, false).get(); - boolean success = response.getStatus() == SubmitCommitmentStatus.SUCCESS; + boolean success = response.getStatus() == CertificationStatus.SUCCESS; long end = System.nanoTime(); return new CommitmentResult(userName + "-" + aggregatorId, Thread.currentThread().getName(), - requestId, success, start, end); + stateId, success, start, end); } catch (Exception e) { long end = System.nanoTime(); return new CommitmentResult(userName + "-" + aggregatorId, Thread.currentThread().getName(), - requestId, false, start, end); + stateId, false, start, end); } }, executor); @@ -439,7 +436,7 @@ public void allCommitmentsShouldBeProcessedSuccessfully() { byte[] txData = TestUtils.generateRandomBytes(32); DataHash stateHash = TestUtils.hashData(stateBytes); DataHash txDataHash = TestUtils.hashData(txData); - RequestId requestId = TestUtils.createRequestId(signingService, stateHash); + StateId stateId = TestUtils.createStateId(signingService, stateHash); // Submit to all aggregators with the same data for (int aggIndex = 0; aggIndex < aggregatorClients.size(); aggIndex++) { @@ -448,22 +445,22 @@ public void allCommitmentsShouldBeProcessedSuccessfully() { long start = System.nanoTime(); try { - Authenticator authenticator = TestUtils.createAuthenticator(signingService, txDataHash, stateHash); + CertificationData certificationData = TestUtils.createCertificationData(signingService, txDataHash, stateHash); - SubmitCommitmentResponse response = aggregatorClient - .submitCommitment(requestId, txDataHash, authenticator).get(); + CertificationResponse response = aggregatorClient + .submitCertificationRequest(certificationData, false).get(); - boolean success = response.getStatus() == SubmitCommitmentStatus.SUCCESS; + boolean success = response.getStatus() == CertificationStatus.SUCCESS; long end = System.nanoTime(); results.add(new CommitmentResult(userName + "-" + aggregatorId, Thread.currentThread().getName(), - requestId, success, start, end)); + stateId, success, start, end)); } catch (Exception e) { long end = System.nanoTime(); results.add(new CommitmentResult(userName + "-" + aggregatorId, Thread.currentThread().getName(), - requestId, false, start, end)); + stateId, false, start, end)); } } @@ -524,7 +521,7 @@ public void allMintCommitmentsShouldReceiveInclusionProofsFromAllAggregatorsWith aggregatorResults.stream() .filter(r -> !r.isVerified()) .forEach(r -> System.out.println( - " ❌ Failed: requestId=" + r.getRequestId().toString() + + " ❌ Failed: stateId=" + r.getStateId().toString() + ", status=" + (r.getStatus() != null ? r.getStatus() : "Unknown") + ", user=" + r.getUserName() )); diff --git a/src/test/java/org/unicitylabs/sdk/e2e/steps/shared/StepHelper.java b/src/test/java/org/unicitylabs/sdk/e2e/steps/shared/StepHelper.java index 09c5c9b..999ecbb 100644 --- a/src/test/java/org/unicitylabs/sdk/e2e/steps/shared/StepHelper.java +++ b/src/test/java/org/unicitylabs/sdk/e2e/steps/shared/StepHelper.java @@ -4,8 +4,10 @@ import org.unicitylabs.sdk.address.DirectAddress; import org.unicitylabs.sdk.address.ProxyAddress; import org.unicitylabs.sdk.api.AggregatorClient; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.e2e.config.CucumberConfiguration; import org.unicitylabs.sdk.e2e.context.TestContext; import org.unicitylabs.sdk.hash.DataHash; @@ -71,8 +73,8 @@ public Token createNameTagTokenForUser(String username, Token token, String name ) ); - SubmitCommitmentResponse response = context.getClient().submitCommitment(nametagMintCommitment).get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + CertificationResponse response = context.getClient().submitCommitment(nametagMintCommitment).get(); + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new Exception("Failed to submit nametag mint commitment: " + response.getStatus()); } @@ -111,8 +113,8 @@ public void transferToken(String fromUser, String toUser, Token token, Address t fromSigningService ); - SubmitCommitmentResponse response = context.getClient().submitCommitment(transferCommitment).get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + CertificationResponse response = context.getClient().submitCommitment(transferCommitment).get(); + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new Exception("Failed to submit transfer commitment: " + response.getStatus()); } @@ -189,12 +191,13 @@ public boolean submitSingleCommitment() { DataHash stateHash = TestUtils.hashData(stateBytes); DataHash txDataHash = TestUtils.hashData(txData); SigningService signingService = SigningService.createFromSecret(randomSecret); - var requestId = TestUtils.createRequestId(signingService, stateHash); - var authenticator = TestUtils.createAuthenticator(signingService, txDataHash, stateHash); + CertificationData certificationData = TestUtils.createCertificationData(signingService, txDataHash, stateHash); - SubmitCommitmentResponse response = context.getAggregatorClient() - .submitCommitment(requestId, txDataHash, authenticator).get(); - return response.getStatus() == SubmitCommitmentStatus.SUCCESS; + CertificationResponse response = context.getAggregatorClient().submitCertificationRequest( + certificationData, + false + ).get(); + return response.getStatus() == CertificationStatus.SUCCESS; } catch (Exception e) { return false; } @@ -219,15 +222,15 @@ public void verifyAllInclusionProofsInParallel(int timeoutSeconds) while (System.nanoTime() < globalTimeout && !verified) { try { InclusionProof proof = context.getAggregatorClient() - .getInclusionProof(result.getRequestId()) + .getInclusionProof(result.getStateId()) .get(calculateRemainingTimeout(globalTimeout), TimeUnit.MILLISECONDS).getInclusionProof(); - if (proof != null && proof.verify(result.getRequestId(), context.getTrustBase()) + if (proof != null && proof.verify(context.getTrustBase(), result.getStateId()) == InclusionProofVerificationStatus.OK) { result.markVerified(inclStart, System.nanoTime()); verified = true; } else { - InclusionProofVerificationStatus status = proof.verify(result.getRequestId(), context.getTrustBase()); + InclusionProofVerificationStatus status = proof.verify(context.getTrustBase(), result.getStateId()); errorMessage = status.toString(); Thread.sleep(1000); // Небольшая пауза перед повторной попыткой } @@ -349,15 +352,15 @@ private void verifyInclusionProofsForAggregator(AggregatorClient aggregatorClien try { // Check if inclusion proof is available InclusionProof proofResponse = aggregatorClient - .getInclusionProof(result.getRequestId()).get(5, TimeUnit.SECONDS).getInclusionProof(); - if (proofResponse != null && proofResponse.verify(result.getRequestId(), context.getTrustBase()) + .getInclusionProof(result.getStateId()).get(5, TimeUnit.SECONDS).getInclusionProof(); + if (proofResponse != null && proofResponse.verify(context.getTrustBase(), result.getStateId()) == InclusionProofVerificationStatus.OK) { System.out.println("InclusionProofVerificationStatus.OK"); result.markVerified(inclusionStartTime, System.nanoTime()); verified = true; break; } else { - InclusionProofVerificationStatus status = proofResponse.verify(result.getRequestId(), context.getTrustBase()); + InclusionProofVerificationStatus status = proofResponse.verify(context.getTrustBase(), result.getStateId()); System.out.println(status.toString()); statusMessage = status.toString(); } @@ -422,7 +425,7 @@ public void printDetailedResultsByAggregator(List results, int if (!failed.isEmpty()) { System.out.println(" Failed verifications (" + failed.size() + "):"); - failed.forEach(r -> System.out.println(" ❌ " + r.getRequestId() + + failed.forEach(r -> System.out.println(" ❌ " + r.getStateId() + " - " + (r.getStatus() != null ? r.getStatus() : "Unknown error"))); } else { System.out.println(" ✅ All commitments verified successfully!"); diff --git a/src/test/java/org/unicitylabs/sdk/functional/FunctionalCommonFlowTest.java b/src/test/java/org/unicitylabs/sdk/functional/FunctionalCommonFlowTest.java index 8a1b9fc..2f67df1 100644 --- a/src/test/java/org/unicitylabs/sdk/functional/FunctionalCommonFlowTest.java +++ b/src/test/java/org/unicitylabs/sdk/functional/FunctionalCommonFlowTest.java @@ -3,9 +3,9 @@ import org.junit.jupiter.api.BeforeEach; import org.unicitylabs.sdk.StateTransitionClient; import org.unicitylabs.sdk.TestAggregatorClient; +import org.unicitylabs.sdk.bft.RootTrustBaseUtils; import org.unicitylabs.sdk.common.CommonTestFlow; import org.unicitylabs.sdk.signing.SigningService; -import org.unicitylabs.sdk.bft.RootTrustBaseUtils; public class FunctionalCommonFlowTest extends CommonTestFlow { diff --git a/src/test/java/org/unicitylabs/sdk/functional/FunctionalUnsignedPredicateDoubleSpendPreventionTest.java b/src/test/java/org/unicitylabs/sdk/functional/FunctionalUnsignedPredicateDoubleSpendPreventionTest.java index 3d2cee9..78439c6 100644 --- a/src/test/java/org/unicitylabs/sdk/functional/FunctionalUnsignedPredicateDoubleSpendPreventionTest.java +++ b/src/test/java/org/unicitylabs/sdk/functional/FunctionalUnsignedPredicateDoubleSpendPreventionTest.java @@ -10,8 +10,8 @@ import org.unicitylabs.sdk.StateTransitionClient; import org.unicitylabs.sdk.TestAggregatorClient; import org.unicitylabs.sdk.address.Address; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.hash.HashAlgorithm; import org.unicitylabs.sdk.mtree.BranchExistsException; @@ -50,8 +50,8 @@ private String[] transferToken(Token token, byte[] secret, Address address) t ) ); - SubmitCommitmentResponse response = this.client.submitCommitment(commitment).get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + CertificationResponse response = this.client.submitCommitment(commitment).get(); + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new RuntimeException("Failed to submit transfer commitment: " + response); } diff --git a/src/test/java/org/unicitylabs/sdk/hash/DataHashTest.java b/src/test/java/org/unicitylabs/sdk/hash/DataHashTest.java index 2737000..31dd336 100644 --- a/src/test/java/org/unicitylabs/sdk/hash/DataHashTest.java +++ b/src/test/java/org/unicitylabs/sdk/hash/DataHashTest.java @@ -18,7 +18,7 @@ public void testInvalidDataHashArguments() { } @Test - public void testDataHashJsonSerialization() throws JsonProcessingException { + public void testDataHashJsonSerialization() { Assertions.assertEquals( "\"00000000000000000000000000000000000000000000000000000000000000000000\"", diff --git a/src/test/java/org/unicitylabs/sdk/mtree/CommonPathTest.java b/src/test/java/org/unicitylabs/sdk/mtree/CommonPathTest.java index 47134a9..6535860 100644 --- a/src/test/java/org/unicitylabs/sdk/mtree/CommonPathTest.java +++ b/src/test/java/org/unicitylabs/sdk/mtree/CommonPathTest.java @@ -8,7 +8,7 @@ public class CommonPathTest { @Test - public void shouldCalculateCommonPath() throws Exception { + public void shouldCalculateCommonPath() { Assertions.assertEquals(CommonPath.create( BigInteger.valueOf(0b11), BigInteger.valueOf(0b111101111) diff --git a/src/test/java/org/unicitylabs/sdk/mtree/plain/SparseMerkleTreePathFixture.java b/src/test/java/org/unicitylabs/sdk/mtree/plain/SparseMerkleTreePathFixture.java index 1b65309..6442cba 100644 --- a/src/test/java/org/unicitylabs/sdk/mtree/plain/SparseMerkleTreePathFixture.java +++ b/src/test/java/org/unicitylabs/sdk/mtree/plain/SparseMerkleTreePathFixture.java @@ -1,10 +1,8 @@ package org.unicitylabs.sdk.mtree.plain; import java.util.List; -import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.DataHasher; import org.unicitylabs.sdk.hash.HashAlgorithm; -import org.unicitylabs.sdk.util.BigIntegerConverter; public class SparseMerkleTreePathFixture { diff --git a/src/test/java/org/unicitylabs/sdk/token/TokenIdTest.java b/src/test/java/org/unicitylabs/sdk/token/TokenIdTest.java index 9335be6..961759a 100644 --- a/src/test/java/org/unicitylabs/sdk/token/TokenIdTest.java +++ b/src/test/java/org/unicitylabs/sdk/token/TokenIdTest.java @@ -1,6 +1,8 @@ package org.unicitylabs.sdk.token; +import java.math.BigInteger; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class TokenIdTest { @@ -8,7 +10,9 @@ class TokenIdTest { @Test void toBigInt() { TokenId tokenId = new TokenId(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}); -// BigInteger expected = new BigInteger(1, tokenId.toCBOR()); -// assertEquals(expected, tokenId.toBigInt()); + Assertions.assertEquals( + new BigInteger("116247956593636886635080929986192315456660021052790183176621769190627866451744"), + tokenId.toBitString().toBigInteger() + ); } } diff --git a/src/test/java/org/unicitylabs/sdk/token/TokenSplitBuilderTest.java b/src/test/java/org/unicitylabs/sdk/token/TokenSplitBuilderTest.java index 19e81d6..b698f35 100644 --- a/src/test/java/org/unicitylabs/sdk/token/TokenSplitBuilderTest.java +++ b/src/test/java/org/unicitylabs/sdk/token/TokenSplitBuilderTest.java @@ -27,7 +27,7 @@ public class TokenSplitBuilderTest { - private Token createToken(TokenCoinData coinData) throws VerificationException { + private Token createToken(TokenCoinData coinData) { SigningService signingService = new SigningService(SigningService.generatePrivateKey()); UnicityCertificate unicityCertificate = UnicityCertificateUtils.generateCertificate( signingService, DataHash.fromImprint(new byte[34])); @@ -60,7 +60,6 @@ private Token createToken(TokenCoinData coinData) throws VerificationExceptio InclusionProofFixture.create( SparseMerkleTreePathFixture.create(), null, - null, unicityCertificate ) ), @@ -71,7 +70,7 @@ private Token createToken(TokenCoinData coinData) throws VerificationExceptio @Test public void testTokenSplitIntoMultipleTokens() - throws LeafOutOfBoundsException, BranchExistsException, VerificationException, IOException { + throws LeafOutOfBoundsException, BranchExistsException { Token token = this.createToken( new TokenCoinData( Map.of( @@ -145,7 +144,7 @@ public void testTokenSplitIntoMultipleTokens() } @Test - public void testTokenSplitUnknownSplitCoin() throws VerificationException, IOException { + public void testTokenSplitUnknownSplitCoin() { Token token = this.createToken(null); Predicate predicate = new MaskedPredicate( diff --git a/src/test/java/org/unicitylabs/sdk/token/TokenTest.java b/src/test/java/org/unicitylabs/sdk/token/TokenTest.java index f0fe1d1..4de056b 100644 --- a/src/test/java/org/unicitylabs/sdk/token/TokenTest.java +++ b/src/test/java/org/unicitylabs/sdk/token/TokenTest.java @@ -27,7 +27,7 @@ public class TokenTest { @Test - public void testJsonSerialization() throws IOException, VerificationException { + public void testJsonSerialization() throws IOException { SigningService signingService = new SigningService(SigningService.generatePrivateKey()); UnicityCertificate unicityCertificate = UnicityCertificateUtils.generateCertificate( signingService, DataHash.fromImprint(new byte[34])); @@ -71,7 +71,6 @@ public void testJsonSerialization() throws IOException, VerificationException { InclusionProofFixture.create( SparseMerkleTreePathFixture.create(), null, - null, unicityCertificate ) ), @@ -97,7 +96,6 @@ public void testJsonSerialization() throws IOException, VerificationException { InclusionProofFixture.create( SparseMerkleTreePathFixture.create(), null, - null, unicityCertificate ) ), diff --git a/src/test/java/org/unicitylabs/sdk/transaction/InclusionProofFixture.java b/src/test/java/org/unicitylabs/sdk/transaction/InclusionProofFixture.java index 51bddf1..b06d679 100644 --- a/src/test/java/org/unicitylabs/sdk/transaction/InclusionProofFixture.java +++ b/src/test/java/org/unicitylabs/sdk/transaction/InclusionProofFixture.java @@ -1,17 +1,15 @@ package org.unicitylabs.sdk.transaction; -import org.unicitylabs.sdk.api.Authenticator; +import org.unicitylabs.sdk.api.CertificationData; import org.unicitylabs.sdk.bft.UnicityCertificate; -import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.mtree.plain.SparseMerkleTreePath; public class InclusionProofFixture { public static InclusionProof create( SparseMerkleTreePath path, - Authenticator authenticator, - DataHash transactionHash, + CertificationData certificationData, UnicityCertificate certificate ) { - return new InclusionProof(path, authenticator, transactionHash, certificate); + return new InclusionProof(path, certificationData, certificate); } } diff --git a/src/test/java/org/unicitylabs/sdk/transaction/InclusionProofTest.java b/src/test/java/org/unicitylabs/sdk/transaction/InclusionProofTest.java index 031de46..f50da77 100644 --- a/src/test/java/org/unicitylabs/sdk/transaction/InclusionProofTest.java +++ b/src/test/java/org/unicitylabs/sdk/transaction/InclusionProofTest.java @@ -4,9 +4,8 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; -import org.unicitylabs.sdk.api.Authenticator; -import org.unicitylabs.sdk.api.LeafValue; -import org.unicitylabs.sdk.api.RequestId; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.bft.RootTrustBaseUtils; import org.unicitylabs.sdk.bft.UnicityCertificate; @@ -15,16 +14,16 @@ import org.unicitylabs.sdk.hash.HashAlgorithm; import org.unicitylabs.sdk.mtree.plain.SparseMerkleTree; import org.unicitylabs.sdk.mtree.plain.SparseMerkleTreePath; +import org.unicitylabs.sdk.serializer.cbor.CborSerializer; import org.unicitylabs.sdk.signing.SigningService; import org.unicitylabs.sdk.util.HexConverter; @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class InclusionProofTest { - RequestId requestId; - DataHash transactionHash; + StateId stateId; SparseMerkleTreePath merkleTreePath; - Authenticator authenticator; + CertificationData certificationData; RootTrustBase trustBase; UnicityCertificate unicityCertificate; @@ -33,17 +32,18 @@ public void createMerkleTreePath() throws Exception { SigningService signingService = new SigningService( HexConverter.decode("0000000000000000000000000000000000000000000000000000000000000001")); - transactionHash = new DataHash(HashAlgorithm.SHA256, new byte[32]); - authenticator = Authenticator.create(signingService, transactionHash, - new DataHash(HashAlgorithm.SHA256, new byte[32])); + certificationData = CertificationData.create( + new DataHash(HashAlgorithm.SHA256, new byte[32]), + new DataHash(HashAlgorithm.SHA256, new byte[32]), + signingService + ); - LeafValue leaf = LeafValue.create(authenticator, transactionHash); - requestId = RequestId.create(signingService.getPublicKey(), authenticator.getStateHash()); + stateId = StateId.create(signingService.getPublicKey(), certificationData.getSourceStateHash()); SparseMerkleTree smt = new SparseMerkleTree(HashAlgorithm.SHA256); - smt.addLeaf(requestId.toBitString().toBigInteger(), leaf.getBytes()); + smt.addLeaf(stateId.toBitString().toBigInteger(), certificationData.calculateLeafValue().getImprint()); - merkleTreePath = smt.calculateRoot().getPath(requestId.toBitString().toBigInteger()); + merkleTreePath = smt.calculateRoot().getPath(stateId.toBitString().toBigInteger()); SigningService ucSigningService = new SigningService(SigningService.generatePrivateKey()); trustBase = RootTrustBaseUtils.generateRootTrustBase(ucSigningService.getPublicKey()); unicityCertificate = UnicityCertificateUtils.generateCertificate(ucSigningService, @@ -51,64 +51,54 @@ public void createMerkleTreePath() throws Exception { } @Test - public void testJsonSerialization() throws Exception { + public void testJsonSerialization() { InclusionProof inclusionProof = new InclusionProof( merkleTreePath, - authenticator, - transactionHash, + certificationData, unicityCertificate ); Assertions.assertEquals(inclusionProof, InclusionProof.fromJson(inclusionProof.toJson())); } @Test - public void testStructure() { - Assertions.assertThrows(IllegalArgumentException.class, - () -> new InclusionProof( - merkleTreePath, - authenticator, - null, - unicityCertificate - ) - ); - Assertions.assertThrows(IllegalArgumentException.class, - () -> new InclusionProof( - merkleTreePath, - null, - transactionHash, - unicityCertificate - ) + public void testCborSerialization() { + InclusionProof inclusionProof = new InclusionProof( + merkleTreePath, + certificationData, + unicityCertificate ); + + Assertions.assertEquals(inclusionProof, InclusionProof.fromCbor(inclusionProof.toCbor())); + } + + @Test + public void testStructure() { Assertions.assertThrows(NullPointerException.class, () -> new InclusionProof( null, - authenticator, - transactionHash, - unicityCertificate + this.certificationData, + this.unicityCertificate ) ); Assertions.assertThrows(NullPointerException.class, () -> new InclusionProof( - merkleTreePath, - authenticator, - transactionHash, + this.merkleTreePath, + this.certificationData, null ) ); Assertions.assertInstanceOf(InclusionProof.class, new InclusionProof( - merkleTreePath, - authenticator, - transactionHash, - unicityCertificate + this.merkleTreePath, + this.certificationData, + this.unicityCertificate ) ); Assertions.assertInstanceOf(InclusionProof.class, new InclusionProof( - merkleTreePath, - null, + this.merkleTreePath, null, - unicityCertificate + this.unicityCertificate ) ); } @@ -117,34 +107,60 @@ public void testStructure() { public void testItVerifies() { InclusionProof inclusionProof = new InclusionProof( this.merkleTreePath, - this.authenticator, - this.transactionHash, + this.certificationData, this.unicityCertificate ); Assertions.assertEquals( InclusionProofVerificationStatus.OK, - inclusionProof.verify(this.requestId, this.trustBase) + inclusionProof.verify(this.trustBase, this.stateId) ); Assertions.assertEquals(InclusionProofVerificationStatus.PATH_NOT_INCLUDED, inclusionProof.verify( - RequestId.create(new byte[32], new DataHash(HashAlgorithm.SHA256, new byte[32])), - this.trustBase + this.trustBase, + StateId.create(new byte[32], new DataHash(HashAlgorithm.SHA256, new byte[32])) ) ); + } + @Test + public void testItNotAuthenticated() { InclusionProof invalidInclusionProof = new InclusionProof( this.merkleTreePath, - this.authenticator, - new DataHash( - HashAlgorithm.SHA224, - HexConverter.decode("FF000000000000000000000000000000000000000000000000000000000000FF") + CertificationData.fromCbor( + CborSerializer.encodeArray( + CborSerializer.encodeByteString(certificationData.getPublicKey()), + certificationData.getSourceStateHash().toCbor(), + DataHash.fromImprint( + HexConverter.decode("00000000000000000000000000000000000000000000000000000000000000000001")) + .toCbor(), + certificationData.getSignature().toCbor() + ) ), this.unicityCertificate ); Assertions.assertEquals( InclusionProofVerificationStatus.NOT_AUTHENTICATED, - invalidInclusionProof.verify(this.requestId, this.trustBase) + invalidInclusionProof.verify(this.trustBase, this.stateId) + ); + } + + @Test + public void testVerificationFailsWithInvalidTrustbase() { + InclusionProof inclusionProof = new InclusionProof( + this.merkleTreePath, + this.certificationData, + this.unicityCertificate + ); + + Assertions.assertEquals( + InclusionProofVerificationStatus.INVALID_TRUST_BASE, + inclusionProof.verify( + RootTrustBaseUtils.generateRootTrustBase( + HexConverter.decode("020000000000000000000000000000000000000000000000000000000000000001") + ), + this.stateId + ) ); } } diff --git a/src/test/java/org/unicitylabs/sdk/transaction/MintTransactionFixture.java b/src/test/java/org/unicitylabs/sdk/transaction/MintTransactionFixture.java index d0cdfe2..5f85623 100644 --- a/src/test/java/org/unicitylabs/sdk/transaction/MintTransactionFixture.java +++ b/src/test/java/org/unicitylabs/sdk/transaction/MintTransactionFixture.java @@ -1,10 +1,5 @@ package org.unicitylabs.sdk.transaction; -import org.unicitylabs.sdk.api.Authenticator; -import org.unicitylabs.sdk.bft.UnicityCertificate; -import org.unicitylabs.sdk.hash.DataHash; -import org.unicitylabs.sdk.mtree.plain.SparseMerkleTreePath; - public class MintTransactionFixture { public static MintTransaction create( MintTransaction.Data data, diff --git a/src/test/java/org/unicitylabs/sdk/utils/TestUtils.java b/src/test/java/org/unicitylabs/sdk/utils/TestUtils.java index bc35e1f..c6c7173 100644 --- a/src/test/java/org/unicitylabs/sdk/utils/TestUtils.java +++ b/src/test/java/org/unicitylabs/sdk/utils/TestUtils.java @@ -5,13 +5,12 @@ import java.security.SecureRandom; import java.util.List; import java.util.Map; - import org.unicitylabs.sdk.StateTransitionClient; import org.unicitylabs.sdk.address.Address; -import org.unicitylabs.sdk.api.Authenticator; -import org.unicitylabs.sdk.api.RequestId; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; +import org.unicitylabs.sdk.api.CertificationData; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.DataHasher; @@ -25,7 +24,11 @@ import org.unicitylabs.sdk.token.TokenType; import org.unicitylabs.sdk.token.fungible.CoinId; import org.unicitylabs.sdk.token.fungible.TokenCoinData; -import org.unicitylabs.sdk.transaction.*; +import org.unicitylabs.sdk.transaction.InclusionProof; +import org.unicitylabs.sdk.transaction.MintCommitment; +import org.unicitylabs.sdk.transaction.MintTransaction; +import org.unicitylabs.sdk.transaction.TransferCommitment; +import org.unicitylabs.sdk.transaction.TransferTransaction; import org.unicitylabs.sdk.util.InclusionProofUtils; /** @@ -68,7 +71,7 @@ public static TokenCoinData randomCoinData(int numCoins) { /** * Creates a token mint commitment and submits it to the client */ - public static Token mintTokenForUser( + public static Token mintTokenForUser( StateTransitionClient client, SigningService signingService, byte[] nonce, @@ -95,8 +98,8 @@ public static Token mintTokenForUser( ) ); - SubmitCommitmentResponse response = client.submitCommitment(mintCommitment).get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + CertificationResponse response = client.submitCommitment(mintCommitment).get(); + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new Exception("Failed to submit mint commitment: " + response.getStatus()); } @@ -116,9 +119,9 @@ public static Token mintTokenForUser( /** * Transfers a token from one user to another */ - public static Token transferToken( + public static Token transferToken( StateTransitionClient client, - Token sourceToken, + Token sourceToken, SigningService fromSigningService, SigningService toSigningService, byte[] toNonce, @@ -144,8 +147,8 @@ public static Token transferToken( fromSigningService ); - SubmitCommitmentResponse response = client.submitCommitment(transferCommitment).get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + CertificationResponse response = client.submitCommitment(transferCommitment).get(); + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new Exception("Failed to submit transfer commitment: " + response.getStatus()); } @@ -235,19 +238,19 @@ public static void setupUser(String userName, /** * Validates that a token is properly owned by a signing service */ - public static boolean validateTokenOwnership(Token token, SigningService signingService, RootTrustBase trustBase) { + public static boolean validateTokenOwnership(Token token, SigningService signingService, RootTrustBase trustBase) { if (!token.verify(trustBase).isSuccessful()) { return false; } return PredicateEngineService.createPredicate(token.getState().getPredicate()).isOwner(signingService.getPublicKey()); } - public static RequestId createRequestId(SigningService signingService, DataHash stateHash) { - return RequestId.create(signingService.getPublicKey(), stateHash); + public static StateId createStateId(SigningService signingService, DataHash stateHash) { + return StateId.create(signingService.getPublicKey(), stateHash); } - public static Authenticator createAuthenticator(SigningService signingService, DataHash txDataHash, DataHash stateHash) { - return Authenticator.create(signingService, txDataHash, stateHash); + public static CertificationData createCertificationData(SigningService signingService, DataHash txDataHash, DataHash stateHash) { + return CertificationData.create(stateHash, txDataHash, signingService); } /** @@ -299,17 +302,17 @@ public static void validateSuccessRate(long successful, long total, double minSu public static class TokenOperationResult { private final boolean success; private final String message; - private final Token token; + private final Token token; private final Exception error; - public TokenOperationResult(boolean success, String message, Token token, Exception error) { + public TokenOperationResult(boolean success, String message, Token token, Exception error) { this.success = success; this.message = message; this.token = token; this.error = error; } - public static TokenOperationResult success(String message, Token token) { + public static TokenOperationResult success(String message, Token token) { return new TokenOperationResult(true, message, token, null); } @@ -319,7 +322,7 @@ public static TokenOperationResult failure(String message, Exception error) { public boolean isSuccess() { return success; } public String getMessage() { return message; } - public Token getToken() { return token; } + public Token getToken() { return token; } public Exception getError() { return error; } } diff --git a/src/test/java/org/unicitylabs/sdk/utils/TokenUtils.java b/src/test/java/org/unicitylabs/sdk/utils/TokenUtils.java index 6ccff5d..38b17ab 100644 --- a/src/test/java/org/unicitylabs/sdk/utils/TokenUtils.java +++ b/src/test/java/org/unicitylabs/sdk/utils/TokenUtils.java @@ -5,8 +5,8 @@ import org.unicitylabs.sdk.StateTransitionClient; import org.unicitylabs.sdk.address.Address; -import org.unicitylabs.sdk.api.SubmitCommitmentResponse; -import org.unicitylabs.sdk.api.SubmitCommitmentStatus; +import org.unicitylabs.sdk.api.CertificationResponse; +import org.unicitylabs.sdk.api.CertificationStatus; import org.unicitylabs.sdk.bft.RootTrustBase; import org.unicitylabs.sdk.hash.DataHash; import org.unicitylabs.sdk.hash.HashAlgorithm; @@ -83,10 +83,10 @@ public static Token mintToken( ); // Submit mint transaction using StateTransitionClient - SubmitCommitmentResponse response = client + CertificationResponse response = client .submitCommitment(commitment) .get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new Exception(String.format("Failed to submit mint commitment: %s", response.getStatus())); } @@ -154,10 +154,10 @@ public static Token mintNametagToken( ); // Submit mint transaction using StateTransitionClient - SubmitCommitmentResponse response = client + CertificationResponse response = client .submitCommitment(commitment) .get(); - if (response.getStatus() != SubmitCommitmentStatus.SUCCESS) { + if (response.getStatus() != CertificationStatus.SUCCESS) { throw new Exception(String.format("Failed to submit mint commitment: %s", response.getStatus())); } diff --git a/src/test/java/org/unicitylabs/sdk/utils/helpers/CommitmentResult.java b/src/test/java/org/unicitylabs/sdk/utils/helpers/CommitmentResult.java index 345f56d..b5dd28e 100644 --- a/src/test/java/org/unicitylabs/sdk/utils/helpers/CommitmentResult.java +++ b/src/test/java/org/unicitylabs/sdk/utils/helpers/CommitmentResult.java @@ -1,12 +1,12 @@ package org.unicitylabs.sdk.utils.helpers; -import org.unicitylabs.sdk.api.RequestId; +import org.unicitylabs.sdk.api.StateId; import org.unicitylabs.sdk.transaction.InclusionProofVerificationStatus; public class CommitmentResult { private final String userName; private final String threadName; - private final RequestId requestId; + private final StateId stateId; private final boolean success; private final long startTime; private final long endTime; @@ -16,11 +16,11 @@ public class CommitmentResult { private long inclusionEnd; private String status; - public CommitmentResult(String userName, String threadName, RequestId requestId, + public CommitmentResult(String userName, String threadName, StateId stateId, boolean success, long startTime, long endTime) { this.userName = userName; this.threadName = threadName; - this.requestId = requestId; + this.stateId = stateId; this.success = success; this.startTime = startTime; this.endTime = endTime; @@ -35,8 +35,8 @@ public void markVerified(long start, long end) { this.status = InclusionProofVerificationStatus.OK.toString(); } - public RequestId getRequestId() { - return this.requestId; + public StateId getStateId() { + return this.stateId; } public void markFailedVerification(long start, long end, String status) {