-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
454 additions
and
548 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.