* Adding mweb_wtx_info to WalletTxToJSON

* Better handling of conflicting wallet tx data during rescan
* Fix create tx dialog for txs using subtract fee from amount
* Safer MWEB block undo logic
pull/816/head
David Burkett 3 years ago committed by Loshan T
parent e07a311aeb
commit cca9cfe7c8

@ -96,16 +96,16 @@ void CoinsViewCache::UndoBlock(const mw::BlockUndo::CPtr& pUndo)
{
assert(pUndo != nullptr);
for (const mw::Hash& coinToRemove : pUndo->GetCoinsAdded()) {
m_pUpdates->SpendUTXO(coinToRemove);
}
std::vector<mmr::LeafIndex> leavesToAdd;
for (const UTXO& coinToAdd : pUndo->GetCoinsSpent()) {
leavesToAdd.push_back(coinToAdd.GetLeafIndex());
m_pUpdates->AddUTXO(std::make_shared<UTXO>(coinToAdd));
}
for (const mw::Hash& coinToRemove : pUndo->GetCoinsAdded()) {
m_pUpdates->SpendUTXO(coinToRemove);
}
auto pHeader = pUndo->GetPreviousHeader();
if (pHeader == nullptr) {
m_pLeafSet->Rewind(0, {});

@ -140,6 +140,10 @@ void Transact::AddMWEBTx(InProcessTx& new_tx)
m_wallet.GetMWWallet()->SaveToWallet(output_coins);
}
// TxBuilder::BuildTx only builds partial coins.
// We still need to rewind them to populate any remaining fields, like address index.
m_wallet.GetMWWallet()->RewindOutputs(CTransaction(new_tx.tx));
// Update pegin output
auto pegins = new_tx.tx.mweb_tx.GetPegIns();
if (!pegins.empty()) {

@ -44,24 +44,27 @@ void WalletModelTransaction::setTransactionFee(const CAmount& newFee)
void WalletModelTransaction::reassignAmounts(interfaces::Wallet& wallet, int nChangePosRet)
{
std::vector<CTxOutput> outputs = wtx->GetOutputs();
std::vector<PegOutCoin> pegouts = wtx->mweb_tx.GetPegOuts();
if (nChangePosRet == -1) {
for (size_t i = 0; i < outputs.size(); i++) {
if (wallet.isChange(outputs[i])) {
nChangePosRet = i;
break;
}
}
}
int i = 0;
size_t i = 0;
for (QList<SendCoinsRecipient>::iterator it = recipients.begin(); it != recipients.end(); ++it)
{
SendCoinsRecipient& rcp = (*it);
{
if (i == nChangePosRet)
while (i < outputs.size()) {
if (wallet.isChange(outputs[i]) || (!outputs[i].IsMWEB() && outputs[i].GetScriptPubKey().IsMWEBPegin())) {
i++;
} else {
break;
}
}
if (i < outputs.size()) {
rcp.amount = wallet.getValue(outputs[i]);
} else if (pegouts.size() > (i - outputs.size())) {
rcp.amount = pegouts[i - outputs.size()].GetAmount();
}
i++;
}
}

@ -172,6 +172,26 @@ static void WalletTxToJSON(interfaces::Chain& chain, const CWalletTx& wtx, UniVa
entry.pushKV("time", wtx.GetTxTime());
entry.pushKV("timereceived", (int64_t)wtx.nTimeReceived);
if (wtx.mweb_wtx_info) {
UniValue partial_mweb(UniValue::VOBJ);
if (wtx.mweb_wtx_info->received_coin) {
UniValue received_entry(UniValue::VOBJ);
const mw::Coin& received = *wtx.mweb_wtx_info->received_coin;
received_entry.pushKV("output_id", received.output_id.ToHex());
received_entry.pushKV("amount", received.amount);
partial_mweb.pushKV("received", received_entry);
}
if (wtx.mweb_wtx_info->spent_input) {
UniValue spent_entry(UniValue::VOBJ);
spent_entry.pushKV("output_id", wtx.mweb_wtx_info->spent_input->ToHex());
partial_mweb.pushKV("spent", spent_entry);
}
entry.pushKV("partial_mweb", partial_mweb);
}
// Add opt-in RBF status
std::string rbfStatus = "no";
if (confirms <= 0) {

@ -927,17 +927,14 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const boost::optional<MWEB::
if (!fInsertedNew)
{
if (confirm.status != wtx.m_confirm.status) {
if (confirm != wtx.m_confirm) {
wtx.m_confirm.status = confirm.status;
wtx.m_confirm.nIndex = confirm.nIndex;
wtx.m_confirm.hashBlock = confirm.hashBlock;
wtx.m_confirm.block_height = confirm.block_height;
fUpdated = true;
} else {
assert(wtx.m_confirm.nIndex == confirm.nIndex);
assert(wtx.m_confirm.hashBlock == confirm.hashBlock);
assert(wtx.m_confirm.block_height == confirm.block_height);
}
// If we have a witness-stripped version of this transaction, and we
// see a new version with a witness, then we must be upgrading a pre-segwit
// wallet. Store the new version of the transaction with the witness,
@ -947,6 +944,13 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const boost::optional<MWEB::
wtx.SetTx(tx);
fUpdated = true;
}
// MWEB: If we have only a partial transaction, and tx is not partial, replace it.
if (wtx.tx->IsNull() && !tx->IsNull()) {
wtx.SetTx(tx);
wtx.mweb_wtx_info = mweb_wtx_info;
fUpdated = true;
}
}
//// debug print
@ -995,7 +999,7 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx
uint256 wtx_hash = wtx_tmp.GetHash();
if (mapWallet.count(wtx_hash) > 0 && wtx_tmp.tx->IsNull()) {
LogPrintf("%s already exists\n", wtx_hash.ToString());
WalletLogPrintf("%s already exists\n", wtx_hash.ToString());
return true;
}
@ -2086,7 +2090,12 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
for (const Kernel& kernel : block.mweb_block.m_block->GetKernels()) {
const CWalletTx* wtx = FindWalletTxByKernelId(kernel.GetKernelID());
if (wtx) {
SyncTransaction(wtx->tx, wtx->mweb_wtx_info, {CWalletTx::Status::CONFIRMED, block_height, block_hash, wtx->m_confirm.nIndex}, fUpdate);
SyncTransaction(
wtx->tx,
wtx->mweb_wtx_info,
{CWalletTx::Status::CONFIRMED, block_height, block_hash, wtx->m_confirm.nIndex},
fUpdate
);
}
}
@ -2095,7 +2104,12 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
if (mweb_wallet->RewindOutput(output, mweb_coin)) {
const CWalletTx* wtx = FindWalletTx(mweb_coin.output_id);
if (wtx) {
SyncTransaction(wtx->tx, wtx->mweb_wtx_info, {CWalletTx::Status::CONFIRMED, block_height, block_hash, wtx->m_confirm.nIndex}, fUpdate);
SyncTransaction(
wtx->tx,
wtx->mweb_wtx_info,
{CWalletTx::Status::CONFIRMED, block_height, block_hash, wtx->m_confirm.nIndex},
fUpdate
);
} else {
AddToWallet(
MakeTransactionRef(),
@ -2117,7 +2131,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
SyncTransaction(
tx_iter->second.tx,
tx_iter->second.mweb_wtx_info,
{CWalletTx::Status::CONFIRMED, block_height, block_hash, 0},
{CWalletTx::Status::CONFIRMED, block_height, block_hash, tx_iter->second.m_confirm.nIndex},
fUpdate
);
}

@ -394,6 +394,7 @@ public:
uint256 hashBlock;
int nIndex;
Confirmation(Status s = UNCONFIRMED, int b = 0, uint256 h = uint256(), int i = 0) : status(s), block_height(b), hashBlock(h), nIndex(i) {}
bool operator!=(const Confirmation& c) const { return status != c.status || block_height != c.block_height || hashBlock != c.hashBlock || nIndex != c.nIndex; }
};
Confirmation m_confirm;

Loading…
Cancel
Save