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:
- DApps to register
NotaryInfoconfigurations that define how assets should be verified - Users to notarise assets by providing verifiable presentations that prove asset validity
- 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:
- Calculate
AssetIdas SHA256 hash of asset data components (x/notary/keeper/keeper_notarise.go:63) - Add the calculated
AssetIdto the route's additional requirements (x/notary/keeper/keeper_notarise.go:69) - Call
VerifiablePresentationCheckerto verify the VP against the asset route - If verification passes, store the
NotarisedAssetin 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:
- Retrieves the NotaryInfo for the given NotaryInfoId
- Gets the caller route configuration
- Adds the
notaryinfoidas an additional requirement - Adds the sender address to the route
- 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:
- The VCV AnteHandler intercepts the transaction
- Calls notary keeper's
GetRouteAndRequirementsto get the caller route - Extracts the verifiable presentation from the transaction's ExtensionOptions
- Verifies the VP against the caller route using the verifier contract
- If verification fails, the transaction is rejected
Asset Verification (during message execution)
After the transaction passes the AnteHandler:
- The
Notarisekeeper method is executed - Asset data is parsed and AssetId is calculated
- The AssetId is added to the asset route's requirements
VcvKeeper.VerifiablePresentationCheckeris called to verify the asset VP- 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:
- Validates that routes exist on verifier contracts (during registration/updates)
- Passes route references and requirements to x/vcv (during verification)
- 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
- Separation of Concerns: x/notary handles business logic (asset registration, fees, storage), while x/vcv handles all cryptographic verification
- Route Validation: Routes must exist on verifier contracts before they can be used in NotaryInfo
- Dynamic Requirements: Additional verification requirements (like AssetId) can be computed and added at runtime
- Dual Verification: Caller identity (via AnteHandler) and asset data (via keeper) are verified separately
- Contract Agnostic: x/notary doesn't know how verification works - it only provides routes and requirements to x/vcv