Skip to content

Commit 707fc0b

Browse files
committed
Provide a Rustier wrapper for zcash_script
This adds a `Script` trait that exposes slightly Rustier types in order to have a common interface for the existing C++ implementation as well as the upcoming Rust implementation (and a third instance that runs both and checks that the Rust result matches the C++ one).
1 parent c9d7507 commit 707fc0b

File tree

4 files changed

+336
-13
lines changed

4 files changed

+336
-13
lines changed

Cargo.lock

Lines changed: 41 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "zcash_script"
3-
version = "0.2.0"
3+
version = "0.3.0"
44
authors = ["Tamas Blummer <[email protected]>", "Zcash Foundation <[email protected]>"]
55
license = "Apache-2.0"
66
readme = "README.md"
@@ -60,6 +60,9 @@ path = "src/lib.rs"
6060
external-secp = []
6161

6262
[dependencies]
63+
bitflags = "2.5.0"
64+
enum_primitive = "0.1.1"
65+
num-traits = "0.2.19"
6366

6467
[build-dependencies]
6568
# The `bindgen` dependency should automatically upgrade to match the version used by zebra-state's `rocksdb` dependency in:

src/api.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2+
#[repr(u32)]
3+
pub enum Error {
4+
OK = 0,
5+
TxIndex,
6+
TxSizeMismatch,
7+
TxDeserialize,
8+
TxVersion,
9+
AllPrevOutputsSizeMismatch,
10+
AllPrevOutputsDeserialize,
11+
VerifyScript,
12+
Unknown(u32),
13+
}
14+
15+
bitflags::bitflags! {
16+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
17+
pub struct VerificationFlags: u32 {
18+
const None = 0;
19+
const P2SH = 1 << 0;
20+
const CHECKLOCKTIMEVERIFY = 1 << 9;
21+
}
22+
}
23+
24+
bitflags::bitflags! {
25+
/// The different SigHash types, as defined in <https://zips.z.cash/zip-0143>
26+
///
27+
/// TODO: There are three implementations of this (with three distinct primitive types):
28+
/// - u8 constants in librustzcash,
29+
/// - i32 (well, c_int) bitflags from the C++ constants here, and
30+
/// - u32 bitflags in zebra-chain.
31+
///
32+
/// Ideally we could unify on bitflags in librustzcash.
33+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
34+
pub struct HashType: i32 {
35+
/// Sign all the outputs
36+
const All = 1;
37+
/// Sign none of the outputs - anyone can spend
38+
const None = 2;
39+
/// Sign one of the outputs - anyone can spend the rest
40+
const Single = Self::All.bits() | Self::None.bits();
41+
/// Anyone can add inputs to this transaction
42+
const AnyoneCanPay = 0x80;
43+
}
44+
}
45+
46+
/// A function which is called to obtain the sighash.
47+
/// - script_code: the scriptCode being validated. Note that this not always
48+
/// matches script_sig, i.e. for P2SH.
49+
/// - hash_type: the hash type being used.
50+
///
51+
/// The underlying C++ callback doesn’t give much opportunity for rich failure reporting, but
52+
/// returning `None` indicates _some_ failure to produce the desired hash.
53+
///
54+
/// TODO: Can we get the “32” from somewhere rather than hardcoding it?
55+
pub type SighashCallback = dyn Fn(&[u8], HashType) -> Option<[u8; 32]>;
56+
57+
/// The external API of zcash_script. This is defined to make it possible to compare the C++ and
58+
/// Rust implementations.
59+
pub trait Script {
60+
/// Returns 1 if the a transparent input correctly spends the matching output
61+
/// under the additional constraints specified by flags. This function
62+
/// receives only the required information to validate the spend and not
63+
/// the transaction itself. In particular, the sighash for the spend
64+
/// is obtained using a callback function.
65+
///
66+
/// - sighash_callback: a callback function which is called to obtain the sighash.
67+
/// - n_lock_time: the lock time of the transaction being validated.
68+
/// - is_final: a boolean indicating whether the input being validated is final
69+
/// (i.e. its sequence number is 0xFFFFFFFF).
70+
/// - script_pub_key: the scriptPubKey of the output being spent.
71+
/// - script_sig: the scriptSig of the input being validated.
72+
/// - flags: the script verification flags to use.
73+
/// - err: if not NULL, err will contain an error/success code for the operation.
74+
///
75+
/// Note that script verification failure is indicated by err being set to
76+
/// zcash_script_ERR_OK and a return value of 0.
77+
fn verify_callback(
78+
sighash_callback: &SighashCallback,
79+
n_lock_time: i64,
80+
is_final: bool,
81+
script_pub_key: &[u8],
82+
script_sig: &[u8],
83+
flags: VerificationFlags,
84+
) -> Result<(), Error>;
85+
86+
/// Returns the number of transparent signature operations in the input or
87+
/// output script pointed to by script.
88+
fn legacy_sigop_count_script(script: &[u8]) -> u32;
89+
}

0 commit comments

Comments
 (0)