Add unified key components to the transparent & Sapling wallet parts.
This commit is contained in:
parent
24ff7b36ec
commit
6d36921b94
|
@ -79,6 +79,7 @@ static SaplingPaymentAddress DefaultSaplingAddress(CWallet* pwallet) {
|
|||
auto usk = pwallet->GenerateUnifiedSpendingKeyForAccount(0);
|
||||
|
||||
return usk.value()
|
||||
.first
|
||||
.ToFullViewingKey()
|
||||
.GetSaplingKey().value()
|
||||
.FindAddress(libzcash::diversifier_index_t(0)).first;
|
||||
|
|
|
@ -172,7 +172,6 @@ std::pair<SaplingExtendedSpendingKey, bool> CWallet::GenerateLegacySaplingZKey(u
|
|||
} else {
|
||||
return std::make_pair(xsk.first, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add spending key to keystore
|
||||
|
@ -288,14 +287,26 @@ CPubKey CWallet::GenerateNewKey()
|
|||
// if we did not successfully generate a key, try again.
|
||||
} while (!extKey.has_value());
|
||||
|
||||
CKey secret = extKey.value().first.key;
|
||||
auto pubkey = AddKey(seed.Fingerprint(), extKey.value());
|
||||
|
||||
// Update the persisted chain information
|
||||
if (fFileBacked && !CWalletDB(strWalletFile).WriteMnemonicHDChain(hdChain)) {
|
||||
throw std::runtime_error("CWallet::GenerateNewKey(): Writing HD chain model failed");
|
||||
}
|
||||
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
CPubKey CWallet::AddKey(const uint256& seedFingerprint, const std::pair<CExtKey, HDKeyPath>& extSecret)
|
||||
{
|
||||
CKey secret = extSecret.first.key;
|
||||
CPubKey pubkey = secret.GetPubKey();
|
||||
assert(secret.VerifyPubKey(pubkey));
|
||||
|
||||
// Create new metadata
|
||||
CKeyMetadata keyMeta(GetTime());
|
||||
keyMeta.hdKeypath = extKey.value().second;
|
||||
keyMeta.seedFp = seed.Fingerprint();
|
||||
keyMeta.hdKeypath = extSecret.second;
|
||||
keyMeta.seedFp = seedFingerprint;
|
||||
mapKeyMetadata[pubkey.GetID()] = keyMeta;
|
||||
if (nTimeFirstKey == 0 || keyMeta.nCreateTime < nTimeFirstKey)
|
||||
nTimeFirstKey = keyMeta.nCreateTime;
|
||||
|
@ -303,11 +314,6 @@ CPubKey CWallet::GenerateNewKey()
|
|||
if (!AddKeyPubKey(secret, pubkey))
|
||||
throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
|
||||
|
||||
// Update the persisted chain information
|
||||
if (fFileBacked && !CWalletDB(strWalletFile).WriteMnemonicHDChain(hdChain)) {
|
||||
throw std::runtime_error("CWallet::GenerateNewKey(): Writing HD chain model failed");
|
||||
}
|
||||
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
|
@ -407,7 +413,7 @@ bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullVi
|
|||
return false;
|
||||
}
|
||||
|
||||
ZcashdUnifiedSpendingKey CWallet::GenerateNewUnifiedSpendingKey() {
|
||||
std::pair<ZcashdUnifiedSpendingKey, ZcashdUnifiedKeyMetadata> CWallet::GenerateNewUnifiedSpendingKey() {
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
if (!mnemonicHDChain.has_value()) {
|
||||
|
@ -431,7 +437,8 @@ ZcashdUnifiedSpendingKey CWallet::GenerateNewUnifiedSpendingKey() {
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<libzcash::ZcashdUnifiedSpendingKey> CWallet::GenerateUnifiedSpendingKeyForAccount(libzcash::AccountId accountId) {
|
||||
std::optional<std::pair<libzcash::ZcashdUnifiedSpendingKey, libzcash::ZcashdUnifiedKeyMetadata>>
|
||||
CWallet::GenerateUnifiedSpendingKeyForAccount(libzcash::AccountId accountId) {
|
||||
auto seed = GetMnemonicSeed();
|
||||
if (!seed.has_value()) {
|
||||
throw std::runtime_error(std::string(__func__) + ": Wallet has no mnemonic HD seed.");
|
||||
|
@ -439,14 +446,60 @@ std::optional<libzcash::ZcashdUnifiedSpendingKey> CWallet::GenerateUnifiedSpendi
|
|||
|
||||
auto usk = ZcashdUnifiedSpendingKey::ForAccount(seed.value(), BIP44CoinType(), accountId);
|
||||
if (usk.has_value()) {
|
||||
// TODO: Save the unified full viewing key & metadata to the wallet
|
||||
if (!AddUnifiedSpendingKey(usk.value().first, usk.value().second)) {
|
||||
throw std::runtime_error("CWallet::GenerateUnifiedSpendingKeyForAccount(): AddUnifiedSpendingKey failed.");
|
||||
}
|
||||
|
||||
return usk.value().first;
|
||||
return usk.value();
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
// Add spending key to keystore
|
||||
bool CWallet::AddUnifiedSpendingKey(
|
||||
const libzcash::ZcashdUnifiedSpendingKey& sk,
|
||||
const libzcash::ZcashdUnifiedKeyMetadata& metadata) {
|
||||
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
||||
|
||||
auto ufvk = sk.ToFullViewingKey();
|
||||
auto metaKey = std::make_pair(metadata.GetSeedFingerprint(), metadata.GetAccountId());
|
||||
mapUnifiedKeyMetadata.insert({metaKey, metadata});
|
||||
|
||||
// Add Transparent component to the wallet
|
||||
if (sk.GetTransparentKey().has_value()) {
|
||||
AddKey(metadata.GetSeedFingerprint(),
|
||||
std::make_pair(sk.GetTransparentKey().value(), metadata.TransparentKeyPath().value()));
|
||||
}
|
||||
|
||||
// Add Sapling component to the wallet
|
||||
auto addSpendingKey = AddSpendingKeyToWallet(
|
||||
this, Params().GetConsensus(), GetTime(),
|
||||
metadata.SaplingKeyPath(), metadata.GetSeedFingerprint().GetHex(), true);
|
||||
if (sk.GetSaplingExtendedSpendingKey().has_value() &&
|
||||
addSpendingKey(sk.GetSaplingExtendedSpendingKey().value()) == KeyNotAdded) {
|
||||
// If adding the Sapling key to the wallet failed, abort the process.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fFileBacked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsCrypted()) {
|
||||
//return CWalletDB(strWalletFile).WriteUnifiedFullViewingKey(ufvk, metadata);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWallet::LoadUnifiedKeyMetadata(const libzcash::ZcashdUnifiedKeyMetadata &meta)
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapUnifiedKeyMetadata
|
||||
auto key = std::make_pair(meta.GetSeedFingerprint(), meta.GetAccountId());
|
||||
mapUnifiedKeyMetadata.insert({key, meta});
|
||||
}
|
||||
|
||||
void CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
||||
|
@ -5542,7 +5595,7 @@ KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedS
|
|||
if (m_wallet->HaveSaplingSpendingKey(extfvk)) {
|
||||
return KeyAlreadyExists;
|
||||
} else {
|
||||
if (!m_wallet-> AddSaplingZKey(sk)) {
|
||||
if (!m_wallet->AddSaplingZKey(sk)) {
|
||||
return KeyNotAdded;
|
||||
}
|
||||
|
||||
|
@ -5556,7 +5609,7 @@ KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedS
|
|||
if (hdKeypath.has_value()) {
|
||||
m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath = hdKeypath.value();
|
||||
}
|
||||
if (seedFpStr) {
|
||||
if (seedFpStr.has_value()) {
|
||||
uint256 seedFp;
|
||||
seedFp.SetHex(seedFpStr.value());
|
||||
m_wallet->mapSaplingZKeyMetadata[ivk].seedFp = seedFp;
|
||||
|
|
|
@ -803,6 +803,9 @@ private:
|
|||
void SyncMetaData(std::pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::iterator>);
|
||||
void ChainTipAdded(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree);
|
||||
|
||||
/* Add an extended secret key to the wallet. Internal use only. */
|
||||
CPubKey AddKey(const uint256& seedFingerprint, const std::pair<CExtKey, HDKeyPath>& extSecret);
|
||||
|
||||
protected:
|
||||
bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx);
|
||||
void MarkAffectedTransactionsDirty(const CTransaction& tx);
|
||||
|
@ -830,6 +833,7 @@ public:
|
|||
std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
|
||||
std::map<libzcash::SproutPaymentAddress, CKeyMetadata> mapSproutZKeyMetadata;
|
||||
std::map<libzcash::SaplingIncomingViewingKey, CKeyMetadata> mapSaplingZKeyMetadata;
|
||||
std::map<std::pair<libzcash::SeedFingerprint, libzcash::AccountId>, libzcash::ZcashdUnifiedKeyMetadata> mapUnifiedKeyMetadata;
|
||||
|
||||
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
|
||||
MasterKeyMap mapMasterKeys;
|
||||
|
@ -1096,11 +1100,27 @@ public:
|
|||
bool LoadCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||
const std::vector<unsigned char> &vchCryptedSecret);
|
||||
|
||||
/**
|
||||
* Unified keys & addresses
|
||||
*/
|
||||
libzcash::ZcashdUnifiedSpendingKey GenerateNewUnifiedSpendingKey();
|
||||
std::optional<libzcash::ZcashdUnifiedSpendingKey> GenerateUnifiedSpendingKeyForAccount(libzcash::AccountId accountId);
|
||||
//
|
||||
// Unified keys & addresses
|
||||
//
|
||||
|
||||
//! Generate the unified spending key from the wallet's mnemonic seed
|
||||
//! for the next unused account identifier.
|
||||
std::pair<libzcash::ZcashdUnifiedSpendingKey, libzcash::ZcashdUnifiedKeyMetadata>
|
||||
GenerateNewUnifiedSpendingKey();
|
||||
|
||||
//! Generate the next available unified spending key from the wallet's
|
||||
//! mnemonic seed.
|
||||
std::optional<std::pair<libzcash::ZcashdUnifiedSpendingKey, libzcash::ZcashdUnifiedKeyMetadata>>
|
||||
GenerateUnifiedSpendingKeyForAccount(libzcash::AccountId accountId);
|
||||
|
||||
//! Add the specified unified spending key to the wallet with the provided key
|
||||
//! metadata.
|
||||
bool AddUnifiedSpendingKey(
|
||||
const libzcash::ZcashdUnifiedSpendingKey& sk,
|
||||
const libzcash::ZcashdUnifiedKeyMetadata& metadata);
|
||||
|
||||
void LoadUnifiedKeyMetadata(const libzcash::ZcashdUnifiedKeyMetadata &meta);
|
||||
|
||||
/**
|
||||
* Increment the next transaction order id
|
||||
|
|
|
@ -169,6 +169,7 @@ bool CWalletDB::WriteZKey(const libzcash::SproutPaymentAddress& addr, const libz
|
|||
// pair is: tuple_key("zkey", paymentaddress) --> secretkey
|
||||
return Write(std::make_pair(std::string("zkey"), addr), key, false);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk,
|
||||
const libzcash::SaplingExtendedSpendingKey &key,
|
||||
const CKeyMetadata &keyMeta)
|
||||
|
|
|
@ -20,6 +20,30 @@ enum class ReceiverType: uint32_t {
|
|||
Orchard = 0x03
|
||||
};
|
||||
|
||||
class ZcashdUnifiedKeyMetadata;
|
||||
|
||||
// Serialization wrapper for reading and writing ReceiverType
|
||||
// in CompactSize format.
|
||||
class ReceiverTypeSer {
|
||||
private:
|
||||
ReceiverType t;
|
||||
|
||||
friend class ZcashdUnifiedKeyMetadata;
|
||||
public:
|
||||
ReceiverTypeSer() {} // for serialization only
|
||||
ReceiverTypeSer(ReceiverType t): t(t) {}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream &s) const {
|
||||
WriteCompactSize<Stream>(s, (uint64_t) t);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s) {
|
||||
t = (ReceiverType) ReadCompactSize<Stream>(s);
|
||||
}
|
||||
};
|
||||
|
||||
class ZcashdUnifiedSpendingKey;
|
||||
class ZcashdUnifiedFullViewingKey;
|
||||
|
||||
|
@ -30,23 +54,56 @@ class UnifiedFullViewingKey;
|
|||
|
||||
class ZcashdUnifiedKeyMetadata {
|
||||
private:
|
||||
uint256 seedFp;
|
||||
SeedFingerprint seedFp;
|
||||
uint32_t bip44CoinType;
|
||||
libzcash::AccountId accountId;
|
||||
std::vector<ReceiverType> receiverTypes;
|
||||
std::vector<libzcash::ReceiverType> receiverTypes;
|
||||
|
||||
ZcashdUnifiedKeyMetadata() {}
|
||||
public:
|
||||
ZcashdUnifiedKeyMetadata(
|
||||
uint256 seedFp, uint32_t bip44CoinType, libzcash::AccountId accountId, std::vector<ReceiverType> receiverTypes):
|
||||
SeedFingerprint seedFp, uint32_t bip44CoinType, libzcash::AccountId accountId, std::vector<ReceiverType> receiverTypes):
|
||||
seedFp(seedFp), bip44CoinType(bip44CoinType), accountId(accountId), receiverTypes(receiverTypes) {}
|
||||
|
||||
const uint256& GetSeedFingerprint() const {
|
||||
const SeedFingerprint& GetSeedFingerprint() const {
|
||||
return seedFp;
|
||||
}
|
||||
libzcash::AccountId GetAccountId() const {
|
||||
return accountId;
|
||||
}
|
||||
const std::vector<ReceiverType>& GetReceiverTypes() const {
|
||||
return receiverTypes;
|
||||
}
|
||||
std::optional<HDKeyPath> TransparentKeyPath() const;
|
||||
std::optional<HDKeyPath> SaplingKeyPath() const;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(seedFp);
|
||||
READWRITE(bip44CoinType);
|
||||
READWRITE(accountId);
|
||||
if (ser_action.ForRead()) {
|
||||
std::vector<ReceiverTypeSer> serReceiverTypes;
|
||||
READWRITE(serReceiverTypes);
|
||||
receiverTypes.clear();
|
||||
for (ReceiverTypeSer r : serReceiverTypes)
|
||||
receiverTypes.push_back(r.t);
|
||||
} else {
|
||||
std::vector<ReceiverTypeSer> serReceiverTypes;
|
||||
for (ReceiverType r : receiverTypes)
|
||||
serReceiverTypes.push_back(ReceiverTypeSer(r));
|
||||
READWRITE(serReceiverTypes);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
static ZcashdUnifiedKeyMetadata Read(Stream& stream) {
|
||||
ZcashdUnifiedKeyMetadata meta;
|
||||
stream >> meta;
|
||||
return meta;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -62,6 +62,7 @@ uint256 ovkForShieldingFromTaddr(HDSeed& seed);
|
|||
|
||||
namespace libzcash {
|
||||
|
||||
typedef uint256 SeedFingerprint;
|
||||
typedef uint32_t AccountId;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue