mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-18 13:17:55 +02:00
UPSTREAM MERGE BROKEN: Merge commit 'f617e05c38' into master
This commit is contained in:
commit
7f894ae00b
393 changed files with 7992 additions and 3340 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue