Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 43 additions & 41 deletions src/main/java/org/unicitylabs/sdk/StateTransitionClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
import org.unicitylabs.sdk.predicate.PredicateEngineService;
import org.unicitylabs.sdk.signing.MintSigningService;
import org.unicitylabs.sdk.token.Token;
import org.unicitylabs.sdk.token.TokenId;
import org.unicitylabs.sdk.token.TokenState;
import org.unicitylabs.sdk.transaction.InclusionProofVerificationStatus;
import org.unicitylabs.sdk.transaction.MintCommitment;
import org.unicitylabs.sdk.transaction.MintTransaction;
import org.unicitylabs.sdk.transaction.MintTransactionReason;
import org.unicitylabs.sdk.transaction.MintTransactionState;
import org.unicitylabs.sdk.transaction.TransferCommitment;
import org.unicitylabs.sdk.transaction.TransferTransaction;
import org.unicitylabs.sdk.verification.VerificationException;
Expand Down Expand Up @@ -134,65 +136,65 @@ public CompletableFuture<InclusionProofResponse> getInclusionProof(RequestId req
}

/**
* Get inclusion proof for mint transaction.
* Check if state is already spent for given request id.
*
* @param transaction mint transaction.
* @return A CompletableFuture that resolves to the inclusion proof response from the aggregator.
* @param requestId request id
* @param trustBase root trust base
* @return A CompletableFuture that resolves to true if state is spent, false otherwise.
*/
public CompletableFuture<InclusionProofResponse> getInclusionProof(MintTransaction<?> transaction) {
return this.client.getInclusionProof(
RequestId.create(
MintSigningService.create(transaction.getData().getTokenId()).getPublicKey(),
transaction.getData().getSourceState()
)
);
public CompletableFuture<Boolean> isStateSpent(RequestId requestId, RootTrustBase trustBase) {
return this.getInclusionProof(requestId)
.thenApply(inclusionProof -> {
InclusionProofVerificationStatus result = inclusionProof.getInclusionProof().verify(requestId, trustBase);
switch (result) {
case OK:
return true;
case PATH_NOT_INCLUDED:
return false;
default:
throw new RuntimeException(
String.format("Inclusion proof verification failed with status %s", result)
);
}
});
}


/**
* Get inclusion proof for transfer transaction. This method does not check if transaction is owned by public key.
* Get inclusion proof for current token state.
*
* @param transaction transfer transaction.
* @param publicKey public key of transaction sender
* @param token token
* @param publicKey public key
* @param trustBase trustBase
* @return A CompletableFuture that resolves to the inclusion proof response from the aggregator.
*/
public CompletableFuture<InclusionProofResponse> getInclusionProof(
TransferTransaction transaction,
byte[] publicKey
public CompletableFuture<Boolean> isStateSpent(
Token<?> token,
byte[] publicKey,
RootTrustBase trustBase
) {
Predicate predicate = PredicateEngineService.createPredicate(transaction.getData().getSourceState().getPredicate());
Predicate predicate = PredicateEngineService.createPredicate(token.getState().getPredicate());
if (!predicate.isOwner(publicKey)) {
throw new IllegalArgumentException("Given key is not owner of the token.");
}

return this.client.getInclusionProof(
RequestId.create(
publicKey,
transaction.getData().getSourceState()
)
);
return this.isStateSpent(RequestId.create(publicKey, token.getState()), trustBase);
}

/**
* Get inclusion proof for current token state.
* Check if token id is already minted.
*
* @param token token.
* @param publicKey public key of transaction sender
* @return A CompletableFuture that resolves to the inclusion proof response from the aggregator.
* @param tokenId token id
* @param trustBase root trust base
* @return A CompletableFuture that resolves to true if token id is spent, false otherwise.
*/
public CompletableFuture<InclusionProofResponse> getInclusionProof(
Token<?> token,
byte[] publicKey
) {
Predicate predicate = PredicateEngineService.createPredicate(token.getState().getPredicate());
if (!predicate.isOwner(publicKey)) {
throw new IllegalArgumentException("Given key is not owner of the token.");
}

return this.client.getInclusionProof(
public CompletableFuture<Boolean> isMinted(TokenId tokenId, RootTrustBase trustBase) {
return this.isStateSpent(
RequestId.create(
publicKey,
token.getState()
)
MintSigningService.create(tokenId).getPublicKey(),
MintTransactionState.create(tokenId)
),
trustBase
);
}

Expand Down
28 changes: 2 additions & 26 deletions src/test/java/org/unicitylabs/sdk/common/CommonTestFlow.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,8 @@ public void testTransferFlow() throws Exception {
ALICE_SECRET
);

assertTrue(this.client.isMinted(aliceToken.getId(), this.trustBase).get());
assertTrue(aliceToken.verify(this.trustBase).isSuccessful());
assertEquals(
InclusionProofVerificationStatus.OK,
this.client.getInclusionProof(aliceToken.getGenesis())
.get()
.getInclusionProof()
.verify(
RequestId.create(
MintSigningService.create(aliceToken.getId()).getPublicKey(),
aliceToken.getGenesis().getData().getSourceState()
),
this.trustBase
)
);

String bobNameTag = UUID.randomUUID().toString();

Expand Down Expand Up @@ -127,19 +115,7 @@ public void testTransferFlow() throws Exception {
);

// Check if alice token is spent
assertEquals(
InclusionProofVerificationStatus.OK,
this.client.getInclusionProof(aliceToken, aliceSigningService.getPublicKey())
.get()
.getInclusionProof()
.verify(
RequestId.create(
aliceSigningService.getPublicKey(),
aliceToken.getState()
),
this.trustBase
)
);
assertTrue(this.client.isStateSpent(aliceToken, aliceSigningService.getPublicKey(), this.trustBase).get());

// Bob prepares to receive the token
DirectAddress bobAddress = UnmaskedPredicateReference.create(
Expand Down
Loading