ZIP 213: Add checks to support Orchard shielded coinbase outputs.

This commit is contained in:
Kris Nuttycombe 2021-06-30 13:23:56 -06:00 committed by Jack Grigg
parent 6bbe0906a8
commit 7a2be88768
6 changed files with 67 additions and 26 deletions

30
Cargo.lock generated
View File

@ -482,7 +482,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
[[package]] [[package]]
name = "equihash" name = "equihash"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6" source = "git+https://github.com/zcash/librustzcash.git?rev=3cab105c9c3bf4ba31f779095d939ad0c7057539#3cab105c9c3bf4ba31f779095d939ad0c7057539"
dependencies = [ dependencies = [
"blake2b_simd", "blake2b_simd",
"byteorder", "byteorder",
@ -632,12 +632,6 @@ dependencies = [
"rand", "rand",
] ]
[[package]]
name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.11.2" version = "0.11.2"
@ -729,12 +723,12 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.6.2" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown 0.9.1", "hashbrown",
] ]
[[package]] [[package]]
@ -937,7 +931,7 @@ dependencies = [
"crossbeam-epoch 0.9.5", "crossbeam-epoch 0.9.5",
"crossbeam-utils 0.8.5", "crossbeam-utils 0.8.5",
"dashmap", "dashmap",
"hashbrown 0.11.2", "hashbrown",
"indexmap", "indexmap",
"metrics", "metrics",
"num_cpus", "num_cpus",
@ -982,9 +976,9 @@ dependencies = [
[[package]] [[package]]
name = "nonempty" name = "nonempty"
version = "0.6.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fa586da3e43cc7df44aae0e21ed2e743218b876de3f38035683d30bd8a3828e" checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
[[package]] [[package]]
name = "ntapi" name = "ntapi"
@ -1050,7 +1044,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "orchard" name = "orchard"
version = "0.0.0" version = "0.0.0"
source = "git+https://github.com/zcash/orchard.git?rev=1f861423c2d8e4d1f8415f9a634084fc5ca608da#1f861423c2d8e4d1f8415f9a634084fc5ca608da" source = "git+https://github.com/zcash/orchard.git?rev=21b77d6ec56fc7e37aab9da68e88bc5dd754fe10#21b77d6ec56fc7e37aab9da68e88bc5dd754fe10"
dependencies = [ dependencies = [
"aes", "aes",
"arrayvec 0.7.1", "arrayvec 0.7.1",
@ -1700,7 +1694,7 @@ dependencies = [
[[package]] [[package]]
name = "zcash_history" name = "zcash_history"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6" source = "git+https://github.com/zcash/librustzcash.git?rev=3cab105c9c3bf4ba31f779095d939ad0c7057539#3cab105c9c3bf4ba31f779095d939ad0c7057539"
dependencies = [ dependencies = [
"bigint", "bigint",
"blake2b_simd", "blake2b_simd",
@ -1710,7 +1704,7 @@ dependencies = [
[[package]] [[package]]
name = "zcash_note_encryption" name = "zcash_note_encryption"
version = "0.0.0" version = "0.0.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6" source = "git+https://github.com/zcash/librustzcash.git?rev=3cab105c9c3bf4ba31f779095d939ad0c7057539#3cab105c9c3bf4ba31f779095d939ad0c7057539"
dependencies = [ dependencies = [
"blake2b_simd", "blake2b_simd",
"byteorder", "byteorder",
@ -1724,7 +1718,7 @@ dependencies = [
[[package]] [[package]]
name = "zcash_primitives" name = "zcash_primitives"
version = "0.5.0" version = "0.5.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6" source = "git+https://github.com/zcash/librustzcash.git?rev=3cab105c9c3bf4ba31f779095d939ad0c7057539#3cab105c9c3bf4ba31f779095d939ad0c7057539"
dependencies = [ dependencies = [
"aes", "aes",
"bitvec", "bitvec",
@ -1754,7 +1748,7 @@ dependencies = [
[[package]] [[package]]
name = "zcash_proofs" name = "zcash_proofs"
version = "0.5.0" version = "0.5.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=02052526925fba9389f1428d6df254d4dec967e6#02052526925fba9389f1428d6df254d4dec967e6" source = "git+https://github.com/zcash/librustzcash.git?rev=3cab105c9c3bf4ba31f779095d939ad0c7057539#3cab105c9c3bf4ba31f779095d939ad0c7057539"
dependencies = [ dependencies = [
"bellman", "bellman",
"blake2b_simd", "blake2b_simd",

View File

@ -30,7 +30,7 @@ group = "0.10"
incrementalmerkletree = "0.1" incrementalmerkletree = "0.1"
libc = "0.2" libc = "0.2"
jubjub = "0.7" jubjub = "0.7"
nonempty = "0.6" nonempty = "0.7"
orchard = "0.0" orchard = "0.0"
subtle = "2.2" subtle = "2.2"
rand_core = "0.6" rand_core = "0.6"
@ -65,8 +65,8 @@ codegen-units = 1
ed25519-zebra = { git = "https://github.com/ZcashFoundation/ed25519-zebra.git", rev = "d3512400227a362d08367088ffaa9bd4142a69c7" } ed25519-zebra = { git = "https://github.com/ZcashFoundation/ed25519-zebra.git", rev = "d3512400227a362d08367088ffaa9bd4142a69c7" }
halo2 = { git = "https://github.com/zcash/halo2.git", rev = "d04b532368d05b505e622f8cac4c0693574fbd93" } halo2 = { git = "https://github.com/zcash/halo2.git", rev = "d04b532368d05b505e622f8cac4c0693574fbd93" }
incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "8b59049f1746827ffa3763efa8af948f680491d0" } incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "8b59049f1746827ffa3763efa8af948f680491d0" }
orchard = { git = "https://github.com/zcash/orchard.git", rev = "1f861423c2d8e4d1f8415f9a634084fc5ca608da" } orchard = { git = "https://github.com/zcash/orchard.git", rev = "21b77d6ec56fc7e37aab9da68e88bc5dd754fe10" }
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "02052526925fba9389f1428d6df254d4dec967e6" } zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "3cab105c9c3bf4ba31f779095d939ad0c7057539" }
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "02052526925fba9389f1428d6df254d4dec967e6" } zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "3cab105c9c3bf4ba31f779095d939ad0c7057539" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "02052526925fba9389f1428d6df254d4dec967e6" } zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "3cab105c9c3bf4ba31f779095d939ad0c7057539" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "02052526925fba9389f1428d6df254d4dec967e6" } zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "3cab105c9c3bf4ba31f779095d939ad0c7057539" }

View File

@ -1135,7 +1135,12 @@ bool ContextualCheckTransaction(
} }
if (tx.IsCoinBase()) { if (tx.IsCoinBase()) {
// TODO: Check that Orchard coinbase outputs can be decrypted with the all-zeros OVK if (!orchard_bundle.CoinbaseOutputsAreValid()) {
return state.DoS(
DOS_LEVEL_BLOCK,
error("ContextualCheckTransaction(): Orchard coinbase action has invalid ciphertext"),
REJECT_INVALID, "bad-cb-action-invalid-ciphertext");
}
} else { } else {
// ZIP 203: From NU5, the upper limit on nExpiryHeight is removed for coinbase // ZIP 203: From NU5, the upper limit on nExpiryHeight is removed for coinbase
// transactions. // transactions.

View File

@ -121,6 +121,10 @@ public:
bool SpendsEnabled() const { bool SpendsEnabled() const {
return orchard_bundle_spends_enabled(inner.get()); return orchard_bundle_spends_enabled(inner.get());
} }
bool CoinbaseOutputsAreValid() const {
return orchard_bundle_coinbase_outputs_are_valid(inner.get());
}
}; };
#endif // ZCASH_PRIMITIVES_ORCHARD_H #endif // ZCASH_PRIMITIVES_ORCHARD_H

View File

@ -117,6 +117,11 @@ bool orchard_bundle_outputs_enabled(const OrchardBundlePtr* bundle);
/// are enabled. /// are enabled.
bool orchard_bundle_spends_enabled(const OrchardBundlePtr* bundle); bool orchard_bundle_spends_enabled(const OrchardBundlePtr* bundle);
/// Returns whether all actions contained in the Orchard bundle
/// can be decrypted with the all-zeros OVK. Returns `true`
/// if no Orchard actions are present.
bool orchard_bundle_coinbase_outputs_are_valid(const OrchardBundlePtr* bundle);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -2,11 +2,13 @@ use std::ptr;
use orchard::{ use orchard::{
bundle::Authorized, bundle::Authorized,
keys::OutgoingViewingKey,
primitives::redpallas::{self, Binding, SpendAuth}, primitives::redpallas::{self, Binding, SpendAuth},
Bundle, Bundle, OrchardDomain,
}; };
use rand_core::OsRng; use rand_core::OsRng;
use tracing::{debug, error}; use tracing::{debug, error};
use zcash_note_encryption::try_output_recovery_with_ovk;
use zcash_primitives::transaction::{ use zcash_primitives::transaction::{
components::{orchard as orchard_serialization, Amount}, components::{orchard as orchard_serialization, Amount},
TxId, TxId,
@ -285,3 +287,34 @@ pub extern "C" fn orchard_bundle_spends_enabled(bundle: *const Bundle<Authorized
let bundle = unsafe { bundle.as_ref() }; let bundle = unsafe { bundle.as_ref() };
bundle.map(|b| b.flags().spends_enabled()).unwrap_or(false) bundle.map(|b| b.flags().spends_enabled()).unwrap_or(false)
} }
/// Returns whether all actions contained in the Orchard bundle
/// can be decrypted with the all-zeros OVK. Returns `true`
/// if no Orchard actions are present.
///
/// This should only be called on an Orchard bundle that is
/// an element of a coinbase transaction.
#[no_mangle]
pub extern "C" fn orchard_bundle_coinbase_outputs_are_valid(
bundle: *const Bundle<Authorized, Amount>,
) -> bool {
if let Some(bundle) = unsafe { bundle.as_ref() } {
for act in bundle.actions() {
if try_output_recovery_with_ovk(
&OrchardDomain::for_action(act),
&OutgoingViewingKey::from([0u8; 32]),
act,
act.cv_net(),
&act.encrypted_note().out_ciphertext,
)
.is_none()
{
return false;
}
}
}
// Either there are no Orchard actions, or all of the outputs
// are decryptable with the all-zeros OVK.
true
}