@@ -21,10 +21,6 @@ export enum VerificationStatus {
2121 SelectingCredentials = 'SelectingCredentials' ,
2222}
2323
24- function isRangeProofTemplate ( templateJSON ) {
25- return templateJSON . proving_key ;
26- }
27-
2824type CredentialId = string ;
2925type CredentialSelection = {
3026 credential : any ;
@@ -52,7 +48,6 @@ export function createVerificationController({
5248 let filteredCredentials = [ ] ;
5349 let selectedCredentials : CredentialSelectionMap = new Map ( ) ;
5450 let selectedDID = null ;
55- let provingKey = null ;
5651
5752 if ( ! credentialProvider ) {
5853 credentialProvider = createCredentialProvider ( { wallet} ) ;
@@ -62,23 +57,6 @@ export function createVerificationController({
6257 didProvider = createDIDProvider ( { wallet} ) ;
6358 }
6459
65- async function fetchProvingKey ( templateJSON : any ) {
66- if ( templateJSON . proving_key ) {
67- setState ( VerificationStatus . FetchingProvingKey ) ;
68- try {
69- provingKey = await axios
70- . get ( templateJSON . proving_key )
71- . then ( res => res . data ) ;
72- } catch ( err ) {
73- setState ( VerificationStatus . Error , {
74- message : 'failed_to_fetch_proving_key' ,
75- } ) ;
76-
77- throw err ;
78- }
79- }
80- }
81-
8260 async function start ( { template} : { template : string | any } ) {
8361 setState ( VerificationStatus . LoadingTemplate ) ;
8462
@@ -96,7 +74,6 @@ export function createVerificationController({
9674 selectedDID = dids [ 0 ] . didDocument . id ;
9775 templateJSON = await getJSON ( template ) ;
9876
99- await fetchProvingKey ( templateJSON ) ;
10077 await loadCredentials ( ) ;
10178
10279 setState ( VerificationStatus . SelectingCredentials ) ;
@@ -154,71 +131,110 @@ export function createVerificationController({
154131 return credentialServiceRPC . isKvacCredential ( { credential} ) ;
155132 }
156133
134+ async function deriveNonBbsCredentials ( sdJwtSelections , regularSelections ) {
135+ const credentials = [ ] ;
136+
137+ for ( const sel of sdJwtSelections ) {
138+ const derived = await credentialServiceRPC . createSDJWTPresentation ( {
139+ attributesToReveal : sel . attributesToReveal ,
140+ credential : sel . credential . _sd_jwt . encoded ,
141+ } ) ;
142+ credentials . push ( derived ) ;
143+ }
144+
145+ for ( const sel of regularSelections ) {
146+ credentials . push ( sel . credential ) ;
147+ }
148+
149+ return credentials ;
150+ }
151+
152+ function getKeyId ( keyDoc ) {
153+ return keyDoc . controller . startsWith ( 'did:key:' )
154+ ? keyDoc . id
155+ : `${ keyDoc . controller } #keys-1` ;
156+ }
157+
158+ async function assembleSignedPresentation ( credentials , keyDoc ) {
159+ return credentialServiceRPC . createPresentation ( {
160+ credentials,
161+ challenge : templateJSON . nonce ,
162+ keyDoc,
163+ id : getKeyId ( keyDoc ) ,
164+ domain : 'dock.io' ,
165+ } ) ;
166+ }
167+
157168 async function createPresentation ( ) {
158169 assert ( ! ! selectedDID , 'No DID selected' ) ;
159170 assert ( ! ! selectedCredentials . size , 'No credentials selected' ) ;
160171
161- if ( isRangeProofTemplate ( templateJSON ) ) {
162- // TODO: Implement proving key usage for range-proofs
163- assert ( ! ! provingKey , 'No proving key found' ) ;
164- }
172+ const didKeyPairList = await didProvider . getDIDKeyPairs ( ) ;
173+ const keyDoc = didKeyPairList . find ( doc => doc . controller === selectedDID ) ;
174+ assert ( keyDoc , `No key pair found for the selected DID ${ selectedDID } ` ) ;
165175
166- const credentials = [ ] ;
176+ const sdJwtSelections = [ ] ;
177+ const bbsKvacSelections = [ ] ;
178+ const regularSelections = [ ] ;
167179
168180 for ( const credentialSelection of selectedCredentials . values ( ) ) {
169- const isBBS = await isBBSPlusCredential ( credentialSelection . credential ) ;
170- const isKVAC = await isKvacCredential ( credentialSelection . credential ) ;
171-
172181 if ( credentialSelection . credential . _sd_jwt ) {
173- const derivedCredential =
174- await credentialServiceRPC . createSDJWTPresentation ( {
175- attributesToReveal : credentialSelection . attributesToReveal ,
176- credential : credentialSelection . credential . _sd_jwt . encoded ,
177- } ) ;
178-
179- credentials . push ( derivedCredential ) ;
180- } else if ( isBBS || isKVAC ) {
181- // derive credential
182- const derivedCredentials =
183- await credentialServiceRPC . deriveVCFromPresentation ( {
184- proofRequest : templateJSON ,
185-
186- credentials : [
187- {
188- credential : credentialSelection . credential ,
189- witness : await credentialProvider . getMembershipWitness ( credentialSelection . credential . id ) ,
190- attributesToReveal : [
191- ...( credentialSelection . attributesToReveal || [ ] ) ,
192- 'id' ,
193- ] ,
194- } ,
195- ] ,
196- } ) ;
197-
198- console . log ( 'Credential derived' ) ;
199-
200- credentials . push ( derivedCredentials [ 0 ] ) ;
182+ sdJwtSelections . push ( credentialSelection ) ;
201183 } else {
202- credentials . push ( credentialSelection . credential ) ;
184+ const isBBS = await isBBSPlusCredential ( credentialSelection . credential ) ;
185+ const isKVAC = await isKvacCredential ( credentialSelection . credential ) ;
186+ if ( isBBS || isKVAC ) {
187+ bbsKvacSelections . push ( credentialSelection ) ;
188+ } else {
189+ regularSelections . push ( credentialSelection ) ;
190+ }
203191 }
204192 }
205193
206- const didKeyPairList = await didProvider . getDIDKeyPairs ( ) ;
207- const keyDoc = didKeyPairList . find ( doc => doc . controller === selectedDID ) ;
194+ if ( bbsKvacSelections . length > 0 ) {
195+ const credentialsWithWitness = await Promise . all (
196+ bbsKvacSelections . map ( async sel => ( {
197+ credential : sel . credential ,
198+ witness : await credentialProvider . getMembershipWitness ( sel . credential . id ) ,
199+ attributesToReveal : sel . attributesToReveal || [ ] ,
200+ } ) ) ,
201+ ) ;
208202
209- assert ( keyDoc , `No key pair found for the selected DID ${ selectedDID } ` ) ;
203+ // Pure BBS+/KVAC: use generatePresentationFromPex end-to-end
204+ if ( sdJwtSelections . length === 0 && regularSelections . length === 0 ) {
205+ return credentialServiceRPC . generatePresentationFromPex ( {
206+ credentials : credentialsWithWitness ,
207+ pexRequest : templateJSON . request ,
208+ holderKeyDoc : keyDoc ,
209+ holderDid : selectedDID ,
210+ challenge : templateJSON . nonce ,
211+ domain : 'dock.io' ,
212+ boundCheckSnarkKey : templateJSON . boundCheckSnarkKey ,
213+ skipSigning : true ,
214+ } ) ;
215+ }
210216
211- const presentation = await credentialServiceRPC . createPresentation ( {
212- credentials,
213- challenge : templateJSON . nonce ,
214- keyDoc,
215- id : keyDoc . controller . startsWith ( 'did:key:' )
216- ? keyDoc . id
217- : `${ keyDoc . controller } #keys-1` ,
218- domain : 'dock.io' ,
219- } ) ;
217+ // Mixed: derive BBS+/KVAC, then combine with SD-JWT and regular
218+ const derivedCredentials =
219+ await credentialServiceRPC . deriveVCFromPresentation ( {
220+ proofRequest : templateJSON ,
221+ credentials : credentialsWithWitness . map ( c => ( {
222+ credential : c . credential ,
223+ witness : c . witness ,
224+ attributesToReveal : [ ...( c . attributesToReveal || [ ] ) , 'id' ] ,
225+ } ) ) ,
226+ } ) ;
227+
228+ const nonBbsCredentials = await deriveNonBbsCredentials ( sdJwtSelections , regularSelections ) ;
229+ return assembleSignedPresentation (
230+ [ ...derivedCredentials , ...nonBbsCredentials ] ,
231+ keyDoc ,
232+ ) ;
233+ }
220234
221- return presentation ;
235+ // No BBS+/KVAC: handle SD-JWT and regular only
236+ const credentials = await deriveNonBbsCredentials ( sdJwtSelections , regularSelections ) ;
237+ return assembleSignedPresentation ( credentials , keyDoc ) ;
222238 }
223239
224240 /**
0 commit comments