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
50 changes: 30 additions & 20 deletions src/main/java/org/unicitylabs/sdk/StateTransitionClient.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@

package org.unicitylabs.sdk;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import org.unicitylabs.sdk.api.IAggregatorClient;
import org.unicitylabs.sdk.api.InclusionProofResponse;
import org.unicitylabs.sdk.api.RequestId;
import org.unicitylabs.sdk.api.SubmitCommitmentResponse;
import org.unicitylabs.sdk.bft.RootTrustBase;
import org.unicitylabs.sdk.predicate.PredicateEngineService;
import org.unicitylabs.sdk.token.Token;
import org.unicitylabs.sdk.token.TokenState;
import org.unicitylabs.sdk.verification.VerificationException;
import org.unicitylabs.sdk.transaction.Commitment;
import org.unicitylabs.sdk.transaction.InclusionProof;
import org.unicitylabs.sdk.transaction.InclusionProofVerificationStatus;
import org.unicitylabs.sdk.transaction.MintCommitment;
import org.unicitylabs.sdk.transaction.MintTransactionData;
import org.unicitylabs.sdk.transaction.Transaction;
import org.unicitylabs.sdk.transaction.TransferCommitment;
import org.unicitylabs.sdk.transaction.TransferTransactionData;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

public class StateTransitionClient {

Expand All @@ -27,7 +30,8 @@ public StateTransitionClient(IAggregatorClient client) {
}

public <T extends MintTransactionData<?>> CompletableFuture<SubmitCommitmentResponse> submitCommitment(
MintCommitment<T> commitment) {
MintCommitment<T> commitment
) {
return this.client.submitCommitment(
commitment.getRequestId(),
commitment.getTransactionData().calculateHash(),
Expand All @@ -36,47 +40,53 @@ public <T extends MintTransactionData<?>> CompletableFuture<SubmitCommitmentResp
}

public CompletableFuture<SubmitCommitmentResponse> submitCommitment(
Token<?> token,
TransferCommitment commitment) {
if (!commitment.getTransactionData().getSourceState().getUnlockPredicate()
.isOwner(commitment.getAuthenticator().getPublicKey())) {
TransferCommitment commitment
) {
if (
!PredicateEngineService.createPredicate(
commitment.getTransactionData().getSourceState().getPredicate()
).isOwner(commitment.getAuthenticator().getPublicKey())
) {
throw new IllegalArgumentException(
"Ownership verification failed: Authenticator does not match source state predicate.");
}

return this.client.submitCommitment(commitment.getRequestId(), commitment.getTransactionData()
.calculateHash(token.getId(), token.getType()), commitment.getAuthenticator());
.calculateHash(), commitment.getAuthenticator());
}

public <T extends MintTransactionData<?>> Token<T> finalizeTransaction(
RootTrustBase trustBase,
Token<T> token,
TokenState state,
Transaction<TransferTransactionData> transaction
) {
return this.finalizeTransaction(token, state, transaction, List.of());
) throws VerificationException {
return this.finalizeTransaction(trustBase, token, state, transaction, List.of());
}

public <T extends MintTransactionData<?>> Token<T> finalizeTransaction(
RootTrustBase trustBase,
Token<T> token,
TokenState state,
Transaction<TransferTransactionData> transaction,
List<Token<?>> nametagTokens
) {
List<Token<?>> nametags
) throws VerificationException {
Objects.requireNonNull(token, "Token is null");

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

public CompletableFuture<InclusionProofVerificationStatus> getTokenStatus(
Token<? extends MintTransactionData<?>> token,
byte[] publicKey) {
RequestId requestId = RequestId.create(publicKey,
token.getState().calculateHash(token.getId(), token.getType()));
byte[] publicKey,
RootTrustBase trustBase
) {
RequestId requestId = RequestId.create(publicKey, token.getState().calculateHash());
return this.client.getInclusionProof(requestId)
.thenApply(inclusionProof -> inclusionProof.verify(requestId));
.thenApply(response -> response.getInclusionProof().verify(requestId, trustBase));
}

public CompletableFuture<InclusionProof> getInclusionProof(Commitment<?> commitment) {
public CompletableFuture<InclusionProofResponse> getInclusionProof(Commitment<?> commitment) {
return this.client.getInclusionProof(commitment.getRequestId());
}
}
9 changes: 4 additions & 5 deletions src/main/java/org/unicitylabs/sdk/api/AggregatorClient.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package org.unicitylabs.sdk.api;

import org.unicitylabs.sdk.hash.DataHash;
import org.unicitylabs.sdk.jsonrpc.JsonRpcHttpTransport;
import org.unicitylabs.sdk.transaction.InclusionProof;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import org.unicitylabs.sdk.hash.DataHash;
import org.unicitylabs.sdk.jsonrpc.JsonRpcHttpTransport;

public class AggregatorClient implements IAggregatorClient {

Expand All @@ -24,10 +23,10 @@ public CompletableFuture<SubmitCommitmentResponse> submitCommitment(
return this.transport.request("submit_commitment", request, SubmitCommitmentResponse.class);
}

public CompletableFuture<InclusionProof> getInclusionProof(RequestId requestId) {
public CompletableFuture<InclusionProofResponse> getInclusionProof(RequestId requestId) {
InclusionProofRequest request = new InclusionProofRequest(requestId);

return this.transport.request("get_inclusion_proof", request, InclusionProof.class);
return this.transport.request("get_inclusion_proof", request, InclusionProofResponse.class);
}

public CompletableFuture<Long> getBlockHeight() {
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/org/unicitylabs/sdk/api/IAggregatorClient.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@

package org.unicitylabs.sdk.api;

import org.unicitylabs.sdk.hash.DataHash;
import org.unicitylabs.sdk.transaction.InclusionProof;

import java.util.concurrent.CompletableFuture;
import org.unicitylabs.sdk.hash.DataHash;

public interface IAggregatorClient {

Expand All @@ -13,7 +11,7 @@ CompletableFuture<SubmitCommitmentResponse> submitCommitment(
DataHash transactionHash,
Authenticator authenticator);

CompletableFuture<InclusionProof> getInclusionProof(RequestId requestId);
CompletableFuture<InclusionProofResponse> getInclusionProof(RequestId requestId);

CompletableFuture<Long> getBlockHeight();
}
16 changes: 16 additions & 0 deletions src/main/java/org/unicitylabs/sdk/api/InclusionProofResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.unicitylabs.sdk.api;

import org.unicitylabs.sdk.transaction.InclusionProof;

public class InclusionProofResponse {

private final InclusionProof inclusionProof;

public InclusionProofResponse(InclusionProof inclusionProof) {
this.inclusionProof = inclusionProof;
}

public InclusionProof getInclusionProof() {
return this.inclusionProof;
}
}
129 changes: 129 additions & 0 deletions src/main/java/org/unicitylabs/sdk/bft/InputRecord.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package org.unicitylabs.sdk.bft;

import java.util.Arrays;
import java.util.Objects;
import org.unicitylabs.sdk.util.HexConverter;

public class InputRecord {

private final int version;
private final long roundNumber;
private final long epoch;
private final byte[] previousHash;
private final byte[] hash;
private final byte[] summaryValue;
private final long timestamp;
private final byte[] blockHash;
private final long sumOfEarnedFees;
private final byte[] executedTransactionsHash;

public InputRecord(
int version,
long roundNumber,
long epoch,
byte[] previousHash,
byte[] hash,
byte[] summaryValue,
long timestamp,
byte[] blockHash,
long sumOfEarnedFees,
byte[] executedTransactionsHash
) {
Objects.requireNonNull(hash, "Hash cannot be null");
Objects.requireNonNull(summaryValue, "Summary value cannot be null");

this.version = version;
this.roundNumber = roundNumber;
this.epoch = epoch;
this.previousHash = previousHash;
this.hash = hash;
this.summaryValue = summaryValue;
this.timestamp = timestamp;
this.blockHash = blockHash;
this.sumOfEarnedFees = sumOfEarnedFees;
this.executedTransactionsHash = executedTransactionsHash;
}

public int getVersion() {
return this.version;
}

public long getRoundNumber() {
return this.roundNumber;
}

public long getEpoch() {
return this.epoch;
}

public byte[] getPreviousHash() {
return this.previousHash != null ? Arrays.copyOf(this.previousHash, this.previousHash.length) : null;
}

public byte[] getHash() {
return this.hash != null ? Arrays.copyOf(this.hash, this.hash.length) : null;
}

public byte[] getSummaryValue() {
return Arrays.copyOf(this.summaryValue, this.summaryValue.length);
}

public long getTimestamp() {
return this.timestamp;
}

public byte[] getBlockHash() {
return this.blockHash != null ? Arrays.copyOf(this.blockHash, this.blockHash.length) : null;
}

public long getSumOfEarnedFees() {
return this.sumOfEarnedFees;
}

public byte[] getExecutedTransactionsHash() {
return this.executedTransactionsHash != null ? Arrays.copyOf(this.executedTransactionsHash, this.executedTransactionsHash.length) : null;
}

@Override
public boolean equals(Object o) {
if (!(o instanceof InputRecord)) {
return false;
}
InputRecord that = (InputRecord) o;
return Objects.equals(this.version, that.version) && Objects.equals(this.roundNumber,
that.roundNumber) && Objects.equals(this.epoch, that.epoch)
&& Objects.deepEquals(this.previousHash, that.previousHash)
&& Objects.deepEquals(this.hash, that.hash) && Objects.deepEquals(this.summaryValue,
that.summaryValue) && Objects.equals(this.timestamp, that.timestamp)
&& Objects.deepEquals(this.blockHash, that.blockHash) && Objects.equals(
this.sumOfEarnedFees, that.sumOfEarnedFees) && Objects.deepEquals(
this.executedTransactionsHash, that.executedTransactionsHash);
}

@Override
public int hashCode() {
return Objects.hash(this.version, this.roundNumber, this.epoch,
Arrays.hashCode(this.previousHash),
Arrays.hashCode(this.hash), Arrays.hashCode(this.summaryValue), this.timestamp,
Arrays.hashCode(this.blockHash),
this.sumOfEarnedFees, Arrays.hashCode(this.executedTransactionsHash));
}

@Override
public String toString() {
return String.format("InputRecord{version=%s, roundNumber=%s, epoch=%s, previousHash=%s, "
+ "hash=%s, summaryValue=%s, timestamp=%s, blockHash=%s, sumOfEarnedFees=%s, "
+ "executedTransactionsHash=%s}",
this.version,
this.roundNumber,
this.epoch,
this.previousHash != null ? HexConverter.encode(this.previousHash) : null,
this.hash != null ? HexConverter.encode(this.hash) : null,
HexConverter.encode(this.summaryValue),
this.timestamp,
this.blockHash != null ? HexConverter.encode(this.blockHash) : null,
this.sumOfEarnedFees,
this.executedTransactionsHash != null ? HexConverter.encode(this.executedTransactionsHash) : null
);
}
}
Loading
Loading