Skip to content

Commit

Permalink
Remove dependencies by switching to simplified API with a callback in…
Browse files Browse the repository at this point in the history
…terface (#157)

* created zcash_script_verify_prehashed; compiles

* removed unneded code; callback API

* revert formatting changes to interpreter.cpp/.h

* remove prehashed code

* moving code around

* use #if 0 instead of commenting out to make diff clearer

* tmp

* remove debug prints

* cleanups

* deleted unneeded rust files

* remove unneeded dependencies

* remove more unneeded files

* add new tests and remove old ones

* remove unneded params; add sighashLen to callback

* remove unneeded code

* msvc fixes
  • Loading branch information
conradoplg committed Jun 4, 2024
1 parent ef2a7fd commit 4924030
Show file tree
Hide file tree
Showing 30 changed files with 354 additions and 3,132 deletions.
1,876 changes: 149 additions & 1,727 deletions Cargo.lock

Large diffs are not rendered by default.

79 changes: 28 additions & 51 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,40 @@ include = [
"build.rs",
"src/*.rs",
"/depend/check_uint128_t.c",
"/depend/zcash/src/script/zcash_script.h",
"/depend/zcash/src/script/zcash_script.cpp",
"/depend/zcash/src/utilstrencodings.cpp",
"/depend/zcash/src/uint256.cpp",
"/depend/zcash/src/pubkey.cpp",
"/depend/zcash/src/hash.cpp",
"/depend/zcash/src/primitives/transaction.cpp",
"/depend/zcash/src/amount.cpp",
"/depend/zcash/src/amount.h",
"/depend/zcash/src/compat/byteswap.h",
"/depend/zcash/src/compat/endian.h",
"/depend/zcash/src/consensus/consensus.h",
"/depend/zcash/src/crypto/common.h",
"/depend/zcash/src/crypto/ripemd160.cpp",
"/depend/zcash/src/crypto/ripemd160.h",
"/depend/zcash/src/crypto/sha1.cpp",
"/depend/zcash/src/crypto/sha1.h",
"/depend/zcash/src/crypto/sha256.cpp",
"/depend/zcash/src/crypto/sha512.cpp",
"/depend/zcash/src/crypto/hmac_sha512.cpp",
"/depend/zcash/src/crypto/sha256.h",
"/depend/zcash/src/hash.h",
"/depend/zcash/src/key_constants.h",
"/depend/zcash/src/prevector.h",
"/depend/zcash/src/primitives/transaction.h",
"/depend/zcash/src/pubkey.cpp",
"/depend/zcash/src/pubkey.h",
"/depend/zcash/src/script/interpreter.cpp",
"/depend/zcash/src/script/script.cpp",
"/depend/zcash/src/script/interpreter.h",
"/depend/zcash/src/script/script_error.cpp",
"/depend/zcash/src/",
"/depend/zcash/src/rust/include/",
"/depend/zcash/src/secp256k1/include/",
"/depend/zcash/src/script/script_error.h",
"/depend/zcash/src/script/script.cpp",
"/depend/zcash/src/script/script.h",
"/depend/zcash/src/script/zcash_script.cpp",
"/depend/zcash/src/script/zcash_script.h",
"/depend/zcash/src/secp256k1/",
"/depend/zcash/src/support/cleanse.cpp",
"/depend/zcash/src/support/cleanse.h",
"/depend/zcash/src/rust/gen/",
"/depend/expected/include/",
"/depend/zcash/src/serialize.h",
"/depend/zcash/src/tinyformat.h",
"/depend/zcash/src/uint256.cpp",
"/depend/zcash/src/uint256.h",
"/depend/zcash/src/util/strencodings.cpp",
"/depend/zcash/src/util/strencodings.h",
"/depend/zcash/src/version.h",
]

[lib]
Expand All @@ -49,35 +60,6 @@ path = "src/lib.rs"
external-secp = []

[dependencies]
# All these dependencies must match the versions in:
# https://github.com/zcash/zcash/blob/<git subtree version>/Cargo.toml
bellman = "0.14"
blake2b_simd = "1"
blake2s_simd = "1"
bls12_381 = "0.8"
byteorder = "1"
crossbeam-channel = "0.5"
cxx = { version = "=1.0.113", features = ["c++17"] }
group = "0.13"
incrementalmerkletree = "0.5"
jubjub = "0.10"
libc = "0.2"
memuse = "0.2"
metrics = "0.21"
orchard = "0.7"
rand_core = "0.6"
rayon = "1.5"
redjubjub = "0.7"
sapling = { package = "sapling-crypto", version = "0.1", features = ["temporary-zcashd"] }
subtle = "2.2"
tracing = "0.1"
zcash_address = "0.3"
zcash_encoding = "0.2"
zcash_note_encryption = "0.4"
zcash_primitives = { version = "=0.14.0", features = ["temporary-zcashd", "transparent-inputs"] }
zcash_proofs = { version = "=0.14.0", features = ["directories"] }
bridgetree = "0.4"
rand = "0.8"

[build-dependencies]
# The `bindgen` dependency should automatically upgrade to match the version used by zebra-state's `rocksdb` dependency in:
Expand All @@ -90,9 +72,6 @@ bindgen = ">= 0.64.0"
# so they are configured to automatically upgrade to match Zebra.
# But we try to use the latest versions here, to catch any bugs in `zcash_script`'s CI.
cc = { version = "1.0.94", features = ["parallel"] }
# Treat minor versions with a zero major version as compatible (cargo doesn't by default).
cxx-gen = ">= 0.7.107"
syn = { version = "1.0.109", features = ["full", "printing"] }

[dev-dependencies]
# These dependencies are shared with a lot of other Zebra dependencies.
Expand All @@ -101,8 +80,6 @@ syn = { version = "1.0.109", features = ["full", "printing"] }
# Treat minor versions with a zero major version as compatible (cargo doesn't by default).
hex = ">= 0.4.3"
lazy_static = "1.4.0"
incrementalmerkletree = { version = "0.5", features = ["test-dependencies"] }
zcash_primitives = { version = "=0.14.0", features = ["temporary-zcashd", "transparent-inputs", "test-dependencies"] }

[[package.metadata.release.pre-release-replacements]]
file = "CHANGELOG.md"
Expand Down
145 changes: 6 additions & 139 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! Build script for zcash_script.

use std::{env, fmt, fs, io::Read, path::PathBuf};

use syn::__private::ToTokens;
use std::{env, fmt, path::PathBuf};

type Result<T, E = Error> = std::result::Result<T, E>;

Expand Down Expand Up @@ -47,125 +45,8 @@ fn bindgen_headers() -> Result<()> {
Ok(())
}

/// Use cxx_gen to generate headers and source files for FFI bindings,
/// just like zcash does (see depend/zcash/src/Makefile.am).
/// (Note that zcash uses the cxxbridge-cmd binary, while we use the
/// cxx_gen library, but the result is the same.)
///
/// We could use [`cxx_build`](https://cxx.rs/tutorial.html#compiling-the-c-code-with-cargo)
/// to do this automatically. But zcash uses the
/// [manual approach](https://cxx.rs/tutorial.html#c-generated-code) which
/// creates the headers with non-standard names and paths (e.g. "blake2b.h",
/// instead of "blake2b.rs.h" which what cxx_build would create). This would
/// requires us to rename/link files which is awkward.
///
/// Note that we must generate the files in the target dir (OUT_DIR) and not in
/// any source folder, because `cargo package` does not allow that.
/// (This is in contrast to zcash which generates in `depend/zcash/src/rust/gen/`)
fn gen_cxxbridge() -> Result<()> {
let out_path = env::var("OUT_DIR").map_err(Error::Env)?;
let out_path = PathBuf::from(out_path).join("gen");
let src_out_path = PathBuf::from(&out_path).join("src");
let header_out_path = PathBuf::from(&out_path).join("include").join("rust");

// These must match `CXXBRIDGE_RS` in depend/zcash/src/Makefile.am
let filenames = [
"blake2b",
"ed25519",
"equihash",
"streams",
"bridge",
"sapling/zip32",
];

// The output folder must exist
fs::create_dir_all(&src_out_path).unwrap();
fs::create_dir_all(&header_out_path).unwrap();

// Generate the generic header file
fs::write(header_out_path.join("cxx.h"), cxx_gen::HEADER).unwrap();

// Generate the source and header for each bridge file
for filename in filenames {
println!(
"cargo:rerun-if-changed=depend/zcash/src/rust/src/{}.rs",
filename
);

let mut file =
fs::File::open(format!("depend/zcash/src/rust/src/{}.rs", filename).as_str()).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();

let ast = syn::parse_file(&content).unwrap();
let token_stream = ast.to_token_stream();
let mut opt = cxx_gen::Opt::default();
opt.include.push(cxx_gen::Include {
path: "rust/cxx.h".to_string(),
kind: cxx_gen::IncludeKind::Quoted,
});
let output = cxx_gen::generate_header_and_cc(token_stream, &opt).unwrap_or_else(|err| {
panic!(
"invalid bridge file {filename}: {err}. Try updating `filenames` to match zcashd"
)
});

let header_path = header_out_path.join(format!("{}.h", filename));
// Create output dir if does not exist (since `filename` can have a subdir)
fs::create_dir_all(header_path.parent().unwrap()).unwrap();
fs::write(header_path, output.header).unwrap();

let src_path = src_out_path.join(format!("{}.cpp", filename));
// Create output dir if does not exist (since `filename` can have a subdir)
fs::create_dir_all(src_path.parent().unwrap()).unwrap();
fs::write(src_path, output.implementation).unwrap();
}
Ok(())
}

fn main() -> Result<()> {
bindgen_headers()?;
gen_cxxbridge()?;

let rust_path = env::var("OUT_DIR").map_err(Error::Env)?;
let rust_path = PathBuf::from(rust_path).join("rust");

// We want to compile `depend/zcash/src/rust/src/sapling.rs`, which we used
// to do in `src/sapling.rs` by just including it. However, now that it has
// submodules, that approach doesn't work because for some reason Rust
// searches for the submodules in `depend/zcash/src/rust/src/` instead of
// `depend/zcash/src/rust/src/sapling/` where they are located. This can
// be solved if `depend/zcash/src/rust/src/sapling.rs` is renamed to
// `depend/zcash/src/rust/src/sapling/mod.rs`. But we can't do that directly
// because we can't change the source tree inside `build.rs`. Therefore we
// copy the required files to OUT_DIR, with a renamed sapling.rs, and include
// the copied file instead (see src/sapling.rs).
// See also https://stackoverflow.com/questions/77310390/how-to-include-a-source-file-that-has-modules
fs::create_dir_all(rust_path.join("sapling")).unwrap();
for filename in &["sapling.rs", "sapling/spec.rs", "sapling/zip32.rs"] {
println!(
"cargo:rerun-if-changed=depend/zcash/src/rust/src/{}.rs",
filename
);
}
fs::copy(
"depend/zcash/src/rust/src/sapling.rs",
rust_path.join("sapling/mod.rs"),
)
.unwrap();
fs::copy(
"depend/zcash/src/rust/src/sapling/spec.rs",
rust_path.join("sapling/spec.rs"),
)
.unwrap();
fs::copy(
"depend/zcash/src/rust/src/sapling/zip32.rs",
rust_path.join("sapling/zip32.rs"),
)
.unwrap();

let gen_path = env::var("OUT_DIR").map_err(Error::Env)?;
let gen_path = PathBuf::from(gen_path).join("gen");

let target = env::var("TARGET").expect("TARGET was not set");
let mut base_config = cc::Build::new();
Expand All @@ -177,7 +58,6 @@ fn main() -> Result<()> {
.include("depend/zcash/src/rust/include/")
.include("depend/zcash/src/secp256k1/include/")
.include("depend/expected/include/")
.include(&gen_path.join("include"))
.flag_if_supported("-Wno-implicit-fallthrough")
.flag_if_supported("-Wno-catch-value")
.flag_if_supported("-Wno-reorder")
Expand All @@ -201,30 +81,17 @@ fn main() -> Result<()> {
}

base_config
.file("depend/zcash/src/script/zcash_script.cpp")
.file("depend/zcash/src/util/strencodings.cpp")
.file("depend/zcash/src/amount.cpp")
.file("depend/zcash/src/uint256.cpp")
.file("depend/zcash/src/pubkey.cpp")
.file("depend/zcash/src/hash.cpp")
.file("depend/zcash/src/streams_rust.cpp")
.file("depend/zcash/src/zip317.cpp")
.file("depend/zcash/src/primitives/transaction.cpp")
.file("depend/zcash/src/crypto/ripemd160.cpp")
.file("depend/zcash/src/crypto/sha1.cpp")
.file("depend/zcash/src/crypto/sha256.cpp")
.file("depend/zcash/src/crypto/sha512.cpp")
.file("depend/zcash/src/crypto/hmac_sha512.cpp")
.file("depend/zcash/src/pubkey.cpp")
.file("depend/zcash/src/script/interpreter.cpp")
.file("depend/zcash/src/script/script.cpp")
.file("depend/zcash/src/script/script_error.cpp")
.file("depend/zcash/src/support/cleanse.cpp")
.file("depend/zcash/src/zcash/cache.cpp")
// A subset of the files generated by gen_cxxbridge
// which are required by zcash_script.
.file(gen_path.join("src/blake2b.cpp"))
.file(gen_path.join("src/bridge.cpp"))
.file(gen_path.join("src/streams.cpp"))
.file("depend/zcash/src/script/script.cpp")
.file("depend/zcash/src/script/zcash_script.cpp")
.file("depend/zcash/src/uint256.cpp")
.file("depend/zcash/src/util/strencodings.cpp")
.compile("libzcash_script.a");

Ok(())
Expand Down
48 changes: 0 additions & 48 deletions depend/zcash/src/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@

#include <vector>

#include <rust/blake2b.h>
#include <rust/constants.h>
#include <rust/cxx.h>

typedef uint256 ChainCode;

/** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */
Expand Down Expand Up @@ -157,50 +153,6 @@ class CHashWriter
};


/** A writer stream (for serialization) that computes a 256-bit BLAKE2b hash. */
class CBLAKE2bWriter
{
private:
rust::Box<blake2b::State> state;

public:
int nType;
int nVersion;

CBLAKE2bWriter(int nTypeIn, int nVersionIn, const unsigned char* personal) :
nType(nTypeIn),
nVersion(nVersionIn),
state(blake2b::init(32, {personal, blake2b::PERSONALBYTES})) {}

int GetType() const { return nType; }
int GetVersion() const { return nVersion; }

void write_u8(const unsigned char* pch, size_t size)
{
state->update({pch, size});
}

CBLAKE2bWriter& write(const char *pch, size_t size) {
state->update({(const unsigned char*)pch, size});
return (*this);
}

// invalidates the object
uint256 GetHash() {
uint256 result;
state->finalize({result.begin(), result.size()});
return result;
}

template<typename T>
CBLAKE2bWriter& operator<<(const T& obj) {
// Serialize to this stream
::Serialize(*this, obj);
return (*this);
}
};


/** Compute the 256-bit hash of an object's serialization. */
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Expand Down
6 changes: 6 additions & 0 deletions depend/zcash/src/pubkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchS
return secp256k1_ecdsa_verify(secp256k1_context_static, &sig, hash.begin(), &pubkey);
}

#if 0

bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
if (vchSig.size() != COMPACT_SIGNATURE_SIZE)
return false;
Expand Down Expand Up @@ -138,6 +140,7 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
out.nChild = _nChild;
return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode);
}
#endif

/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
secp256k1_ecdsa_signature sig;
Expand All @@ -149,10 +152,13 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_static, NULL, &sig));
}

#if 0
/* static */ std::optional<CChainablePubKey> CChainablePubKey::FromParts(ChainCode chaincode, CPubKey pubkey) {
if (pubkey.IsCompressed()) {
return CChainablePubKey(chaincode, pubkey);
} else {
return std::nullopt;
}
}

#endif
Loading

0 comments on commit 4924030

Please sign in to comment.