Skip to content

Commit

Permalink
allows constructing NativeSigningCommitment from raw (#5378)
Browse files Browse the repository at this point in the history
updates ironfish-frost dependency to latest commit

adds napi binding for SigningCommitment::from_raw to support constructing a
signing commitment from its raw parts (the signer identity, the raw commitments,
and the transaction hash and list of signers for computing a checksum)

removes signing_package_from_raw in favor of constructing SingingCommitments and
using existing signing_package method
  • Loading branch information
hughy authored Sep 17, 2024
1 parent 1249c3c commit baf314e
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 44 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion ironfish-rust-nodejs/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,6 @@ export class UnsignedTransaction {
publicKeyRandomness(): string
hash(): Buffer
signingPackage(nativeIdentiferCommitments: Array<string>): string
signingPackageFromRaw(identities: Array<string>, rawCommitments: Array<string>): string
sign(spenderHexKey: string): Buffer
addSignature(signature: Buffer): Buffer
}
Expand Down Expand Up @@ -361,6 +360,8 @@ export namespace multisig {
export type NativeSigningCommitment = SigningCommitment
export class SigningCommitment {
constructor(jsBytes: Buffer)
static fromRaw(identity: string, rawCommitments: Buffer, transactionHash: Buffer, signers: Array<string>): NativeSigningCommitment
serialize(): Buffer
identity(): Buffer
rawCommitments(): Buffer
verifyChecksum(transactionHash: Buffer, signerIdentities: Array<string>): boolean
Expand Down
37 changes: 36 additions & 1 deletion ironfish-rust-nodejs/src/multisig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
use crate::{structs::NativeUnsignedTransaction, to_napi_err};
use ironfish::{
frost::{
frost::round2::SignatureShare as FrostSignatureShare, keys::KeyPackage, round2, Randomizer,
frost::{round1::SigningCommitments, round2::SignatureShare as FrostSignatureShare},
keys::KeyPackage,
round2, Randomizer,
},
frost_utils::{
account_keys::derive_account_keys, signing_package::SigningPackage,
Expand Down Expand Up @@ -379,6 +381,39 @@ impl NativeSigningCommitment {
.map_err(to_napi_err)
}

#[napi(factory)]
pub fn from_raw(
identity: String,
raw_commitments: JsBuffer,
transaction_hash: JsBuffer,
signers: Vec<String>,
) -> Result<NativeSigningCommitment> {
let identity =
Identity::deserialize_from(&hex_to_vec_bytes(&identity).map_err(to_napi_err)?[..])
.map_err(to_napi_err)?;

let raw_commitments =
SigningCommitments::deserialize(raw_commitments.into_value()?.as_ref())
.map_err(to_napi_err)?;

let signers = try_deserialize_identities(signers)?;

let signing_commitment = SigningCommitment::from_raw(
raw_commitments,
identity,
transaction_hash.into_value()?.as_ref(),
&signers[..],
)
.map_err(to_napi_err)?;

Ok(NativeSigningCommitment { signing_commitment })
}

#[napi]
pub fn serialize(&self) -> Buffer {
Buffer::from(self.signing_commitment.serialize().as_slice())
}

#[napi]
pub fn identity(&self) -> Buffer {
Buffer::from(self.signing_commitment.identity().serialize().as_slice())
Expand Down
32 changes: 0 additions & 32 deletions ironfish-rust-nodejs/src/structs/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use ironfish::frost::round1::SigningCommitments;
use ironfish::frost::round2::SignatureShare as FrostSignatureShare;
use ironfish::frost::Identifier;
use ironfish::frost_utils::signing_package::SigningPackage;
use ironfish::participant::Identity;
use ironfish::serializing::bytes_to_hex;
use ironfish::serializing::fr::FrSerializable;
use ironfish::serializing::hex_to_vec_bytes;
Expand Down Expand Up @@ -456,37 +455,6 @@ impl NativeUnsignedTransaction {
Ok(bytes_to_hex(&vec))
}

#[napi]
pub fn signing_package_from_raw(
&self,
identities: Vec<String>,
raw_commitments: Vec<String>,
) -> Result<String> {
let mut commitments = Vec::new();

for (index, identity) in identities.iter().enumerate() {
let identity_bytes = hex_to_vec_bytes(identity).map_err(to_napi_err)?;
let identity = Identity::deserialize_from(&identity_bytes[..]).map_err(to_napi_err)?;

let raw_commitment = &raw_commitments[index];
let commitment_bytes = hex_to_vec_bytes(raw_commitment).map_err(to_napi_err)?;
let commitment =
SigningCommitments::deserialize(&commitment_bytes[..]).map_err(to_napi_err)?;

commitments.push((identity, commitment));
}

let signing_package = self
.transaction
.signing_package(commitments)
.map_err(to_napi_err)?;

let mut vec: Vec<u8> = vec![];
signing_package.write(&mut vec).map_err(to_napi_err)?;

Ok(bytes_to_hex(&vec))
}

#[napi]
pub fn sign(&mut self, spender_hex_key: String) -> Result<Buffer> {
let spender_key = SaplingKey::from_hex(&spender_hex_key).map_err(to_napi_err)?;
Expand Down
23 changes: 14 additions & 9 deletions ironfish/src/multisig.test.slow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,23 @@ describe('multisig', () => {

// Simulates receiving raw commitments from Ledger
// Ledger app generates raw commitments, not wrapped SigningCommitment
const commitmentIdentities: string[] = []
const rawCommitments: string[] = []
const signingCommitments: string[] = []
for (const commitment of commitments) {
const signingCommitment = new multisig.SigningCommitment(Buffer.from(commitment, 'hex'))
commitmentIdentities.push(signingCommitment.identity().toString('hex'))
rawCommitments.push(signingCommitment.rawCommitments().toString('hex'))
const deserializedSigningCommitment = new multisig.SigningCommitment(
Buffer.from(commitment, 'hex'),
)

const signingCommitment = multisig.SigningCommitment.fromRaw(
deserializedSigningCommitment.identity().toString('hex'),
deserializedSigningCommitment.rawCommitments(),
transactionHash,
identities,
)

signingCommitments.push(signingCommitment.serialize().toString('hex'))
}

const signingPackage = unsignedTransaction.signingPackageFromRaw(
commitmentIdentities,
rawCommitments,
)
const signingPackage = unsignedTransaction.signingPackage(signingCommitments)

// Ensure that we can extract deserialize and extract frost signing package
// Ledger app needs frost signing package to generate signature shares
Expand Down

0 comments on commit baf314e

Please sign in to comment.