From 36c60105cbe29b4bcc23219e9e4cce95291daf20 Mon Sep 17 00:00:00 2001 From: Martti Marran Date: Tue, 7 Jul 2026 20:17:33 +0000 Subject: [PATCH] Remove current version of nametag --- .../builtin/BuiltInPredicateType.java | 4 +- ...cityIdMintTransactionVerificationRule.java | 92 ------ .../CertifiedUnicityIdMintTransaction.java | 189 ------------ .../unicitylabs/sdk/unicityid/UnicityId.java | 127 -------- .../unicityid/UnicityIdMintTransaction.java | 280 ------------------ .../sdk/unicityid/UnicityIdToken.java | 150 ---------- .../sdk/common/CommonTestFlow.java | 69 ----- 7 files changed, 1 insertion(+), 910 deletions(-) delete mode 100644 src/main/java/org/unicitylabs/sdk/transaction/verification/CertifiedUnicityIdMintTransactionVerificationRule.java delete mode 100644 src/main/java/org/unicitylabs/sdk/unicityid/CertifiedUnicityIdMintTransaction.java delete mode 100644 src/main/java/org/unicitylabs/sdk/unicityid/UnicityId.java delete mode 100644 src/main/java/org/unicitylabs/sdk/unicityid/UnicityIdMintTransaction.java delete mode 100644 src/main/java/org/unicitylabs/sdk/unicityid/UnicityIdToken.java diff --git a/src/main/java/org/unicitylabs/sdk/predicate/builtin/BuiltInPredicateType.java b/src/main/java/org/unicitylabs/sdk/predicate/builtin/BuiltInPredicateType.java index ffb0222..13d9125 100644 --- a/src/main/java/org/unicitylabs/sdk/predicate/builtin/BuiltInPredicateType.java +++ b/src/main/java/org/unicitylabs/sdk/predicate/builtin/BuiltInPredicateType.java @@ -7,9 +7,7 @@ public enum BuiltInPredicateType { /** Predicate that locks state to a public key. */ SIGNATURE(0x01), /** Predicate that marks state as unspendable (burned). */ - BURN(0x02), - /** Predicate that references a Unicity identifier. */ - UNICITY_ID(0x100); + BURN(0x02); private final int id; diff --git a/src/main/java/org/unicitylabs/sdk/transaction/verification/CertifiedUnicityIdMintTransactionVerificationRule.java b/src/main/java/org/unicitylabs/sdk/transaction/verification/CertifiedUnicityIdMintTransactionVerificationRule.java deleted file mode 100644 index ac05ca2..0000000 --- a/src/main/java/org/unicitylabs/sdk/transaction/verification/CertifiedUnicityIdMintTransactionVerificationRule.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.unicitylabs.sdk.transaction.verification; - -import org.unicitylabs.sdk.predicate.EncodedPredicate; -import org.unicitylabs.sdk.predicate.builtin.SignaturePredicate; -import org.unicitylabs.sdk.unicityid.CertifiedUnicityIdMintTransaction; -import org.unicitylabs.sdk.util.verification.VerificationResult; -import org.unicitylabs.sdk.util.verification.VerificationStatus; - -import java.util.ArrayList; -import java.util.List; - -/** - * Verification rule for the genesis (mint) of a unicity id token. Validates the inclusion proof of - * the certified mint transaction, and optionally checks that the genesis lock script matches an - * expected issuer public key. - */ -public class CertifiedUnicityIdMintTransactionVerificationRule { - - private CertifiedUnicityIdMintTransactionVerificationRule() { - } - - /** - * Verify the certified unicity id mint transaction. - * - * @param genesis certified unicity id mint transaction to verify - * @param context shared verification context (trust base + registries) - * @param issuerPublicKey expected issuer public key, or {@code null} to skip the lock-script - * issuer check (e.g., when minting a fresh token where no external issuer is being asserted) - * - * @return verification result - */ - public static VerificationResult verify( - CertifiedUnicityIdMintTransaction genesis, - VerificationContext context, - byte[] issuerPublicKey - ) { - List> results = new ArrayList<>(); - - if (!genesis.getNetworkId().equals(context.getTrustBase().getNetworkId())) { - results.add(new VerificationResult<>("MintNetworkMatchesTrustBaseRule", - VerificationStatus.FAIL)); - return new VerificationResult<>( - "CertifiedUnicityIdMintTransactionVerificationRule", - VerificationStatus.FAIL, - "Mint network does not match trust base.", - results - ); - } - results.add(new VerificationResult<>("MintNetworkMatchesTrustBaseRule", - VerificationStatus.OK)); - - if (issuerPublicKey != null) { - EncodedPredicate expectedLockScript = EncodedPredicate.fromPredicate( - SignaturePredicate.create(issuerPublicKey)); - if (!expectedLockScript.equals(genesis.getLockScript())) { - results.add(new VerificationResult<>("IsLockScriptValidVerificationRule", - VerificationStatus.FAIL)); - return new VerificationResult<>( - "CertifiedUnicityIdMintTransactionVerificationRule", - VerificationStatus.FAIL, - "Lock script does not match expected unicity-id issuer.", - results - ); - } - results.add(new VerificationResult<>("IsLockScriptValidVerificationRule", - VerificationStatus.OK)); - } - - VerificationResult result = InclusionProofVerificationRule.verify( - context.getTrustBase(), - context.getPredicateVerifier(), - genesis.getInclusionProof(), - genesis - ); - results.add(result); - if (result.getStatus() != InclusionProofVerificationStatus.OK) { - return new VerificationResult<>( - "CertifiedUnicityIdMintTransactionVerificationRule", - VerificationStatus.FAIL, - String.format("Inclusion proof verification failed: %s", result.getStatus()), - results - ); - } - - return new VerificationResult<>( - "CertifiedUnicityIdMintTransactionVerificationRule", - VerificationStatus.OK, - "", - results - ); - } -} diff --git a/src/main/java/org/unicitylabs/sdk/unicityid/CertifiedUnicityIdMintTransaction.java b/src/main/java/org/unicitylabs/sdk/unicityid/CertifiedUnicityIdMintTransaction.java deleted file mode 100644 index 8c2c93d..0000000 --- a/src/main/java/org/unicitylabs/sdk/unicityid/CertifiedUnicityIdMintTransaction.java +++ /dev/null @@ -1,189 +0,0 @@ -package org.unicitylabs.sdk.unicityid; - -import org.unicitylabs.sdk.api.InclusionProof; -import org.unicitylabs.sdk.api.NetworkId; -import org.unicitylabs.sdk.api.bft.RootTrustBase; -import org.unicitylabs.sdk.crypto.hash.DataHash; -import org.unicitylabs.sdk.predicate.EncodedPredicate; -import org.unicitylabs.sdk.predicate.builtin.SignaturePredicate; -import org.unicitylabs.sdk.predicate.verification.PredicateVerifierService; -import org.unicitylabs.sdk.serializer.cbor.CborDeserializer; -import org.unicitylabs.sdk.serializer.cbor.CborSerializer; -import org.unicitylabs.sdk.transaction.StateMask; -import org.unicitylabs.sdk.transaction.TokenId; -import org.unicitylabs.sdk.transaction.TokenType; -import org.unicitylabs.sdk.transaction.Transaction; -import org.unicitylabs.sdk.transaction.verification.InclusionProofVerificationRule; -import org.unicitylabs.sdk.transaction.verification.InclusionProofVerificationStatus; -import org.unicitylabs.sdk.util.verification.VerificationException; -import org.unicitylabs.sdk.util.verification.VerificationResult; - -import java.util.List; -import java.util.Objects; -import java.util.Optional; - -/** - * Unicity id mint transaction bundled with a verified inclusion proof. - */ -public final class CertifiedUnicityIdMintTransaction implements Transaction { - - private final UnicityIdMintTransaction transaction; - private final InclusionProof inclusionProof; - - private CertifiedUnicityIdMintTransaction(UnicityIdMintTransaction transaction, - InclusionProof inclusionProof) { - this.transaction = transaction; - this.inclusionProof = inclusionProof; - } - - @Override - public Optional getData() { - return this.transaction.getData(); - } - - @Override - public EncodedPredicate getLockScript() { - return this.transaction.getLockScript(); - } - - @Override - public EncodedPredicate getRecipient() { - return this.transaction.getRecipient(); - } - - /** - * Returns the network identifier. - * - * @return network identifier - */ - public NetworkId getNetworkId() { - return this.transaction.getNetworkId(); - } - - @Override - public DataHash getSourceStateHash() { - return this.transaction.getSourceStateHash(); - } - - @Override - public StateMask getStateMask() { - return this.transaction.getStateMask(); - } - - /** - * Returns the token id derived from the unicity id. - * - * @return token id - */ - public TokenId getTokenId() { - return this.transaction.getTokenId(); - } - - /** - * Returns the token type. - * - * @return token type - */ - public TokenType getTokenType() { - return this.transaction.getTokenType(); - } - - /** - * Returns the target predicate. - * - * @return target predicate - */ - public SignaturePredicate getTargetPredicate() { - return this.transaction.getTargetPredicate(); - } - - /** - * Returns the unicity id. - * - * @return unicity id - */ - public UnicityId getUnicityId() { - return this.transaction.getUnicityId(); - } - - /** - * Returns the inclusion proof certifying this transaction. - * - * @return inclusion proof - */ - public InclusionProof getInclusionProof() { - return this.inclusionProof; - } - - /** - * Deserializes a certified unicity id mint transaction from CBOR. - * - * @param bytes CBOR-encoded certified mint transaction - * - * @return decoded certified mint transaction - */ - public static CertifiedUnicityIdMintTransaction fromCbor(byte[] bytes) { - List data = CborDeserializer.decodeArray(bytes, 2); - return new CertifiedUnicityIdMintTransaction( - UnicityIdMintTransaction.fromCbor(data.get(0)), - InclusionProof.fromCbor(data.get(1)) - ); - } - - /** - * Creates a certified unicity id mint transaction after verifying its inclusion proof. - * - * @param trustBase trust base used to verify inclusion proof signatures - * @param predicateVerifier predicate verifier service - * @param transaction unicity id mint transaction to certify - * @param inclusionProof inclusion proof for the transaction - * - * @return certified mint transaction - * - * @throws VerificationException if inclusion proof verification fails - */ - public static CertifiedUnicityIdMintTransaction fromTransaction( - RootTrustBase trustBase, - PredicateVerifierService predicateVerifier, - UnicityIdMintTransaction transaction, - InclusionProof inclusionProof - ) { - Objects.requireNonNull(trustBase, "trustBase cannot be null"); - Objects.requireNonNull(predicateVerifier, "predicateVerifier cannot be null"); - Objects.requireNonNull(transaction, "transaction cannot be null"); - Objects.requireNonNull(inclusionProof, "inclusionProof cannot be null"); - - VerificationResult result = InclusionProofVerificationRule.verify( - trustBase, - predicateVerifier, - inclusionProof, - transaction - ); - if (result.getStatus() != InclusionProofVerificationStatus.OK) { - throw new VerificationException("Inclusion proof verification failed", result); - } - - return new CertifiedUnicityIdMintTransaction(transaction, inclusionProof); - } - - @Override - public DataHash calculateStateHash() { - return this.transaction.calculateStateHash(); - } - - @Override - public DataHash calculateTransactionHash() { - return this.transaction.calculateTransactionHash(); - } - - @Override - public byte[] toCbor() { - return CborSerializer.encodeArray(this.transaction.toCbor(), this.inclusionProof.toCbor()); - } - - @Override - public String toString() { - return String.format("CertifiedUnicityIdMintTransaction{transaction=%s, inclusionProof=%s}", - this.transaction, this.inclusionProof); - } -} diff --git a/src/main/java/org/unicitylabs/sdk/unicityid/UnicityId.java b/src/main/java/org/unicitylabs/sdk/unicityid/UnicityId.java deleted file mode 100644 index d783e9b..0000000 --- a/src/main/java/org/unicitylabs/sdk/unicityid/UnicityId.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.unicitylabs.sdk.unicityid; - -import org.unicitylabs.sdk.crypto.hash.DataHash; -import org.unicitylabs.sdk.crypto.hash.DataHasher; -import org.unicitylabs.sdk.crypto.hash.HashAlgorithm; -import org.unicitylabs.sdk.serializer.cbor.CborDeserializer; -import org.unicitylabs.sdk.serializer.cbor.CborSerializer; -import org.unicitylabs.sdk.transaction.TokenSalt; - -import java.util.List; -import java.util.Objects; - -/** - * Human-readable identifier for a unicity token. The pair (domain, name) is hashed deterministically - * to derive the corresponding {@link TokenSalt}. - */ -public final class UnicityId { - - private final String name; - private final String domain; - - /** - * Create a unicity id with name only (no domain). - * - * @param name token name - */ - public UnicityId(String name) { - this(name, null); - } - - /** - * Create a unicity id. - * - * @param name token name - * @param domain optional domain; may be null - */ - public UnicityId(String name, String domain) { - this.name = Objects.requireNonNull(name, "name cannot be null"); - this.domain = domain; - } - - /** - * Get the token name. - * - * @return name - */ - public String getName() { - return this.name; - } - - /** - * Get the optional domain. - * - * @return domain, or null if not set - */ - public String getDomain() { - return this.domain; - } - - /** - * Deserialize a unicity id from CBOR bytes. - * - * @param bytes CBOR bytes - * - * @return unicity id - */ - public static UnicityId fromCbor(byte[] bytes) { - List data = CborDeserializer.decodeArray(bytes, 2); - return new UnicityId( - CborDeserializer.decodeTextString(data.get(0)), - CborDeserializer.decodeNullable(data.get(1), CborDeserializer::decodeTextString) - ); - } - - /** - * Serialize the unicity id to CBOR bytes. - * - * @return CBOR bytes - */ - public byte[] toCbor() { - return CborSerializer.encodeArray( - CborSerializer.encodeTextString(this.name), - CborSerializer.encodeNullable(this.domain, CborSerializer::encodeTextString) - ); - } - - /** - * Derive the token salt from this unicity id by hashing the tagged ("NAMETAG_", domain, name) - * tuple with SHA-256. - * - * @return derived token salt - */ - public TokenSalt toTokenSalt() { - DataHash hash = new DataHasher(HashAlgorithm.SHA256) - .update( - CborSerializer.encodeArray( - CborSerializer.encodeTextString("NAMETAG_"), - CborSerializer.encodeNullable(this.domain, CborSerializer::encodeTextString), - CborSerializer.encodeTextString(this.name) - ) - ) - .digest(); - return TokenSalt.fromBytes(hash.getData()); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof UnicityId)) { - return false; - } - UnicityId that = (UnicityId) o; - return this.name.equals(that.name) && Objects.equals(this.domain, that.domain); - } - - @Override - public int hashCode() { - return Objects.hash(this.name, this.domain); - } - - @Override - public String toString() { - return "@" + (this.domain != null ? this.domain + "/" : "") + this.name; - } -} diff --git a/src/main/java/org/unicitylabs/sdk/unicityid/UnicityIdMintTransaction.java b/src/main/java/org/unicitylabs/sdk/unicityid/UnicityIdMintTransaction.java deleted file mode 100644 index e3c3b46..0000000 --- a/src/main/java/org/unicitylabs/sdk/unicityid/UnicityIdMintTransaction.java +++ /dev/null @@ -1,280 +0,0 @@ -package org.unicitylabs.sdk.unicityid; - -import org.unicitylabs.sdk.api.InclusionProof; -import org.unicitylabs.sdk.api.NetworkId; -import org.unicitylabs.sdk.api.bft.RootTrustBase; -import org.unicitylabs.sdk.crypto.hash.DataHash; -import org.unicitylabs.sdk.crypto.hash.DataHasher; -import org.unicitylabs.sdk.crypto.hash.HashAlgorithm; -import org.unicitylabs.sdk.predicate.EncodedPredicate; -import org.unicitylabs.sdk.predicate.Predicate; -import org.unicitylabs.sdk.predicate.builtin.SignaturePredicate; -import org.unicitylabs.sdk.predicate.verification.PredicateVerifierService; -import org.unicitylabs.sdk.serializer.cbor.CborDeserializer; -import org.unicitylabs.sdk.serializer.cbor.CborSerializationException; -import org.unicitylabs.sdk.serializer.cbor.CborSerializer; -import org.unicitylabs.sdk.transaction.StateMask; -import org.unicitylabs.sdk.transaction.MintTransactionState; -import org.unicitylabs.sdk.transaction.TokenId; -import org.unicitylabs.sdk.transaction.TokenType; -import org.unicitylabs.sdk.transaction.Transaction; - -import java.util.List; -import java.util.Objects; -import java.util.Optional; - -/** - * Mint transaction that derives its token id from a {@link UnicityId}. The token's data field is - * the encoded target predicate. - */ -public final class UnicityIdMintTransaction implements Transaction { - public static final long CBOR_TAG = 39041; - private static final int VERSION = 1; - - private final MintTransactionState sourceStateHash; - private final EncodedPredicate lockScript; - private final NetworkId networkId; - private final EncodedPredicate recipient; - private final TokenId tokenId; - private final TokenType tokenType; - private final SignaturePredicate targetPredicate; - private final UnicityId unicityId; - - private UnicityIdMintTransaction( - MintTransactionState sourceStateHash, - EncodedPredicate lockScript, - NetworkId networkId, - EncodedPredicate recipient, - TokenId tokenId, - TokenType tokenType, - SignaturePredicate targetPredicate, - UnicityId unicityId - ) { - this.sourceStateHash = sourceStateHash; - this.lockScript = lockScript; - this.networkId = networkId; - this.recipient = recipient; - this.tokenId = tokenId; - this.tokenType = tokenType; - this.targetPredicate = targetPredicate; - this.unicityId = unicityId; - } - - /** - * Get the version number. - * - * @return version - */ - public int getVersion() { - return UnicityIdMintTransaction.VERSION; - } - - @Override - public MintTransactionState getSourceStateHash() { - return this.sourceStateHash; - } - - @Override - public EncodedPredicate getLockScript() { - return this.lockScript; - } - - @Override - public EncodedPredicate getRecipient() { - return this.recipient; - } - - /** - * Get the network identifier. - * - * @return network identifier - */ - public NetworkId getNetworkId() { - return this.networkId; - } - - /** - * Get the token id derived from the unicity id. - * - * @return token id - */ - public TokenId getTokenId() { - return this.tokenId; - } - - /** - * Get the token type. - * - * @return token type - */ - public TokenType getTokenType() { - return this.tokenType; - } - - /** - * Get the target predicate (the predicate the minted token is locked to). - * - * @return target predicate - */ - public SignaturePredicate getTargetPredicate() { - return this.targetPredicate; - } - - /** - * Get the unicity id. - * - * @return unicity id - */ - public UnicityId getUnicityId() { - return this.unicityId; - } - - @Override - public Optional getData() { - return Optional.of(EncodedPredicate.fromPredicate(this.targetPredicate).toCbor()); - } - - @Override - public StateMask getStateMask() { - return StateMask.fromBytes(this.tokenId.getBytes()); - } - - /** - * Create a unicity id mint transaction. The token id is derived from the unicity id; the lock - * script is supplied by the caller. - * - * @param networkId network identifier - * @param lockScript lock script predicate (the predicate that must be unlocked to spend this - * transaction) - * @param recipient recipient predicate - * @param unicityId unicity id producing the token id - * @param tokenType token type identifier - * @param targetPredicate target predicate the minted token will be locked to - * - * @return mint transaction - */ - public static UnicityIdMintTransaction create( - NetworkId networkId, - SignaturePredicate lockScript, - Predicate recipient, - UnicityId unicityId, - TokenType tokenType, - SignaturePredicate targetPredicate - ) { - Objects.requireNonNull(networkId, "Network ID must not be null"); - Objects.requireNonNull(lockScript, "lockScript cannot be null"); - Objects.requireNonNull(recipient, "recipient cannot be null"); - Objects.requireNonNull(unicityId, "unicityId cannot be null"); - Objects.requireNonNull(tokenType, "tokenType cannot be null"); - Objects.requireNonNull(targetPredicate, "targetPredicate cannot be null"); - - TokenId tokenId = TokenId.fromSalt(networkId, unicityId.toTokenSalt()); - - return new UnicityIdMintTransaction( - MintTransactionState.create(tokenId), - EncodedPredicate.fromPredicate(lockScript), - networkId, - EncodedPredicate.fromPredicate(recipient), - tokenId, - tokenType, - targetPredicate, - unicityId - ); - } - - /** - * Deserialize a unicity id mint transaction from CBOR bytes. - * - * @param bytes CBOR bytes - * - * @return mint transaction - * - * @throws CborSerializationException if the bytes do not carry the expected tag, version, or if - * the encoded token id does not match the unicity id - */ - public static UnicityIdMintTransaction fromCbor(byte[] bytes) { - CborDeserializer.CborTag tag = CborDeserializer.decodeTag(bytes); - if (tag.getTag() != UnicityIdMintTransaction.CBOR_TAG) { - throw new CborSerializationException(String.format("Invalid CBOR tag: %s", tag.getTag())); - } - List data = CborDeserializer.decodeArray(tag.getData(), 7); - - int version = CborDeserializer.decodeUnsignedInteger(data.get(0)).asInt(); - if (version != UnicityIdMintTransaction.VERSION) { - throw new CborSerializationException(String.format("Unsupported version: %s", version)); - } - - return UnicityIdMintTransaction.create( - NetworkId.fromId(CborDeserializer.decodeUnsignedInteger(data.get(1)).asShort()), - SignaturePredicate.fromPredicate( - EncodedPredicate.fromCbor(data.get(2)) - ), - EncodedPredicate.fromCbor(data.get(3)), - UnicityId.fromCbor(data.get(4)), - TokenType.fromCbor(data.get(5)), - SignaturePredicate.fromPredicate( - EncodedPredicate.fromCbor(data.get(6)) - ) - ); - } - - @Override - public DataHash calculateStateHash() { - return new DataHasher(HashAlgorithm.SHA256) - .update( - CborSerializer.encodeArray( - CborSerializer.encodeByteString(this.sourceStateHash.getImprint()), - this.getStateMask().toCbor() - ) - ) - .digest(); - } - - @Override - public DataHash calculateTransactionHash() { - return new DataHasher(HashAlgorithm.SHA256).update(this.toCbor()).digest(); - } - - @Override - public byte[] toCbor() { - return CborSerializer.encodeTag( - UnicityIdMintTransaction.CBOR_TAG, - CborSerializer.encodeArray( - CborSerializer.encodeUnsignedInteger(UnicityIdMintTransaction.VERSION), - CborSerializer.encodeUnsignedInteger(this.networkId.getId()), - this.lockScript.toCbor(), - this.recipient.toCbor(), - this.unicityId.toCbor(), - this.tokenType.toCbor(), - EncodedPredicate.fromPredicate(this.targetPredicate).toCbor() - ) - ); - } - - /** - * Build the certified version by attaching and verifying an inclusion proof. - * - * @param trustBase root trust base - * @param predicateVerifier predicate verifier - * @param inclusionProof inclusion proof - * - * @return certified mint transaction - */ - public CertifiedUnicityIdMintTransaction toCertifiedTransaction( - RootTrustBase trustBase, - PredicateVerifierService predicateVerifier, - InclusionProof inclusionProof - ) { - return CertifiedUnicityIdMintTransaction.fromTransaction(trustBase, predicateVerifier, this, - inclusionProof); - } - - @Override - public String toString() { - return String.format( - "UnicityIdMintTransaction{networkId=%s, lockScript=%s, recipient=%s, tokenId=%s, tokenType=%s, unicityId=%s, targetPredicate=%s}", - this.networkId, this.lockScript, this.recipient, this.tokenId, this.tokenType, - this.unicityId, this.targetPredicate - ); - } -} diff --git a/src/main/java/org/unicitylabs/sdk/unicityid/UnicityIdToken.java b/src/main/java/org/unicitylabs/sdk/unicityid/UnicityIdToken.java deleted file mode 100644 index 5196362..0000000 --- a/src/main/java/org/unicitylabs/sdk/unicityid/UnicityIdToken.java +++ /dev/null @@ -1,150 +0,0 @@ -package org.unicitylabs.sdk.unicityid; - -import org.unicitylabs.sdk.serializer.cbor.CborDeserializer; -import org.unicitylabs.sdk.serializer.cbor.CborSerializer; -import org.unicitylabs.sdk.transaction.TokenId; -import org.unicitylabs.sdk.transaction.TokenType; -import org.unicitylabs.sdk.transaction.verification.CertifiedUnicityIdMintTransactionVerificationRule; -import org.unicitylabs.sdk.transaction.verification.VerificationContext; -import org.unicitylabs.sdk.util.verification.VerificationException; -import org.unicitylabs.sdk.util.verification.VerificationResult; -import org.unicitylabs.sdk.util.verification.VerificationStatus; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * Token whose genesis is a {@link CertifiedUnicityIdMintTransaction}. The token's identifier is - * deterministically derived from a {@link UnicityId}. - */ -public final class UnicityIdToken { - - private final CertifiedUnicityIdMintTransaction genesis; - - private UnicityIdToken(CertifiedUnicityIdMintTransaction genesis) { - this.genesis = genesis; - } - - /** - * Returns the certified genesis mint transaction. - * - * @return genesis transaction - */ - public CertifiedUnicityIdMintTransaction getGenesis() { - return this.genesis; - } - - /** - * Returns the token id. - * - * @return token id - */ - public TokenId getId() { - return this.genesis.getTokenId(); - } - - /** - * Returns the token type. - * - * @return token type - */ - public TokenType getType() { - return this.genesis.getTokenType(); - } - - /** - * Returns the unicity id used to derive this token's identifier. - * - * @return unicity id - */ - public UnicityId getUnicityId() { - return this.genesis.getUnicityId(); - } - - /** - * Deserialize a unicity id token from CBOR bytes. - * - * @param bytes CBOR bytes - * - * @return decoded token - */ - public static UnicityIdToken fromCbor(byte[] bytes) { - List data = CborDeserializer.decodeArray(bytes, 1); - return new UnicityIdToken(CertifiedUnicityIdMintTransaction.fromCbor(data.get(0))); - } - - /** - * Build a unicity id token from a certified genesis transaction and verify it. - * - * @param genesis certified mint transaction - * @param context shared verification context (trust base + registries) - * - * @return verified token - * - * @throws VerificationException if genesis verification fails - */ - public static UnicityIdToken mint( - CertifiedUnicityIdMintTransaction genesis, - VerificationContext context - ) { - Objects.requireNonNull(genesis, "genesis cannot be null"); - Objects.requireNonNull(context, "context cannot be null"); - - VerificationResult result = - CertifiedUnicityIdMintTransactionVerificationRule.verify( - genesis, - context, - null - ); - if (result.getStatus() != VerificationStatus.OK) { - throw new VerificationException("Invalid token genesis", result); - } - - return new UnicityIdToken(genesis); - } - - /** - * Serialize this token to CBOR bytes. - * - * @return CBOR bytes - */ - public byte[] toCbor() { - return CborSerializer.encodeArray(this.genesis.toCbor()); - } - - /** - * Verify the token by validating its certified mint transaction against an expected issuer. - * - * @param context shared verification context (trust base + registries) - * @param issuerPublicKey expected issuer public key - * - * @return verification result - * @throws NullPointerException if {@code issuerPublicKey} is {@code null} - */ - public VerificationResult verify( - VerificationContext context, - byte[] issuerPublicKey - ) { - Objects.requireNonNull(context, "context cannot be null"); - Objects.requireNonNull(issuerPublicKey, "issuerPublicKey cannot be null"); - - List> results = new ArrayList<>(); - VerificationResult result = CertifiedUnicityIdMintTransactionVerificationRule.verify( - this.genesis, - context, - issuerPublicKey - ); - results.add(result); - if (result.getStatus() != VerificationStatus.OK) { - return new VerificationResult<>("TokenVerification", VerificationStatus.FAIL, "", results); - } - - return new VerificationResult<>("TokenVerification", VerificationStatus.OK, "", results); - } - - @Override - public String toString() { - return String.format("UnicityIdToken{genesis=%s}", this.genesis); - } -} diff --git a/src/test/java/org/unicitylabs/sdk/common/CommonTestFlow.java b/src/test/java/org/unicitylabs/sdk/common/CommonTestFlow.java index 74989a6..c7e7538 100644 --- a/src/test/java/org/unicitylabs/sdk/common/CommonTestFlow.java +++ b/src/test/java/org/unicitylabs/sdk/common/CommonTestFlow.java @@ -3,19 +3,10 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.unicitylabs.sdk.StateTransitionClient; -import org.unicitylabs.sdk.api.CertificationData; -import org.unicitylabs.sdk.api.CertificationResponse; -import org.unicitylabs.sdk.api.CertificationStatus; import org.unicitylabs.sdk.crypto.secp256k1.SigningService; import org.unicitylabs.sdk.predicate.builtin.SignaturePredicate; -import org.unicitylabs.sdk.predicate.builtin.SignaturePredicateUnlockScript; import org.unicitylabs.sdk.transaction.Token; -import org.unicitylabs.sdk.transaction.TokenType; import org.unicitylabs.sdk.transaction.verification.VerificationContext; -import org.unicitylabs.sdk.unicityid.UnicityId; -import org.unicitylabs.sdk.unicityid.UnicityIdMintTransaction; -import org.unicitylabs.sdk.unicityid.UnicityIdToken; -import org.unicitylabs.sdk.util.InclusionProofUtils; import org.unicitylabs.sdk.util.verification.VerificationStatus; import org.unicitylabs.sdk.utils.TokenUtils; @@ -62,64 +53,4 @@ public void testTransferFlow() throws Exception { Assertions.assertEquals(VerificationStatus.OK, carolToken.verify(this.context).getStatus()); } - - /** - * Default successful flow: mint a unicity-id token and then mint a regular token whose recipient - * is the unicity-id token's target predicate. - */ - @Test - public void testUnicityIdMintFlow() throws Exception { - SigningService unicityIdSigningService = SigningService.generate(); - SignaturePredicate targetPredicate = SignaturePredicate.create( - ALICE_SIGNING_SERVICE.getPublicKey()); - - UnicityId unicityId = new UnicityId("testuser", "unicity-labs/test"); - UnicityIdMintTransaction unicityIdMintTransaction = UnicityIdMintTransaction.create( - this.context.getTrustBase().getNetworkId(), - SignaturePredicate.fromSigningService(unicityIdSigningService), - targetPredicate, - unicityId, - TokenType.generate(), - targetPredicate - ); - - CertificationData unicityIdCertificationData = CertificationData.fromTransaction( - unicityIdMintTransaction, - SignaturePredicateUnlockScript.create(unicityIdMintTransaction, unicityIdSigningService) - ); - - CertificationResponse unicityIdResponse = this.client - .submitCertificationRequest(unicityIdCertificationData).get(); - Assertions.assertEquals(CertificationStatus.SUCCESS, unicityIdResponse.getStatus()); - - UnicityIdToken aliceUnicityIdToken = UnicityIdToken.mint( - unicityIdMintTransaction.toCertifiedTransaction( - this.context.getTrustBase(), - this.context.getPredicateVerifier(), - InclusionProofUtils.waitInclusionProof(this.client, - this.context.getTrustBase(), - this.context.getPredicateVerifier(), unicityIdMintTransaction).get() - ), - this.context - ); - - Assertions.assertEquals(VerificationStatus.OK, - aliceUnicityIdToken.verify(this.context, unicityIdSigningService.getPublicKey()).getStatus()); - - UnicityIdToken decodedUnicityIdToken = UnicityIdToken.fromCbor(aliceUnicityIdToken.toCbor()); - Assertions.assertArrayEquals(aliceUnicityIdToken.toCbor(), decodedUnicityIdToken.toCbor()); - Assertions.assertEquals(aliceUnicityIdToken.getId(), decodedUnicityIdToken.getId()); - Assertions.assertEquals(VerificationStatus.OK, - decodedUnicityIdToken.verify(this.context, unicityIdSigningService.getPublicKey()).getStatus()); - - Token aliceToken = TokenUtils.mintToken( - this.client, - this.context, - aliceUnicityIdToken.getGenesis().getTargetPredicate() - ); - - Assertions.assertEquals(VerificationStatus.OK, - aliceToken.verify(this.context) - .getStatus()); - } } \ No newline at end of file