diff --git a/src/index.ts b/src/index.ts index d3cb085d..84e3b839 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,8 +7,7 @@ import { Adapter } from './signing/adapters/types' import { isValidPair } from './keys' import { Signer, Address } from './types' import ProgramManager from './programs' -import { runDkgProtocol, ValidatorInfo } from '@entropyxyz/entropy-protocol-nodejs' -import { fromHex } from '@entropyxyz/entropy-protocol-nodejs' +import { runDkgProtocol, ValidatorInfo, fromHex } from '@entropyxyz/entropy-protocol-nodejs' export interface EntropyAccount { sigRequestKey?: Signer programModKey?: Signer | string @@ -41,7 +40,7 @@ export interface EntropyOpts { * programModKey: signer, * } * - * const entropy = new Entropy({ account: entropyAccount }); + * const entropy = new Entropy({ account: entropyAccount }) * await entropy.ready * * await entropy.register({ @@ -235,7 +234,9 @@ export default class Entropy { } async participateInDkgForPrivateVisibility (address: string): Promise { + console.log("PRIVATE REGISTER") const blockNumber = await this.substrate.rpc.chain.getHeader().then((header) => header.number.toNumber()) + console.log("block", blockNumber) const validatorsInfo = await this.getDKGCommittee(blockNumber + 1) if (validatorsInfo.length === 0) { throw new Error('No validators info available for DKG.') @@ -253,25 +254,33 @@ export default class Entropy { } async getDKGCommittee (blockNumber: number): Promise { + console.log("GET DKG COMMITTEE") const validatorsInfo: ValidatorInfo[] = [] const SIGNING_PARTY_SIZE = 2 for (let i = 0; i < SIGNING_PARTY_SIZE; i++) { try { const accountId = await this.selectValidatorFromSubgroup(i, blockNumber) + console.log({accountId}) const serverInfoOption = await this.substrate.query.stakingExtension.thresholdServers(accountId) if (serverInfoOption.isNone) { throw new Error("Stash Fetch Error") } + console.log("pre server info") + const serverInfo = serverInfoOption.unwrap() - validatorsInfo.push(new ValidatorInfo(fromHex(serverInfo.x25519PublicKey.toString()), serverInfo.endpoint.toString(), fromHex(serverInfo.tssAccount.toString()))) + console.log("PubKey", serverInfo.x25519PublicKey.toString()) + console.log("endpoint", serverInfo.endpoint.toString()) + console.log("tss", serverInfo.tssAccount.toString()) + validatorsInfo.push(new ValidatorInfo(fromHex(serverInfo.x25519PublicKey.toString()), serverInfo.endpoint.toString(), serverInfo.tssAccount)) } catch (error) { console.error(`Error fetching validator info: ${error}`) throw error } } + console.log("ABOUT TO CONSOLE VALIDATOR INFO") return validatorsInfo } @@ -279,30 +288,36 @@ export default class Entropy { try { const subgroupInfo = await this.substrate.query.stakingExtension.signingGroups(signingGroup) if (subgroupInfo.isNone || subgroupInfo.unwrap().isEmpty) { - throw new Error("Subgroup Fetch Error") + throw new Error("Subgroup information not available or empty.") } - - const subgroupAddresses = subgroupInfo.unwrap() - - for (let attempt = 0; attempt < subgroupAddresses.length; attempt++) { + const subgroupAddresses = subgroupInfo.unwrap().toArray() + + while (subgroupAddresses.length > 0) { const selectionIndex = blockNumber % subgroupAddresses.length const address = subgroupAddresses[selectionIndex] - - const isSynced = await this.substrate.query.stakingExtension.isValidatorSynced(address) - if (isSynced) { - return address.toString() - } else { + + try { + const isSynced = await this.substrate.query.stakingExtension.isValidatorSynced(address) + + if (isSynced) { + console.log(`Address ${address.toString()} is synced.`) + return address.toString() + } else { + subgroupAddresses.splice(selectionIndex, 1) + blockNumber++ + console.log(`Address ${address.toString()} is not synced. Trying next validator.`) + } + } catch (error) { + console.error(`Error checking sync status for address ${address.toString()}:`, error) subgroupAddresses.splice(selectionIndex, 1) } } - throw new Error("No synced validators found in the subgroup.") } catch (error) { - console.error(`Error selecting validator from subgroup: ${error}`) + console.error("Failed to select a validator:", error) throw error } } - /** * Retrieves the verifying key associated with the given address's registration record. * @@ -318,6 +333,13 @@ export default class Entropy { return registeredInfo.toHuman().verifyingKey } + async getKeyVisibility ( address: Address): Promise { + const registeredInfo = await this.substrate.query.relayer.registered(address) + + // @ts-ignore: next line + return registeredInfo.toHuman().keyVisibility + } + /** * Signs a given transaction based on the provided parameters. * @@ -343,9 +365,20 @@ export default class Entropy { throw new Error( 'Initialized in read only state: can not use write functions' ) - return this.signingManager.signTransaction(params) + + const keyVisibilityInfo = await this.getKeyVisibility(this.account.sigRequestKey.wallet.address) + + if (keyVisibilityInfo === 'Private') { + return this.signingManager.privateSign(params) + } else { + return this.signingManager.signTransaction(params) + } } + + + + /** * Signs a signature request hash. This method involves various steps including validator * selection, transaction request formatting, and submission of these requests to validators @@ -365,6 +398,8 @@ export default class Entropy { throw new Error( 'Initialized in read only state: can not use write functions' ) + + return this.signingManager.sign(params) } } diff --git a/src/registration/index.ts b/src/registration/index.ts index 642006d8..ef48361c 100644 --- a/src/registration/index.ts +++ b/src/registration/index.ts @@ -59,7 +59,7 @@ export default class RegistrationManager extends ExtrinsicBaseClass { async register ({ freeTx = false, initialPrograms = [], - keyVisibility = 'Permissioned', + keyVisibility, programModAccount, }: RegistrationParams): Promise { const programModificationAccount = programModAccount @@ -134,6 +134,8 @@ export default class RegistrationManager extends ExtrinsicBaseClass { return registered } + + /** * Verifies the registration status of an address. * diff --git a/src/utils/index.ts b/src/utils/index.ts index 85da31d0..d3efe7ee 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,6 +1,8 @@ import { decodeAddress, encodeAddress } from '@polkadot/keyring' import { hexToU8a, isHex } from '@polkadot/util' import { Address } from '../types' +import { ValidatorInfo } from '../types' +import { ApiPromise } from '@polkadot/api' export interface AnyObject { [key: string]: number | string | string[] | AnyObject @@ -17,7 +19,6 @@ export function typeofthing (thing) { } } - export function stripHexPrefix (str: string): string { if (str.startsWith('0x')) return str.slice(2) return str @@ -88,4 +89,38 @@ export function hex2buf (hex: string): ArrayBuffer { bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16) } return bytes.buffer -} \ No newline at end of file +} + +export async function pickValidatorsBySignature ( + substrate: ApiPromise, + sigRequest: string +): Promise { + const entries = await substrate.query.stakingExtension.signingGroups.entries() + const stashKeys = entries.map((group) => { + const keyGroup = group[1] + const index = parseInt(sigRequest, 16) % keyGroup.unwrap().length + return keyGroup.unwrap()[index] + }) + + const rawValidatorInfo = await Promise.all( + stashKeys.map((stashKey) => + substrate.query.stakingExtension.thresholdServers(stashKey) + ) + ) + + const validatorsInfo: ValidatorInfo[] = rawValidatorInfo.map((validator) => { + const validatorHuman = validator.toHuman() as { + x25519PublicKey: string + endpoint: string + tssAccount: string + } + + return { + x25519_public_key: validatorHuman.x25519PublicKey, + ip_address: validatorHuman.endpoint, + tss_account: validatorHuman.tssAccount, + } + }) + + return validatorsInfo +} diff --git a/tests/index.test.ts b/tests/index.test.ts index d1182fdc..035c1ddb 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -179,7 +179,7 @@ const programConfig = util.u8aToHex(new Uint8Array(byteArray)) await entropy.register({ - keyVisibility: 'Permissioned', + keyVisibility: 'Private', freeTx: false, // initialPrograms: [{ pointer: programData.pointer, config: programData.config }], initialPrograms: [programData], @@ -238,7 +238,9 @@ const programConfig = util.u8aToHex(new Uint8Array(byteArray)) data: '0x' + Buffer.from('Created On Entropy').toString('hex'), } - const signature = await entropy.signTransaction({txParams: basicTx, type: 'eth' }) as string + // const signature = await entropy.signTransaction({txParams: basicTx, type: 'eth' }) as string + const signature = await entropy.signingManager.privateSign({txParams: basicTx, type: 'eth' }) as string + // encoding signature