Skip to content

Commit

Permalink
Intermediate refactoring work
Browse files Browse the repository at this point in the history
  • Loading branch information
ntn-x2 committed Apr 30, 2024
1 parent 1f9506f commit d2b2d2a
Show file tree
Hide file tree
Showing 13 changed files with 454 additions and 548 deletions.
8 changes: 8 additions & 0 deletions src/dipProof/extensions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Copyright (c) 2024, BOTLabs GmbH.
*
* This source code is licensed under the BSD 4-Clause "Original" license
* found in the LICENSE file in the root directory of this source tree.
*/

export * from './timeBoundDidSignature.js'
137 changes: 137 additions & 0 deletions src/dipProof/extensions/timeBoundDidSignature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* Copyright (c) 2024, BOTLabs GmbH.
*
* This source code is licensed under the BSD 4-Clause "Original" license
* found in the LICENSE file in the root directory of this source tree.
*/

import { toChain } from "@kiltprotocol/did"
import { BN } from "@polkadot/util"

import type {
DidUri,
SignExtrinsicCallback,
VerificationKeyRelationship,
VerificationKeyType,
} from "@kiltprotocol/types"
import type { ApiPromise } from "@polkadot/api"
import type { KeyringPair } from "@polkadot/keyring/types"
import type { Call, Hash } from "@polkadot/types/interfaces"
import type { Option } from "@polkadot/types-codec"
import type { Codec } from "@polkadot/types-codec/types"

const defaultValues = {
accountIdRuntimeType: "AccountId",
blockNumberRuntimeType: "u64",
identityDetailsRuntimeType: "Option<u128>",
validUntilOffset: new BN(50),
}

/**
* The Provider options object provided when generating a time-bound DID signature.
*/
export type TimeBoundDidSignatureProviderOpts = {
/** The `DidUri` of the DIP subject that is performing the cross-chain operation. */
didUri: DidUri
/** The `SignatureVerificationRelationship` to use from the provided DID Document to sign the cross-chain payload. */
keyRelationship: VerificationKeyRelationship
/** The list of `Signers` to use to sign the cross-chain payload. */
signer: SignExtrinsicCallback
}
/**
* The Consumer options object provided when generating a DIP DID signature.
*/
export type TimeBoundDidSignatureConsumerOpts = {
/** The runtime definition of an `AccountId`. If not provided, the `AccountId` type is used. */
accountIdRuntimeType?: string
/** The `ApiPromise` instance. */
api: ApiPromise
/** The runtime definition of a `BlockNumber`. If not provided, the `u64` type is used. */
blockNumberRuntimeType?: string
/** The `Call` to DID-authorize. */
call: Call
/** The genesis hash to use for the DID signature. If not provided, it is retrieved at runtime. */
genesisHash?: Hash
/** The runtime definition of the `IdentityDetails`. If not provided, the `Option<u128>` type is used. */
identityDetailsRuntimeType?: string
/** The address of the submitter account on the consumer chain. */
submitterAddress: KeyringPair["address"]
/** The block number until which the DID signature is to be considered fresh. If not provided, the latest best block number + an offset of 50 is used. */
validUntil?: BN
}
/**
* The options object provided when generating a DIP DID signature.
*/
export type TimeBoundDidSignatureOpts = {
consumer: TimeBoundDidSignatureConsumerOpts
provider: TimeBoundDidSignatureProviderOpts
}
/**
* The response object for DIP DID signature.
*/
export type TimeBoundDidSignatureRes = {
signature: Uint8Array
type: VerificationKeyType
validUntil: BN
}
/**
* Generate a DID signature to be used in conjunction with a DIP proof to DID-authorize a cross-chain operation.
*
* @param params The signature generation parameters.
* @returns The generated DIP proof.
*/
export async function generateTimeBoundDipDidSignature({
provider: { didUri, signer, keyRelationship },
consumer: {
api,
call,
submitterAddress,
// Optional
accountIdRuntimeType,
blockNumberRuntimeType,
genesisHash,
identityDetailsRuntimeType,
validUntil,
},
}: TimeBoundDidSignatureOpts): Promise<TimeBoundDidSignatureRes> {
const blockNumber: BN =
validUntil ??
(await api.query.system.number())
.toBn()
.add(defaultValues.validUntilOffset)
const genesis = genesisHash ?? (await api.query.system.blockHash(0))
const actualIdentityDetailsRuntimeType = identityDetailsRuntimeType ?? defaultValues.identityDetailsRuntimeType
const identityDetails = (
await api.query.dipConsumer.identityEntries<Option<Codec>>(toChain(didUri))
).unwrapOr(api.createType(actualIdentityDetailsRuntimeType, null))

const signaturePayload = api
.createType(
`(Call, ${identityDetailsRuntimeType}, ${accountIdRuntimeType ?? defaultValues.accountIdRuntimeType}, ${blockNumberRuntimeType ?? defaultValues.blockNumberRuntimeType}, Hash)`,
[call, identityDetails, submitterAddress, blockNumber, genesis],
)
.toU8a()
const { signature, keyType } = await signer({
data: signaturePayload,
did: didUri,
keyRelationship,
})
return {
validUntil: blockNumber,
signature,
type: keyType,
}
}

export function signatureToCodec(signature: TimeBoundDidSignatureRes): Record<string, Codec> {
const encodedSignature = {
signature: {
[signature.type]: signature.signature
},
validUntil: signature.validUntil
} as any as Codec
return {
signature: encodedSignature
}
}
9 changes: 9 additions & 0 deletions src/dipProof/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Copyright (c) 2024, BOTLabs GmbH.
*
* This source code is licensed under the BSD 4-Clause "Original" license
* found in the LICENSE file in the root directory of this source tree.
*/

export * from './subjectIdentity.js'
export * as extensions from './extensions/index.js'
81 changes: 81 additions & 0 deletions src/dipProof/subjectIdentity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Copyright (c) 2024, BOTLabs GmbH.
*
* This source code is licensed under the BSD 4-Clause "Original" license
* found in the LICENSE file in the root directory of this source tree.
*/

import { toChain } from "@kiltprotocol/did"

import type { PalletDidLookupLinkableAccountLinkableAccountId } from "@kiltprotocol/augment-api"
import type {
DidUri,
DidKey,
} from "@kiltprotocol/types"
import type { ApiPromise } from "@polkadot/api"
import type { Hash } from "@polkadot/types/interfaces"
import type { Codec } from "@polkadot/types-codec/types"

/**
* The options object provided when generating a DIP identity proof.
*/
export type DipIdentityProofOpts = {
/** The `Did` of the subject. */
didUri: DidUri
/** The list of DID verification methods to include in the DIP proof and to reveal to the consumer chain. */
keyIds: Array<DidKey["id"]>
/** A flag indicating whether the web3name should be included in the DIP proof. */
includeWeb3Name: boolean
/** The list of accounts linked to the DID ot include in the DIP proof and to reveal to the consumer chain. */
linkedAccounts: readonly PalletDidLookupLinkableAccountLinkableAccountId[]
/** The `ApiPromise` instance for the provider chain. */
providerApi: ApiPromise
/** The version of the DIP proof to generate. */
version: number
}
/**
* The response object for a generated DIP proof.
*/
export type DipIdentityProofRes = {
/** The generated storage proof. */
proof: {
/** The Merkle proof blinded (not revealed) leaves. */
blinded: Codec
/** The Merkle proof revealed leaves. */
revealed: Codec
}
/** The Merkle root hash which the proof is anchored to. */
root: Hash
}
/**
* Generate a DIP proof that reveals the specified information about the DID subject.
*
* @param params The DIP proof params.
*
* @returns The generated DIP proof.
*/
export async function generateDipIdentityProof({
didUri: did,
keyIds,
includeWeb3Name,
linkedAccounts,
providerApi,
version,
}: DipIdentityProofOpts): Promise<DipIdentityProofRes> {
const proof = await providerApi.call.dipProvider.generateProof({
identifier: toChain(did),
version,
proofKeys: keyIds.map((keyId) => keyId.substring(1)),
accounts: linkedAccounts,
shouldIncludeWeb3Name: includeWeb3Name,
})

if (proof.isErr) {
throw new Error(providerApi.findError(proof.asErr.toHex()).docs.join("\n"))
}

// TODO: Better way to cast this?
const okProof = proof.asOk.toJSON() as any

return okProof
}
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
* @module @kiltprotocol/dip-sdk
*/

export * from "./runtime.js"
export * as stateProof from './stateProof/index.js'
export * as dipProof from './dipProof/index.js'
export * from "./sibling.js"
export * from "./utils.js"
29 changes: 0 additions & 29 deletions src/runtime.ts

This file was deleted.

Loading

0 comments on commit d2b2d2a

Please sign in to comment.