diff --git a/src/kernel/coinstats.cpp b/src/kernel/coinstats.cpp index 9bd755ed27..2292244912 100644 --- a/src/kernel/coinstats.cpp +++ b/src/kernel/coinstats.cpp @@ -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 */; @@ -52,7 +52,7 @@ template static void TxOutSer(T& ss, const COutPoint& outpoint, const Coin& coin) { ss << outpoint; - ss << static_cast((coin.nHeight << 1) + coin.fCoinBase); + ss << static_cast((coin.nHeight << 2) + (coin.fCoinBase ? 1u : 0u) + (coin.fCoinStake ? 2u : 0u)); ss << coin.out; } diff --git a/src/pos.cpp b/src/pos.cpp index 3235133347..4643ea3c0b 100644 --- a/src/pos.cpp +++ b/src/pos.cpp @@ -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__); } @@ -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__); } @@ -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(address)) { if(SignStr::VerifyMessage(ToKeyID(std::get(address)), pubkey.GetID().GetReverseHex(), vchPoD)) { return true; @@ -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(address)) { if(pubkey.GetID() == ToKeyID(std::get(address))) { return true; @@ -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(address)) { if(pubkey.GetID() == ToKeyID(std::get(address))) { return true; diff --git a/src/validation.cpp b/src/validation.cpp index a99ed889ba..3023e27d66 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -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(addressBit)){ PKHash senderAddress(std::get(addressBit)); @@ -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(addressBit)){ PKHash addressKey(std::get(addressBit)); diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index fc0bdcd4c5..6cebd22185 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -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); } @@ -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) { @@ -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; diff --git a/src/wallet/rpc/contract.cpp b/src/wallet/rpc/contract.cpp index 7e2516a877..574a035820 100644 --- a/src/wallet/rpc/contract.cpp +++ b/src/wallet/rpc/contract.cpp @@ -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) @@ -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) @@ -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; @@ -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; diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp index d271bab606..bca0826365 100644 --- a/src/wallet/rpc/spend.cpp +++ b/src/wallet/rpc/spend.cpp @@ -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); @@ -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) diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp index 04c02b0dcc..c23254a9da 100644 --- a/src/wallet/salvage.cpp +++ b/src/wallet/salvage.cpp @@ -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) { @@ -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; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8af226f00e..f2c7e0a193 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -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 diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 91597a1e0d..a111f1772a 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -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); @@ -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", diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 611cc11c8b..f5f5e8b927 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -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