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
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default defineConfig(
...globals.node
},
parserOptions: {
project: ['./tsconfig.eslint.json']
project: ['./tsconfig.json']
},
sourceType: 'module'
},
Expand Down
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"./lib/*": "./lib/*.js"
},
"scripts": {
"build": "tsc",
"build:check": "tsc --project tsconfig.eslint.json --noEmit",
"build": "tsc --project tsconfig.build.json",
"build:check": "tsc --noEmit",
"lint": "eslint \"src/**/*\" \"tests/**/*\"",
"lint:fix": "eslint \"src/**/*\" \"tests/**/*\" --fix",
"test": "npm run-script test:unit",
Expand Down
4 changes: 3 additions & 1 deletion src/predicate/builtin/UnicityIdPredicateUnlockScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SigningService } from '../../crypto/secp256k1/SigningService.js';
import { CborDeserializer } from '../../serialization/cbor/CborDeserializer.js';
import { CborSerializer } from '../../serialization/cbor/CborSerializer.js';
import { ITransaction } from '../../transaction/ITransaction.js';
import { TokenId } from '../../transaction/TokenId.js';
import { UnicityIdToken } from '../../unicity-id/UnicityIdToken.js';
import { IUnlockScript } from '../IUnlockScript.js';

Expand Down Expand Up @@ -42,7 +43,8 @@ export class UnicityIdPredicateUnlockScript implements IUnlockScript {
signingService: SigningService,
): Promise<UnicityIdPredicateUnlockScript> {
const predicate = UnicityIdPredicate.fromPredicate(transaction.lockScript);
if (!token.id.equals(await predicate.unicityId.toTokenId())) {
const tokenId = await TokenId.fromSalt(token.genesis.networkId, await predicate.unicityId.toTokenSalt());
if (!token.id.equals(tokenId)) {
throw new Error('Invalid Unicity ID for transaction');
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { IBuiltInPredicateVerifier } from './IBuiltInPredicateVerifier.js';
import { RootTrustBase } from '../../../api/bft/RootTrustBase.js';
import { DataHash } from '../../../crypto/hash/DataHash.js';
import { TokenId } from '../../../transaction/TokenId.js';
import { VerificationResult } from '../../../verification/VerificationResult.js';
import { VerificationStatus } from '../../../verification/VerificationStatus.js';
import { EncodedPredicate } from '../../EncodedPredicate.js';
Expand Down Expand Up @@ -40,7 +41,7 @@ export class UnicityIdPredicateVerifier implements IBuiltInPredicateVerifier {
const predicate = UnicityIdPredicate.fromPredicate(encodedPredicate);
const decodedUnlockScript = await UnicityIdPredicateUnlockScript.decode(unlockScript);

const tokenId = await predicate.unicityId.toTokenId();
const tokenId = await TokenId.fromSalt(this.trustBase.networkId, await predicate.unicityId.toTokenSalt());
if (!tokenId.equals(decodedUnlockScript.token.id)) {
return new VerificationResult('UnicityIdPredicateVerifier', VerificationStatus.FAIL, 'Token ID mismatch.');
}
Expand Down
2 changes: 2 additions & 0 deletions src/transaction/CertifiedMintTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
* Mint transaction bundled with a verified inclusion proof.
*/
export class CertifiedMintTransaction implements ITransaction {
private readonly _brand = 'CertifiedMintTransaction' as const;

private constructor(
private readonly transaction: MintTransaction,
public readonly inclusionProof: InclusionProof,
Expand Down
2 changes: 2 additions & 0 deletions src/transaction/MintTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export class MintTransaction implements ITransaction {
public static readonly CBOR_TAG = 39041n;
private static readonly VERSION = 1n;

private readonly _brand = 'MintTransaction' as const;

private constructor(
public readonly sourceStateHash: MintTransactionState,
public readonly lockScript: EncodedPredicate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ export class CertifiedUnicityIdMintTransactionVerificationRule {
): Promise<VerificationResult<VerificationStatus>> {
const results: VerificationResult<unknown>[] = [];

if (!genesis.networkId.equals(trustBase.networkId)) {
results.push(new VerificationResult('MintNetworkMatchesTrustBaseRule', VerificationStatus.FAIL));
return new VerificationResult(
'CertifiedUnicityIdMintTransactionVerificationRule',
VerificationStatus.FAIL,
'Mint network does not match trust base.',
results,
);
}
results.push(new VerificationResult('MintNetworkMatchesTrustBaseRule', VerificationStatus.OK));

if (issuerPublicKey !== null) {
const expectedLockScript = EncodedPredicate.fromPredicate(SignaturePredicate.create(issuerPublicKey));
if (!EncodedPredicate.equals(expectedLockScript, genesis.lockScript)) {
Expand Down
10 changes: 10 additions & 0 deletions src/unicity-id/CertifiedUnicityIdMintTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { UnicityId } from './UnicityId.js';
import { UnicityIdMintTransaction } from './UnicityIdMintTransaction.js';
import { RootTrustBase } from '../api/bft/RootTrustBase.js';
import { InclusionProof } from '../api/InclusionProof.js';
import { NetworkId } from '../api/NetworkId.js';
import { DataHash } from '../crypto/hash/DataHash.js';
import { SignaturePredicate } from '../predicate/builtin/SignaturePredicate.js';
import { EncodedPredicate } from '../predicate/EncodedPredicate.js';
Expand All @@ -21,6 +22,8 @@ import { dedent } from '../util/StringUtils.js';
* Unicity-id mint transaction bundled with a verified inclusion proof.
*/
export class CertifiedUnicityIdMintTransaction implements ITransaction {
private readonly _brand = 'CertifiedUnicityIdMintTransaction' as const;

public constructor(
private readonly transaction: UnicityIdMintTransaction,
public readonly inclusionProof: InclusionProof,
Expand All @@ -40,6 +43,13 @@ export class CertifiedUnicityIdMintTransaction implements ITransaction {
return this.transaction.lockScript;
}

/**
* @returns {NetworkId} Network identifier of the inner transaction.
*/
public get networkId(): NetworkId {
return this.transaction.networkId;
}

/**
* @returns {EncodedPredicate} Recipient predicate of the inner transaction.
*/
Expand Down
12 changes: 6 additions & 6 deletions src/unicity-id/UnicityId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { DataHasher } from '../crypto/hash/DataHasher.js';
import { HashAlgorithm } from '../crypto/hash/HashAlgorithm.js';
import { CborDeserializer } from '../serialization/cbor/CborDeserializer.js';
import { CborSerializer } from '../serialization/cbor/CborSerializer.js';
import { TokenId } from '../transaction/TokenId.js';
import { TokenSalt } from '../transaction/TokenSalt.js';

/**
* Human-readable identifier (`@domain/name`) people use to send tokens.
* The bound {@link TokenId} can be derived from it via {@link toTokenId}.
* The bound {@link TokenSalt} can be derived from it via {@link toTokenSalt}.
*/
export class UnicityId {
public constructor(
Expand Down Expand Up @@ -48,11 +48,11 @@ export class UnicityId {
}

/**
* Derive the {@link TokenId} bound to this unicity id.
* Derive the {@link TokenSalt} bound to this unicity id.
*
* @returns {Promise<TokenId>} Derived token id.
* @returns {Promise<TokenSalt>} Derived token id.
*/
public async toTokenId(): Promise<TokenId> {
public async toTokenSalt(): Promise<TokenSalt> {
const hash = await new DataHasher(HashAlgorithm.SHA256)
.update(
CborSerializer.encodeArray(
Expand All @@ -63,6 +63,6 @@ export class UnicityId {
)
.digest();

return new TokenId(hash.data);
return TokenSalt.fromBytes(hash.data);
}
}
24 changes: 17 additions & 7 deletions src/unicity-id/UnicityIdMintTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CertifiedUnicityIdMintTransaction } from './CertifiedUnicityIdMintTrans
import { UnicityId } from './UnicityId.js';
import { RootTrustBase } from '../api/bft/RootTrustBase.js';
import { InclusionProof } from '../api/InclusionProof.js';
import { NetworkId } from '../api/NetworkId.js';
import { DataHash } from '../crypto/hash/DataHash.js';
import { DataHasher } from '../crypto/hash/DataHasher.js';
import { HashAlgorithm } from '../crypto/hash/HashAlgorithm.js';
Expand All @@ -25,9 +26,12 @@ export class UnicityIdMintTransaction implements ITransaction {
public static readonly CBOR_TAG = 39041n;
private static readonly VERSION = 1n;

private readonly _brand = 'UnicityIdMintTransaction' as const;

private constructor(
public readonly sourceStateHash: MintTransactionState,
public readonly lockScript: EncodedPredicate,
public readonly networkId: NetworkId,
public readonly recipient: EncodedPredicate,
public readonly tokenId: TokenId,
public readonly tokenType: TokenType,
Expand Down Expand Up @@ -59,6 +63,7 @@ export class UnicityIdMintTransaction implements ITransaction {
/**
* Create a UnicityIdMintTransaction.
*
* @param {NetworkId} networkId Network identifier.
* @param {SignaturePredicate} lockScript Issuer lock script.
* @param {IPredicate} recipient Predicate that will lock the minted state.
* @param {UnicityId} unicityId Unicity id being minted.
Expand All @@ -67,17 +72,19 @@ export class UnicityIdMintTransaction implements ITransaction {
* @returns {Promise<UnicityIdMintTransaction>} New mint transaction.
*/
public static async create(
networkId: NetworkId,
lockScript: SignaturePredicate,
recipient: IPredicate,
unicityId: UnicityId,
tokenType: TokenType,
targetPredicate: SignaturePredicate,
): Promise<UnicityIdMintTransaction> {
const tokenId = await unicityId.toTokenId();
const tokenId = await TokenId.fromSalt(networkId, await unicityId.toTokenSalt());

return new UnicityIdMintTransaction(
await MintTransactionState.create(tokenId),
EncodedPredicate.fromPredicate(lockScript),
networkId,
EncodedPredicate.fromPredicate(recipient),
tokenId,
tokenType,
Expand All @@ -99,18 +106,19 @@ export class UnicityIdMintTransaction implements ITransaction {
throw new CborError(`Invalid CBOR tag for UnicityIdMintTransaction: ${tag.tag}`);
}

const data = CborDeserializer.decodeArray(tag.data, 6);
const data = CborDeserializer.decodeArray(tag.data, 7);
Comment thread
martti007 marked this conversation as resolved.
const version = CborDeserializer.decodeUnsignedInteger(data[0]);
if (version !== UnicityIdMintTransaction.VERSION) {
throw new CborError(`Unsupported UnicityIdMintTransaction version: ${version}`);
}

return UnicityIdMintTransaction.create(
SignaturePredicate.fromPredicate(EncodedPredicate.fromCBOR(data[1])),
EncodedPredicate.fromCBOR(data[2]),
UnicityId.fromCBOR(data[3]),
TokenType.fromCBOR(data[4]),
SignaturePredicate.fromPredicate(EncodedPredicate.fromCBOR(data[5])),
NetworkId.fromId(CborDeserializer.decodeUnsignedInteger(data[1])),
SignaturePredicate.fromPredicate(EncodedPredicate.fromCBOR(data[2])),
EncodedPredicate.fromCBOR(data[3]),
UnicityId.fromCBOR(data[4]),
TokenType.fromCBOR(data[5]),
SignaturePredicate.fromPredicate(EncodedPredicate.fromCBOR(data[6])),
);
}

Expand Down Expand Up @@ -143,6 +151,7 @@ export class UnicityIdMintTransaction implements ITransaction {
UnicityIdMintTransaction.CBOR_TAG,
CborSerializer.encodeArray(
CborSerializer.encodeUnsignedInteger(this.version),
CborSerializer.encodeUnsignedInteger(this.networkId.id),
this.lockScript.toCBOR(),
this.recipient.toCBOR(),
this.unicityId.toCBOR(),
Expand Down Expand Up @@ -175,6 +184,7 @@ export class UnicityIdMintTransaction implements ITransaction {
return dedent`
UnicityIdMintTransaction
Version: ${this.version.toString()}
Network ID: ${this.networkId.toString()}
Lock Script:
${this.lockScript.toString()}
Recipient: ${this.recipient.toString()}
Expand Down
3 changes: 3 additions & 0 deletions tests/utils/TransitionFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const transitionFlowTest = (client: StateTransitionClient, trustBase: Roo

const unicityId = new UnicityId('testuser', 'unicity-labs/test');
const unicityIdMintTransaction = await UnicityIdMintTransaction.create(
trustBase.networkId,
SignaturePredicate.fromSigningService(unicityIdSigningService),
targetPredicate,
unicityId,
Expand Down Expand Up @@ -66,6 +67,8 @@ export const transitionFlowTest = (client: StateTransitionClient, trustBase: Roo
predicateVerifier,
mintJustificationVerifier,
aliceUnicityIdToken.genesis.targetPredicate,
null,
trustBase.networkId,
);

const bobToken = await transferToken(
Expand Down
10 changes: 5 additions & 5 deletions tsconfig.eslint.json → tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"rootDir": "./",
"rootDir": "./src",
"noEmit": false
},
"exclude": [
"node_modules",
"lib",
"tests"
],
"include": [
"src/**/*.ts",
"tests/**/*.ts",
],
"src/**/*.ts"
]
}
12 changes: 6 additions & 6 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"rootDir": "./src",
"rootDir": "./",
Comment thread
MastaP marked this conversation as resolved.
"outDir": "./lib",
"target": "es2022",
"allowJs": true,
Expand All @@ -14,17 +14,17 @@
"moduleResolution": "nodenext",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": false,
"noEmit": true,
"declaration": true,
"sourceMap": true,
"types": ["jest", "node"]
},
"exclude": [
"node_modules",
"lib",
"tests"
"lib"
],
"include": [
"src/**/*.ts"
"src/**/*.ts",
"tests/**/*.ts"
]
}
}
Loading