Skip to content

Commit

Permalink
displays signers during signature share creation (#4821)
Browse files Browse the repository at this point in the history
allows user to confirm list of signers from signing package before creating
signature share

- adds NativeSigningPackage to napi layer, defines 'signers' and
  'unsigned_transaction' methods
- removes 'from_signing_package' from UnsignedTransaction,
  NativeUnsignedTransaction in favor of constructing from NativeSigningPackage
  • Loading branch information
hughy authored Mar 7, 2024
1 parent 4507d23 commit 7437efd
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 24 deletions.
31 changes: 26 additions & 5 deletions ironfish-cli/src/commands/wallet/multisig/signature/create.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { SigningPackage } from '@ironfish/rust-nodejs'
import { UnsignedTransaction } from '@ironfish/sdk'
import { CliUx, Flags } from '@oclif/core'
import { IronfishCommand } from '../../../../command'
Expand Down Expand Up @@ -32,14 +33,20 @@ export class CreateSignatureShareCommand extends IronfishCommand {

async start(): Promise<void> {
const { flags } = await this.parse(CreateSignatureShareCommand)
let signingPackage = flags.signingPackage?.trim()
let signingPackageString = flags.signingPackage?.trim()

if (!signingPackage) {
signingPackage = await longPrompt('Enter the signing package')
if (!signingPackageString) {
signingPackageString = await longPrompt('Enter the signing package')
}

const client = await this.sdk.connectRpc()
const unsignedTransaction = UnsignedTransaction.fromSigningPackage(signingPackage)

const signingPackage = new SigningPackage(Buffer.from(signingPackageString, 'hex'))
const unsignedTransaction = new UnsignedTransaction(
signingPackage.unsignedTransaction().serialize(),
)

this.renderSigners(signingPackage.signers())

await renderUnsignedTransactionDetails(
client,
Expand All @@ -57,11 +64,25 @@ export class CreateSignatureShareCommand extends IronfishCommand {

const signatureShareResponse = await client.wallet.multisig.createSignatureShare({
account: flags.account,
signingPackage,
signingPackage: signingPackageString,
})

this.log()
this.log('Signature Share:')
this.log(signatureShareResponse.content.signatureShare)
}

renderSigners(signers: Buffer[]): void {
this.log('')
this.log('==================')
this.log('Signer Identities:')
this.log('==================')

for (const [i, signer] of signers.entries()) {
if (i !== 0) {
this.log('------------------')
}
this.log(signer.toString('hex'))
}
}
}
7 changes: 6 additions & 1 deletion ironfish-rust-nodejs/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ export class SigningCommitment {
constructor(jsBytes: Buffer)
identity(): Buffer
}
export type NativeSigningPackage = SigningPackage
export class SigningPackage {
constructor(jsBytes: Buffer)
unsignedTransaction(): NativeUnsignedTransaction
signers(): Array<Buffer>
}
export class BoxKeyPair {
constructor()
static fromHex(secretHex: string): BoxKeyPair
Expand Down Expand Up @@ -253,7 +259,6 @@ export class Transaction {
export type NativeUnsignedTransaction = UnsignedTransaction
export class UnsignedTransaction {
constructor(jsBytes: Buffer)
static fromSigningPackage(signingPackageStr: string): NativeUnsignedTransaction
serialize(): Buffer
publicKeyRandomness(): string
hash(): Buffer
Expand Down
3 changes: 2 additions & 1 deletion ironfish-rust-nodejs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ if (!nativeBinding) {
throw new Error(`Failed to load native binding`)
}

const { FishHashContext, IDENTITY_LEN, SECRET_LEN, createSigningCommitment, createSignatureShare, ParticipantSecret, ParticipantIdentity, generateAndSplitKey, PublicKeyPackage, SigningCommitment, contribute, verifyTransform, KEY_LENGTH, NONCE_LENGTH, BoxKeyPair, randomBytes, boxMessage, unboxMessage, RollingFilter, initSignalHandler, triggerSegfault, ASSET_ID_LENGTH, ASSET_METADATA_LENGTH, ASSET_NAME_LENGTH, ASSET_LENGTH, Asset, NOTE_ENCRYPTION_KEY_LENGTH, MAC_LENGTH, ENCRYPTED_NOTE_PLAINTEXT_LENGTH, ENCRYPTED_NOTE_LENGTH, NoteEncrypted, PUBLIC_ADDRESS_LENGTH, RANDOMNESS_LENGTH, MEMO_LENGTH, AMOUNT_VALUE_LENGTH, DECRYPTED_NOTE_LENGTH, Note, PROOF_LENGTH, TRANSACTION_SIGNATURE_LENGTH, TRANSACTION_PUBLIC_KEY_RANDOMNESS_LENGTH, TRANSACTION_EXPIRATION_LENGTH, TRANSACTION_FEE_LENGTH, LATEST_TRANSACTION_VERSION, TransactionPosted, Transaction, verifyTransactions, UnsignedTransaction, aggregateSignatureShares, LanguageCode, generateKey, spendingKeyToWords, wordsToSpendingKey, generateKeyFromPrivateKey, initializeSapling, FoundBlockResult, ThreadPoolHandler, isValidPublicAddress } = nativeBinding
const { FishHashContext, IDENTITY_LEN, SECRET_LEN, createSigningCommitment, createSignatureShare, ParticipantSecret, ParticipantIdentity, generateAndSplitKey, PublicKeyPackage, SigningCommitment, SigningPackage, contribute, verifyTransform, KEY_LENGTH, NONCE_LENGTH, BoxKeyPair, randomBytes, boxMessage, unboxMessage, RollingFilter, initSignalHandler, triggerSegfault, ASSET_ID_LENGTH, ASSET_METADATA_LENGTH, ASSET_NAME_LENGTH, ASSET_LENGTH, Asset, NOTE_ENCRYPTION_KEY_LENGTH, MAC_LENGTH, ENCRYPTED_NOTE_PLAINTEXT_LENGTH, ENCRYPTED_NOTE_LENGTH, NoteEncrypted, PUBLIC_ADDRESS_LENGTH, RANDOMNESS_LENGTH, MEMO_LENGTH, AMOUNT_VALUE_LENGTH, DECRYPTED_NOTE_LENGTH, Note, PROOF_LENGTH, TRANSACTION_SIGNATURE_LENGTH, TRANSACTION_PUBLIC_KEY_RANDOMNESS_LENGTH, TRANSACTION_EXPIRATION_LENGTH, TRANSACTION_FEE_LENGTH, LATEST_TRANSACTION_VERSION, TransactionPosted, Transaction, verifyTransactions, UnsignedTransaction, aggregateSignatureShares, LanguageCode, generateKey, spendingKeyToWords, wordsToSpendingKey, generateKeyFromPrivateKey, initializeSapling, FoundBlockResult, ThreadPoolHandler, isValidPublicAddress } = nativeBinding

module.exports.FishHashContext = FishHashContext
module.exports.IDENTITY_LEN = IDENTITY_LEN
Expand All @@ -264,6 +264,7 @@ module.exports.ParticipantIdentity = ParticipantIdentity
module.exports.generateAndSplitKey = generateAndSplitKey
module.exports.PublicKeyPackage = PublicKeyPackage
module.exports.SigningCommitment = SigningCommitment
module.exports.SigningPackage = SigningPackage
module.exports.contribute = contribute
module.exports.verifyTransform = verifyTransform
module.exports.KEY_LENGTH = KEY_LENGTH
Expand Down
34 changes: 33 additions & 1 deletion ironfish-rust-nodejs/src/frost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::to_napi_err;
use crate::{structs::NativeUnsignedTransaction, to_napi_err};
use ironfish::{
frost::{keys::KeyPackage, round1::SigningCommitments, round2, Randomizer},
frost_utils::{signing_package::SigningPackage, split_spender_key::split_spender_key},
Expand Down Expand Up @@ -306,3 +306,35 @@ impl NativeSigningCommitment {
Buffer::from(self.signing_commitment.identity().serialize().as_slice())
}
}

#[napi(js_name = "SigningPackage")]
pub struct NativeSigningPackage {
signing_package: SigningPackage,
}

#[napi]
impl NativeSigningPackage {
#[napi(constructor)]
pub fn new(js_bytes: JsBuffer) -> Result<NativeSigningPackage> {
let bytes = js_bytes.into_value()?;
SigningPackage::read(bytes.as_ref())
.map(|signing_package| NativeSigningPackage { signing_package })
.map_err(to_napi_err)
}

#[napi]
pub fn unsigned_transaction(&self) -> NativeUnsignedTransaction {
NativeUnsignedTransaction {
transaction: self.signing_package.unsigned_transaction.clone(),
}
}

#[napi]
pub fn signers(&self) -> Vec<Buffer> {
self.signing_package
.signers
.iter()
.map(|signer| Buffer::from(&signer.serialize()[..]))
.collect()
}
}
12 changes: 1 addition & 11 deletions ironfish-rust-nodejs/src/structs/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ pub fn verify_transactions(serialized_transactions: Vec<JsBuffer>) -> Result<boo

#[napi(js_name = "UnsignedTransaction")]
pub struct NativeUnsignedTransaction {
transaction: UnsignedTransaction,
pub(crate) transaction: UnsignedTransaction,
}

#[napi]
Expand All @@ -397,16 +397,6 @@ impl NativeUnsignedTransaction {
Ok(NativeUnsignedTransaction { transaction })
}

#[napi(factory)]
pub fn from_signing_package(signing_package_str: String) -> Result<Self> {
let bytes = hex_to_vec_bytes(&signing_package_str).map_err(to_napi_err)?;
let signing_package = SigningPackage::read(&bytes[..]).map_err(to_napi_err)?;

Ok(NativeUnsignedTransaction {
transaction: signing_package.unsigned_transaction,
})
}

#[napi]
pub fn serialize(&self) -> Result<Buffer> {
let mut vec: Vec<u8> = vec![];
Expand Down
5 changes: 0 additions & 5 deletions ironfish/src/primitives/unsignedTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,6 @@ export class UnsignedTransaction {
reader.seek(TRANSACTION_SIGNATURE_LENGTH)
}

static fromSigningPackage(signingPackage: string): UnsignedTransaction {
const unsigned = NativeUnsignedTransaction.fromSigningPackage(signingPackage)
return new UnsignedTransaction(unsigned.serialize())
}

serialize(): Buffer {
return this.unsignedTransactionSerialized
}
Expand Down

0 comments on commit 7437efd

Please sign in to comment.