Skip to content

Commit

Permalink
fix: consider dispatchAs in ctype/public credential fetching logic
Browse files Browse the repository at this point in the history
  • Loading branch information
rflechtner committed Feb 14, 2024
1 parent 9d0ea9b commit e691cc2
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 18 deletions.
33 changes: 24 additions & 9 deletions packages/core/src/ctype/CType.chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ import {
serializeForHash,
verifyDataStructure,
} from './CType.js'
import { flattenCalls, isBatch, retrieveExtrinsicFromBlock } from '../utils.js'
import {
type DidAuthorizationCall,
flattenCalls,
isBatch,
retrieveExtrinsicFromBlock,
} from '../utils.js'

/**
* Encodes the provided CType for use in `api.tx.ctype.add()`.
Expand Down Expand Up @@ -130,15 +135,15 @@ function extractCTypeCreationCallsFromDidCall(
)
}

// Given a (nested) call, flattens them and filter by calls that are of type `api.tx.did.submitDidCall`.
// Given a (nested) call, flattens them and filter by calls that are of type `api.tx.did.submitDidCall` or `api.tx.did.dispatchAs`.
function extractDidCallsFromBatchCall(
api: ApiPromise,
call: Call
): Array<GenericCall<typeof api.tx.did.submitDidCall.args>> {
): DidAuthorizationCall[] {
const extrinsicCalls = flattenCalls(api, call)
return extrinsicCalls.filter(
(c): c is GenericCall<typeof api.tx.did.submitDidCall.args> =>
api.tx.did.submitDidCall.is(c)
(c): c is DidAuthorizationCall =>
api.tx.did.submitDidCall.is(c) || api.tx.did.dispatchAs.is(c)
)
}

Expand Down Expand Up @@ -179,9 +184,13 @@ export async function fetchFromChain(
)
}

if (!isBatch(api, extrinsic) && !api.tx.did.submitDidCall.is(extrinsic)) {
if (
!isBatch(api, extrinsic) &&
!api.tx.did.submitDidCall.is(extrinsic) &&
!api.tx.did.dispatchAs.is(extrinsic)
) {
throw new SDKErrors.PublicCredentialError(
'Extrinsic should be either a `did.submitDidCall` extrinsic or a batch with at least a `did.submitDidCall` extrinsic'
'Extrinsic should be either a `did.submitDidCall` or `did.dispatchAs` extrinsic or a batch containing at least one of those'
)
}

Expand All @@ -198,14 +207,20 @@ export async function fetchFromChain(
const ctypeCallContent = didCalls.flatMap((didCall) => {
const ctypeCreationCalls = extractCTypeCreationCallsFromDidCall(
api,
didCall.args[0].call
api.tx.did.submitDidCall.is(didCall)
? didCall.args[0].call
: didCall.args[1]
)
// Re-create the issued public credential for each call identified.
return ctypeCreationCalls.map(
(ctypeCreationCall) =>
[
cTypeInputFromChain(ctypeCreationCall.args[0]),
Did.fromChain(didCall.args[0].did),
Did.fromChain(
api.tx.did.submitDidCall.is(didCall)
? didCall.args[0].did
: didCall.args[0]
),
] as const
)
})
Expand Down
36 changes: 27 additions & 9 deletions packages/core/src/publicCredential/PublicCredential.chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ import { validateUri } from '@kiltprotocol/asset-did'
import { SDKErrors, cbor } from '@kiltprotocol/utils'

import { getIdForCredential } from './PublicCredential.js'
import { flattenCalls, isBatch, retrieveExtrinsicFromBlock } from '../utils.js'
import {
type DidAuthorizationCall,
flattenCalls,
isBatch,
retrieveExtrinsicFromBlock,
} from '../utils.js'

export interface EncodedPublicCredential {
ctypeHash: CTypeHash
Expand Down Expand Up @@ -137,15 +142,15 @@ function extractPublicCredentialCreationCallsFromDidCall(
)
}

// Given a (nested) call, flattens them and filter by calls that are of type `api.tx.did.submitDidCall`.
// Given a (nested) call, flattens them and filter by calls that are of type `api.tx.did.submitDidCall` or `api.tx.did.dispatchAs`.
function extractDidCallsFromBatchCall(
api: ApiPromise,
call: Call
): Array<GenericCall<typeof api.tx.did.submitDidCall.args>> {
): DidAuthorizationCall[] {
const extrinsicCalls = flattenCalls(api, call)
return extrinsicCalls.filter(
(c): c is GenericCall<typeof api.tx.did.submitDidCall.args> =>
api.tx.did.submitDidCall.is(c)
(c): c is DidAuthorizationCall =>
api.tx.did.submitDidCall.is(c) || api.tx.did.dispatchAs.is(c)
)
}

Expand Down Expand Up @@ -184,9 +189,13 @@ export async function fetchCredentialFromChain(
)
}

if (!isBatch(api, extrinsic) && !api.tx.did.submitDidCall.is(extrinsic)) {
if (
!isBatch(api, extrinsic) &&
!api.tx.did.submitDidCall.is(extrinsic) &&
!api.tx.did.dispatchAs.is(extrinsic)
) {
throw new SDKErrors.PublicCredentialError(
'Extrinsic should be either a `did.submitDidCall` extrinsic or a batch with at least a `did.submitDidCall` extrinsic'
'Extrinsic should be either a `did.submitDidCall` or `did.dispatchAs` extrinsic or a batch containing at least one of those'
)
}

Expand All @@ -202,13 +211,22 @@ export async function fetchCredentialFromChain(
// It returns a list of [reconstructedCredential, attesterDid].
const callCredentialsContent = didCalls.flatMap((didCall) => {
const publicCredentialCalls =
extractPublicCredentialCreationCallsFromDidCall(api, didCall.args[0].call)
extractPublicCredentialCreationCallsFromDidCall(
api,
api.tx.did.submitDidCall.is(didCall)
? didCall.args[0].call
: didCall.args[1]
)
// Re-create the issued public credential for each call identified.
return publicCredentialCalls.map(
(credentialCreationCall) =>
[
credentialInputFromChain(credentialCreationCall.args[0]),
didFromChain(didCall.args[0].did),
didFromChain(
api.tx.did.submitDidCall.is(didCall)
? didCall.args[0].did
: didCall.args[0]
),
] as const
)
})
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export function isBatch(
)
}

export type DidAuthorizationCall =
| GenericCall<ApiPromise['tx']['did']['submitDidCall']['args']>
| GenericCall<ApiPromise['tx']['did']['dispatchAs']['args']>

/**
* Flatten all calls into a single array following a DFS approach.
*
Expand Down

0 comments on commit e691cc2

Please sign in to comment.