Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove dependencies by switching to simplified API with a callback interface #157

Merged
merged 16 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
upbqdn marked this conversation as resolved.
Show resolved Hide resolved
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
Loading