implement MoneroWallet.cpp:mergeTx();

MoneroTransfer.getIsOutgoing(), MoneroTx.getHeight() accessors
This commit is contained in:
woodser
2019-06-11 13:08:26 -04:00
parent a255698b12
commit a0a618406e
4 changed files with 152 additions and 48 deletions
+3
View File
@@ -96,6 +96,9 @@ namespace monero {
return node;
}
// -------------------------- MODEL IMPLEMENTATION --------------------------
// ---------------------------- PRIVATE HELPERS -----------------------------
}
+43 -39
View File
@@ -55,9 +55,47 @@ namespace monero {
};
// forward declarations
struct MoneroBlock;
struct MoneroTx;
struct MoneroOutput;
/**
* Models a Monero block header which contains information about the block.
*/
struct MoneroBlockHeader : public SerializableStruct {
boost::optional<string> id;
boost::optional<uint64_t> height;
boost::optional<uint64_t> timestamp;
boost::optional<uint64_t> size;
boost::optional<uint64_t> weight;
boost::optional<uint64_t> longTermWeight;
boost::optional<uint64_t> depth;
boost::optional<uint64_t> difficulty;
boost::optional<uint64_t> cumulativeDifficulty;
boost::optional<uint32_t> majorVersion;
boost::optional<uint32_t> minorVersion;
boost::optional<uint64_t> nonce;
boost::optional<string> coinbaseTxId;
boost::optional<uint32_t> numTxs;
boost::optional<bool> orphanStatus;
boost::optional<string> prevId;
boost::optional<uint64_t> reward;
boost::optional<string> powHash;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Models a Monero block in the blockchain.
*/
struct MoneroBlock : public MoneroBlockHeader {
boost::optional<string> hex;
boost::optional<shared_ptr<MoneroTx>> coinbaseTx;
vector<shared_ptr<MoneroTx>> txs;
vector<string> txIds;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Models a Monero transaction on the blockchain.
*/
@@ -103,44 +141,10 @@ namespace monero {
vector<string> signatures;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Models a Monero block header which contains information about the block.
*/
struct MoneroBlockHeader : public SerializableStruct {
boost::optional<string> id;
boost::optional<uint64_t> height;
boost::optional<uint64_t> timestamp;
boost::optional<uint64_t> size;
boost::optional<uint64_t> weight;
boost::optional<uint64_t> longTermWeight;
boost::optional<uint64_t> depth;
boost::optional<uint64_t> difficulty;
boost::optional<uint64_t> cumulativeDifficulty;
boost::optional<uint32_t> majorVersion;
boost::optional<uint32_t> minorVersion;
boost::optional<uint64_t> nonce;
boost::optional<string> coinbaseTxId;
boost::optional<uint32_t> numTxs;
boost::optional<bool> orphanStatus;
boost::optional<string> prevId;
boost::optional<uint64_t> reward;
boost::optional<string> powHash;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Models a Monero block in the blockchain.
*/
struct MoneroBlock : public MoneroBlockHeader {
boost::optional<string> hex;
boost::optional<shared_ptr<MoneroTx>> coinbaseTx;
vector<shared_ptr<MoneroTx>> txs;
vector<string> txIds;
boost::property_tree::ptree toPropertyTree() const;
boost::optional<uint64_t> getHeight() const {
if (block == boost::none) return boost::none;
return *((*block)->height);
}
};
/**
+102 -4
View File
@@ -174,9 +174,107 @@ namespace monero {
// return incomingTransfer;
// }
void mergeTx(vector<shared_ptr<MoneroTxWallet>> txs, const shared_ptr<MoneroTxWallet>& tx) {
/**
* Merges a transaction into a unique set of transactions.
*
* TODO monero-core: skipIfAbsent only necessary because incoming payments not returned
* when sent from/to same account #4500
*
* @param txs are existing transactions to merge into
* @param tx is the transaction to merge into the existing txs
* @param skipIfAbsent specifies if the tx should not be added if it doesn't already exist
* @returns the merged tx
*/
void mergeTx(vector<shared_ptr<MoneroTxWallet>> txs, const shared_ptr<MoneroTxWallet>& tx, bool skipIfAbsent) {
cout << "mergeTx()" << endl;
throw runtime_error("Not implemented");
if (tx->id == boost::none) throw runtime_error("Tx id is not initialized");
for (const auto& aTx: txs) {
// merge tx
if (*aTx->id == *tx->id) {
// merge blocks if confirmed, txs otherwise
if (aTx->block != boost::none || tx->block != boost::none) {
if (aTx->block == boost::none) {
aTx->block = shared_ptr<MoneroBlock>(new MoneroBlock());
vector<shared_ptr<MoneroTx>> txs;
txs.push_back(tx);
(*aTx->block)->txs = txs;
(*aTx->block)->height = *tx->getHeight();
}
if (tx->block == boost::none) {
tx->block = shared_ptr<MoneroBlock>(new MoneroBlock());
vector<shared_ptr<MoneroTx>> txs;
txs.push_back(tx);
(*tx->block)->txs = txs;
(*tx->block)->height = *aTx->getHeight();
}
aTx->block->merge(tx->block);
} else {
aTx->merge(*tx);
}
return;
}
// merge common block of different txs
if (tx->getHeight() != boost::none && *tx->getHeight() == *aTx->getHeight())
(*aTx-block)->merge(*tx->block);
//if (aTx.getIsConfirmed()) assertTrue(aTx.getBlock().getTxs().contains(aTx));
}
}
// add tx if it doesn't already exist unless skipped
if (!skipIfAbsent) {
txs.push_back(tx);
} else {
cout << "WARNING: tx does not already exist" << endl; // TODO: proper logging
}
}
/**
* Merges a transaction into a unique set of transactions.
*
* TODO monero-wallet-rpc: skipIfAbsent only necessary because incoming payments not returned
* when sent from/to same account
*
* @param txs are existing transactions to merge into
* @param tx is the transaction to merge into the existing txs
* @param skipIfAbsent specifies if the tx should not be added
* if it doesn't already exist. Only necessasry to handle
* missing incoming payments from #4500. // TODO
* @returns the merged tx
*/
private static void mergeTx(List<MoneroTxWallet> txs, MoneroTxWallet tx, boolean skipIfAbsent) {
assertNotNull(tx.getId());
for (MoneroTxWallet aTx : txs) {
// merge tx
if (aTx.getId().equals(tx.getId())) {
// merge blocks which only exist when confirmed
if (aTx.getBlock() != null || tx.getBlock() != null) {
if (aTx.getBlock() == null) aTx.setBlock(new MoneroBlock().setTxs(new ArrayList<MoneroTx>(Arrays.asList(aTx))).setHeight(tx.getHeight()));
if (tx.getBlock() == null) tx.setBlock(new MoneroBlock().setTxs(new ArrayList<MoneroTx>(Arrays.asList(tx))).setHeight(aTx.getHeight()));
aTx.getBlock().merge(tx.getBlock());
} else {
aTx.merge(tx);
}
return;
}
// merge common block of different txs
if (tx.getHeight() != null && tx.getHeight().equals(aTx.getHeight())) {
aTx.getBlock().merge(tx.getBlock());
if (aTx.getIsConfirmed()) assertTrue(aTx.getBlock().getTxs().contains(aTx));
}
}
// add tx if it doesn't already exist unless skipped
if (!skipIfAbsent) {
txs.add(tx);
} else {
LOGGER.warn("WARNING: tx does not already exist");
}
}
// ----------------------------- WALLET LISTENER ----------------------------
@@ -629,8 +727,8 @@ namespace monero {
wallet2->get_payments(payments, minHeight, maxHeight, accountIndex, subaddressIndices);
for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) {
shared_ptr<MoneroTxWallet> tx = buildTxWithIncomingTransfer(i->second.m_tx_hash, i->first, i->second);
//mergeTx(txs, tx); // TODO
txs.push_back(tx);
mergeTx(txs, tx); // TODO
//txs.push_back(tx);
}
}
+4 -5
View File
@@ -101,6 +101,10 @@ namespace monero {
boost::optional<uint32_t> numSuggestedConfirmations;
boost::property_tree::ptree toPropertyTree() const;
boost::optional<bool> getIsOutgoing() const {
if (isIncoming == boost::none ) return boost::none;
return !(*isIncoming);
}
};
/**
@@ -160,11 +164,6 @@ namespace monero {
vector<shared_ptr<MoneroDestination>> destinations;
boost::optional<bool> hasDestinations;
boost::optional<shared_ptr<MoneroTxRequest>> txRequest;
boost::optional<bool> getIsOutgoing() const {
if (isIncoming == boost::none ) return boost::none;
return !(*isIncoming);
}
};
/**