Skip to content

Commit

Permalink
MWEB: Wallet & UI changes
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidBurkett committed Jan 30, 2022
1 parent 9cfd1ad commit c51647e
Show file tree
Hide file tree
Showing 68 changed files with 3,599 additions and 1,358 deletions.
8 changes: 8 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ BITCOIN_CORE_H = \
mweb/mweb_models.h \
mweb/mweb_node.h \
mweb/mweb_policy.h \
mweb/mweb_transact.h \
mweb/mweb_wallet.h \
net.h \
net_permissions.h \
net_processing.h \
Expand Down Expand Up @@ -300,12 +302,14 @@ BITCOIN_CORE_H = \
wallet/coincontrol.h \
wallet/coinselection.h \
wallet/context.h \
wallet/createtransaction.h \
wallet/crypter.h \
wallet/db.h \
wallet/feebumper.h \
wallet/fees.h \
wallet/ismine.h \
wallet/load.h \
wallet/reserve.h \
wallet/rpcwallet.h \
wallet/salvage.h \
wallet/scriptpubkeyman.h \
Expand Down Expand Up @@ -413,15 +417,19 @@ endif
libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(SQLITE_CFLAGS)
libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_wallet_a_SOURCES = \
mweb/mweb_transact.cpp \
mweb/mweb_wallet.cpp \
interfaces/wallet.cpp \
wallet/bdb.cpp \
wallet/coincontrol.cpp \
wallet/context.cpp \
wallet/createtransaction.cpp \
wallet/crypter.cpp \
wallet/db.cpp \
wallet/feebumper.cpp \
wallet/fees.cpp \
wallet/load.cpp \
wallet/reserve.cpp \
wallet/rpcdump.cpp \
wallet/rpcwallet.cpp \
wallet/salvage.cpp \
Expand Down
4 changes: 2 additions & 2 deletions src/bench/coin_selection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ static void CoinSelection(benchmark::Bench& bench)
}

const CoinEligibilityFilter filter_standard(1, 6, 0);
const CoinSelectionParams coin_selection_params(/* use_bnb= */ true, /* change_output_size= */ 34,
const CoinSelectionParams coin_selection_params(/* use_bnb= */ true, /* change_output_size= */ 34, /* mweb_change_output_weight= */ 0,
/* change_spend_size= */ 148, /* effective_feerate= */ CFeeRate(0),
/* long_term_feerate= */ CFeeRate(0), /* discard_feerate= */ CFeeRate(0),
/* tx_no_inputs_size= */ 0);
/* tx_no_inputs_size= */ 0, /* mweb_no_change_weight= */ 0);
bench.run([&] {
std::set<CInputCoin> setCoinsRet;
CAmount nValueRet;
Expand Down
18 changes: 16 additions & 2 deletions src/interfaces/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,24 @@ class NodeImpl : public Node
std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); }
void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); }
void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); }
bool getUnspentOutput(const COutPoint& output, Coin& coin) override
bool getUnspentOutput(const OutputIndex& index, CTxOutput& output) override
{
LOCK(::cs_main);
return ::ChainstateActive().CoinsTip().GetCoin(output, coin);

if (index.type() == typeid(mw::Hash)) {
if (::ChainstateActive().CoinsTip().HaveCoin(index)) {
output = CTxOutput{boost::get<mw::Hash>(index)};
return true;
}
} else {
Coin coin;
if (::ChainstateActive().CoinsTip().GetCoin(boost::get<COutPoint>(index), coin)) {
output = CTxOutput{boost::get<COutPoint>(index), coin.out};
return true;
}
}

return false;
}
WalletClient& walletClient() override
{
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class Node
virtual void rpcUnsetTimerInterface(RPCTimerInterface* iface) = 0;

//! Get unspent outputs associated with a transaction.
virtual bool getUnspentOutput(const COutPoint& output, Coin& coin) = 0;
virtual bool getUnspentOutput(const OutputIndex& index, CTxOutput& output) = 0;

//! Get wallet client.
virtual WalletClient& walletClient() = 0;
Expand Down
183 changes: 137 additions & 46 deletions src/interfaces/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <wallet/fees.h>
#include <wallet/ismine.h>
#include <wallet/load.h>
#include <wallet/reserve.h>
#include <wallet/rpcwallet.h>
#include <wallet/wallet.h>

Expand All @@ -34,32 +35,101 @@
namespace interfaces {
namespace {

//! Construct wallet TxOut struct.
WalletTxOut MakeWalletTxOut(CWallet& wallet,
const CWalletTx& wtx,
const CTxOutput& output) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
WalletTxOut result;
result.txout = output;
result.output_index = output.GetIndex();
result.time = wtx.GetTxTime();
result.depth_in_main_chain = wtx.GetDepthInMainChain();
result.is_spent = wallet.IsSpent(output.GetIndex());

if (output.IsMWEB()) {
mw::Coin coin;
if (wallet.GetCoin(output.ToMWEB(), coin)) {
result.address = wallet.GetMWWallet()->GetStealthAddress(coin.address_index);
result.nValue = coin.amount;
}
} else {
result.address = output.GetTxOut().scriptPubKey;
result.nValue = output.GetTxOut().nValue;
}

return result;
}

WalletTxOut MakeWalletTxOut(CWallet& wallet, const COutputCoin& coin)
{
WalletTxOut result;
if (coin.IsMWEB()) {
result.txout = CTxOutput(boost::get<mw::Hash>(coin.GetIndex()));
} else {
assert(!coin.GetAddress().IsMWEB());
result.txout = CTxOutput(coin.GetIndex(), CTxOut(coin.GetValue(), coin.GetAddress().GetScript()));
}
result.address = coin.GetAddress();
result.output_index = coin.GetIndex();
result.nValue = coin.GetValue();
result.time = coin.GetWalletTx()->GetTxTime();
result.depth_in_main_chain = coin.GetDepth();
result.is_spent = wallet.IsSpent(coin.GetIndex());
return result;
}

//! Construct wallet tx struct.
WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
{
LOCK(wallet.cs_wallet);

WalletTx result;
result.tx = wtx.tx;
result.txin_is_mine.reserve(wtx.tx->vin.size());
for (const auto& txin : wtx.tx->vin) {
result.txin_is_mine.emplace_back(wallet.IsMine(txin));
}
result.txout_is_mine.reserve(wtx.tx->vout.size());
result.txout_address.reserve(wtx.tx->vout.size());
result.txout_address_is_mine.reserve(wtx.tx->vout.size());
for (const auto& txout : wtx.tx->vout) {
result.txout_is_mine.emplace_back(wallet.IsMine(txout));
result.txout_address.emplace_back();
result.txout_address_is_mine.emplace_back(ExtractDestination(txout.scriptPubKey, result.txout_address.back()) ?
wallet.IsMine(result.txout_address.back()) :
ISMINE_NO);
}
result.credit = wtx.GetCredit(ISMINE_ALL);
result.debit = wtx.GetDebit(ISMINE_ALL);
result.change = wtx.GetChange();
result.fee = wtx.GetFee(ISMINE_ALL);
result.time = wtx.GetTxTime();
result.value_map = wtx.mapValue;
result.is_coinbase = wtx.IsCoinBase();
result.wtx_hash = wtx.GetHash();

//
// Inputs
//
result.inputs = wtx.GetInputs();
result.txin_is_mine.reserve(result.inputs.size());

for (const auto& txin : result.inputs) {
result.txin_is_mine.emplace_back(wallet.IsMine(txin));
}

//
// Outputs
//
auto is_address_mine = [&wallet](const CTxOutput& txout) -> isminetype {
CTxDestination dest;
return wallet.ExtractOutputDestination(txout, dest) ? wallet.IsMine(dest) : ISMINE_NO;
};

std::vector<CTxOutput> outputs = wtx.GetOutputs();
result.txout_is_mine.reserve(outputs.size());
result.txout_address_is_mine.reserve(outputs.size());
result.outputs.reserve(outputs.size());

for (const auto& txout : outputs) {
// MWEB Peg-in output pubkey scripts are anyone-can-spend, so don't really have an owner.
// In order for peg-ins to your own address to show up as SendToSelf txs, we need to filter these out.
if (!txout.IsMWEB() && txout.GetScriptPubKey().IsMWEBPegin()) {
continue;
}

result.txout_is_mine.emplace_back(wallet.IsMine(txout));
result.txout_address_is_mine.emplace_back(is_address_mine(txout));
result.outputs.push_back(MakeWalletTxOut(wallet, wtx, txout));
}

return result;
}

Expand All @@ -80,20 +150,6 @@ WalletTxStatus MakeWalletTxStatus(CWallet& wallet, const CWalletTx& wtx)
return result;
}

//! Construct wallet TxOut struct.
WalletTxOut MakeWalletTxOut(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);
return result;
}

class WalletImpl : public Wallet
{
public:
Expand Down Expand Up @@ -121,6 +177,18 @@ class WalletImpl : public Wallet
std::string error;
return m_wallet->GetNewDestination(type, label, dest, error);
}
std::shared_ptr<ReserveDestination> reserveNewDestination(CTxDestination& dest) override
{
LOCK(m_wallet->cs_wallet);

auto output_type = OutputType::BECH32;
auto reserve_dest = std::make_shared<ReserveDestination>(m_wallet.get(), output_type);
if (reserve_dest->GetReservedDestination(dest, true)) {
return reserve_dest;
}

return nullptr;
}
bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) override
{
std::unique_ptr<SigningProvider> provider = m_wallet->GetSolvingProvider(script);
Expand Down Expand Up @@ -185,6 +253,11 @@ class WalletImpl : public Wallet
}
return result;
}
bool extractOutputDestination(const CTxOutput& output, CTxDestination& dest) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->ExtractOutputDestination(output, dest);
}
bool addDestData(const CTxDestination& dest, const std::string& key, const std::string& value) override
{
LOCK(m_wallet->cs_wallet);
Expand All @@ -202,22 +275,27 @@ class WalletImpl : public Wallet
LOCK(m_wallet->cs_wallet);
return m_wallet->GetDestValues(prefix);
}
void lockCoin(const COutPoint& output) override
bool findCoin(const mw::Hash& output_id, mw::Coin& coin) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->GetCoin(output_id, coin);
}
void lockCoin(const OutputIndex& output) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->LockCoin(output);
}
void unlockCoin(const COutPoint& output) override
void unlockCoin(const OutputIndex& output) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->UnlockCoin(output);
}
bool isLockedCoin(const COutPoint& output) override
bool isLockedCoin(const OutputIndex& output) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->IsLockedCoin(output.hash, output.n);
return m_wallet->IsLockedCoin(output);
}
void listLockedCoins(std::vector<COutPoint>& outputs) override
void listLockedCoins(std::vector<OutputIndex>& outputs) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->ListLockedCoins(outputs);
Expand All @@ -240,9 +318,14 @@ class WalletImpl : public Wallet
}
void commitTransaction(CTransactionRef tx,
WalletValueMap value_map,
WalletOrderForm order_form) override
WalletOrderForm order_form,
const std::vector<ReserveDestination*>& reserved_keys) override
{
LOCK(m_wallet->cs_wallet);
for (ReserveDestination* reserved : reserved_keys) {
reserved->KeepDestination();
}

m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form));
}
bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet->TransactionCanBeAbandoned(txid); }
Expand Down Expand Up @@ -376,22 +459,27 @@ class WalletImpl : public Wallet
{
return m_wallet->GetAvailableBalance(&coin_control);
}
isminetype txinIsMine(const CTxIn& txin) override
isminetype txinIsMine(const CTxInput& txin) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->IsMine(txin);
}
isminetype txoutIsMine(const CTxOut& txout) override
isminetype txoutIsMine(const CTxOutput& txout) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->IsMine(txout);
}
CAmount getDebit(const CTxIn& txin, isminefilter filter) override
CAmount getValue(const CTxOutput& txout) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->GetValue(txout);
}
CAmount getDebit(const CTxInput& txin, isminefilter filter) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->GetDebit(txin, filter);
}
CAmount getCredit(const CTxOut& txout, isminefilter filter) override
CAmount getCredit(const CTxOutput& txout, isminefilter filter) override
{
LOCK(m_wallet->cs_wallet);
return m_wallet->GetCredit(txout, filter);
Expand All @@ -403,24 +491,23 @@ class WalletImpl : public Wallet
for (const auto& entry : m_wallet->ListCoins()) {
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(coin.GetIndex(), MakeWalletTxOut(*m_wallet, coin));
}
}
return result;
}
std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) override
std::vector<WalletTxOut> getCoins(const std::vector<OutputIndex>& outputs) override
{
LOCK(m_wallet->cs_wallet);
std::vector<WalletTxOut> result;
result.reserve(outputs.size());
for (const auto& output : outputs) {
for (const OutputIndex& output_idx : outputs) {
result.emplace_back();
auto it = m_wallet->mapWallet.find(output.hash);
if (it != m_wallet->mapWallet.end()) {
int depth = it->second.GetDepthInMainChain();
auto wtx = m_wallet->FindWalletTx(output_idx);
if (wtx != nullptr) {
int depth = wtx->GetDepthInMainChain();
if (depth >= 0) {
result.back() = MakeWalletTxOut(*m_wallet, it->second, output.n, depth);
result.back() = MakeWalletTxOut(*m_wallet, *wtx, wtx->tx->GetOutput(output_idx));
}
}
}
Expand Down Expand Up @@ -451,6 +538,10 @@ class WalletImpl : public Wallet
RemoveWallet(m_wallet, false /* load_on_start */);
}
bool isLegacy() override { return m_wallet->IsLegacy(); }
StealthAddress getPeginAddress() override
{
return m_wallet->GetMWWallet()->GetStealthAddress(mw::PEGIN_INDEX);
}
std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
{
return MakeHandler(m_wallet->NotifyUnload.connect(fn));
Expand Down
Loading

0 comments on commit c51647e

Please sign in to comment.