Skip to content

Commit 9d32d24

Browse files
committed
[Stealth] Process transactions received while wallet was locked
1 parent 4ae95d5 commit 9d32d24

File tree

4 files changed

+129
-13
lines changed

4 files changed

+129
-13
lines changed

src/wallet/wallet.cpp

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -535,8 +535,8 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl
535535
nWalletBackups = GetArg("-createwalletbackups", 10);
536536
}
537537
if (!fForMixingOnly) {
538-
// Process encrypted links in queue
539-
ProcessLinkQueue();
538+
RunProcessStealthQueue(); // Process stealth transactions in queue
539+
ProcessLinkQueue(); // Process encrypted links in queue
540540
}
541541
return true;
542542
}
@@ -5238,8 +5238,9 @@ bool CWallet::InitLoadWallet()
52385238
return false;
52395239
}
52405240
pwalletMain = pwallet;
5241-
// Process link queue.
5242-
ProcessLinkQueue();
5241+
5242+
RunProcessStealthQueue(); // Process stealth transactions in queue
5243+
ProcessLinkQueue(); // Process links in queue.
52435244

52445245
return true;
52455246
}
@@ -5434,11 +5435,59 @@ inline bool MatchPrefix(uint32_t nAddrBits, uint32_t addrPrefix, uint32_t output
54345435
return (addrPrefix & mask) == (outputPrefix & mask);
54355436
}
54365437

5438+
bool CWallet::ProcessStealthQueue()
5439+
{
5440+
CWalletDB* pwdb = GetWalletDB();
5441+
if (!pwdb)
5442+
return false;
5443+
5444+
std::vector<std::pair<CKeyID, CStealthKeyQueueData>> vStealthKeyQueue;
5445+
if (pwdb->GetStealthQueue(vStealthKeyQueue)) {
5446+
for (const std::pair<CKeyID, CStealthKeyQueueData>& data : vStealthKeyQueue) {
5447+
CStealthKeyQueueData stealthData = data.second;
5448+
CKey sSpend;
5449+
if (!GetKey(stealthData.pkSpend.GetID(), sSpend)) {
5450+
LogPrintf("%s: Error getting spend private key (%s) for stealth transaction.\n", __func__, CDynamicAddress(stealthData.pkSpend.GetID()).ToString());
5451+
continue;
5452+
}
5453+
CKey sSpendR;
5454+
if (StealthSharedToSecretSpend(stealthData.SharedKey, sSpend, sSpendR) != 0) {
5455+
LogPrintf("%s: StealthSharedToSecretSpend() failed.\n", __func__);
5456+
continue;
5457+
}
5458+
CPubKey pkT = sSpendR.GetPubKey();
5459+
if (!pkT.IsValid()) {
5460+
LogPrintf("%s: pkT is invalid.\n", __func__);
5461+
continue;
5462+
}
5463+
CKeyID keyID = pkT.GetID();
5464+
if (keyID != data.first) {
5465+
LogPrintf("%s: Spend key mismatch!\n", __func__);
5466+
continue;
5467+
}
5468+
5469+
if (!AddKeyPubKey(sSpendR, pkT)) {
5470+
continue;
5471+
}
5472+
nFoundStealth++;
5473+
}
5474+
}
5475+
return true;
5476+
}
5477+
5478+
bool RunProcessStealthQueue()
5479+
{
5480+
if (!pwalletMain)
5481+
return false;
5482+
5483+
return pwalletMain->ProcessStealthQueue();
5484+
}
5485+
54375486
bool CWallet::ProcessStealthOutput(const CTxDestination& address, std::vector<uint8_t>& vchEphemPK, uint32_t prefix, bool fHavePrefix, CKey& sShared)
54385487
{
54395488
CWalletDB* pwdb = GetWalletDB();
54405489
if (!pwdb)
5441-
return errorN(1, "%s: GetWalletDB failed.", __func__);
5490+
return false;
54425491

54435492
CKeyID idMatchShared = boost::get<CKeyID>(address);
54445493
ec_point pkExtracted;
@@ -5479,8 +5528,9 @@ bool CWallet::ProcessStealthOutput(const CTxDestination& address, std::vector<ui
54795528
AddCryptedKey(pkE, vchEmpty);
54805529
CPubKey cpkEphem(vchEphemPK);
54815530
CPubKey cpkScan(sxAddr.scan_pubkey);
5482-
CStealthKeyQueueData lockedSkQueueData(cpkEphem, cpkScan);
5483-
if (!pwdb->WriteStealthKeyQueue(idExtracted, lockedSkQueueData)) {
5531+
CPubKey cpkSpend(sxAddr.spend_pubkey);
5532+
CStealthKeyQueueData lockedSkQueueData(cpkEphem, cpkScan, cpkSpend, sShared);
5533+
if (!pwdb->WriteStealthKeyQueue(idMatchShared, lockedSkQueueData)) {
54845534
LogPrintf("%s: Error WriteStealthKeyQueue failed for %s.\n", __func__, CDynamicAddress(idExtracted).ToString());
54855535
return false;
54865536
}

src/wallet/wallet.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,21 +634,42 @@ class CStealthKeyQueueData
634634
public:
635635
CStealthKeyQueueData() {}
636636

637-
CStealthKeyQueueData(CPubKey pkEphem_, CPubKey pkScan_)
637+
CStealthKeyQueueData(const CPubKey& pkEphem_, const CPubKey& pkScan_, const CPubKey& pkSpend_, const CKey& SharedKey_)
638638
{
639639
pkEphem = pkEphem_;
640640
pkScan = pkScan_;
641+
pkSpend = pkSpend_;
642+
SharedKey = SharedKey_;
641643
};
642644

643645
CPubKey pkEphem;
644646
CPubKey pkScan;
647+
CPubKey pkSpend;
648+
CKey SharedKey;
649+
650+
inline CStealthKeyQueueData operator=(const CStealthKeyQueueData& b) {
651+
pkEphem = b.pkEphem;
652+
pkScan = b.pkScan;
653+
pkSpend = b.pkSpend;
654+
SharedKey = b.SharedKey;
655+
return *this;
656+
}
645657

646658
ADD_SERIALIZE_METHODS;
647659
template <typename Stream, typename Operation>
648660
inline void SerializationOp(Stream& s, Operation ser_action)
649661
{
650662
READWRITE(pkEphem);
651663
READWRITE(pkScan);
664+
READWRITE(pkSpend);
665+
if (ser_action.ForRead()) {
666+
std::vector<unsigned char> vchSharedKey;
667+
READWRITE(vchSharedKey);
668+
SharedKey.Set(vchSharedKey.begin(), vchSharedKey.end(), true);
669+
} else {
670+
std::vector<unsigned char> vchSharedKey(SharedKey.begin(), SharedKey.end());
671+
READWRITE(vchSharedKey);
672+
}
652673
};
653674
};
654675

@@ -1199,6 +1220,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
11991220

12001221
// Stealth Address Support
12011222
bool GetStealthAddress(const CKeyID& keyid, CStealthAddress& sxAddr) const;
1223+
bool ProcessStealthQueue();
12021224
bool ProcessStealthOutput(const CTxDestination& address, std::vector<uint8_t>& vchEphemPK, uint32_t prefix, bool fHavePrefix, CKey& sShared);
12031225
int CheckForStealthTxOut(const CTxOut* pTxOut, const CTxOut* pTxData);
12041226
bool HasBDAPLinkTx(const CTransaction& tx, CScript& bdapOpScript);
@@ -1269,4 +1291,6 @@ class CAccount
12691291
}
12701292
};
12711293

1294+
bool RunProcessStealthQueue();
1295+
12721296
#endif // DYNAMIC_WALLET_WALLET_H

src/wallet/walletdb.cpp

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,7 @@ bool CWalletDB::LoadStealthKeyAddresses(std::vector<std::pair<CKeyID, CStealthAd
11081108
std::string strType;
11091109
ssKey >> strType;
11101110

1111-
if (strType == "sxaddr1") {
1111+
if (strType == "stealth") {
11121112
CKeyID idAccount;
11131113
ssKey >> idAccount;
11141114
LogPrintf("%s -- Loading shared stealth address %s\n", __func__, idAccount.ToString());
@@ -1130,20 +1130,61 @@ bool CWalletDB::LoadStealthKeyAddresses(std::vector<std::pair<CKeyID, CStealthAd
11301130

11311131
bool CWalletDB::WriteStealthAddress(const CStealthAddress& sxAddr)
11321132
{
1133-
return Write(std::make_pair(std::string("sxaddr1"), sxAddr.GetSpendKeyID()), sxAddr);
1133+
return Write(std::make_pair(std::string("stealth"), sxAddr.GetSpendKeyID()), sxAddr);
11341134
}
11351135

11361136
bool CWalletDB::WriteStealthKeyQueue(const CKeyID& keyId, const CStealthKeyQueueData& sxKeyMeta)
11371137
{
1138-
return Write(std::make_pair(std::string("sxkm"), keyId), sxKeyMeta);
1138+
return Write(std::make_pair(std::string("sxqueue"), keyId), sxKeyMeta);
11391139
}
11401140

11411141
bool CWalletDB::EraseStealthKeyQueue(const CKeyID& keyId)
11421142
{
1143-
return Erase(std::make_pair(std::string("sxkm"), keyId));
1143+
return Erase(std::make_pair(std::string("sxqueue"), keyId));
11441144
}
11451145

11461146
bool CWalletDB::ReadStealthKeyQueue(const CKeyID& keyId, CStealthKeyQueueData& sxKeyMeta)
11471147
{
1148-
return Read(std::make_pair(std::string("sxkm"), keyId), sxKeyMeta);
1148+
return Read(std::make_pair(std::string("sxqueue"), keyId), sxKeyMeta);
1149+
}
1150+
1151+
bool CWalletDB::GetStealthQueue(std::vector<std::pair<CKeyID,CStealthKeyQueueData>>& vStealthKeyQueue)
1152+
{
1153+
try {
1154+
// Get cursor
1155+
Dbc* pcursor = GetCursor();
1156+
if (!pcursor)
1157+
throw std::runtime_error(std::string(__func__) + ": cannot create DB cursor");
1158+
1159+
while (true) {
1160+
// Read next record
1161+
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
1162+
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
1163+
int ret = ReadAtCursor(pcursor, ssKey, ssValue);
1164+
if (ret == DB_NOTFOUND) {
1165+
break;
1166+
}
1167+
else if (ret != 0) {
1168+
LogPrintf("%s -- Error reading next record from wallet database\n", __func__);
1169+
return false;
1170+
}
1171+
1172+
std::string strType;
1173+
ssKey >> strType;
1174+
1175+
if (strType == "sxqueue") {
1176+
CKeyID idAccount;
1177+
ssKey >> idAccount;
1178+
CStealthKeyQueueData stealthData;
1179+
ssValue >> stealthData;
1180+
vStealthKeyQueue.push_back(std::make_pair(idAccount, stealthData));
1181+
}
1182+
}
1183+
pcursor->close();
1184+
} catch (const boost::thread_interrupted&) {
1185+
throw;
1186+
} catch (...) {
1187+
return false;
1188+
}
1189+
return (vStealthKeyQueue.size() > 0);
11491190
}

src/wallet/walletdb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ class CWalletDB : public CDB
161161
bool WriteStealthKeyQueue(const CKeyID& keyId, const CStealthKeyQueueData& sxKeyMeta);
162162
bool EraseStealthKeyQueue(const CKeyID& keyId);
163163
bool ReadStealthKeyQueue(const CKeyID& keyId, CStealthKeyQueueData& sxKeyMeta);
164+
bool GetStealthQueue(std::vector<std::pair<CKeyID,CStealthKeyQueueData>>& vStealthKeyQueue);
164165

165166
private:
166167
CWalletDB(const CWalletDB&);

0 commit comments

Comments
 (0)