Skip to content
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

private flow for register in entropy class WIP #301

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
205 changes: 173 additions & 32 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { isValidPair } from './keys'
import { Signer, Address } from './types'
import ProgramManager from './programs'

import { runDkgProtocol, ValidatorInfo, fromHex } from '@entropyxyz/entropy-protocol-nodejs'
export interface EntropyAccount {
sigRequestKey?: Signer
programModKey?: Signer | string
Expand All @@ -33,21 +33,21 @@
*
* @example
* ```typescript
* const signer = await getWallet(charlieStashSeed);
* const signer = await getWallet(charlieStashSeed)
*
* const entropyAccount: EntropyAccount = {
* sigRequestKey: signer,
* programModKey: signer,
* };
* }
*
* const entropy = new Entropy({ account: entropyAccount });
* await entropy.ready;
* const entropy = new Entropy({ account: entropyAccount })
* await entropy.ready
*
* await entropy.register({
* programModAccount: '5Gw3s7q9...',
* keyVisibility: 'Permissioned',
* freeTx: false
* });
* await entropy.register({
* programModAccount: '5Gw3s7q9...',
* keyVisibility: 'Permissioned',
* freeTx: false
* })
* ```
* @alpha
*/
Expand Down Expand Up @@ -79,7 +79,6 @@
* @param {Adapter[]} [opts.adapters] - A collection of signing adapters for handling various transaction types.
*/


constructor (opts: EntropyOpts) {
this.ready = new Promise((resolve, reject) => {
this.#ready = resolve
Expand All @@ -101,23 +100,37 @@

this.registrationManager = new RegistrationManager({
substrate: this.substrate,
signer: {wallet: this.account.sigRequestKey.wallet, pair: this.account.sigRequestKey.pair},
signer: {
wallet: this.account.sigRequestKey.wallet,
pair: this.account.sigRequestKey.pair,
},
})
this.signingManager = new SignatureRequestManager({
signer: {wallet: this.account.sigRequestKey.wallet, pair: this.account.sigRequestKey.pair},
signer: {
wallet: this.account.sigRequestKey.wallet,
pair: this.account.sigRequestKey.pair,
},
substrate: this.substrate,
adapters: opts.adapters,
crypto,
})

const programModKeyPair = isValidPair(this.account.programModKey as Signer) ? this.account.programModKey : undefined
const programModKeyPair = isValidPair(this.account.programModKey as Signer)
? this.account.programModKey
: undefined

this.programs = new ProgramManager({
substrate: this.substrate,
programModKey: programModKeyPair as Signer || this.account.sigRequestKey,
programDeployKey: this.account.programDeployKey
programModKey:
(programModKeyPair as Signer) || this.account.sigRequestKey,
programDeployKey: this.account.programDeployKey,
})
if (this.#programReadOnly || this.#allReadOnly) this.programs.set = async () => { throw new Error('Programs is in a read only state: Must pass a valid key pair in initialization.') }
if (this.#programReadOnly || this.#allReadOnly)
this.programs.set = async () => {
throw new Error(
'Programs is in a read only state: Must pass a valid key pair in initialization.'
)
}
this.#ready(true)
this.isRegistered = this.registrationManager.checkRegistrationStatus.bind(
this.registrationManager
Expand All @@ -141,10 +154,9 @@
}
}


/** @internal */
#setReadOnlyStates (): void {
// the readOnly state will not allow for write functions
// the readOnly state will not allow for write functions
this.#programReadOnly = false
this.#allReadOnly = false

Expand All @@ -154,11 +166,17 @@
this.#allReadOnly = true
}


if (typeof this.account.sigRequestKey !== 'object') {
throw new Error('AccountTypeError: sigRequestKey can not be a string')
} else if (!isValidPair({ wallet: this.account.sigRequestKey.wallet, pair: this.account.sigRequestKey.pair})) {
throw new Error('AccountTypeError: sigRequestKey not a valid signing pair')
} else if (
!isValidPair({
wallet: this.account.sigRequestKey.wallet,
pair: this.account.sigRequestKey.pair,
})
) {
throw new Error(
'AccountTypeError: sigRequestKey not a valid signing pair'
)
}

if (typeof this.account.programModKey === 'string') {
Expand All @@ -169,7 +187,6 @@
}
}


/**
* Registers an address with Entropy using the provided parameters.
*
Expand All @@ -187,7 +204,10 @@
params: RegistrationParams & { account?: EntropyAccount }
): Promise<void> {
await this.ready
if (this.#allReadOnly) throw new Error('Initialized in read only state: can not use write functions')
if (this.#allReadOnly)
throw new Error(
'Initialized in read only state: can not use write functions'
)
const account = params.account || this.account

if (!account) {
Expand All @@ -198,26 +218,128 @@
params.programModAccount &&
!isValidSubstrateAddress(params.programModAccount)
) {
throw new TypeError('Incompatible address type')
throw new TypeError('Incompatible address type')
}
await this.registrationManager.register(params)
this.account.verifyingKey = await this.getVerifyingKey(this.account.sigRequestKey.wallet.address)

if (params.keyVisibility === 'Private') {
await this.participateInDkgForPrivateVisibility(
this.account.sigRequestKey.wallet.address
)

await this.registrationManager.register(params)
this.account.verifyingKey = await this.getVerifyingKey(
this.account.sigRequestKey.wallet.address
)
}
}

async participateInDkgForPrivateVisibility (address: string): Promise<void> {
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.')
}

const selectedValidatorAccountId = await this.selectValidatorFromSubgroup(0, blockNumber)
const selectedValidatorInfo = validatorsInfo.find(v => v.getTssAccount().toString() === selectedValidatorAccountId)

if (!selectedValidatorInfo) {
throw new Error('Selected validator info not found.')
}

await runDkgProtocol([selectedValidatorInfo], this.account.sigRequestKey.pair.secretKey)
console.log('DKG Protocol completed for address:', address)
}

async getDKGCommittee (blockNumber: number): Promise<ValidatorInfo[]> {
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) {

Check failure on line 267 in src/index.ts

View workflow job for this annotation

GitHub Actions / Build, test, and lint

Property 'isNone' does not exist on type 'Codec'.
throw new Error("Stash Fetch Error")
}

console.log("pre server info")

const serverInfo = serverInfoOption.unwrap()

Check failure on line 273 in src/index.ts

View workflow job for this annotation

GitHub Actions / Build, test, and lint

Property 'unwrap' does not exist on type 'Codec'.
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
}
async selectValidatorFromSubgroup (signingGroup: number, blockNumber: number): Promise<string> {
try {
const subgroupInfo = await this.substrate.query.stakingExtension.signingGroups(signingGroup)
if (subgroupInfo.isNone || subgroupInfo.unwrap().isEmpty) {

Check failure on line 290 in src/index.ts

View workflow job for this annotation

GitHub Actions / Build, test, and lint

Property 'isNone' does not exist on type 'Codec'.

Check failure on line 290 in src/index.ts

View workflow job for this annotation

GitHub Actions / Build, test, and lint

Property 'unwrap' does not exist on type 'Codec'.
throw new Error("Subgroup information not available or empty.")
}
const subgroupAddresses = subgroupInfo.unwrap().toArray()

Check failure on line 293 in src/index.ts

View workflow job for this annotation

GitHub Actions / Build, test, and lint

Property 'unwrap' does not exist on type 'Codec'.

while (subgroupAddresses.length > 0) {
const selectionIndex = blockNumber % subgroupAddresses.length
const address = subgroupAddresses[selectionIndex]

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("Failed to select a validator:", error)
throw error
}
}
/**
* Retrieves the verifying key associated with the given address's registration record.
*
* @param {Address} address - The address for which the verifying key is needed.
* @returns {Promise<string>} - A promise resolving to the verifying key.
*/

async getVerifyingKey (address: Address): Promise<string> {
const registeredInfo = await this.substrate.query.relayer.registered(address)
const registeredInfo = await this.substrate.query.relayer.registered(
address
)
// @ts-ignore: next line

Check warning on line 332 in src/index.ts

View workflow job for this annotation

GitHub Actions / Build, test, and lint

Do not use "@ts-ignore" because it alters compilation errors
return registeredInfo.toHuman().verifyingKey
}

async getKeyVisibility ( address: Address): Promise<string> {
const registeredInfo = await this.substrate.query.relayer.registered(address)

// @ts-ignore: next line

Check warning on line 339 in src/index.ts

View workflow job for this annotation

GitHub Actions / Build, test, and lint

Do not use "@ts-ignore" because it alters compilation errors
return registeredInfo.toHuman().keyVisibility
}

/**
* Signs a given transaction based on the provided parameters.
*
Expand All @@ -239,10 +361,24 @@

async signTransaction (params: SigTxOps): Promise<unknown> {
await this.ready
if (this.#allReadOnly) throw new Error('Initialized in read only state: can not use write functions')
return this.signingManager.signTransaction(params)
if (this.#allReadOnly)
throw new Error(
'Initialized in read only state: can not use write functions'
)

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
Expand All @@ -258,7 +394,12 @@

async sign (params: SigOps): Promise<Uint8Array> {
await this.ready
if (this.#allReadOnly) throw new Error('Initialized in read only state: can not use write functions')
if (this.#allReadOnly)
throw new Error(
'Initialized in read only state: can not use write functions'
)


return this.signingManager.sign(params)
}
}
4 changes: 3 additions & 1 deletion src/registration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
async register ({
freeTx = false,
initialPrograms = [],
keyVisibility = 'Permissioned',
keyVisibility,
programModAccount,
}: RegistrationParams): Promise<RegisteredInfo> {
const programModificationAccount = programModAccount
Expand Down Expand Up @@ -99,11 +99,11 @@
const registeredData = await this.substrate.query.relayer.registered(
this.signer.wallet.address
)
// @ts-ignore: next line

Check warning on line 102 in src/registration/index.ts

View workflow job for this annotation

GitHub Actions / Build, test, and lint

Do not use "@ts-ignore" because it alters compilation errors
if (!registeredData.isSome) {
throw new Error('Registration information not found')
}
// @ts-ignore: next line

Check warning on line 106 in src/registration/index.ts

View workflow job for this annotation

GitHub Actions / Build, test, and lint

Do not use "@ts-ignore" because it alters compilation errors
const data = registeredData.unwrap()
resolve({
keyVisibility: data.keyVisibility.toJSON() as KeyVisibilityInfo,
Expand Down Expand Up @@ -134,6 +134,8 @@
return registered
}



/**
* Verifies the registration status of an address.
*
Expand Down
Loading
Loading