diff --git a/ironfish-cli/src/commands/wallet/multisig/signature/create.ts b/ironfish-cli/src/commands/wallet/multisig/signature/create.ts index dab710dfe1..cefed51da5 100644 --- a/ironfish-cli/src/commands/wallet/multisig/signature/create.ts +++ b/ironfish-cli/src/commands/wallet/multisig/signature/create.ts @@ -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' @@ -32,14 +33,20 @@ export class CreateSignatureShareCommand extends IronfishCommand { async start(): Promise { 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, @@ -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')) + } + } } diff --git a/ironfish-rust-nodejs/index.d.ts b/ironfish-rust-nodejs/index.d.ts index eeafbc0b4c..70ac75887d 100644 --- a/ironfish-rust-nodejs/index.d.ts +++ b/ironfish-rust-nodejs/index.d.ts @@ -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 +} export class BoxKeyPair { constructor() static fromHex(secretHex: string): BoxKeyPair @@ -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 diff --git a/ironfish-rust-nodejs/index.js b/ironfish-rust-nodejs/index.js index 865f8b861d..b29fbafa3a 100644 --- a/ironfish-rust-nodejs/index.js +++ b/ironfish-rust-nodejs/index.js @@ -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 @@ -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 diff --git a/ironfish-rust-nodejs/src/frost.rs b/ironfish-rust-nodejs/src/frost.rs index fe8ee8eb28..874145d723 100644 --- a/ironfish-rust-nodejs/src/frost.rs +++ b/ironfish-rust-nodejs/src/frost.rs @@ -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}, @@ -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 { + 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 { + self.signing_package + .signers + .iter() + .map(|signer| Buffer::from(&signer.serialize()[..])) + .collect() + } +} diff --git a/ironfish-rust-nodejs/src/structs/transaction.rs b/ironfish-rust-nodejs/src/structs/transaction.rs index d14dd55b1b..12bb554159 100644 --- a/ironfish-rust-nodejs/src/structs/transaction.rs +++ b/ironfish-rust-nodejs/src/structs/transaction.rs @@ -383,7 +383,7 @@ pub fn verify_transactions(serialized_transactions: Vec) -> Result Result { - 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 { let mut vec: Vec = vec![]; diff --git a/ironfish/src/primitives/unsignedTransaction.ts b/ironfish/src/primitives/unsignedTransaction.ts index b3a79ddbeb..df644f472b 100644 --- a/ironfish/src/primitives/unsignedTransaction.ts +++ b/ironfish/src/primitives/unsignedTransaction.ts @@ -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 }