diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index e38bb8f..ae47a32 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -457,7 +457,6 @@ impl Builder { // let mut ctx = prover.new_sapling_proving_context(); - let anchor = self.anchor.expect("anchor was set if spends were added"); // Pad Sapling outputs let orig_outputs_len = outputs.len(); @@ -474,40 +473,44 @@ impl Builder { tx_metadata.output_indices.resize(orig_outputs_len, 0); // Create Sapling SpendDescriptions - for (i, (pos, spend)) in spends.iter().enumerate() { - let proof_generation_key = spend.extsk.expsk.proof_generation_key(&JUBJUB); + if !spends.is_empty() { + let anchor = self.anchor.expect("anchor was set if spends were added"); - let mut nullifier = [0u8; 32]; - nullifier.copy_from_slice(&spend.note.nf( - &proof_generation_key.to_viewing_key(&JUBJUB), - spend.witness.position, - &JUBJUB, - )); + for (i, (pos, spend)) in spends.iter().enumerate() { + let proof_generation_key = spend.extsk.expsk.proof_generation_key(&JUBJUB); - let (zkproof, cv, rk) = prover - .spend_proof( - &mut ctx, - proof_generation_key, - spend.diversifier, - spend.note.r, - spend.alpha, - spend.note.value, + let mut nullifier = [0u8; 32]; + nullifier.copy_from_slice(&spend.note.nf( + &proof_generation_key.to_viewing_key(&JUBJUB), + spend.witness.position, + &JUBJUB, + )); + + let (zkproof, cv, rk) = prover + .spend_proof( + &mut ctx, + proof_generation_key, + spend.diversifier, + spend.note.r, + spend.alpha, + spend.note.value, + anchor, + spend.witness.clone(), + ) + .map_err(|()| Error::SpendProof)?; + + self.mtx.shielded_spends.push(SpendDescription { + cv, anchor, - spend.witness.clone(), - ) - .map_err(|()| Error::SpendProof)?; + nullifier, + rk, + zkproof, + spend_auth_sig: None, + }); - self.mtx.shielded_spends.push(SpendDescription { - cv, - anchor, - nullifier, - rk, - zkproof, - spend_auth_sig: None, - }); - - // Record the post-randomized spend location - tx_metadata.spend_indices[*pos] = i; + // Record the post-randomized spend location + tx_metadata.spend_indices[*pos] = i; + } } // Create Sapling OutputDescriptions @@ -622,9 +625,13 @@ impl Builder { let msg = secp256k1::Message::from_slice(&sighash).expect("32 bytes"); let sig = self.legacy.secp.sign(&msg, &info.sk); + // Signature has to have "SIGHASH_ALL" appended to it + let mut sig_bytes: Vec = sig.serialize_der()[..].to_vec(); + sig_bytes.extend(&[SIGHASH_ALL as u8]); + // P2PKH scriptSig self.mtx.vin[i].script_sig = - Script::default() << &sig.serialize_compact()[..] << &info.pubkey[..]; + Script::default() << &sig_bytes[..] << &info.pubkey[..]; } }