Skip to content

Commit 6e6b59b

Browse files
committed
#73 add context to token verification instead of separate parameters
1 parent a502336 commit 6e6b59b

17 files changed

Lines changed: 498 additions & 224 deletions

src/main/java/org/unicitylabs/sdk/transaction/Token.java

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package org.unicitylabs.sdk.transaction;
22

3-
import org.unicitylabs.sdk.api.bft.RootTrustBase;
4-
import org.unicitylabs.sdk.predicate.verification.PredicateVerifierService;
53
import org.unicitylabs.sdk.serializer.cbor.CborDeserializer;
64
import org.unicitylabs.sdk.serializer.cbor.CborSerializationException;
75
import org.unicitylabs.sdk.serializer.cbor.CborSerializer;
86
import org.unicitylabs.sdk.transaction.verification.CertifiedMintTransactionVerificationRule;
97
import org.unicitylabs.sdk.transaction.verification.CertifiedTransferTransactionVerificationRule;
10-
import org.unicitylabs.sdk.transaction.verification.MintJustificationVerifierService;
8+
import org.unicitylabs.sdk.transaction.verification.VerificationContext;
119
import org.unicitylabs.sdk.util.verification.VerificationException;
1210
import org.unicitylabs.sdk.util.verification.VerificationResult;
1311
import org.unicitylabs.sdk.util.verification.VerificationStatus;
@@ -121,26 +119,20 @@ public static Token fromCbor(byte[] bytes) {
121119
/**
122120
* Creates a token from a certified genesis transaction and verifies it.
123121
*
124-
* @param trustBase trust base used for certification checks
125-
* @param predicateVerifier predicate verifier service
126-
* @param mintJustificationVerifier mint justification verifier service
127122
* @param genesis certified mint transaction
123+
* @param context shared verification context (trust base + registries)
128124
* @return verified token instance
129125
* @throws VerificationException if genesis verification fails
130126
*/
131127
public static Token mint(
132-
RootTrustBase trustBase,
133-
PredicateVerifierService predicateVerifier,
134-
MintJustificationVerifierService mintJustificationVerifier,
135-
CertifiedMintTransaction genesis
128+
CertifiedMintTransaction genesis,
129+
VerificationContext context
136130
) {
137-
Objects.requireNonNull(trustBase, "trustBase cannot be null");
138-
Objects.requireNonNull(predicateVerifier, "predicateVerifier cannot be null");
139-
Objects.requireNonNull(mintJustificationVerifier, "mintJustificationVerifier cannot be null");
140131
Objects.requireNonNull(genesis, "genesis cannot be null");
132+
Objects.requireNonNull(context, "context cannot be null");
141133

142134
Token token = new Token(genesis);
143-
VerificationResult<VerificationStatus> result = token.verify(trustBase, predicateVerifier, mintJustificationVerifier);
135+
VerificationResult<VerificationStatus> result = token.verify(context);
144136
if (result.getStatus() != VerificationStatus.OK) {
145137
throw new VerificationException("Invalid token genesis", result);
146138
}
@@ -151,25 +143,21 @@ public static Token mint(
151143
/**
152144
* Returns a new token instance with an additional verified transfer transaction.
153145
*
154-
* @param trustBase trust base used for certification checks
155-
* @param predicateVerifier predicate verifier service
156146
* @param transaction certified transfer transaction to append
147+
* @param context shared verification context (trust base + registries)
157148
* @return new token instance with appended transfer
158149
* @throws VerificationException if transfer verification fails
159150
*/
160151
public Token transfer(
161-
RootTrustBase trustBase,
162-
PredicateVerifierService predicateVerifier,
163-
CertifiedTransferTransaction transaction
152+
CertifiedTransferTransaction transaction,
153+
VerificationContext context
164154
) {
165-
Objects.requireNonNull(trustBase, "trustBase cannot be null");
166-
Objects.requireNonNull(predicateVerifier, "predicateVerifier cannot be null");
167155
Objects.requireNonNull(transaction, "transaction cannot be null");
156+
Objects.requireNonNull(context, "context cannot be null");
168157

169158
VerificationResult<VerificationStatus> result = CertifiedTransferTransactionVerificationRule.verify(
170-
trustBase,
171-
predicateVerifier,
172-
transaction
159+
transaction,
160+
context
173161
);
174162
if (result.getStatus() != VerificationStatus.OK) {
175163
throw new VerificationException("Invalid token transfer transaction", result);
@@ -187,19 +175,11 @@ public Token transfer(
187175
* verified iteratively with a worklist instead of recursion, so arbitrarily long provenance
188176
* chains do not grow the call stack.
189177
*
190-
* @param trustBase trust base used for certification checks
191-
* @param predicateVerifier predicate verifier service
192-
* @param mintJustificationVerifier mint justification verifier service
178+
* @param context shared verification context (trust base + registries)
193179
* @return verification result with a child result per verified token
194180
*/
195-
public VerificationResult<VerificationStatus> verify(
196-
RootTrustBase trustBase,
197-
PredicateVerifierService predicateVerifier,
198-
MintJustificationVerifierService mintJustificationVerifier
199-
) {
200-
Objects.requireNonNull(trustBase, "trustBase cannot be null");
201-
Objects.requireNonNull(predicateVerifier, "predicateVerifier cannot be null");
202-
Objects.requireNonNull(mintJustificationVerifier, "mintJustificationVerifier cannot be null");
181+
public VerificationResult<VerificationStatus> verify(VerificationContext context) {
182+
Objects.requireNonNull(context, "context cannot be null");
203183

204184
ArrayDeque<Token> pending = new ArrayDeque<>();
205185
pending.add(this);
@@ -211,10 +191,8 @@ public VerificationResult<VerificationStatus> verify(
211191

212192
List<VerificationResult<?>> tokenResults = new ArrayList<>();
213193
VerificationResult<?> result = CertifiedMintTransactionVerificationRule.verify(
214-
trustBase,
215-
predicateVerifier,
216-
mintJustificationVerifier,
217194
token.genesis,
195+
context,
218196
pending::add
219197
);
220198
tokenResults.add(result);
@@ -228,7 +206,7 @@ public VerificationResult<VerificationStatus> verify(
228206
List<VerificationResult<?>> transferResults = new ArrayList<>();
229207
for (int i = 0; i < token.transactions.size(); i++) {
230208
CertifiedTransferTransaction transaction = token.transactions.get(i);
231-
result = CertifiedTransferTransactionVerificationRule.verify(trustBase, predicateVerifier, transaction);
209+
result = CertifiedTransferTransactionVerificationRule.verify(transaction, context);
232210
transferResults.add(result);
233211
if (result.getStatus() != VerificationStatus.OK) {
234212
tokenResults.add(

src/main/java/org/unicitylabs/sdk/transaction/verification/CertifiedMintTransactionVerificationRule.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
package org.unicitylabs.sdk.transaction.verification;
22

33
import org.unicitylabs.sdk.api.CertificationData;
4-
import org.unicitylabs.sdk.api.bft.RootTrustBase;
54
import org.unicitylabs.sdk.crypto.MintSigningService;
65
import org.unicitylabs.sdk.crypto.secp256k1.SigningService;
76
import org.unicitylabs.sdk.predicate.EncodedPredicate;
87
import org.unicitylabs.sdk.predicate.builtin.SignaturePredicate;
9-
import org.unicitylabs.sdk.predicate.verification.PredicateVerifierService;
108
import org.unicitylabs.sdk.transaction.CertifiedMintTransaction;
119
import org.unicitylabs.sdk.transaction.Token;
1210
import org.unicitylabs.sdk.util.verification.VerificationResult;
1311
import org.unicitylabs.sdk.util.verification.VerificationStatus;
1412

1513
import java.util.ArrayList;
16-
import java.util.Arrays;
1714
import java.util.List;
1815
import java.util.function.Consumer;
1916

@@ -31,25 +28,21 @@ private CertifiedMintTransactionVerificationRule() {
3128
/**
3229
* Verify a certified mint transaction.
3330
*
34-
* @param trustBase root trust base
35-
* @param predicateVerifier predicate verifier
36-
* @param mintJustificationVerifier mint justification verifier
3731
* @param transaction certified mint transaction to verify
32+
* @param context shared verification context (trust base + registries)
3833
* @param nestedTokenCollector collector receiving tokens embedded in the mint justification that
3934
* the caller must verify
4035
*
4136
* @return verification result with child results for each validation step
4237
*/
4338
public static VerificationResult<VerificationStatus> verify(
44-
RootTrustBase trustBase,
45-
PredicateVerifierService predicateVerifier,
46-
MintJustificationVerifierService mintJustificationVerifier,
4739
CertifiedMintTransaction transaction,
40+
VerificationContext context,
4841
Consumer<Token> nestedTokenCollector
4942
) {
5043
List<VerificationResult<?>> results = new ArrayList<>();
5144

52-
if (!transaction.getNetworkId().equals(trustBase.getNetworkId())) {
45+
if (!transaction.getNetworkId().equals(context.getTrustBase().getNetworkId())) {
5346
results.add(new VerificationResult<>("MintNetworkMatchesTrustBaseRule", VerificationStatus.FAIL));
5447
return new VerificationResult<>("CertifiedMintTransactionVerificationRule",
5548
VerificationStatus.FAIL, "Mint network does not match trust base.", results);
@@ -74,15 +67,26 @@ public static VerificationResult<VerificationStatus> verify(
7467
VerificationStatus.FAIL, "Invalid lock script", results);
7568
}
7669

77-
result = InclusionProofVerificationRule.verify(trustBase, predicateVerifier,
78-
transaction.getInclusionProof(), transaction);
70+
result = InclusionProofVerificationRule.verify(context.getTrustBase(),
71+
context.getPredicateVerifier(), transaction.getInclusionProof(), transaction);
7972
results.add(result);
8073
if (result.getStatus() != InclusionProofVerificationStatus.OK) {
8174
return new VerificationResult<>("CertifiedMintTransactionVerificationRule",
8275
VerificationStatus.FAIL, "Inclusion proof verification failed", results);
8376
}
8477

85-
result = mintJustificationVerifier.verify(transaction, nestedTokenCollector);
78+
result = context.getTokenIssuanceVerifier().verify(transaction);
79+
results.add(result);
80+
if (result.getStatus() != VerificationStatus.OK) {
81+
return new VerificationResult<>(
82+
"CertifiedMintTransactionVerificationRule",
83+
VerificationStatus.FAIL,
84+
"Invalid token issuance",
85+
results
86+
);
87+
}
88+
89+
result = context.getMintJustificationVerifier().verify(transaction, nestedTokenCollector);
8690
results.add(result);
8791
if (result.getStatus() != VerificationStatus.OK) {
8892
return new VerificationResult<>(

src/main/java/org/unicitylabs/sdk/transaction/verification/CertifiedTransferTransactionVerificationRule.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package org.unicitylabs.sdk.transaction.verification;
22

3-
import org.unicitylabs.sdk.api.bft.RootTrustBase;
4-
import org.unicitylabs.sdk.predicate.verification.PredicateVerifierService;
53
import org.unicitylabs.sdk.transaction.CertifiedTransferTransaction;
64
import org.unicitylabs.sdk.util.verification.VerificationResult;
75
import org.unicitylabs.sdk.util.verification.VerificationStatus;
@@ -22,20 +20,18 @@ private CertifiedTransferTransactionVerificationRule() {
2220
/**
2321
* Verify a certified transfer transaction against the previous transaction.
2422
*
25-
* @param trustBase root trust base used for inclusion proof verification
26-
* @param predicateVerifier predicate verifier used by inclusion proof verification
2723
* @param transaction certified transfer transaction to verify
24+
* @param context shared verification context (trust base + registries)
2825
*
2926
* @return verification result with child results for each validation step
3027
*/
3128
public static VerificationResult<VerificationStatus> verify(
32-
RootTrustBase trustBase,
33-
PredicateVerifierService predicateVerifier,
34-
CertifiedTransferTransaction transaction) {
29+
CertifiedTransferTransaction transaction,
30+
VerificationContext context) {
3531
ArrayList<VerificationResult<?>> results = new ArrayList<VerificationResult<?>>();
3632

37-
VerificationResult<?> result = InclusionProofVerificationRule.verify(trustBase,
38-
predicateVerifier, transaction.getInclusionProof(), transaction);
33+
VerificationResult<?> result = InclusionProofVerificationRule.verify(context.getTrustBase(),
34+
context.getPredicateVerifier(), transaction.getInclusionProof(), transaction);
3935
results.add(result);
4036
if (result.getStatus() != InclusionProofVerificationStatus.OK) {
4137
return new VerificationResult<>("CertifiedTransferTransactionVerificationRule",

src/main/java/org/unicitylabs/sdk/transaction/verification/CertifiedUnicityIdMintTransactionVerificationRule.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package org.unicitylabs.sdk.transaction.verification;
22

3-
import org.unicitylabs.sdk.api.bft.RootTrustBase;
43
import org.unicitylabs.sdk.predicate.EncodedPredicate;
54
import org.unicitylabs.sdk.predicate.builtin.SignaturePredicate;
6-
import org.unicitylabs.sdk.predicate.verification.PredicateVerifierService;
75
import org.unicitylabs.sdk.unicityid.CertifiedUnicityIdMintTransaction;
86
import org.unicitylabs.sdk.util.verification.VerificationResult;
97
import org.unicitylabs.sdk.util.verification.VerificationStatus;
@@ -24,23 +22,21 @@ private CertifiedUnicityIdMintTransactionVerificationRule() {
2422
/**
2523
* Verify the certified unicity id mint transaction.
2624
*
27-
* @param trustBase root trust base
28-
* @param predicateVerifier predicate verifier
2925
* @param genesis certified unicity id mint transaction to verify
26+
* @param context shared verification context (trust base + registries)
3027
* @param issuerPublicKey expected issuer public key, or {@code null} to skip the lock-script
3128
* issuer check (e.g., when minting a fresh token where no external issuer is being asserted)
3229
*
3330
* @return verification result
3431
*/
3532
public static VerificationResult<VerificationStatus> verify(
36-
RootTrustBase trustBase,
37-
PredicateVerifierService predicateVerifier,
3833
CertifiedUnicityIdMintTransaction genesis,
34+
VerificationContext context,
3935
byte[] issuerPublicKey
4036
) {
4137
List<VerificationResult<?>> results = new ArrayList<>();
4238

43-
if (!genesis.getNetworkId().equals(trustBase.getNetworkId())) {
39+
if (!genesis.getNetworkId().equals(context.getTrustBase().getNetworkId())) {
4440
results.add(new VerificationResult<>("MintNetworkMatchesTrustBaseRule",
4541
VerificationStatus.FAIL));
4642
return new VerificationResult<>(
@@ -71,8 +67,8 @@ public static VerificationResult<VerificationStatus> verify(
7167
}
7268

7369
VerificationResult<InclusionProofVerificationStatus> result = InclusionProofVerificationRule.verify(
74-
trustBase,
75-
predicateVerifier,
70+
context.getTrustBase(),
71+
context.getPredicateVerifier(),
7672
genesis.getInclusionProof(),
7773
genesis
7874
);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.unicitylabs.sdk.transaction.verification;
2+
3+
import org.unicitylabs.sdk.transaction.CertifiedMintTransaction;
4+
import org.unicitylabs.sdk.transaction.TokenType;
5+
import org.unicitylabs.sdk.util.verification.VerificationResult;
6+
import org.unicitylabs.sdk.util.verification.VerificationStatus;
7+
8+
/**
9+
* Application-supplied policy for tokens of a single {@link TokenType}. Plugged into
10+
* {@link TokenIssuanceVerifierService}, which dispatches by token type and decides whether a
11+
* token's genesis data is acceptable for its type.
12+
*
13+
* <p>Registering a policy is an application trust decision: cryptographic certification alone
14+
* does not authorize an issuance, so a payment consumer should verify both the payload structure
15+
* and its own issuance policy here.
16+
*/
17+
public interface TokenIssuanceVerifier {
18+
19+
/**
20+
* Get the token type this policy applies to.
21+
*
22+
* @return token type
23+
*/
24+
TokenType getTokenType();
25+
26+
/**
27+
* Verify the genesis data and any application-level issuance policy.
28+
*
29+
* @param transaction genesis mint transaction to verify
30+
*
31+
* @return verification result
32+
*/
33+
VerificationResult<VerificationStatus> verify(CertifiedMintTransaction transaction);
34+
}

0 commit comments

Comments
 (0)