UPSTREAM MERGE BROKEN: Merge commit 'f617e05c38' into master

This commit is contained in:
Steven Roose 2019-05-01 19:15:40 +01:00
commit 7f894ae00b
No known key found for this signature in database
GPG key ID: 2F2A88D7F8D68E87
393 changed files with 7992 additions and 3340 deletions

View file

@ -7,12 +7,16 @@
#include <amount.h>
#include <chain.h>
#include <consensus/validation.h>
#include <init.h>
#include <interfaces/chain.h>
#include <interfaces/handler.h>
#include <net.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
#include <rpc/server.h>
#include <scheduler.h>
#include <script/ismine.h>
#include <script/standard.h>
#include <support/allocators/secure.h>
@ -20,10 +24,18 @@
#include <timedata.h>
#include <ui_interface.h>
#include <uint256.h>
#include <util/system.h>
#include <validation.h>
#include <wallet/feebumper.h>
#include <wallet/fees.h>
#include <wallet/rpcwallet.h>
#include <wallet/wallet.h>
#include <wallet/walletutil.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace interfaces {
namespace {
@ -41,7 +53,8 @@ public:
WalletOrderForm order_form,
std::string& reject_reason) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
CValidationState state;
if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), m_keys, g_connman.get(), state, g_con_elementsmode ? &m_blind_details : nullptr)) {
reject_reason = state.GetRejectReason();
@ -57,7 +70,7 @@ public:
};
//! Construct wallet tx struct.
static WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
WalletTx MakeWalletTx(interfaces::Chain::Lock& locked_chain, CWallet& wallet, const CWalletTx& wtx)
{
WalletTx result;
result.tx = wtx.tx;
@ -87,7 +100,7 @@ static WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) EXCLUSIVE_LO
result.txout_amounts.emplace_back(wtx.GetOutputValueOut(i));
result.txout_assets.emplace_back(wtx.GetOutputAsset(i));
}
result.credit = wtx.GetCredit(ISMINE_ALL);
result.credit = wtx.GetCredit(locked_chain, ISMINE_ALL);
result.debit = wtx.GetDebit(ISMINE_ALL);
result.change = wtx.GetChange();
result.time = wtx.GetTxTime();
@ -97,32 +110,38 @@ static WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) EXCLUSIVE_LO
}
//! Construct wallet tx status struct.
static WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
WalletTxStatus MakeWalletTxStatus(interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx)
{
LockAnnotation lock(::cs_main); // Temporary, for CheckFinalTx below. Removed in upcoming commit.
WalletTxStatus result;
auto mi = ::mapBlockIndex.find(wtx.hashBlock);
CBlockIndex* block = mi != ::mapBlockIndex.end() ? mi->second : nullptr;
result.block_height = (block ? block->nHeight : std::numeric_limits<int>::max());
result.blocks_to_maturity = wtx.GetBlocksToMaturity();
result.depth_in_main_chain = wtx.GetDepthInMainChain();
result.blocks_to_maturity = wtx.GetBlocksToMaturity(locked_chain);
result.depth_in_main_chain = wtx.GetDepthInMainChain(locked_chain);
result.time_received = wtx.nTimeReceived;
result.lock_time = wtx.tx->nLockTime;
result.is_final = CheckFinalTx(*wtx.tx);
result.is_trusted = wtx.IsTrusted();
result.is_trusted = wtx.IsTrusted(locked_chain);
result.is_abandoned = wtx.isAbandoned();
result.is_coinbase = wtx.IsCoinBase();
result.is_in_main_chain = wtx.IsInMainChain();
result.is_in_main_chain = wtx.IsInMainChain(locked_chain);
return result;
}
//! Construct wallet TxOut struct.
static WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
WalletTxOut MakeWalletTxOut(interfaces::Chain::Lock& locked_chain,
CWallet& wallet,
const CWalletTx& wtx,
int n,
int depth) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
WalletTxOut result;
result.txout = wtx.tx->vout[n];
result.time = wtx.GetTxTime();
result.depth_in_main_chain = depth;
result.is_spent = wallet.IsSpent(wtx.GetHash(), n);
result.is_spent = wallet.IsSpent(locked_chain, wtx.GetHash(), n);
return result;
}
@ -214,22 +233,26 @@ public:
}
void lockCoin(const COutPoint& output) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
return m_wallet.LockCoin(output);
}
void unlockCoin(const COutPoint& output) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
return m_wallet.UnlockCoin(output);
}
bool isLockedCoin(const COutPoint& output) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
return m_wallet.IsLockedCoin(output.hash, output.n);
}
void listLockedCoins(std::vector<COutPoint>& outputs) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
return m_wallet.ListLockedCoins(outputs);
}
std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients,
@ -240,7 +263,8 @@ public:
std::vector<CAmount>& out_amounts,
std::string& fail_reason) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
auto pending = MakeUnique<PendingWalletTxImpl>(m_wallet);
// Pad change keys to cover total possible number of assets
// One already exists(for policyAsset), so one for each destination
@ -250,7 +274,7 @@ public:
pending->m_keys.emplace_back(new CReserveKey(&m_wallet));
}
}
if (!m_wallet.CreateTransaction(recipients, pending->m_tx, pending->m_keys, fee, change_pos,
if (!m_wallet.CreateTransaction(*locked_chain, recipients, pending->m_tx, pending->m_keys, fee, change_pos,
fail_reason, coin_control, sign, g_con_elementsmode ? &pending->m_blind_details : nullptr)) {
return {};
}
@ -260,8 +284,9 @@ public:
bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet.TransactionCanBeAbandoned(txid); }
bool abandonTransaction(const uint256& txid) override
{
LOCK2(cs_main, m_wallet.cs_wallet);
return m_wallet.AbandonTransaction(txid);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
return m_wallet.AbandonTransaction(*locked_chain, txid);
}
bool transactionCanBeBumped(const uint256& txid) override
{
@ -289,7 +314,8 @@ public:
}
CTransactionRef getTx(const uint256& txid) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
auto mi = m_wallet.mapWallet.find(txid);
if (mi != m_wallet.mapWallet.end()) {
return mi->second.tx;
@ -298,29 +324,30 @@ public:
}
WalletTx getWalletTx(const uint256& txid) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
auto mi = m_wallet.mapWallet.find(txid);
if (mi != m_wallet.mapWallet.end()) {
return MakeWalletTx(m_wallet, mi->second);
return MakeWalletTx(*locked_chain, m_wallet, mi->second);
}
return {};
}
std::vector<WalletTx> getWalletTxs() override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
std::vector<WalletTx> result;
result.reserve(m_wallet.mapWallet.size());
for (const auto& entry : m_wallet.mapWallet) {
result.emplace_back(MakeWalletTx(m_wallet, entry.second));
result.emplace_back(MakeWalletTx(*locked_chain, m_wallet, entry.second));
}
return result;
}
bool tryGetTxStatus(const uint256& txid,
interfaces::WalletTxStatus& tx_status,
int& num_blocks,
int64_t& adjusted_time) override
int& num_blocks) override
{
TRY_LOCK(::cs_main, locked_chain);
auto locked_chain = m_wallet.chain().lock(true /* try_lock */);
if (!locked_chain) {
return false;
}
@ -333,26 +360,24 @@ public:
return false;
}
num_blocks = ::chainActive.Height();
adjusted_time = GetAdjustedTime();
tx_status = MakeWalletTxStatus(mi->second);
tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
return true;
}
WalletTx getWalletTxDetails(const uint256& txid,
WalletTxStatus& tx_status,
WalletOrderForm& order_form,
bool& in_mempool,
int& num_blocks,
int64_t& adjusted_time) override
int& num_blocks) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
auto mi = m_wallet.mapWallet.find(txid);
if (mi != m_wallet.mapWallet.end()) {
num_blocks = ::chainActive.Height();
adjusted_time = GetAdjustedTime();
in_mempool = mi->second.InMempool();
order_form = mi->second.vOrderForm;
tx_status = MakeWalletTxStatus(mi->second);
return MakeWalletTx(m_wallet, mi->second);
tx_status = MakeWalletTxStatus(*locked_chain, mi->second);
return MakeWalletTx(*locked_chain, m_wallet, mi->second);
}
return {};
}
@ -372,7 +397,7 @@ public:
}
bool tryGetBalances(WalletBalances& balances, int& num_blocks) override
{
TRY_LOCK(cs_main, locked_chain);
auto locked_chain = m_wallet.chain().lock(true /* try_lock */);
if (!locked_chain) return false;
TRY_LOCK(m_wallet.cs_wallet, locked_wallet);
if (!locked_wallet) {
@ -389,49 +414,55 @@ public:
}
isminetype txinIsMine(const CTxIn& txin) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
return m_wallet.IsMine(txin);
}
isminetype txoutIsMine(const CTxOut& txout) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
return m_wallet.IsMine(txout);
}
CAmountMap getDebit(const CTxIn& txin, isminefilter filter) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
return m_wallet.GetDebit(txin, filter);
}
CAmountMap getCredit(const CTxOut& txout, isminefilter filter) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
return m_wallet.GetCredit(txout, filter);
}
CoinsList listCoins() override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
CoinsList result;
for (const auto& entry : m_wallet.ListCoins()) {
for (const auto& entry : m_wallet.ListCoins(*locked_chain)) {
auto& group = result[entry.first];
for (const auto& coin : entry.second) {
group.emplace_back(
COutPoint(coin.tx->GetHash(), coin.i), MakeWalletTxOut(m_wallet, *coin.tx, coin.i, coin.nDepth));
group.emplace_back(COutPoint(coin.tx->GetHash(), coin.i),
MakeWalletTxOut(*locked_chain, m_wallet, *coin.tx, coin.i, coin.nDepth));
}
}
return result;
}
std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto locked_chain = m_wallet.chain().lock();
LOCK(m_wallet.cs_wallet);
std::vector<WalletTxOut> result;
result.reserve(outputs.size());
for (const auto& output : outputs) {
result.emplace_back();
auto it = m_wallet.mapWallet.find(output.hash);
if (it != m_wallet.mapWallet.end()) {
int depth = it->second.GetDepthInMainChain();
int depth = it->second.GetDepthInMainChain(*locked_chain);
if (depth >= 0) {
result.back() = MakeWalletTxOut(m_wallet, it->second, output.n, depth);
result.back() = MakeWalletTxOut(*locked_chain, m_wallet, it->second, output.n, depth);
}
}
}
@ -487,8 +518,32 @@ public:
CWallet& m_wallet;
};
class WalletClientImpl : public ChainClient
{
public:
WalletClientImpl(Chain& chain, std::vector<std::string> wallet_filenames)
: m_chain(chain), m_wallet_filenames(std::move(wallet_filenames))
{
}
void registerRpcs() override { return RegisterWalletRPCCommands(::tableRPC); }
bool verify() override { return VerifyWallets(m_chain, m_wallet_filenames); }
bool load() override { return LoadWallets(m_chain, m_wallet_filenames); }
void start(CScheduler& scheduler) override { return StartWallets(scheduler); }
void flush() override { return FlushWallets(); }
void stop() override { return StopWallets(); }
~WalletClientImpl() override { UnloadWallets(); }
Chain& m_chain;
std::vector<std::string> m_wallet_filenames;
};
} // namespace
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return MakeUnique<WalletImpl>(wallet); }
std::unique_ptr<ChainClient> MakeWalletClient(Chain& chain, std::vector<std::string> wallet_filenames)
{
return MakeUnique<WalletClientImpl>(chain, std::move(wallet_filenames));
}
} // namespace interfaces