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]]
name = "equihash"
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 = [
"blake2b_simd",
"byteorder",
@ -632,12 +632,6 @@ dependencies = [
"rand",
]
[[package]]
name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
[[package]]
name = "hashbrown"
version = "0.11.2"
@ -729,12 +723,12 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.6.2"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown 0.9.1",
"hashbrown",
]
[[package]]
@ -937,7 +931,7 @@ dependencies = [
"crossbeam-epoch 0.9.5",
"crossbeam-utils 0.8.5",
"dashmap",
"hashbrown 0.11.2",
"hashbrown",
"indexmap",
"metrics",
"num_cpus",
@ -982,9 +976,9 @@ dependencies = [
[[package]]
name = "nonempty"
version = "0.6.0"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fa586da3e43cc7df44aae0e21ed2e743218b876de3f38035683d30bd8a3828e"
checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
[[package]]
name = "ntapi"
@ -1050,7 +1044,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "orchard"
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 = [
"aes",
"arrayvec 0.7.1",
@ -1700,7 +1694,7 @@ dependencies = [
[[package]]
name = "zcash_history"
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 = [
"bigint",
"blake2b_simd",
@ -1710,7 +1704,7 @@ dependencies = [
[[package]]
name = "zcash_note_encryption"
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 = [
"blake2b_simd",
"byteorder",
@ -1724,7 +1718,7 @@ dependencies = [
[[package]]
name = "zcash_primitives"
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 = [
"aes",
"bitvec",
@ -1754,7 +1748,7 @@ dependencies = [
[[package]]
name = "zcash_proofs"
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 = [
"bellman",
"blake2b_simd",

View File

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

View File

@ -1135,7 +1135,12 @@ bool ContextualCheckTransaction(
}
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 {
// ZIP 203: From NU5, the upper limit on nExpiryHeight is removed for coinbase
// transactions.

View File

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

View File

@ -117,6 +117,11 @@ bool orchard_bundle_outputs_enabled(const OrchardBundlePtr* bundle);
/// are enabled.
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
}
#endif

View File

@ -2,11 +2,13 @@ use std::ptr;
use orchard::{
bundle::Authorized,
keys::OutgoingViewingKey,
primitives::redpallas::{self, Binding, SpendAuth},
Bundle,
Bundle, OrchardDomain,
};
use rand_core::OsRng;
use tracing::{debug, error};
use zcash_note_encryption::try_output_recovery_with_ovk;
use zcash_primitives::transaction::{
components::{orchard as orchard_serialization, Amount},
TxId,
@ -285,3 +287,34 @@ pub extern "C" fn orchard_bundle_spends_enabled(bundle: *const Bundle<Authorized
let bundle = unsafe { bundle.as_ref() };
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
}