Skip to content

Commit

Permalink
Address Str4d’s comments on ZcashFoundation#171
Browse files Browse the repository at this point in the history
Notably, `HashType` has changed incompatibly, so
ZcashFoundation/zebra#8751 will need to be updated.
  • Loading branch information
sellout committed Sep 27, 2024
1 parent 9d16e79 commit 1fde7fd
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 21 deletions.
46 changes: 31 additions & 15 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
bitflags::bitflags! {
/// The different SigHash types, as defined in <https://zips.z.cash/zip-0143>
///
/// TODO: This is currently defined as `i32` to match the `c_int` constants in this package, but
/// should use librustzcash’s `u8` constants once we’ve removed the C++.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct HashType: i32 {
/// Sign all the outputs
const All = 1;
/// Sign none of the outputs - anyone can spend
const None = 2;
/// Sign one of the outputs - anyone can spend the rest
const Single = 3;
/// Anyone can add inputs to this transaction
const AnyoneCanPay = 0x80;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SignedOutputs {
/// Sign all the outputs
All,
/// Sign one of the outputs - anyone can spend the rest
Single,
/// Sign none of the outputs - anyone can spend
None,
}

/// The different SigHash types, as defined in <https://zips.z.cash/zip-0143>
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct HashType {
pub signed_outputs: SignedOutputs,
/// Anyone can add inputs to this transaction
pub anyone_can_pay: bool,
}

impl HashType {
pub fn from_bits(bits: i32) -> Option<Self> {
let msigned_outputs = match (bits & 2 != 0, bits & 1 != 0) {
(false, false) => None,
(false, true) => Some(SignedOutputs::All),
(true, false) => Some(SignedOutputs::None),
(true, true) => Some(SignedOutputs::Single),
};

msigned_outputs.map(|signed_outputs| HashType {
signed_outputs,
anyone_can_pay: bits & 0x80 != 0,
})
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ extern "C" fn sighash_callback(
let ctx = ctx as *const SighashCalculator;
// SAFETY: `ctx` is a valid `SighashCalculator` passed to `verify_callback` which forwards it to
// the `CallbackTransactionSignatureChecker`.
if let Some(sighash) = unsafe { *ctx }(script_code_vec, HashType::from_bits_retain(hash_type)) {
if let Some(sighash) =
HashType::from_bits(hash_type).and_then(|ht| unsafe { *ctx }(script_code_vec, ht)) {
assert_eq!(sighash_out_len, sighash.len().try_into().unwrap());
// SAFETY: `sighash_out` is a valid buffer created in
// `CallbackTransactionSignatureChecker::CheckSig`.
Expand Down
11 changes: 6 additions & 5 deletions src/zcash_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ use super::interpreter::*;
/// replicates the still-used cases, and then an `Unknown` bucket for anything else that might
/// happen.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum Error {
/// Any failure that results in the script being invalid.
Ok = 0,
Ok,
/// An exception was caught.
VerifyScript = 7,
VerifyScript,
/// The script size can’t fit in a `u32`, as required by the C++ code.
InvalidScriptSize(TryFromIntError),
/// Some other failure value recovered from C++.
Expand All @@ -21,7 +20,9 @@ pub enum Error {
Unknown(i64),
}

/// All signature hashes are 32 bits, since they are necessarily produced by SHA256.
/// All signature hashes are 32 bytes, since they are either:
/// - a SHA-256 output (for v1 or v2 transactions).
/// - a BLAKE2b-256 output (for v3 and above transactions).
pub const SIGHASH_SIZE: usize = 32;

/// A function which is called to obtain the sighash.
Expand All @@ -44,7 +45,7 @@ pub trait ZcashScript {
/// the transaction itself. In particular, the sighash for the spend
/// is obtained using a callback function.
///
/// - sighash_callback: a callback function which is called to obtain the sighash.
/// - sighash: a callback function which is called to obtain the sighash.
/// - n_lock_time: the lock time of the transaction being validated.
/// - is_final: a boolean indicating whether the input being validated is final
/// (i.e. its sequence number is 0xFFFFFFFF).
Expand Down

0 comments on commit 1fde7fd

Please sign in to comment.