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

[NayNay] Sign takes a verifying key now #382

Merged
merged 18 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from 13 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
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApiPromise, WsProvider } from '@polkadot/api'
import { isValidSubstrateAddress } from './utils'
import RegistrationManager, { RegistrationParams } from './registration'
import SignatureRequestManager, { SigOps, SigWithAdapptersOps } from './signing'
import SignatureRequestManager, { SigOps, SigWithAdaptersOps } from './signing'
import { crypto, loadCryptoLib } from './utils/crypto'
import { Adapter } from './signing/adapters/types'
import ProgramManager from './programs'
Expand Down Expand Up @@ -149,12 +149,12 @@ export default class Entropy {
/**
* Signs a given transaction based on the provided parameters using the appropriate adapter.
*
* @param {SigWithAdapptersOps} params - The parameters for signing the transaction.
* @param {SigWithAdaptersOps} params - The parameters for signing the transaction.
* @returns {Promise<unknown>} A promise that resolves to the transaction signature.
* @throws {Error} If no adapter is found for the specified transaction type.
*/

async signWithAdaptersInOrder (params: SigWithAdapptersOps): Promise<unknown> {
async signWithAdaptersInOrder (params: SigWithAdaptersOps): Promise<unknown> {
(await this.ready) && this.substrate.isReady
return await this.signingManager.signWithAdaptersInOrder(params)
}
Expand Down
37 changes: 22 additions & 15 deletions src/signing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ export interface SigMsgOps {
type?: string
}

export interface SigWithAdapptersOps extends SigMsgOps {
export interface SigWithAdaptersOps extends SigMsgOps {
order: string[]
signatureVerifyingKey?: string
}

export interface SigOps {
sigRequestHash: string
hash: string
type?: string
auxiliaryData?: unknown[]
signatureVerifyingKey?: string
}

/**
Expand Down Expand Up @@ -104,25 +106,24 @@ export default class SignatureRequestManager {
return key
}

/*



/**
DO NOT DELET THIS CODE BLOCK!

Signs a message using the appropriate adapter.

@param {SigMsgOps} params - The message and type for signing.
@param {TxParams} SigMsgOps.txParams - The parameters of the transaction to be signed.
@param {string} [sigTxOps.type] - The type of transaction.
@returns {Promise<unknown>} A promise resolving with the signed transaction.
@param {SigWithAdaptersOps} sigWithAdaptersOps - Parameters for the signature operation
@param {MsgParams} sigWithAdaptersOps.msg - object containing the msg hex string to be sign, in the shape of { msg: string }
@param {string[]} sigWithAdaptersOps.order - array containing the names of adapters in the expected order ['deviceKeyProxy', 'noop']
@param {string} sigWithAdaptersOps.signatureVerifyingKey - verifying key that can be supplied by the user to overwrite the verifying key used from the keyring
@returns {Promise<unknown>} A promise resolving with the signature.
@throws {Error} If no adapter or preSign function is found for the given type.
*/

async signWithAdaptersInOrder ({
msg,
order,
}: SigWithAdapptersOps): Promise<unknown> {
signatureVerifyingKey
}: SigWithAdaptersOps): Promise<unknown> {
if (!order) {
throw new Error(
`must provide order: expecting a string[] of adapter types got: ${order}`
Expand All @@ -142,7 +143,7 @@ export default class SignatureRequestManager {
}
return agg
}, [])
// const { sigRequestHash, auxilary_data } = await
// this is the named keys we care about from post sign. { sigRequestHash, auxilary_data }
const results = await Promise.all(
adaptersToRun.map((adapter) => {
return adapter.preSign(this.signer, msg)
Expand All @@ -161,6 +162,7 @@ export default class SignatureRequestManager {
sigRequestHash,
hash: adaptersToRun[0].HASHING_ALGORITHM,
auxiliaryData,
signatureVerifyingKey,
})
return signature
}
Expand All @@ -170,16 +172,17 @@ export default class SignatureRequestManager {
*
* @param {SigOps} sigOps - Parameters for the signature operation.
* @param {string} sigOps.sigRequestHash - The hash of the signature request to be signed.
* @param {string} [sigOps.hash] - The hash type.
* @param {unknown[]} [sigOps.auxilaryData] - Additional data for the signature operation.
* @param {signatureVerifyingKey} signatureVerifyingKey - The verifying key for the signature requested
* @param {string} sigOps.hash - The name of the hashing algorithm used to hash the signature.
* @param {unknown[]} sigOps.auxilaryData - Additional data for the signature operation.
* @param {signatureVerifyingKey} sigOps.signatureVerifyingKey - The verifying key for the signature requested
* @returns {Promise<Uint8Array>} A promise resolving to the signed hash as a Uint8Array.
*/

async sign ({
sigRequestHash,
hash,
auxiliaryData,
signatureVerifyingKey: signatureVerifyingKeyOverwrite,
rh0delta marked this conversation as resolved.
Show resolved Hide resolved
}: SigOps): Promise<Uint8Array> {
const strippedsigRequestHash = stripHexPrefix(sigRequestHash)
const validatorsInfo: Array<ValidatorInfo> = await this.pickValidators(
Expand All @@ -188,7 +191,11 @@ export default class SignatureRequestManager {
// TO-DO: this needs to be and accounId ie hex string of the address
// which means you need a new key ie device key here

const signatureVerifyingKey = this.verifyingKey
// The need to overwrite the signature verifying key in certain cases is for when
// the program being used to sign a message may require a different verifying key than
// that is generated by the keyring. An example of this is available in the faucet flow within
// Entropy CLI.
const signatureVerifyingKey = signatureVerifyingKeyOverwrite || this.verifyingKey

const txRequest = {
strippedsigRequestHash,
Expand Down
51 changes: 51 additions & 0 deletions tests/sign.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
spinNetworkUp,
spinNetworkDown,
charlieStashSeed,
charlieSeed,
} from './testing-utils'

const NETWORK_TYPE = 'two-nodes'
Expand Down Expand Up @@ -64,6 +65,56 @@ test('Sign', async (t) => {
t.end()
})

test('Sign: custom signatureVerifyingKey', async (t) => {
const run = promiseRunner(t)

/* Setup Network */
await run('network up', spinNetworkUp(NETWORK_TYPE))
await sleep(process.env.GITHUB_WORKSPACE ? 30_000 : 5_000)
t.teardown(async () => {
// this gets called after all tests are run
await charlieStashEntropy.close()
await spinNetworkDown(NETWORK_TYPE).catch((error) =>
console.error('Error while spinning network down', error.message)
)
})

/* Setup Entropy */
await run('wasm', wasmGlobalsReady())
const charlieStashKeyring = new Keyring({ seed: charlieStashSeed, debug: true })
const charlieStashEntropy = new Entropy({
keyring: charlieStashKeyring,
endpoint: 'ws://127.0.0.1:9944',
})

await run('charlieStashEntropy ready', charlieStashEntropy.ready),
await run('charlie stash register', charlieStashEntropy.register())
await run('charlie stash second register', charlieStashEntropy.register())

/* Sign */
const msg = Buffer
.from('Hello world: new signature from charlieStashEntropy!')
.toString('hex')

// no rhyme or reason for the choice of using the charlie seed verifying key, needed to use
rh0delta marked this conversation as resolved.
Show resolved Hide resolved
// a pre-loaded acct on our local devnet in order to get a valid verifying key
rh0delta marked this conversation as resolved.
Show resolved Hide resolved
const signatureVerifyingKey = charlieStashEntropy.keyring.accounts.deviceKey.verifyingKeys[1]
t.notEqual(signatureVerifyingKey, charlieStashEntropy.signingManager.verifyingKey, 'choose non-default signatureVerifyingKey')

const signature = await run(
'sign',
charlieStashEntropy.signWithAdaptersInOrder({
msg: { msg },
order: ['deviceKeyProxy'],
signatureVerifyingKey
})
)

t.true(signature && signature.length > 32, 'signature has some body!')
signature && console.log(signature)

t.end()
})

test('Sign:issue#380', async (t) => {
const { run, entropy } = await setupTest(t)
Expand Down
Loading