Skip to main content

libid_contracts/bindings/
ceremony.rs

1//! Bindings for the ceremony verification path (`solidity/contracts/ceremony/`):
2//! the Notary Service every notarized session is authenticated through, the
3//! Proof Verifier that routes a claim to the Platform Verifier registered for
4//! its version, and the Google JWT root list the `google/v1` verifier reads.
5
6/// Bindings for `ceremony/NotaryService.sol` (which implements
7/// `INotaryService`).
8///
9/// Authenticates one attestation and charges one fee for it. The digest is
10/// derived from the attested bytes on chain, never taken from the caller
11/// (REQ-COMMON-33), which is why `verify` is not on this interface: a
12/// consumer contract calls it with the fee attached, and the decoded record
13/// comes back to that contract, not to an off-chain reader. What an operator
14/// does from here is hold the trusted key set, set the fee and withdraw what
15/// accrued.
16#[allow(clippy::too_many_arguments, unused_attributes)]
17mod notary_service_inner {
18    use alloy::sol;
19
20    sol! {
21        #[sol(rpc)]
22        interface NotaryService {
23            /// `notary_` is the first trusted key; `fee_` may be zero (a
24            /// deployment may meter at no charge, and the exact-value rule
25            /// still applies).
26            function initialize(address owner_, address notary_, uint256 fee_) external;
27            /// What one verification costs, in the chain's native asset.
28            /// Readable before a submission is built, so it can be bounded.
29            function fee() external view returns (uint256);
30            function setFee(uint256 fee_) external;
31            /// Add or remove a trusted notary key. Several are held at once so
32            /// a rotation can overlap: add the incoming key, remove the
33            /// outgoing one once nothing can still present under it.
34            function setNotary(address key, bool trusted_) external;
35            function isTrustedNotary(address key) external view returns (bool);
36            /// Fees accrue here rather than being forwarded per verification.
37            function withdraw(address to, uint256 amount) external;
38
39            function owner() external view returns (address);
40            function pendingOwner() external view returns (address);
41            function transferOwnership(address newOwner) external;
42            function acceptOwnership() external;
43
44            event FeeChanged(uint256 previousFee, uint256 newFee);
45            event NotaryTrustChanged(address indexed key, bool trusted);
46            event FeesWithdrawn(address indexed to, uint256 amount);
47        }
48    }
49}
50
51pub use notary_service_inner::NotaryService;
52
53/// Bindings for `ceremony/CeremonyProofVerifier.sol` (which implements
54/// `IProofVerifier`).
55///
56/// The Supported Version Set: which Platform Verifier answers for a
57/// `(platformId, verifierVersion)` pair. Governance registers one with
58/// `setVerifier`; `IdentityNames.claim` dispatches through `verify`, which is
59/// not on this interface for the same reason `NotaryService.verify` is not —
60/// it is called by the consumer contract with the fee attached.
61#[allow(clippy::too_many_arguments, unused_attributes)]
62mod proof_verifier_inner {
63    use alloy::sol;
64
65    sol! {
66        #[sol(rpc)]
67        interface CeremonyProofVerifier {
68            function initialize(address owner_) external;
69            /// Register (or, with the zero address, remove) the Platform
70            /// Verifier for a pair. The verifier must serve `platformId`.
71            function setVerifier(bytes32 platformId, uint16 verifierVersion, address verifier) external;
72            /// The Platform Verifier registered for a pair, or zero.
73            function verifierOf(bytes32 platformId, uint16 verifierVersion) external view returns (address);
74            /// What one claim under this pair costs: the registered
75            /// verifier's quote, forwarded whole.
76            function quote(bytes32 platformId, uint16 verifierVersion) external view returns (uint256);
77            /// Whether any version is registered for the platform at all.
78            function verifiesPlatform(bytes32 platformId) external view returns (bool);
79            /// This chain's identifier, as the digest construction takes it.
80            function chainId() external view returns (bytes32);
81
82            function owner() external view returns (address);
83            function pendingOwner() external view returns (address);
84            function transferOwnership(address newOwner) external;
85            function acceptOwnership() external;
86
87            event VerifierConfigured(bytes32 indexed platformId, uint16 indexed verifierVersion, address verifier);
88        }
89    }
90}
91
92pub use proof_verifier_inner::CeremonyProofVerifier;
93
94/// Bindings for `ceremony/GoogleJwtRoots.sol` — the signing keys the
95/// `google/v1` Platform Verifier trusts, and until when. Starts EMPTY:
96/// Google names bind only once a notarized reading of Google's JWKS has
97/// landed here.
98///
99/// The list is two generations of Google's key set and nothing else:
100/// `current` is the latest reading applied, `previous` the reading before
101/// it, kept for the tokens still in flight under a key Google has since
102/// dropped. A newer reading of the same set restarts `current`'s clock
103/// (`ReadingRefreshed`); a newer reading of a different set shifts `current`
104/// into `previous` and drops what `previous` held (`KeysRotated`). A
105/// generation is trusted until `READING_LIFETIME` after its reading's own
106/// `createdAt`, so there is nothing to prune or untrust by hand.
107///
108/// A rotation is an ordinary notarized session: the keeper reveals the whole
109/// `GET /oauth2/v3/certs` exchange, `rotate` hands the attested bytes and the
110/// notary's proof to the Notary Service with the Notary Fee attached (read
111/// it with `quoteRotation`, which is the service's `fee()`), and the contract
112/// reads the JWKS out of the transcript it vouched for.
113#[allow(clippy::too_many_arguments, unused_attributes)]
114mod google_jwt_roots_inner {
115    use alloy::sol;
116
117    sol! {
118        #[sol(rpc)]
119        interface GoogleJwtRoots {
120            /// One reading of Google's key set: the notary's clock, and the
121            /// limb hash of every modulus it listed, in Google's order.
122            #[derive(Debug, serde::Serialize, serde::Deserialize)]
123            struct Generation {
124                uint64 observedAt;
125                bytes32[] moduli;
126            }
127
128            function initialize(address owner_, address notary_) external;
129            /// The Notary Service a rotation is verified through.
130            function notaryService() external view returns (address);
131            function setNotaryService(address notary_) external;
132            /// What one rotation costs beyond gas: the Notary Fee, forwarded
133            /// whole. `rotate` must be sent with exactly this value.
134            function quoteRotation() external view returns (uint256);
135            /// Permissionless. `attestedData` is the ceremony-common section
136            /// 9.1 record of the JWKS session, `proof` the notary's
137            /// authentication of it (a 65-byte EIP-191 signature today). A
138            /// reading dated no later than the current generation is refused
139            /// with `NotNewer(createdAt, observedAt)`, and the revert hands
140            /// the fee back.
141            function rotate(bytes calldata attestedData, bytes calldata proof) external payable;
142
143            /// What `GooglePlatformVerifier` reads: modulus hash -> when it
144            /// stops being trusted, zero when neither generation lists it.
145            function trustedHashExpiresAt(bytes32 modulusHash) external view returns (uint256);
146            /// Both generations, as stored.
147            function currentKeys() external view returns (Generation memory current, Generation memory previous);
148            /// The current generation's `observedAt`: the notary's clock on
149            /// the reading in force.
150            function freshestObservedAt() external view returns (uint256);
151            /// True until the current generation is guaranteed trusted
152            /// `RENEWAL_MARGIN` from now; true on an empty list.
153            function needsRotation() external view returns (bool);
154            function READING_LIFETIME() external view returns (uint256);
155            function RENEWAL_MARGIN() external view returns (uint256);
156            function MAX_KEYS() external view returns (uint256);
157
158            function owner() external view returns (address);
159            function pendingOwner() external view returns (address);
160            function transferOwnership(address newOwner) external;
161            function acceptOwnership() external;
162
163            event NotaryServiceChanged(address notary);
164            /// A different set landed: `kids` and `moduli` in the order
165            /// Google listed them, `observedAt` the notary's clock.
166            event KeysRotated(uint64 observedAt, string[] kids, bytes32[] moduli);
167            /// A newer reading of the set already current.
168            event ReadingRefreshed(uint64 observedAt);
169        }
170    }
171}
172
173pub use google_jwt_roots_inner::GoogleJwtRoots;