Skip to content

refactor!: integrate feedback on alpha release #894

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 26 additions & 12 deletions packages/credentials/src/V1/KiltAttestationProofV1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import type {
IDelegationNode,
KiltAddress,
SharedArguments,
SignerInterface,
} from '@kiltprotocol/types'
import { Caip19, JsonSchema, SDKErrors, Signers } from '@kiltprotocol/utils'

Expand Down Expand Up @@ -670,19 +671,14 @@ async function defaultTxSubmit({
call,
signers,
submitter,
}: Omit<SharedArguments, 'submitter'> & {
}: SharedArguments & {
call: Extrinsic
submitter: KiltAddress
}): Promise<SimplifiedTransactionResult> {
let extrinsic = await authorizeTx(
didDocument,
call,
await signersForDid(didDocument, ...signers),
submitter
)

if (!extrinsic.isSigned) {
const accountSigners = (
let submitterAddress: KiltAddress
let accountSigners: SignerInterface[] = []
if (typeof submitter === 'string') {
submitterAddress = submitter
accountSigners = (
await Promise.all(
signers.map((keypair) =>
'algorithm' in keypair
Expand All @@ -691,7 +687,25 @@ async function defaultTxSubmit({
)
)
).flat()
extrinsic = await extrinsic.signAsync(submitter, {
} else if ('algorithm' in submitter) {
submitterAddress = submitter.id
accountSigners = [submitter]
} else {
accountSigners = await Signers.getSignersForKeypair({
keypair: submitter,
})
submitterAddress = accountSigners[0].id as KiltAddress
}

let extrinsic = await authorizeTx(
didDocument,
call,
await signersForDid(didDocument, ...signers),
submitterAddress
)

if (!extrinsic.isSigned) {
extrinsic = await extrinsic.signAsync(submitterAddress, {
signer: Signers.getPolkadotSigner(accountSigners),
})
}
Expand Down
92 changes: 48 additions & 44 deletions packages/credentials/src/holder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,48 +52,47 @@ function pointerToAttributeName(
/**
* Allows creating derivative proofs from a Verifiable Credential, for the purpose of disclosing only a subset of the credential's claims to a verifier.
*
* @param credential A Verifiable Credential containing a proof.
* @param proofOptions Options for creating the derived proof.
* @param proofOptions.disclose Allows selecting which claims/attributes in the credential should be disclosed, hiding others.
* @param proofOptions.disclose.only An array of {@link https://www.rfc-editor.org/info/rfc6901 JSON Pointer} expressions selecting attributes to be disclosed.
* All other (non-mandatory) attributes that can be hidden will be hidden.
* Takes precedence over `allBut`.
* @param proofOptions.disclose.allBut An array of {@link https://www.rfc-editor.org/info/rfc6901 JSON Pointer} expressions selecting attributes to be hidden.
* @param params Holds all named parameters.
* @param params.credential A Verifiable Credential containing a proof.
* @param params.proofOptions Options for creating the derived proof.
* @param params.proofOptions.includeClaims An array of {@link https://www.rfc-editor.org/info/rfc6901 JSON Pointer} expressions.
* Allows selecting which claims/attributes in the credential should be disclosed, hiding all other (non-mandatory) attributes.
* @param params.proofOptions.excludeClaims An array of {@link https://www.rfc-editor.org/info/rfc6901 JSON Pointer} expressions selecting attributes to be hidden.
* This means that all other properties are being revealed.
* Selecting mandatory properties will result in an error.
* It is ignored if `only` is set.
* _Ignored if `includeClaims` is set_.
* @returns A copy of the original credential and proof, altered according to the derivation rules and `proofOptions`.
*/
export async function deriveProof(
credential: VerifiableCredential,
// TODO: do we need a holder interface here at some point? Would be required if some holder secret would become necessary to create a derived proof, e.g., a link secret.
export async function deriveProof({
credential,
proofOptions = {},
}: {
credential: VerifiableCredential
proofOptions?: {
disclose?: {
allBut?: string[]
only?: string[]
}
includeClaims?: string[]
excludeClaims?: string[]
}
): Promise<VerifiableCredential> {
}): Promise<VerifiableCredential> {
const proof = getProof(credential)
switch (proof.type) {
case KiltAttestationProofV1.PROOF_TYPE: {
KiltCredentialV1.validateStructure(
credential as KiltCredentialV1.Interface
)

const { allBut, only } = proofOptions?.disclose ?? {}
const { includeClaims, excludeClaims } = proofOptions
let discloseProps: string[] = []
if (only) {
if (includeClaims) {
const attributes = new Set<string>()
only.forEach((path) => {
includeClaims.forEach((path) => {
attributes.add(pointerToAttributeName(credential, path, false))
})
discloseProps = Array.from(attributes)
} else if (allBut) {
} else if (excludeClaims) {
const attributes = new Set<string>(
Object.keys(credential.credentialSubject)
)
allBut.forEach((path) => {
excludeClaims.forEach((path) => {
attributes.delete(pointerToAttributeName(credential, path, true))
})
discloseProps = Array.from(attributes)
Expand All @@ -118,48 +117,53 @@ export async function deriveProof(
* Creates a Verifiable Presentation from one or more credentials and adds a proof for the purpose of holder authentication.
* To that end, the presentation can be scoped to a specific transaction, timeframe, purpose, or verifier, by means of multiple mechanisms.
*
* @param credentials Array of one or more Verifiable Credentials to be included in the presentation.
* @param holder Interfaces for interacting with the holder identity for the purpose of generating a presentation proof.
* @param holder.did The Decentralized Identifier (DID) of the holder.
* @param holder.didDocument The DID Document of the holder.
* @param holder.signers An array of signer interfaces, each allowing to request signatures made with a key associated with the holder DID Document.
* @param params Holds all named parameters.
* @param params.credentials Array of one or more Verifiable Credentials to be included in the presentation.
* @param params.holder Interfaces for interacting with the holder identity for the purpose of generating a presentation proof.
* @param params.holder.didDocument The DID Document of the holder.
* @param params.holder.signers An array of signer interfaces, each allowing to request signatures made with a key associated with the holder DID Document.
* The function will select the first signer that matches requirements around signature algorithm and relationship of the key to the DID as given by the DID Document.
* @param presentationOptions Object holding optional arguments for scoping the presentation.
* @param presentationOptions.validFrom A Date or date-time string indicating the earliest point in time where the presentation becomes valid.
* @param params.presentationOptions Object holding optional arguments for scoping the presentation.
* @param params.presentationOptions.validFrom A Date or date-time string indicating the earliest point in time where the presentation becomes valid.
* Represented as `issuanceDate` on the presentation.
* Defaults to `proofOptions.now`.
* @param presentationOptions.validUntil A Date or date-time string indicating when the presentation is no longer valid.
* @param params.presentationOptions.validUntil A Date or date-time string indicating when the presentation is no longer valid.
* Represented as `expirationDate` on the presentation.
* @param presentationOptions.verifier Identifier (DID) of the verifier to prevent unauthorized re-use of the presentation.
* @param proofOptions Object holding optional arguments for creating and scoping the presentation proof.
* @param proofOptions.proofPurpose Controls the `proofPurpose` property and consequently which verificationMethods can be used for signing.
* @param proofOptions.proofType Controls the type of proof to be created for the presentation.
* @param params.presentationOptions.verifier Identifier (DID) of the verifier to prevent unauthorized re-use of the presentation.
* @param params.proofOptions Object holding optional arguments for creating and scoping the presentation proof.
* @param params.proofOptions.proofPurpose Controls the `proofPurpose` property and consequently which verificationMethods can be used for signing.
* @param params.proofOptions.proofType Controls the type of proof to be created for the presentation.
* Currently, this function only produces {@link DataIntegrity.PROOF_TYPE DataIntegrityProof} type proofs;
* Any other values will be mapped to a known algorithm or cryptosuite for use with this proof type, thus allowing to control the signature algorithm to be used.
* @param proofOptions.challenge A challenge supplied by a verifier in a challenge-response protocol, which allows verifiers to assure signature freshness, preventing unauthorized re-use.
* @param proofOptions.domain A domain string to be included in the proof.
* @param params.proofOptions.challenge A challenge supplied by a verifier in a challenge-response protocol, which allows verifiers to assure signature freshness, preventing unauthorized re-use.
* @param params.proofOptions.domain A domain string to be included in the proof.
* This plays a role similar to the `verifier` option, but is not restricted to DIDs.
* This could, for example, be the domain of a web-application requesting credential presentation.
* @param proofOptions.now Allows manipulating the current date and time for the purpose of presentation & proof generation.
* @param params.proofOptions.now Allows manipulating the current date and time for the purpose of presentation & proof generation.
* Defaults to the current date and time.
* @returns A holder-signed presentation.
*/
export async function createPresentation(
credentials: VerifiableCredential[],
holder: HolderOptions,
presentationOptions: {
export async function createPresentation({
credentials,
holder,
presentationOptions = {},
proofOptions = {},
}: {
credentials: VerifiableCredential[]
holder: HolderOptions
presentationOptions?: {
validFrom?: Date
validUntil?: Date
verifier?: Did
} = {},
proofOptions: {
}
proofOptions?: {
proofPurpose?: string
proofType?: string
challenge?: string
domain?: string
now?: Date
} = {}
): Promise<VerifiablePresentation> {
}
}): Promise<VerifiablePresentation> {
const { didDocument, signers } = holder
const { validFrom, validUntil, verifier } = presentationOptions
const { proofPurpose, proofType, challenge, domain, now } = proofOptions
Expand Down
3 changes: 1 addition & 2 deletions packages/credentials/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import type {
DidDocument,
DidHelpersAcceptedSigners,
HexString,
KiltAddress,
SharedArguments,
TransactionResult,
} from '@kiltprotocol/types'
Expand All @@ -36,7 +35,7 @@ export type SubmitOverride = (
) => Promise<SimplifiedTransactionResult | TransactionResult>

interface SubmitterAddressOrOverride {
submitter: KiltAddress | SubmitOverride
submitter: SharedArguments['submitter'] | SubmitOverride
}

export type IssuerOptions = HolderOptions & SubmitterAddressOrOverride
Expand Down
37 changes: 18 additions & 19 deletions packages/credentials/src/issuer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,34 +90,33 @@ export async function createCredential({
/**
* Issues a Verifiable Credential from on the input document by attaching a proof. Edits to the document may be made depending on the proof type.
*
* @param credential A credential document as returned by {@link createCredential}.
* @param issuer Interfaces for interacting with the issuer identity for the purpose of generating a proof.
* @param issuer.didDocument The DID Document of the issuer.
* @param issuer.signers An array of signer interfaces, each allowing to request signatures made with a key associated with the issuer DID Document.
* @param params Holds all named parameters.
* @param params.credential A credential document as returned by {@link createCredential}.
* @param params.issuer Interfaces for interacting with the issuer identity for the purpose of generating a proof.
* @param params.issuer.didDocument The DID Document of the issuer.
* @param params.issuer.signers An array of signer interfaces, each allowing to request signatures made with a key associated with the issuer DID Document.
* The function will select the first signer that matches requirements around signature algorithm and relationship of the key to the DID as given by the DID Document.
* @param issuer.submitter Some proof types require making transactions to effect state changes on the KILT blockchain.
* @param params.issuer.submitter Some proof types require making transactions to effect state changes on the KILT blockchain.
* The blockchain account whose address is specified here will be used to cover all transaction fees and deposits due for this operation.
* As transactions to the blockchain need to be signed, `signers` is expected to contain a signer interface where the `id` matches this address.
*
* Alternatively, you can pass a {@link SubmitOverride} callback that takes care of Did-authorizing and submitting the transaction.
* If you are using a service that helps you submit and pay for transactions, this is your point of integration to it.
* @param proofOptions Options that control proof generation.
* @param proofOptions.proofType The type of proof to be created.
* @param params.proofOptions Options that control proof generation.
* @param params.proofOptions.proofType The type of proof to be created.
* Defaults to {@link KiltAttestationProofV1.PROOF_TYPE KiltAttestationProofV1} which, as of now, is the only type suppported.
* @param proofOptions.proofPurpose Controls which relationship to the DID is expected of the key selected for creating the proof.
* Defaults to `assertionMethod`, which is also the only value supported for {@link KiltAttestationProofV1.PROOF_TYPE KiltAttestationProofV1} proofs.
* @param proofOptions.now Allows manipulating the current date and time for the purpose of proof generation.
* As of now, this has no effect though.
*/
export async function issue(
credential: UnsignedVc,
issuer: IssuerOptions,
proofOptions: {
export async function issue({
credential,
issuer,
proofOptions = {},
}: {
credential: UnsignedVc
issuer: IssuerOptions
proofOptions?: {
proofType?: string
proofPurpose?: string
now?: Date // given that this has no effect, should I remove it for now?
} = {}
): Promise<VerifiableCredential> {
}
}): Promise<VerifiableCredential> {
const { proofType } = proofOptions
switch (proofType) {
case undefined:
Expand Down
Loading