Skip to content

Commit

Permalink
Port walletdb and update extract destination address
Browse files Browse the repository at this point in the history
  • Loading branch information
timemarkovqtum committed Mar 21, 2024
1 parent 93fb9d9 commit eeae1e5
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 23 deletions.
4 changes: 2 additions & 2 deletions src/kernel/coinstats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ uint64_t GetBogoSize(const CScript& script_pub_key)
{
return 32 /* txid */ +
4 /* vout index */ +
4 /* height + coinbase */ +
4 /* height + coinbase + coinstake*/ +
8 /* amount */ +
2 /* scriptPubKey len */ +
script_pub_key.size() /* scriptPubKey */;
Expand All @@ -52,7 +52,7 @@ template <typename T>
static void TxOutSer(T& ss, const COutPoint& outpoint, const Coin& coin)
{
ss << outpoint;
ss << static_cast<uint32_t>((coin.nHeight << 1) + coin.fCoinBase);
ss << static_cast<uint32_t>((coin.nHeight << 2) + (coin.fCoinBase ? 1u : 0u) + (coin.fCoinStake ? 2u : 0u));
ss << coin.out;
}

Expand Down
10 changes: 5 additions & 5 deletions src/pos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ bool CheckBlockInputPubKeyMatchesOutputPubKey(const CBlock& block, CCoinsViewCac
// If the input does not exactly match the output, it MUST be on P2PKH spent and P2PK out.
CTxDestination inputAddress;
TxoutType inputTxType=TxoutType::NONSTANDARD;
if(!ExtractDestination(coinIn.out.scriptPubKey, inputAddress, &inputTxType)) {
if(!ExtractDestination(coinIn.out.scriptPubKey, inputAddress, &inputTxType, true)) {
return error("%s: Could not extract address from input", __func__);
}

Expand All @@ -303,7 +303,7 @@ bool CheckBlockInputPubKeyMatchesOutputPubKey(const CBlock& block, CCoinsViewCac

CTxDestination outputAddress;
TxoutType outputTxType=TxoutType::NONSTANDARD;
if(!ExtractDestination(txout.scriptPubKey, outputAddress, &outputTxType)) {
if(!ExtractDestination(txout.scriptPubKey, outputAddress, &outputTxType, true)) {
return error("%s: Could not extract address from output", __func__);
}

Expand Down Expand Up @@ -346,7 +346,7 @@ bool CheckRecoveredPubKeyFromBlockSignature(CBlockIndex* pindexPrev, const CBloc
CTxDestination address;
TxoutType txType=TxoutType::NONSTANDARD;
if(pubkey.RecoverCompact(hash, vchBlockSig) &&
ExtractDestination(coinPrev.out.scriptPubKey, address, &txType)){
ExtractDestination(coinPrev.out.scriptPubKey, address, &txType, true)){
if ((txType == TxoutType::PUBKEY || txType == TxoutType::PUBKEYHASH) && std::holds_alternative<PKHash>(address)) {
if(SignStr::VerifyMessage(ToKeyID(std::get<PKHash>(address)), pubkey.GetID().GetReverseHex(), vchPoD)) {
return true;
Expand All @@ -360,7 +360,7 @@ bool CheckRecoveredPubKeyFromBlockSignature(CBlockIndex* pindexPrev, const CBloc
CTxDestination address;
TxoutType txType=TxoutType::NONSTANDARD;
if(pubkey.RecoverCompact(hash, vchBlockSig) &&
ExtractDestination(coinPrev.out.scriptPubKey, address, &txType)){
ExtractDestination(coinPrev.out.scriptPubKey, address, &txType, true)){
if ((txType == TxoutType::PUBKEY || txType == TxoutType::PUBKEYHASH) && std::holds_alternative<PKHash>(address)) {
if(pubkey.GetID() == ToKeyID(std::get<PKHash>(address))) {
return true;
Expand All @@ -380,7 +380,7 @@ bool CheckRecoveredPubKeyFromBlockSignature(CBlockIndex* pindexPrev, const CBloc

CTxDestination address;
TxoutType txType=TxoutType::NONSTANDARD;
if(ExtractDestination(coinPrev.out.scriptPubKey, address, &txType)){
if(ExtractDestination(coinPrev.out.scriptPubKey, address, &txType, true)){
if ((txType == TxoutType::PUBKEY || txType == TxoutType::PUBKEYHASH) && std::holds_alternative<PKHash>(address)) {
if(pubkey.GetID() == ToKeyID(std::get<PKHash>(address))) {
return true;
Expand Down
4 changes: 2 additions & 2 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2794,7 +2794,7 @@ valtype GetSenderAddress(const CTransaction& tx, const CCoinsViewCache* coinsVie

CTxDestination addressBit;
TxoutType txType=TxoutType::NONSTANDARD;
if(ExtractDestination(script, addressBit, &txType)){
if(ExtractDestination(script, addressBit, &txType, true)){
if ((txType == TxoutType::PUBKEY || txType == TxoutType::PUBKEYHASH) &&
std::holds_alternative<PKHash>(addressBit)){
PKHash senderAddress(std::get<PKHash>(addressBit));
Expand Down Expand Up @@ -2987,7 +2987,7 @@ dev::eth::EnvInfo ByteCodeExec::BuildEVMEnvironment(){
dev::Address ByteCodeExec::EthAddrFromScript(const CScript& script){
CTxDestination addressBit;
TxoutType txType=TxoutType::NONSTANDARD;
if(ExtractDestination(script, addressBit, &txType)){
if(ExtractDestination(script, addressBit, &txType, true)){
if ((txType == TxoutType::PUBKEY || txType == TxoutType::PUBKEYHASH) &&
std::holds_alternative<PKHash>(addressBit)){
PKHash addressKey(std::get<PKHash>(addressBit));
Expand Down
6 changes: 3 additions & 3 deletions src/wallet/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
{
CTxDestination tx_sender_address;
if(wtx.tx && wtx.tx->vin.size() > 0 && wallet.mapWallet.find(wtx.tx->vin[0].prevout.hash) != wallet.mapWallet.end() &&
ExtractDestination(wallet.mapWallet.at(wtx.tx->vin[0].prevout.hash).tx->vout[wtx.tx->vin[0].prevout.n].scriptPubKey, tx_sender_address)) {
ExtractDestination(wallet.mapWallet.at(wtx.tx->vin[0].prevout.hash).tx->vout[wtx.tx->vin[0].prevout.n].scriptPubKey, tx_sender_address, nullptr, true)) {
result.tx_sender_key = wallet.GetKeyForDestination(tx_sender_address);
}

Expand Down Expand Up @@ -712,7 +712,7 @@ class WalletImpl : public Wallet
{
CTxDestination address;
const CScript& scriptPubKey = out.txout.scriptPubKey;
bool fValidAddress = ExtractDestination(scriptPubKey, address);
bool fValidAddress = ExtractDestination(scriptPubKey, address, nullptr, true);

if(fValidAddress && EncodeDestination(address) == qtumAddress && out.txout.nValue)
{
Expand Down Expand Up @@ -770,7 +770,7 @@ class WalletImpl : public Wallet
{
CTxDestination address;
const CScript& scriptPubKey = out.txout.scriptPubKey;
bool fValidAddress = ExtractDestination(scriptPubKey, address);
bool fValidAddress = ExtractDestination(scriptPubKey, address, nullptr, true);

if (!fValidAddress || !m_wallet->IsMine(address)) continue;

Expand Down
8 changes: 4 additions & 4 deletions src/wallet/rpc/contract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ bool SetDefaultPayForContractAddress(const CWallet& wallet, CCoinControl & coinC
for (const COutput& out : vecOutputs) {
CTxDestination destAdress;
const CScript& scriptPubKey = out.txout.scriptPubKey;
bool fValidAddress = out.spendable && ExtractDestination(scriptPubKey, destAdress)
bool fValidAddress = out.spendable && ExtractDestination(scriptPubKey, destAdress, nullptr, true)
&& IsValidContractSenderAddress(destAdress);

if (!fValidAddress)
Expand All @@ -57,7 +57,7 @@ bool SetDefaultSignSenderAddress(const CWallet& wallet, CTxDestination& destAdre

for (const COutput& out : vecOutputs) {
const CScript& scriptPubKey = out.txout.scriptPubKey;
bool fValidAddress = out.spendable && ExtractDestination(scriptPubKey, destAdress)
bool fValidAddress = out.spendable && ExtractDestination(scriptPubKey, destAdress, nullptr, true)
&& IsValidContractSenderAddress(destAdress);

if (!fValidAddress)
Expand Down Expand Up @@ -238,7 +238,7 @@ RPCHelpMan createcontract()
for (const COutput& out : vecOutputs) {
CTxDestination destAdress;
const CScript& scriptPubKey = out.txout.scriptPubKey;
bool fValidAddress = out.spendable && ExtractDestination(scriptPubKey, destAdress);
bool fValidAddress = out.spendable && ExtractDestination(scriptPubKey, destAdress, nullptr, true);

if (!fValidAddress || senderAddress != destAdress)
continue;
Expand Down Expand Up @@ -499,7 +499,7 @@ UniValue SendToContract(CWallet& wallet, const UniValue& params, ChainstateManag

CTxDestination destAdress;
const CScript& scriptPubKey = out.txout.scriptPubKey;
bool fValidAddress = out.spendable && ExtractDestination(scriptPubKey, destAdress);
bool fValidAddress = out.spendable && ExtractDestination(scriptPubKey, destAdress, nullptr, true);

if (!fValidAddress || senderAddress != destAdress)
continue;
Expand Down
8 changes: 4 additions & 4 deletions src/wallet/rpc/spend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,9 @@ RPCHelpMan sendtoaddress()
for(const COutput& out : vecOutputs) {
CTxDestination destAdress;
const CScript& scriptPubKey = out.txout.scriptPubKey;
bool fValidAddress = ExtractDestination(scriptPubKey, destAdress);
bool fValidAddress = ExtractDestination(scriptPubKey, destAdress, nullptr, true);

if (!fValidAddress || !(senderAddress == destAdress))
if (!fValidAddress || senderAddress != destAdress)
continue;

coin_control.Select(out.outpoint);
Expand Down Expand Up @@ -2045,10 +2045,10 @@ RPCHelpMan splitutxosforaddress()
for(const COutput& out : vecOutputs) {
CTxDestination destAdress;
const CScript& scriptPubKey = out.txout.scriptPubKey;
bool fValidAddress = ExtractDestination(scriptPubKey, destAdress);
bool fValidAddress = ExtractDestination(scriptPubKey, destAdress, nullptr, true);

CAmount val = out.txout.nValue;
if (!fValidAddress || !(address == destAdress) || (val >= minValue && val <= maxValue ) )
if (!fValidAddress || address != destAdress || (val >= minValue && val <= maxValue ) )
continue;

if(nSelectedAmount <= nRequiredAmount)
Expand Down
10 changes: 8 additions & 2 deletions src/wallet/salvage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,10 @@ bool RecoverDatabaseFile(const ArgsManager& args, const fs::path& file_path, bil
{
/* Filter for only private key type KV pairs to be added to the salvaged wallet */
DataStream ssKey{row.first};
DataStream ssValue(row.second);
CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION);
std::string strType, strErr;

// We only care about KEY, MASTER_KEY, CRYPTED_KEY, and HDCHAIN types
// We only care about KEY, MASTER_KEY, CRYPTED_KEY, HDCHAIN, TOKEN, TOKENTX and DELEGATION types
ssKey >> strType;
bool fReadOK = false;
if (strType == DBKeys::KEY) {
Expand All @@ -197,6 +197,12 @@ bool RecoverDatabaseFile(const ArgsManager& args, const fs::path& file_path, bil
fReadOK = LoadEncryptionKey(&dummyWallet, ssKey, ssValue, strErr);
} else if (strType == DBKeys::HDCHAIN) {
fReadOK = LoadHDChain(&dummyWallet, ssValue, strErr);
} else if (strType == DBKeys::TOKEN) {
fReadOK = LoadToken(&dummyWallet, ssKey, ssValue, strErr);
} else if (strType == DBKeys::TOKENTX) {
fReadOK = LoadTokenTx(&dummyWallet, ssKey, ssValue, strErr);
} else if (strType == DBKeys::DELEGATION) {
fReadOK = LoadDelegation(&dummyWallet, ssKey, ssValue, strErr);
} else {
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5509,7 +5509,7 @@ bool CWallet::GetSenderDest(const CTransaction &tx, CTxDestination &txSenderDest
}

// Extract destination from script
return ExtractDestination(senderPubKey, txSenderDest);
return ExtractDestination(senderPubKey, txSenderDest, nullptr, true);
}

bool CWallet::GetHDKeyPath(const CTxDestination &dest, std::string &hdkeypath) const
Expand Down
149 changes: 149 additions & 0 deletions src/wallet/walletdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,120 @@ bool LoadHDChain(CWallet* pwallet, DataStream& ssValue, std::string& strErr)
return true;
}

bool LoadToken(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strErr)
{
LOCK(pwallet->cs_wallet);
try {
uint256 hash;
ssKey >> hash;
CTokenInfo wtoken;
ssValue >> wtoken;
if (wtoken.GetHash() != hash)
{
strErr = "Error reading wallet database: CTokenInfo corrupt";
return false;
}
pwallet->LoadToken(wtoken);
} catch (const std::exception& e) {
if (strErr.empty()) {
strErr = e.what();
}
return false;
}
return true;
}

bool LoadTokenTx(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strErr)
{
LOCK(pwallet->cs_wallet);
try {
uint256 hash;
ssKey >> hash;
CTokenTx wTokenTx;
ssValue >> wTokenTx;
if (wTokenTx.GetHash() != hash)
{
strErr = "Error reading wallet database: CTokenTx corrupt";
return false;
}
pwallet->LoadTokenTx(wTokenTx);
} catch (const std::exception& e) {
if (strErr.empty()) {
strErr = e.what();
}
return false;
}
return true;
}

bool LoadDelegation(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strErr)
{
LOCK(pwallet->cs_wallet);
try {
uint256 hash;
ssKey >> hash;
CDelegationInfo wdelegation;
ssValue >> wdelegation;
if (wdelegation.GetHash() != hash)
{
strErr = "Error reading wallet database: CDelegationInfo corrupt";
return false;
}
pwallet->LoadDelegation(wdelegation);
} catch (const std::exception& e) {
if (strErr.empty()) {
strErr = e.what();
}
return false;
}
return true;
}

bool LoadSuperStaker(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strErr)
{
LOCK(pwallet->cs_wallet);
try {
uint256 hash;
ssKey >> hash;
CSuperStakerInfo wsuperStaker;
ssValue >> wsuperStaker;
if (wsuperStaker.GetHash() != hash)
{
strErr = "Error reading wallet database: CSuperStakerInfo corrupt";
return false;
}
pwallet->LoadSuperStaker(wsuperStaker);
} catch (const std::exception& e) {
if (strErr.empty()) {
strErr = e.what();
}
return false;
}
return true;
}

bool LoadContractData(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr)
{
LOCK(pwallet->cs_wallet);
try {
std::string strAddress, strKey, strValue;
ssKey >> strAddress;
ssKey >> strKey;
ssValue >> strValue;
if (!pwallet->LoadContractData(strAddress, strKey, strValue))
{
strErr = "Error reading wallet database: LoadContractData failed";
return false;
}
} catch (const std::exception& e) {
if (strErr.empty()) {
strErr = e.what();
}
return false;
}
return true;
}

static DBErrors LoadMinVersion(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
{
AssertLockHeld(pwallet->cs_wallet);
Expand Down Expand Up @@ -758,6 +872,41 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
});
result = std::max(result, wkey_res.m_result);

// Load token
LoadResult token_res = LoadRecords(pwallet, batch, DBKeys::TOKEN,
[] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
return LoadToken(pwallet, key, value, err) ? DBErrors:: LOAD_OK : DBErrors::CORRUPT;
});
result = std::max(result, token_res.m_result);

// Load token transaction
LoadResult token_tx_res = LoadRecords(pwallet, batch, DBKeys::TOKENTX,
[] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
return LoadTokenTx(pwallet, key, value, err) ? DBErrors:: LOAD_OK : DBErrors::CORRUPT;
});
result = std::max(result, token_tx_res.m_result);

// Load delegation
LoadResult delegation_res = LoadRecords(pwallet, batch, DBKeys::DELEGATION,
[] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
return LoadDelegation(pwallet, key, value, err) ? DBErrors:: LOAD_OK : DBErrors::CORRUPT;
});
result = std::max(result, delegation_res.m_result);

// Load super staker
LoadResult super_staker_res = LoadRecords(pwallet, batch, DBKeys::SUPERSTAKER,
[] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
return LoadSuperStaker(pwallet, key, value, err) ? DBErrors:: LOAD_OK : DBErrors::CORRUPT;
});
result = std::max(result, super_staker_res.m_result);

// Load contract data
LoadResult contract_data_res = LoadRecords(pwallet, batch, DBKeys::CONTRACTDATA,
[] (CWallet* pwallet, DataStream& key, CDataStream& value, std::string& err) {
return LoadContractData(pwallet, key, value, err) ? DBErrors:: LOAD_OK : DBErrors::CORRUPT;
});
result = std::max(result, contract_data_res.m_result);

if (result <= DBErrors::NONCRITICAL_ERROR) {
// Only do logging and time first key update if there were no critical errors
pwallet->WalletLogPrintf("Legacy Wallet Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total.\n",
Expand Down
5 changes: 5 additions & 0 deletions src/wallet/walletdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,11 @@ bool LoadKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::stri
bool LoadCryptedKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr);
bool LoadEncryptionKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr);
bool LoadHDChain(CWallet* pwallet, DataStream& ssValue, std::string& strErr);
bool LoadToken(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strErr);
bool LoadTokenTx(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strErr);
bool LoadDelegation(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strErr);
bool LoadSuperStaker(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue, std::string& strErr);
bool LoadContractData(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr);
} // namespace wallet

#endif // BITCOIN_WALLET_WALLETDB_H

0 comments on commit eeae1e5

Please sign in to comment.