Skip to main content

Concept

This module facilitates decentralised applications to register verification route configurations for notarisation data representing assets. The module integrates with the x/vcv (Verifiable Credential Verification) module to perform cryptographic verification of credentials and asset data.

For more background design information, see the Verifiable data notary section.

Overview

The x/notary module enables:

  1. DApps to register NotaryInfo configurations that define how assets should be verified
  2. Users to notarise assets by providing verifiable presentations that prove asset validity
  3. Integration with x/vcv module for all cryptographic verification operations

The sequence of events is as follows:

How It Works

The x/notary module uses x/vcv to call verifier contracts for cryptographic verification:

User Transaction → VCV AnteHandler → Verify Caller VP → Execute Notarise

Calculate AssetId → VCV Verification → Store Asset

How x/notary Uses x/vcv

The x/notary module depends on the x/vcv module through the VCVKeeper interface (x/notary/types/expected_keepers.go:16-17):

type VCVKeeper interface{ vcvexported.VCVKeeperI }

The VCVKeeper is injected into the notary keeper during initialization (x/notary/keeper/keeper.go:28,67,76) and provides three key methods:

1. CheckAppOrRouteOnVerifier

Used during NotaryInfo registration and updates to validate that routes exist on verifier contracts.

Location: x/notary/keeper/ms_notaryinfo.go:56,66,99,110

Usage:

hasApp, hasRoute, err := ms.k.VcvKeeper.CheckAppOrRouteOnVerifier(
ctx,
route.AppAddr, // Verifier contract address
route.VerifierType, // Type of verifier (e.g., "sdjwt")
route.RouteId // Route ID on the contract
)

This is called when:

  • A DApp registers a new NotaryInfo with caller or asset routes
  • A DApp updates existing routes on a NotaryInfo

If the routes don't exist on the verifier contract, the registration/update fails with ErrVPRouteNotFound.

2. VerifiablePresentationChecker

Used during asset notarisation to verify the asset data against the configured route.

Location: x/notary/keeper/keeper_notarise.go:70

Usage:

err = k.VcvKeeper.VerifiablePresentationChecker(
sdkCtx,
verifierInput, // The verifiable presentation bytes
ni.AssetRouteAndAdditionalReq.Route, // Route configuration
ni.AssetRouteAndAdditionalReq.CriterionKVs // Additional requirements (including AssetId)
)

The notarisation flow:

  1. Calculate AssetId as SHA256 hash of asset data components (x/notary/keeper/keeper_notarise.go:63)
  2. Add the calculated AssetId to the route's additional requirements (x/notary/keeper/keeper_notarise.go:69)
  3. Call VerifiablePresentationChecker to verify the VP against the asset route
  4. If verification passes, store the NotarisedAsset in state

3. VPVerifierRouter Implementation

The notary keeper implements the VPVerifierRouterI interface (x/notary/keeper/verifier_router.go:14), which allows x/vcv's AnteHandler to retrieve route information for transaction verification:

func (k Keeper) GetRouteAndRequirements(ctx context.Context, msg sdk.Msg) (*vcvtypes.RouteAndAdditionalReq, error)

This method handles different message types:

  • MsgNotarise: Returns the caller route with dynamic requirements (e.g., notaryinfoid)
  • MsgRegisterNotaryInfo: No VP requirements (returns nil)
  • MsgUpdateVerifierRoutes: No VP requirements (returns nil)
  • MsgUpdateAdmin: No VP requirements (returns nil)
  • MsgRemoveNotaryInfo: No VP requirements (returns nil)

For MsgNotarise, the implementation:

  1. Retrieves the NotaryInfo for the given NotaryInfoId
  2. Gets the caller route configuration
  3. Adds the notaryinfoid as an additional requirement
  4. Adds the sender address to the route
  5. Returns the route for VCV's AnteHandler to verify

Route Configuration

Routes are stored directly in the NotaryInfo structure:

message NotaryInfo {
string notary_info_admin = 1;
uint64 notarised_asset_id = 2;
d.vcv.v1.RouteAndAdditionalReq caller_route_and_additional_req = 3;
d.vcv.v1.RouteAndAdditionalReq asset_route_and_additional_req = 4;
}

Each RouteAndAdditionalReq contains:

  • Route: Reference to a verifier contract (app address, verifier type, route ID)
  • CriterionKVs: Base verification requirements (key-value pairs of criteria)

Additional requirements can be dynamically added during verification (e.g., calculated AssetId).

Verification Flow

Caller Verification (via AnteHandler)

When a user submits a MsgNotarise transaction:

  1. The VCV AnteHandler intercepts the transaction
  2. Calls notary keeper's GetRouteAndRequirements to get the caller route
  3. Extracts the verifiable presentation from the transaction's ExtensionOptions
  4. Verifies the VP against the caller route using the verifier contract
  5. If verification fails, the transaction is rejected

Asset Verification (during message execution)

After the transaction passes the AnteHandler:

  1. The Notarise keeper method is executed
  2. Asset data is parsed and AssetId is calculated
  3. The AssetId is added to the asset route's requirements
  4. VcvKeeper.VerifiablePresentationChecker is called to verify the asset VP
  5. If verification passes, the asset is stored as a NotarisedAsset

Verifier Contracts

The x/vcv module manages smart contracts (CosmWasm) that implement the actual cryptographic verification logic. x/notary doesn't interact with these contracts directly - it only:

  1. Validates that routes exist on verifier contracts (during registration/updates)
  2. Passes route references and requirements to x/vcv (during verification)
  3. Relies on x/vcv to execute the verification and return results

Currently, x/vcv supports SD-JWT (Selective Disclosure JWT) verifiers, which enable privacy-preserving credential verification where users can selectively disclose only required claims from their verifiable credentials.

Key Design Points

  1. Separation of Concerns: x/notary handles business logic (asset registration, fees, storage), while x/vcv handles all cryptographic verification
  2. Route Validation: Routes must exist on verifier contracts before they can be used in NotaryInfo
  3. Dynamic Requirements: Additional verification requirements (like AssetId) can be computed and added at runtime
  4. Dual Verification: Caller identity (via AnteHandler) and asset data (via keeper) are verified separately
  5. Contract Agnostic: x/notary doesn't know how verification works - it only provides routes and requirements to x/vcv