-
Notifications
You must be signed in to change notification settings - Fork 0
[NayNay] Registration verifying keys being stripped at Keyring #353
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
Changes from all commits
ee61cd5
5df040a
c3fa46e
935b6a1
0706fe6
f31c7b4
9a98979
eea8541
f3e498c
78704a4
a9f6e68
54b72b1
a2ee367
8eead88
cc2a8be
380c008
682e56b
deeadb7
8b13909
b0eaff6
29e3c45
3a7cdde
264c04a
bfe1c36
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,6 +78,7 @@ export default class Entropy { | |
signer: this.keyring.getLazyLoadAccountProxy(ChildKey.registration), | ||
}) | ||
this.signingManager = new SignatureRequestManager({ | ||
keyring: this.keyring, | ||
signer: this.keyring.getLazyLoadAccountProxy(ChildKey.deviceKey), | ||
substrate: this.substrate, | ||
adapters: opts.adapters, | ||
|
@@ -130,15 +131,11 @@ export default class Entropy { | |
|
||
const verifyingKey = await this.registrationManager.register(params) | ||
// fuck frankie TODO: Make legit function | ||
const vk = this.keyring.accounts[ChildKey.registration].verifyingKeys || [] | ||
this.keyring.accounts[ChildKey.registration].verifyingKeys = [ | ||
...vk, | ||
verifyingKey, | ||
] | ||
this.keyring.accounts[ChildKey.deviceKey].verifyingKeys = [ | ||
...vk, | ||
verifyingKey, | ||
] | ||
const admin = this.keyring.getLazyLoadAccountProxy(ChildKey.registration) | ||
const vk = admin.verifyingKeys || [] | ||
// HACK: these assignments trigger important `account-update` flows via the Proxy | ||
admin.verifyingKeys = [...vk, verifyingKey] | ||
deviceKey.verifyingKeys = [verifyingKey, ...vk] | ||
Comment on lines
+137
to
+138
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question: you changed the order of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the order change is to ensure the new verifying key is the first verifying key in the list on the device keys account. this will be the new verifying key used for signing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. related to #365 |
||
return verifyingKey | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import EventEmitter from 'node:events' | ||
import { deepCopy } from '../utils/housekeeping' | ||
import * as utils from './utils' | ||
import { EntropyAccount, KeyMaterial, PairMaterial } from './types/json' | ||
import { | ||
|
@@ -33,6 +34,7 @@ export default class Keyring { | |
*/ | ||
|
||
constructor (account: KeyMaterial) { | ||
// this repersents keys that are used by the user | ||
this.#used = ['admin', ChildKey.registration] | ||
Object.keys(account).forEach((key) => { | ||
if (typeof account[key] === 'object' && account[key].userContext) { | ||
|
@@ -51,49 +53,47 @@ export default class Keyring { | |
} | ||
const accountsJson = this.#formatAccounts(account) | ||
this.accounts = this.#createFunctionalAccounts(accountsJson) | ||
this.accounts.masterAccountView = accountsJson | ||
} | ||
|
||
/** | ||
* Retrieves the current account information. | ||
* | ||
* @returns An object containing the Entropy account details. | ||
*/ | ||
#formatAccounts (accounts: EntropyAccount): EntropyAccount { | ||
|
||
// IMPORTANT!! WE SHOULD DECIDE IF WE WILL ALWAYS BE GENERATING UUID FOR ACCOUNTS OR IF WE | ||
// WILL ALLOW USERS TO PASS THEIR OWN STRINGS | ||
const { seed, type, admin } = accounts | ||
const debug = true | ||
const entropyAccountsJson = { | ||
debug, | ||
// previously was seed ? seed : utils.seedFromMnemonic(mnemonic) but this has already been derived in the constructor | ||
// @frankie correct if im wrong here | ||
seed: this.#seed, | ||
type, | ||
admin, | ||
} | ||
|
||
getAccount (): EntropyAccount { | ||
const { debug, seed, type, verifyingKeys } = this.accounts.masterAccountView | ||
const entropyAccount: EntropyAccount = { debug, seed, type, verifyingKeys } | ||
this.#used.forEach((accountName) => { | ||
entropyAccount[accountName] = this.accounts.masterAccountView[accountName] | ||
}) | ||
entropyAccount.admin = this.accounts.registration | ||
return entropyAccount | ||
} | ||
|
||
#createFunctionalAccounts ( | ||
masterAccountView: EntropyAccount | ||
): AccountsEmitter { | ||
const accounts = new EventEmitter() as AccountsEmitter | ||
accounts.type = accounts.type || EntropyAccountType.MIXED_ACCOUNT | ||
Object.keys(masterAccountView).forEach((name) => { | ||
if (name) { | ||
if (typeof masterAccountView[name] !== 'object') return | ||
const { seed, path } = masterAccountView[name] | ||
if (!seed) return | ||
const { pair, address } = utils.generateKeyPairFromSeed(seed, path) | ||
const functionalAccount = { | ||
seed, | ||
path, | ||
address, | ||
pair, | ||
Object.keys(accounts) | ||
.concat(ACCOUNTS) | ||
.forEach((key) => { | ||
|
||
let account: PairMaterial | ||
if (entropyAccountsJson[key]) return | ||
if (key === ChildKey.registration && admin?.seed) { | ||
if (accounts[key]) { | ||
account = { ...admin, ...accounts[key] } | ||
} else { | ||
account = admin | ||
} | ||
|
||
entropyAccountsJson[key] = this.#jsonAccountCreator(account, debug) | ||
return | ||
} | ||
accounts[name] = functionalAccount | ||
} | ||
}) | ||
accounts.masterAccountView = masterAccountView | ||
return accounts | ||
if (accounts[key] && accounts[key].userContext) account = accounts[key] | ||
else if (ChildKey[key]) account = { type: ChildKey[key], seed } | ||
if (!account) return | ||
entropyAccountsJson[key] = this.#jsonAccountCreator(account, debug) | ||
}) | ||
if (!admin) entropyAccountsJson.admin = entropyAccountsJson[ChildKey.registration] | ||
|
||
return entropyAccountsJson as EntropyAccount | ||
} | ||
|
||
/** | ||
|
@@ -129,34 +129,50 @@ export default class Keyring { | |
return jsonAccount | ||
} | ||
|
||
#formatAccounts (accounts: EntropyAccount): EntropyAccount { | ||
const { seed, mnemonic, type, admin } = accounts | ||
// this is because stuff is broken outside of debug mode so making it true always | ||
const debug = true | ||
const entropyAccountsJson = { | ||
debug, | ||
seed: seed ? seed : utils.seedFromMnemonic(mnemonic), | ||
type, | ||
admin, | ||
} | ||
#createFunctionalAccounts ( | ||
masterAccountView: EntropyAccount | ||
): AccountsEmitter { | ||
|
||
Object.keys(accounts) | ||
.concat(ACCOUNTS) | ||
.forEach((key) => { | ||
let account: PairMaterial | ||
if (entropyAccountsJson[key]) return | ||
if (key === ChildKey.registration && admin?.seed) { | ||
account = admin | ||
entropyAccountsJson[key] = this.#jsonAccountCreator(account, debug) | ||
return | ||
const accounts = new EventEmitter() as AccountsEmitter | ||
accounts.type = accounts.type || EntropyAccountType.MIXED_ACCOUNT | ||
Object.keys(masterAccountView).forEach((name) => { | ||
if (name) { | ||
if (typeof masterAccountView[name] !== 'object') return | ||
const { seed, path, ...accountData } = masterAccountView[name] | ||
if (!seed) return | ||
const { pair, address } = utils.generateKeyPairFromSeed(seed, path) | ||
const functionalAccount = { | ||
...accountData, | ||
seed, | ||
path, | ||
address, | ||
pair, | ||
} | ||
if (accounts[key] && accounts[key].userContext) account = accounts[key] | ||
else if (ChildKey[key]) account = { type: ChildKey[key], seed } | ||
if (!account) return | ||
entropyAccountsJson[key] = this.#jsonAccountCreator(account, debug) | ||
}) | ||
accounts[name] = functionalAccount | ||
} | ||
}) | ||
accounts.masterAccountView = masterAccountView | ||
return accounts | ||
} | ||
|
||
return entropyAccountsJson as EntropyAccount | ||
/** | ||
* Retrieves the current account information. | ||
* | ||
* @returns An object containing the Entropy account details. | ||
*/ | ||
|
||
// IMPORTANT!! WE SHOULD DECIDE IF WE WILL ALWAYS BE GENERATING UUID FOR ACCOUNTS OR IF WE | ||
// WILL ALLOW USERS TO PASS THEIR OWN STRINGS | ||
|
||
getAccount (): EntropyAccount { | ||
const { debug, seed, type, verifyingKeys } = this.accounts.masterAccountView | ||
const entropyAccount: EntropyAccount = { debug, seed, type, verifyingKeys } | ||
this.#used.forEach((accountName) => { | ||
if (this.accounts[accountName] === undefined) return | ||
entropyAccount[accountName] = deepCopy(this.accounts[accountName] as PairMaterial) | ||
}) | ||
entropyAccount.admin = entropyAccount.registration | ||
return entropyAccount | ||
} | ||
|
||
/** | ||
|
@@ -178,8 +194,12 @@ export default class Keyring { | |
this.#used.push(childKey) | ||
} | ||
this.accounts[childKey][k] = v | ||
this.accounts.emit(`#account-update`, this.getAccount()) | ||
this.accounts.masterAccountView[childKey][k] = v | ||
// DO NOT REMOVE setTimeout UNLESS YOU SOLVED THE RACE CONDITION | ||
setTimeout( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment why this is necessary/ needed plz |
||
() => this.accounts.emit(`account-update`, this.getAccount()), | ||
10 | ||
) | ||
return v | ||
}, | ||
}) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,10 @@ import { EncMsg, ValidatorInfo } from '../types/internal' | |
import { stripHexPrefix, sendHttpPost, toHex } from '../utils' | ||
import { crypto } from '../utils/crypto' | ||
import { CryptoLib } from '../utils/crypto/types' | ||
import Keyring from '../keys' | ||
|
||
export interface Config { | ||
keyring: Keyring | ||
signer: Signer | ||
substrate: ApiPromise | ||
adapters: { [key: string | number]: Adapter } | ||
|
@@ -51,6 +53,7 @@ export interface UserSignatureRequest { | |
* Constructs a SignatureRequestManager instance. | ||
* | ||
* @param {Config} config - The configuration for the SignatureRequestManager. | ||
* @param {Keyring} config.keyring - The full keyring | ||
* @param {Signer} config.signer - The Signer instance. | ||
* @param {ApiPromise} config.substrate - The Substrate API instance. | ||
* @param {Adapter} config.adapters - The adapters for handling different types of transactions. | ||
|
@@ -60,20 +63,23 @@ export interface UserSignatureRequest { | |
export default class SignatureRequestManager { | ||
adapters: { [key: string | number]: Adapter } | ||
crypto: CryptoLib | ||
keyring: Keyring | ||
signer: Signer | ||
Comment on lines
+66
to
67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think that maybe we do keyring or signer but not both. Your thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the signer in this case is coming from the deviceKeys account, we could remove the keyring from here and include the deviceKey signer and the registration signer and just switch between the two, thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't comment on this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think for now we should leave this as-is until we can solidify that registering is working as expected |
||
substrate: ApiPromise | ||
|
||
/** | ||
* Initializes a new instance of `SignatureRequestManager`. | ||
* | ||
* @param {Config} config - Configuration settings for the manager. | ||
* @param {Keyring} config.keyring - The full keyring | ||
* @param {Signer} config.signer - The signer for authorizing transactions. | ||
* @param {ApiPromise} config.substrate - Instance of the Polkadot/Substrate API. | ||
* @param {Adapter[]} config.adapters - Set of adapters for handling different types of transactions. | ||
* @param {CryptoLib} config.crypto - Instance of CryptoLib for cryptographic operations. | ||
*/ | ||
|
||
constructor ({ signer, substrate, adapters, crypto }: Config) { | ||
constructor ({ keyring, signer, substrate, adapters, crypto }: Config) { | ||
this.keyring = keyring | ||
this.signer = signer | ||
this.substrate = substrate | ||
this.crypto = crypto | ||
|
@@ -90,7 +96,12 @@ export default class SignatureRequestManager { | |
*/ | ||
|
||
get verifyingKey () { | ||
return this.signer.verifyingKeys ? this.signer.verifyingKeys[0] : undefined | ||
let key = this.signer?.verifyingKeys?.[0] | ||
// Returning verifying key from regsitration account if device key keys do not exist | ||
if (!key) { | ||
key = this.keyring.accounts.registration.verifyingKeys[0] | ||
} | ||
frankiebee marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return key | ||
} | ||
|
||
/* | ||
|
@@ -137,6 +148,7 @@ export default class SignatureRequestManager { | |
return adapter.preSign(this.signer, msg) | ||
}) | ||
) | ||
|
||
// [AuxData[], ...] | ||
const auxiliaryDataCollection = results.map(({ auxilary_data }) => { | ||
return auxilary_data | ||
|
@@ -247,8 +259,8 @@ export default class SignatureRequestManager { | |
|
||
// TODO: auxilaryData full implementation | ||
if (auxiliaryData) { | ||
txRequestData.auxilary_data = auxiliaryData.map((signleAuxData) => | ||
toHex(JSON.stringify(signleAuxData)) | ||
txRequestData.auxilary_data = auxiliaryData.map((singleAuxData) => | ||
toHex(JSON.stringify(singleAuxData)) | ||
) | ||
} | ||
// TODO handle array here | ||
|
@@ -302,10 +314,12 @@ export default class SignatureRequestManager { | |
txReq.map(async (message: EncMsg) => { | ||
// Extract the required fields from parsedMsg | ||
const parsedMsg = JSON.parse(message.msg) | ||
|
||
const payload = { | ||
...parsedMsg, | ||
msg: parsedMsg.msg, | ||
} | ||
|
||
const sigProof = (await sendHttpPost( | ||
`http://${message.url}/user/sign_tx`, | ||
JSON.stringify(payload) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
|
||
|
||
|
||
|
||
// maybe lodash maybe not? | ||
// keep in mind registering can take over 20 seconds | ||
// if we | ||
|
||
/** | ||
* returns a deep copy of the object */ | ||
export function deepCopy (thing: any): any { | ||
return JSON.parse(JSON.stringify(thing)) | ||
} |
Uh oh!
There was an error while loading. Please reload this page.