Implement derivation of the internal Sapling spending key.

This commit is contained in:
Kris Nuttycombe 2022-01-25 16:32:21 -07:00
parent 3ddbe1fa06
commit b46d85976d
5 changed files with 53 additions and 2 deletions

View File

@ -299,6 +299,12 @@ extern "C" {
unsigned char *xsk_i
);
/// Derive a internal ExtendedSpendingKey from an external key
void librustzcash_zip32_xsk_derive_internal(
const unsigned char *xsk_external,
unsigned char *xsk_internal
);
/// Derive a child ExtendedFullViewingKey from a parent.
bool librustzcash_zip32_xfvk_derive(
const unsigned char *xfvk_parent,

View File

@ -1059,6 +1059,23 @@ pub extern "C" fn librustzcash_zip32_xsk_derive(
.expect("should be able to serialize an ExtendedSpendingKey");
}
/// Derive the Sapling internal spending key from the external extended
/// spending key
#[no_mangle]
pub extern "C" fn librustzcash_zip32_xsk_derive_internal(
xsk_external: *const [c_uchar; 169],
xsk_internal_ret: *mut [c_uchar; 169],
) {
let xsk_external = zip32::ExtendedSpendingKey::read(&unsafe { *xsk_external }[..])
.expect("valid ExtendedSpendingKey");
let xsk_internal = xsk_external.derive_internal();
xsk_internal
.write(&mut (unsafe { &mut *xsk_internal_ret })[..])
.expect("should be able to serialize an ExtendedSpendingKey");
}
/// Derive a child ExtendedFullViewingKey from a parent.
#[no_mangle]
pub extern "C" fn librustzcash_zip32_xfvk_derive(
@ -1081,7 +1098,7 @@ pub extern "C" fn librustzcash_zip32_xfvk_derive(
true
}
/// Derive the Sapling internal
/// Derive the Sapling internal full viewing key from the corresponding external full viewing key
#[no_mangle]
pub extern "C" fn librustzcash_zip32_sapling_derive_internal_fvk(
fvk: *const [c_uchar; 96],

View File

@ -4013,6 +4013,15 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp)
// Generate the common ovk for recovering t->z outputs.
HDSeed seed = pwalletMain->GetHDSeedForRPC();
ovks.insert(ovkForShieldingFromTaddr(seed));
auto legacyAcctUFVK = pwalletMain->GetUnifiedFullViewingKeyByAccount(ZCASH_LEGACY_ACCOUNT);
if (legacyAcctUFVK.has_value()) {
auto legacyAcctOVKs = legacyAcctUFVK.value().GetTransparentOVKsForShielding();
if (legacyAcctOVKs.has_value()) {
ovks.insert(legacyAcctOVKs.value().first);
ovks.insert(legacyAcctOVKs.value().second);
}
}
}
// Sapling spends

View File

@ -504,6 +504,13 @@ std::optional<libzcash::ZcashdUnifiedSpendingKey>
throw std::runtime_error("CWalletDB::GenerateUnifiedSpendingKeyForAccount(): Unable to add Sapling key component to the wallet.");
}
// Add the Sapling change key to the wallet
auto saplingChangeEsk = saplingEsk.DeriveInternalKey();
if (addSpendingKey(saplingChangeEsk) == KeyNotAdded) {
// If adding the Sapling change key to the wallet failed, abort the process.
throw std::runtime_error("CWalletDB::GenerateUnifiedSpendingKeyForAccount(): Unable to add Sapling key component to the wallet.");
}
auto zufvk = ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(Params(), ufvk);
if (!CCryptoKeyStore::AddUnifiedFullViewingKey(zufvk)) {
throw std::runtime_error("CWalletDB::GenerateUnifiedSpendingKeyForAccount(): Failed to add UFVK to the keystore.");

View File

@ -232,7 +232,19 @@ SaplingExtendedFullViewingKey SaplingExtendedSpendingKey::ToXFVK() const
}
SaplingExtendedSpendingKey SaplingExtendedSpendingKey::DeriveInternalKey() const {
throw std::runtime_error("Not yet implemented");
CDataStream ss_p(SER_NETWORK, PROTOCOL_VERSION);
ss_p << *this;
CSerializeData external_key_bytes(ss_p.begin(), ss_p.end());
CSerializeData internal_key_bytes(ZIP32_XSK_SIZE);
librustzcash_zip32_xsk_derive_internal(
reinterpret_cast<unsigned char*>(external_key_bytes.data()),
reinterpret_cast<unsigned char*>(internal_key_bytes.data()));
CDataStream ss_i(internal_key_bytes, SER_NETWORK, PROTOCOL_VERSION);
SaplingExtendedSpendingKey xsk_internal;
ss_i >> xsk_internal;
return xsk_internal;
}
HDKeyPath Zip32AccountKeyPath(