separate models from daemon and wallet classes

This commit is contained in:
woodser
2019-06-16 11:54:35 -04:00
parent d646894707
commit e831338138
9 changed files with 793 additions and 801 deletions
+2
View File
@@ -292,7 +292,9 @@ target_link_libraries(scratchpad
set(
LIBRARY_SRC_FILES
src/daemon/MoneroDaemonModel.cpp
src/daemon/MoneroDaemon.cpp
src/wallet/MoneroWalletModel.cpp
src/wallet/MoneroWallet.cpp
src/utils/MoneroUtils.cpp
)
+2 -277
View File
@@ -1,284 +1,9 @@
#include "MoneroDaemon.h"
#include "utils/MoneroUtils.h"
#include "include_base_utils.h"
#include "common/util.h"
/**
* Public interface for libmonero-cpp library.
* Public library intereface.
*/
namespace monero {
// ------------------------- INITIALIZE CONSTANTS ---------------------------
const string MoneroTx::DEFAULT_PAYMENT_ID = string("0000000000000000");
// -------------------------- MODEL SERIALIZATION ---------------------------
string SerializableStruct::serialize() const {
return MoneroUtils::serialize(toPropertyTree());
}
boost::property_tree::ptree MoneroBlockHeader::toPropertyTree() const {
//cout << "MoneroBlockHeader::toPropertyTree(block)" << endl;
boost::property_tree::ptree node;
if (id != boost::none) node.put("id", *id);
if (height != boost::none) node.put("height", *height);
if (timestamp != boost::none) node.put("timestamp", *timestamp);
if (size != boost::none) node.put("size", *size);
if (weight != boost::none) node.put("weight", *weight);
if (longTermWeight != boost::none) node.put("longTermWeight", *longTermWeight);
if (depth != boost::none) node.put("depth", *depth);
if (difficulty != boost::none) node.put("difficulty", *difficulty);
if (cumulativeDifficulty != boost::none) node.put("cumulativeDifficulty", *height);
if (majorVersion != boost::none) node.put("majorVersion", *majorVersion);
if (minorVersion != boost::none) node.put("minorVersion", *minorVersion);
if (nonce != boost::none) node.put("nonce", *nonce);
if (coinbaseTxId != boost::none) node.put("coinbaseTxId", *coinbaseTxId);
if (numTxs != boost::none) node.put("numTxs", *numTxs);
if (orphanStatus != boost::none) node.put("orphanStatus", *orphanStatus);
if (prevId != boost::none) node.put("prevId", *prevId);
if (reward != boost::none) node.put("reward", *reward);
if (powHash != boost::none) node.put("powHash", *powHash);
return node;
}
boost::property_tree::ptree MoneroBlock::toPropertyTree() const {
//cout << "MoneroBlock::toPropertyTree(block)" << endl;
boost::property_tree::ptree node = MoneroBlockHeader::toPropertyTree();
if (hex != boost::none) node.put("hex", *hex);
if (coinbaseTx != boost::none) node.add_child("coinbaseTx", (*coinbaseTx)->toPropertyTree());
node.add_child("txs", MoneroUtils::toPropertyTree(txs));
// TODO: handle txIds
return node;
}
boost::property_tree::ptree MoneroTx::toPropertyTree() const {
//cout << "MoneroTx::txToPropertyTree(tx)" << endl;
boost::property_tree::ptree node;
if (id != boost::none) node.put("id", *id);
if (version != boost::none) node.put("version", *version);
if (isCoinbase != boost::none) node.put("isCoinbase", *isCoinbase);
if (paymentId != boost::none) node.put("paymentId", *paymentId);
if (fee != boost::none) node.put("fee", *fee);
if (mixin != boost::none) node.put("mixin", *mixin);
if (doNotRelay != boost::none) node.put("doNotRelay", *doNotRelay);
if (isRelayed != boost::none) node.put("isRelayed", *isRelayed);
if (isConfirmed != boost::none) node.put("isConfirmed", *isConfirmed);
if (inTxPool != boost::none) node.put("inTxPool", *inTxPool);
if (numConfirmations != boost::none) node.put("numConfirmations", *numConfirmations);
if (unlockTime != boost::none) node.put("unlockTime", *unlockTime);
if (lastRelayedTimestamp != boost::none) node.put("lastRelayedTimestamp", *lastRelayedTimestamp);
if (receivedTimestamp != boost::none) node.put("receivedTimestamp", *receivedTimestamp);
if (isDoubleSpend != boost::none) node.put("isDoubleSpend", *isDoubleSpend);
if (key != boost::none) node.put("key", *key);
if (fullHex != boost::none) node.put("fullHex", *fullHex);
if (prunedHex != boost::none) node.put("prunedHex", *prunedHex);
if (prunableHex != boost::none) node.put("prunableHex", *prunableHex);
if (prunableHash != boost::none) node.put("prunableHash", *prunableHash);
if (size != boost::none) node.put("size", *size);
if (weight != boost::none) node.put("weight", *weight);
if (!vins.empty()) throw runtime_error("not implemented");
if (!vouts.empty()) throw runtime_error("not implemented");
if (!outputIndices.empty()) throw runtime_error("not implemented");
if (metadata != boost::none) node.put("metadata", *metadata);
if (commonTxSets != boost::none) throw runtime_error("not implemented");
if (!extra.empty()) throw runtime_error("not implemented");
if (rctSignatures != boost::none) throw runtime_error("not implemented");
if (rctSigPrunable != boost::none) throw runtime_error("not implemented");
if (isKeptByBlock != boost::none) node.put("isKeptByBlock", *isKeptByBlock);
if (isFailed != boost::none) node.put("isFailed", *isFailed);
if (lastFailedHeight != boost::none) node.put("lastFailedHeight", *lastFailedHeight);
if (lastFailedId != boost::none) node.put("lastFailedId", *lastFailedId);
if (maxUsedBlockHeight != boost::none) node.put("maxUsedBlockHeight", *maxUsedBlockHeight);
if (maxUsedBlockId != boost::none) node.put("maxUsedBlockId", *maxUsedBlockId);
if (!signatures.empty()) throw runtime_error("not implemented");
return node;
}
// -------------------------- MODEL IMPLEMENTATION --------------------------
void MoneroBlockHeader::merge(const shared_ptr<MoneroBlockHeader>& header) {
cout << "MoneroBlockHeader::merge()" << endl;
// if (this == &header) return;
// id = MoneroUtils::reconcile(id, header.id);
// height = MoneroUtils::reconcile(height, header.height, boost::none, boost::none, true); // height can increase
// timestamp = MoneroUtils::reconcile(timestamp, header.timestamp, boost::none, boost::none, true); // timestamp can increase
// size = MoneroUtils::reconcile(size, header.size);
// weight = MoneroUtils::reconcile(weight, header.weight);
// longTermWeight = MoneroUtils::reconcile(longTermWeight, header.longTermWeight);
// depth = MoneroUtils::reconcile(depth, header.depth);
// difficulty = MoneroUtils::reconcile(difficulty, header.difficulty);
// cumulativeDifficulty = MoneroUtils::reconcile(cumulativeDifficulty, header.cumulativeDifficulty);
// majorVersion = MoneroUtils::reconcile(majorVersion, header.majorVersion);
// minorVersion = MoneroUtils::reconcile(minorVersion, header.minorVersion);
// nonce = MoneroUtils::reconcile(nonce, header.nonce);
// coinbaseTxId = MoneroUtils::reconcile(coinbaseTxId, header.coinbaseTxId);
// numTxs = MoneroUtils::reconcile(numTxs, header.numTxs);
// orphanStatus = MoneroUtils::reconcile(orphanStatus, header.orphanStatus);
// prevId = MoneroUtils::reconcile(prevId, header.prevId);
// reward = MoneroUtils::reconcile(reward, header.reward);
// powHash = MoneroUtils::reconcile(powHash, header.powHash);
}
void MoneroBlock::merge(const shared_ptr<MoneroBlockHeader>& block) {
cout << "MoneroBlock::merge()" << endl;
// if (this == &block) return;
//
// // merge header fields
// MoneroBlockHeader::merge(block);
//
// // merge coinbase tx
// if (coinbaseTx == boost::none) coinbaseTx = block.coinbaseTx;
// else if (block.coinbaseTx != boost::none) (**coinbaseTx).merge(**block.coinbaseTx);
//
// // merge non-coinbase txs
// if (txs.empty()) txs = block.txs;
// else if (!block.txs.empty()) {
// for (const shared_ptr<MoneroTx>& thatTx : block.txs) {
// bool found = false;
// for (const shared_ptr<MoneroTx>& thisTx : txs) {
// if (thatTx->id == thisTx->id) {
// thisTx->merge(*thatTx);
// found = true;
// break;
// }
// }
// if (!found) txs.push_back(thatTx);
// }
// }
// if (!txs.empty()) {
// for (const shared_ptr<MoneroTx>& tx : txs) {
// tx->block = shared_ptr<MoneroBlock>(this);
// }
// }
//
// // merge other fields
// hex = MoneroUtils::reconcile(hex, block.hex);
// //txIds = MoneroUtils::reconcile(txIds, block.txIds); // TODO: implement
// cout << "Returning from block::merge()!" << endl;
}
void MoneroTx::merge(const shared_ptr<MoneroTx>& self, const shared_ptr<MoneroTx>& other) {
cout << "MoneroTx::merge()" << endl;
// if (this == &tx) return;
// id = MoneroUtils::reconcile(id, tx.id);
// version = MoneroUtils::reconcile(version, tx.version);
// paymentId = MoneroUtils::reconcile(paymentId, tx.paymentId);
// fee = MoneroUtils::reconcile(fee, tx.fee);
// mixin = MoneroUtils::reconcile(mixin, tx.mixin);
// isConfirmed = MoneroUtils::reconcile(isConfirmed, tx.isConfirmed);
// doNotRelay = MoneroUtils::reconcile(doNotRelay, tx.doNotRelay);
// isRelayed = MoneroUtils::reconcile(isRelayed, tx.isRelayed);
// isDoubleSpend = MoneroUtils::reconcile(isDoubleSpend, tx.isDoubleSpend);
// key = MoneroUtils::reconcile(key, tx.key);
// fullHex = MoneroUtils::reconcile(fullHex, tx.fullHex);
// prunedHex = MoneroUtils::reconcile(prunedHex, tx.prunedHex);
// prunableHex = MoneroUtils::reconcile(prunableHex, tx.prunableHex);
// prunableHash = MoneroUtils::reconcile(prunableHash, tx.prunableHash);
// size = MoneroUtils::reconcile(size, tx.size);
// weight = MoneroUtils::reconcile(weight, tx.weight);
// //outputIndices = MoneroUtils::reconcile(outputIndices, tx.outputIndices); // TODO
// metadata = MoneroUtils::reconcile(metadata, tx.metadata);
// commonTxSets = MoneroUtils::reconcile(commonTxSets, tx.commonTxSets);
// //extra = MoneroUtils::reconcile(extra, tx.extra); // TODO
// rctSignatures = MoneroUtils::reconcile(rctSignatures, tx.rctSignatures);
// rctSigPrunable = MoneroUtils::reconcile(rctSigPrunable, tx.rctSigPrunable);
// isKeptByBlock = MoneroUtils::reconcile(isKeptByBlock, tx.isKeptByBlock);
// isFailed = MoneroUtils::reconcile(isFailed, tx.isFailed);
// lastFailedHeight = MoneroUtils::reconcile(lastFailedHeight, tx.lastFailedHeight);
// lastFailedId = MoneroUtils::reconcile(lastFailedId, tx.lastFailedId);
// maxUsedBlockHeight = MoneroUtils::reconcile(maxUsedBlockHeight, tx.maxUsedBlockHeight);
// maxUsedBlockId = MoneroUtils::reconcile(maxUsedBlockId, tx.maxUsedBlockId);
// //signatures = MoneroUtils::reconcile(signatures, tx.signatures); // TODO
// unlockTime = MoneroUtils::reconcile(unlockTime, tx.unlockTime);
// numConfirmations = MoneroUtils::reconcile(numConfirmations, tx.numConfirmations);
//
// // merge vins
// if (!tx.vins.empty()) {
// for (const shared_ptr<MoneroOutput>& merger : tx.vins) {
// bool merged = false;
// merger->tx = shared_ptr<MoneroTx>(this); // TODO: can this cause this* to be deleted prematurely?
// for (const shared_ptr<MoneroOutput>& mergee : vins) {
// if ((*mergee->keyImage)->hex == (*merger->keyImage)->hex) {
// mergee->merge(*merger);
// merged = true;
// break;
// }
// }
// if (!merged) vins.push_back(merger);
// }
// }
//
// // merge vouts
// if (!tx.vouts.empty()) {
// for (const shared_ptr<MoneroOutput>& vout : tx.vouts) vout->tx = shared_ptr<MoneroTx>(this);
// if (vouts.empty()) vouts = tx.vouts;
// else {
//
// // determine if key images present
// int numKeyImages = 0;
// for (const shared_ptr<MoneroOutput> vout : vouts) {
// if (vout->keyImage != boost::none) {
// if ((*vout->keyImage)->hex == boost::none) throw runtime_error("Key image hex cannot be null");
// numKeyImages++;
// }
// }
// for (const shared_ptr<MoneroOutput>& vout : tx.vouts) {
// if (vout->keyImage != boost::none) {
// if ((*vout->keyImage)->hex == boost::none) throw runtime_error("Key image hex cannot be null");
// numKeyImages++;
// }
// }
// if (numKeyImages != 0 && vouts.size() + tx.vouts.size() != numKeyImages) throw runtime_error("Some vouts have a key image and some do not");
//
// // merge by key images
// if (numKeyImages > 0) {
// for (const shared_ptr<MoneroOutput>& merger : tx.vouts) {
// bool merged = false;
// for (const shared_ptr<MoneroOutput>& mergee : vouts) {
// if ((*mergee->keyImage)->hex == (*merger->keyImage)->hex) {
// mergee->merge(*merger);
// merged = true;
// break;
// }
// }
// if (!merged) vouts.push_back(merger);
// }
// }
//
// // merge by position
// else {
// if (vouts.size() != tx.vouts.size()) throw runtime_error("Vout sizes are different");
// for (int i = 0; i < tx.vouts.size(); i++) {
// vouts.at(i)->merge(*tx.vouts.at(i));
// }
// }
// }
// }
//
// // handle unrelayed -> relayed -> confirmed
// if (*isConfirmed) {
// inTxPool = false;
// receivedTimestamp = boost::none;
// lastRelayedTimestamp = boost::none;
// } else {
// inTxPool = MoneroUtils::reconcile(inTxPool, tx.inTxPool, boost::none, true, boost::none); // unrelayed -> tx pool
// receivedTimestamp = MoneroUtils::reconcile(receivedTimestamp, tx.receivedTimestamp, boost::none, boost::none, false); // take earliest receive time
// lastRelayedTimestamp = MoneroUtils::reconcile(lastRelayedTimestamp, tx.lastRelayedTimestamp, boost::none, boost::none, true); // take latest relay time
// }
}
void MoneroKeyImage::merge(const shared_ptr<MoneroKeyImage>& self, const shared_ptr<MoneroKeyImage>& other) {
cout << "MoneroKeyImage::merge()" << endl;
throw runtime_error("Not implemented");
}
void MoneroOutput::merge(const shared_ptr<MoneroOutput>& self, const shared_ptr<MoneroOutput>& other) {
cout << "MoneroOutput::merge()" << endl;
throw runtime_error("Not implemented");
}
// ---------------------------- PRIVATE HELPERS -----------------------------
// TODO: MoneroDaemon class implementation
}
+3 -199
View File
@@ -1,209 +1,13 @@
#pragma once
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include "MoneroDaemonModel.h"
using namespace std;
/**
* Public interface for libmonero-cpp library.
* Public library interface.
*/
namespace monero {
/**
* Base struct which can be serialized.
*
* TODO: move this to MoneroUtils?
*/
struct SerializableStruct {
/**
* Serializes the struct to a json string.
*
* @return the struct serialized to a json string
*/
string serialize() const;
/**
* Convert the struct to a property tree.
*
* @return the converted property tree
*/
virtual boost::property_tree::ptree toPropertyTree() const = 0;
};
/**
* Enumerates Monero network types.
*/
enum MoneroNetworkType : uint8_t {
MAINNET = 0,
TESTNET,
STAGENET
};
/**
* Models a connection to a daemon.
*
* TODO: switch to boost::optional<string>
*/
struct MoneroRpcConnection {
string uri;
string username;
string password;
//MoneroRpcConnection() : uri(""), username(""), password("")) {}
MoneroRpcConnection(const string& uri = "", const string& username = "", const string& password = "") : uri(uri), username(username), password(password) {}
};
// forward declarations
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;
void merge(const shared_ptr<MoneroBlockHeader>& header);
};
/**
* 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;
void merge(const shared_ptr<MoneroBlockHeader>& block);
};
/**
* Models a Monero transaction on the blockchain.
*/
struct MoneroTx : public SerializableStruct {
static const string DEFAULT_PAYMENT_ID; // default payment id "0000000000000000"
boost::optional<shared_ptr<MoneroBlock>> block;
boost::optional<string> id;
boost::optional<string> version;
boost::optional<bool> isCoinbase;
boost::optional<string> paymentId;
boost::optional<uint64_t> fee;
boost::optional<uint32_t> mixin;
boost::optional<bool> doNotRelay;
boost::optional<bool> isRelayed;
boost::optional<bool> isConfirmed;
boost::optional<bool> inTxPool;
boost::optional<uint64_t> numConfirmations;
boost::optional<uint64_t> unlockTime;
boost::optional<uint64_t> lastRelayedTimestamp;
boost::optional<uint64_t> receivedTimestamp;
boost::optional<bool> isDoubleSpend;
boost::optional<string> key;
boost::optional<string> fullHex;
boost::optional<string> prunedHex;
boost::optional<string> prunableHex;
boost::optional<string> prunableHash;
boost::optional<uint32_t> size;
boost::optional<uint32_t> weight;
vector<shared_ptr<MoneroOutput>> vins;
vector<shared_ptr<MoneroOutput>> vouts;
vector<uint32_t> outputIndices;
boost::optional<string> metadata;
boost::optional<string> commonTxSets;
vector<uint32_t> extra;
boost::optional<string> rctSignatures; // TODO: implement
boost::optional<string> rctSigPrunable; // TODO: implement
boost::optional<bool> isKeptByBlock;
boost::optional<bool> isFailed;
boost::optional<uint32_t> lastFailedHeight;
boost::optional<string> lastFailedId;
boost::optional<uint32_t> maxUsedBlockHeight;
boost::optional<string> maxUsedBlockId;
vector<string> signatures;
boost::property_tree::ptree toPropertyTree() const;
boost::optional<uint64_t> getHeight() const {
if (block == boost::none) return boost::none;
return *((*block)->height);
}
void merge(const shared_ptr<MoneroTx>& self, const shared_ptr<MoneroTx>& other);
};
/**
* Models a Monero key image.
*/
struct MoneroKeyImage {
boost::optional<string> hex;
boost::optional<string> signature;
void merge(const shared_ptr<MoneroKeyImage>& self, const shared_ptr<MoneroKeyImage>& other);
};
/**
* Models a Monero transaction output.
*/
struct MoneroOutput {
shared_ptr<MoneroTx> tx;
boost::optional<shared_ptr<MoneroKeyImage>> keyImage;
boost::optional<uint64_t> amount;
boost::optional<uint32_t> index;
vector<uint32_t> ringOutputIndices;
boost::optional<string> stealthPublicKey;
void merge(const shared_ptr<MoneroOutput>& self, const shared_ptr<MoneroOutput>& other);
};
// TODO: MoneroDaemon class definition
}
//// --------------------------- MODEL SERIALIZATION ----------------------------
//
//BOOST_CLASS_VERSION(monero::MoneroTx, 0)
//BOOST_CLASS_VERSION(monero::MoneroOutput, 0)
//BOOST_CLASS_VERSION(monero::MoneroKeyImage, 0)
//
//namespace boost {
// namespace serialization {
// template <class Archive>
// inline void serialize(Archive &a, monero::MoneroTx& x, const boost::serialization::version_type ver)
// {
//// a & x.m_L;
//// a & x.m_R;
// }
//
// template <class Archive>
// inline void serialize(Archive &a, monero::MoneroOutput& x, const boost::serialization::version_type ver)
// {
//// a & x.m_signer;
//// a & x.m_LR;
//// a & x.m_partial_key_images;
// }
//
// template <class Archive>
// inline void serialize(Archive &a, monero::MoneroKeyImage& x, const boost::serialization::version_type ver)
// {
//// a & x.m_signer;
//// a & x.m_LR;
//// a & x.m_partial_key_images;
// }
// } // namepsace serialization
//} // namespace boost
+289
View File
@@ -0,0 +1,289 @@
#include "MoneroDaemonModel.h"
#include "utils/MoneroUtils.h"
#include "include_base_utils.h"
#include "common/util.h"
/**
* Public library interface.
*/
namespace monero {
// ------------------------- INITIALIZE CONSTANTS ---------------------------
const string MoneroTx::DEFAULT_PAYMENT_ID = string("0000000000000000");
// -------------------------- MODEL SERIALIZATION ---------------------------
string SerializableStruct::serialize() const {
return MoneroUtils::serialize(toPropertyTree());
}
boost::property_tree::ptree MoneroBlockHeader::toPropertyTree() const {
//cout << "MoneroBlockHeader::toPropertyTree(block)" << endl;
boost::property_tree::ptree node;
if (id != boost::none) node.put("id", *id);
if (height != boost::none) node.put("height", *height);
if (timestamp != boost::none) node.put("timestamp", *timestamp);
if (size != boost::none) node.put("size", *size);
if (weight != boost::none) node.put("weight", *weight);
if (longTermWeight != boost::none) node.put("longTermWeight", *longTermWeight);
if (depth != boost::none) node.put("depth", *depth);
if (difficulty != boost::none) node.put("difficulty", *difficulty);
if (cumulativeDifficulty != boost::none) node.put("cumulativeDifficulty", *height);
if (majorVersion != boost::none) node.put("majorVersion", *majorVersion);
if (minorVersion != boost::none) node.put("minorVersion", *minorVersion);
if (nonce != boost::none) node.put("nonce", *nonce);
if (coinbaseTxId != boost::none) node.put("coinbaseTxId", *coinbaseTxId);
if (numTxs != boost::none) node.put("numTxs", *numTxs);
if (orphanStatus != boost::none) node.put("orphanStatus", *orphanStatus);
if (prevId != boost::none) node.put("prevId", *prevId);
if (reward != boost::none) node.put("reward", *reward);
if (powHash != boost::none) node.put("powHash", *powHash);
return node;
}
boost::property_tree::ptree MoneroBlock::toPropertyTree() const {
//cout << "MoneroBlock::toPropertyTree(block)" << endl;
boost::property_tree::ptree node = MoneroBlockHeader::toPropertyTree();
if (hex != boost::none) node.put("hex", *hex);
if (coinbaseTx != boost::none) node.add_child("coinbaseTx", (*coinbaseTx)->toPropertyTree());
node.add_child("txs", MoneroUtils::toPropertyTree(txs));
// TODO: handle txIds
return node;
}
boost::property_tree::ptree MoneroTx::toPropertyTree() const {
//cout << "MoneroTx::txToPropertyTree(tx)" << endl;
boost::property_tree::ptree node;
if (id != boost::none) node.put("id", *id);
if (version != boost::none) node.put("version", *version);
if (isCoinbase != boost::none) node.put("isCoinbase", *isCoinbase);
if (paymentId != boost::none) node.put("paymentId", *paymentId);
if (fee != boost::none) node.put("fee", *fee);
if (mixin != boost::none) node.put("mixin", *mixin);
if (doNotRelay != boost::none) node.put("doNotRelay", *doNotRelay);
if (isRelayed != boost::none) node.put("isRelayed", *isRelayed);
if (isConfirmed != boost::none) node.put("isConfirmed", *isConfirmed);
if (inTxPool != boost::none) node.put("inTxPool", *inTxPool);
if (numConfirmations != boost::none) node.put("numConfirmations", *numConfirmations);
if (unlockTime != boost::none) node.put("unlockTime", *unlockTime);
if (lastRelayedTimestamp != boost::none) node.put("lastRelayedTimestamp", *lastRelayedTimestamp);
if (receivedTimestamp != boost::none) node.put("receivedTimestamp", *receivedTimestamp);
if (isDoubleSpend != boost::none) node.put("isDoubleSpend", *isDoubleSpend);
if (key != boost::none) node.put("key", *key);
if (fullHex != boost::none) node.put("fullHex", *fullHex);
if (prunedHex != boost::none) node.put("prunedHex", *prunedHex);
if (prunableHex != boost::none) node.put("prunableHex", *prunableHex);
if (prunableHash != boost::none) node.put("prunableHash", *prunableHash);
if (size != boost::none) node.put("size", *size);
if (weight != boost::none) node.put("weight", *weight);
if (!vins.empty()) throw runtime_error("not implemented");
if (!vouts.empty()) throw runtime_error("not implemented");
if (!outputIndices.empty()) throw runtime_error("not implemented");
if (metadata != boost::none) node.put("metadata", *metadata);
if (commonTxSets != boost::none) throw runtime_error("not implemented");
if (!extra.empty()) throw runtime_error("not implemented");
if (rctSignatures != boost::none) throw runtime_error("not implemented");
if (rctSigPrunable != boost::none) throw runtime_error("not implemented");
if (isKeptByBlock != boost::none) node.put("isKeptByBlock", *isKeptByBlock);
if (isFailed != boost::none) node.put("isFailed", *isFailed);
if (lastFailedHeight != boost::none) node.put("lastFailedHeight", *lastFailedHeight);
if (lastFailedId != boost::none) node.put("lastFailedId", *lastFailedId);
if (maxUsedBlockHeight != boost::none) node.put("maxUsedBlockHeight", *maxUsedBlockHeight);
if (maxUsedBlockId != boost::none) node.put("maxUsedBlockId", *maxUsedBlockId);
if (!signatures.empty()) throw runtime_error("not implemented");
return node;
}
// -------------------------- MODEL IMPLEMENTATION --------------------------
void MoneroBlockHeader::merge(const shared_ptr<MoneroBlockHeader>& self, const shared_ptr<MoneroBlockHeader>& other) {
cout << "MoneroBlockHeader::merge()" << endl;
if (this != &*self) throw runtime_error("this != self");
if (self == other) return;
id = MoneroUtils::reconcile(id, other->id);
height = MoneroUtils::reconcile(height, other->height, boost::none, boost::none, true); // height can increase
timestamp = MoneroUtils::reconcile(timestamp, other->timestamp, boost::none, boost::none, true); // timestamp can increase
size = MoneroUtils::reconcile(size, other->size);
weight = MoneroUtils::reconcile(weight, other->weight);
longTermWeight = MoneroUtils::reconcile(longTermWeight, other->longTermWeight);
depth = MoneroUtils::reconcile(depth, other->depth);
difficulty = MoneroUtils::reconcile(difficulty, other->difficulty);
cumulativeDifficulty = MoneroUtils::reconcile(cumulativeDifficulty, other->cumulativeDifficulty);
majorVersion = MoneroUtils::reconcile(majorVersion, other->majorVersion);
minorVersion = MoneroUtils::reconcile(minorVersion, other->minorVersion);
nonce = MoneroUtils::reconcile(nonce, other->nonce);
coinbaseTxId = MoneroUtils::reconcile(coinbaseTxId, other->coinbaseTxId);
numTxs = MoneroUtils::reconcile(numTxs, other->numTxs);
orphanStatus = MoneroUtils::reconcile(orphanStatus, other->orphanStatus);
prevId = MoneroUtils::reconcile(prevId, other->prevId);
reward = MoneroUtils::reconcile(reward, other->reward);
powHash = MoneroUtils::reconcile(powHash, other->powHash);
}
void MoneroBlock::merge(const shared_ptr<MoneroBlockHeader>& self, const shared_ptr<MoneroBlockHeader>& other) {
cout << "MoneroBlock::merge()" << endl;
if (this != &*self) throw runtime_error("this != self");
if (self == other) return;
// merge header fields
MoneroBlockHeader::merge(self, other);
// convert other to MoneroBlock*
MoneroBlock* otherBlock = static_cast<MoneroBlock*>(&*other);
// merge coinbase tx
if (coinbaseTx == boost::none) coinbaseTx = otherBlock->coinbaseTx;
else if (otherBlock->coinbaseTx != boost::none) (**coinbaseTx).merge(*coinbaseTx, *otherBlock->coinbaseTx);
// merge non-coinbase txs
if (txs.empty()) txs = otherBlock->txs;
else if (!otherBlock->txs.empty()) {
for (const shared_ptr<MoneroTx>& thatTx : otherBlock->txs) {
bool found = false;
for (const shared_ptr<MoneroTx>& thisTx : txs) {
if (thatTx->id == thisTx->id) {
thisTx->merge(thisTx, thatTx);
found = true;
break;
}
}
if (!found) txs.push_back(thatTx);
}
}
if (!txs.empty()) {
for (const shared_ptr<MoneroTx>& tx : txs) {
tx->block = self;
}
}
// merge other fields
hex = MoneroUtils::reconcile(hex, otherBlock->hex);
//txIds = MoneroUtils::reconcile(txIds, otherBlock->txIds); // TODO: implement
cout << "Returning from block::merge()!" << endl;
}
void MoneroTx::merge(const shared_ptr<MoneroTx>& self, const shared_ptr<MoneroTx>& other) {
cout << "MoneroTx::merge()" << endl;
// if (this == &tx) return;
// id = MoneroUtils::reconcile(id, tx.id);
// version = MoneroUtils::reconcile(version, tx.version);
// paymentId = MoneroUtils::reconcile(paymentId, tx.paymentId);
// fee = MoneroUtils::reconcile(fee, tx.fee);
// mixin = MoneroUtils::reconcile(mixin, tx.mixin);
// isConfirmed = MoneroUtils::reconcile(isConfirmed, tx.isConfirmed);
// doNotRelay = MoneroUtils::reconcile(doNotRelay, tx.doNotRelay);
// isRelayed = MoneroUtils::reconcile(isRelayed, tx.isRelayed);
// isDoubleSpend = MoneroUtils::reconcile(isDoubleSpend, tx.isDoubleSpend);
// key = MoneroUtils::reconcile(key, tx.key);
// fullHex = MoneroUtils::reconcile(fullHex, tx.fullHex);
// prunedHex = MoneroUtils::reconcile(prunedHex, tx.prunedHex);
// prunableHex = MoneroUtils::reconcile(prunableHex, tx.prunableHex);
// prunableHash = MoneroUtils::reconcile(prunableHash, tx.prunableHash);
// size = MoneroUtils::reconcile(size, tx.size);
// weight = MoneroUtils::reconcile(weight, tx.weight);
// //outputIndices = MoneroUtils::reconcile(outputIndices, tx.outputIndices); // TODO
// metadata = MoneroUtils::reconcile(metadata, tx.metadata);
// commonTxSets = MoneroUtils::reconcile(commonTxSets, tx.commonTxSets);
// //extra = MoneroUtils::reconcile(extra, tx.extra); // TODO
// rctSignatures = MoneroUtils::reconcile(rctSignatures, tx.rctSignatures);
// rctSigPrunable = MoneroUtils::reconcile(rctSigPrunable, tx.rctSigPrunable);
// isKeptByBlock = MoneroUtils::reconcile(isKeptByBlock, tx.isKeptByBlock);
// isFailed = MoneroUtils::reconcile(isFailed, tx.isFailed);
// lastFailedHeight = MoneroUtils::reconcile(lastFailedHeight, tx.lastFailedHeight);
// lastFailedId = MoneroUtils::reconcile(lastFailedId, tx.lastFailedId);
// maxUsedBlockHeight = MoneroUtils::reconcile(maxUsedBlockHeight, tx.maxUsedBlockHeight);
// maxUsedBlockId = MoneroUtils::reconcile(maxUsedBlockId, tx.maxUsedBlockId);
// //signatures = MoneroUtils::reconcile(signatures, tx.signatures); // TODO
// unlockTime = MoneroUtils::reconcile(unlockTime, tx.unlockTime);
// numConfirmations = MoneroUtils::reconcile(numConfirmations, tx.numConfirmations);
//
// // merge vins
// if (!tx.vins.empty()) {
// for (const shared_ptr<MoneroOutput>& merger : tx.vins) {
// bool merged = false;
// merger->tx = shared_ptr<MoneroTx>(this); // TODO: can this cause this* to be deleted prematurely?
// for (const shared_ptr<MoneroOutput>& mergee : vins) {
// if ((*mergee->keyImage)->hex == (*merger->keyImage)->hex) {
// mergee->merge(*merger);
// merged = true;
// break;
// }
// }
// if (!merged) vins.push_back(merger);
// }
// }
//
// // merge vouts
// if (!tx.vouts.empty()) {
// for (const shared_ptr<MoneroOutput>& vout : tx.vouts) vout->tx = shared_ptr<MoneroTx>(this);
// if (vouts.empty()) vouts = tx.vouts;
// else {
//
// // determine if key images present
// int numKeyImages = 0;
// for (const shared_ptr<MoneroOutput> vout : vouts) {
// if (vout->keyImage != boost::none) {
// if ((*vout->keyImage)->hex == boost::none) throw runtime_error("Key image hex cannot be null");
// numKeyImages++;
// }
// }
// for (const shared_ptr<MoneroOutput>& vout : tx.vouts) {
// if (vout->keyImage != boost::none) {
// if ((*vout->keyImage)->hex == boost::none) throw runtime_error("Key image hex cannot be null");
// numKeyImages++;
// }
// }
// if (numKeyImages != 0 && vouts.size() + tx.vouts.size() != numKeyImages) throw runtime_error("Some vouts have a key image and some do not");
//
// // merge by key images
// if (numKeyImages > 0) {
// for (const shared_ptr<MoneroOutput>& merger : tx.vouts) {
// bool merged = false;
// for (const shared_ptr<MoneroOutput>& mergee : vouts) {
// if ((*mergee->keyImage)->hex == (*merger->keyImage)->hex) {
// mergee->merge(*merger);
// merged = true;
// break;
// }
// }
// if (!merged) vouts.push_back(merger);
// }
// }
//
// // merge by position
// else {
// if (vouts.size() != tx.vouts.size()) throw runtime_error("Vout sizes are different");
// for (int i = 0; i < tx.vouts.size(); i++) {
// vouts.at(i)->merge(*tx.vouts.at(i));
// }
// }
// }
// }
//
// // handle unrelayed -> relayed -> confirmed
// if (*isConfirmed) {
// inTxPool = false;
// receivedTimestamp = boost::none;
// lastRelayedTimestamp = boost::none;
// } else {
// inTxPool = MoneroUtils::reconcile(inTxPool, tx.inTxPool, boost::none, true, boost::none); // unrelayed -> tx pool
// receivedTimestamp = MoneroUtils::reconcile(receivedTimestamp, tx.receivedTimestamp, boost::none, boost::none, false); // take earliest receive time
// lastRelayedTimestamp = MoneroUtils::reconcile(lastRelayedTimestamp, tx.lastRelayedTimestamp, boost::none, boost::none, true); // take latest relay time
// }
}
void MoneroKeyImage::merge(const shared_ptr<MoneroKeyImage>& self, const shared_ptr<MoneroKeyImage>& other) {
cout << "MoneroKeyImage::merge()" << endl;
throw runtime_error("Not implemented");
}
void MoneroOutput::merge(const shared_ptr<MoneroOutput>& self, const shared_ptr<MoneroOutput>& other) {
cout << "MoneroOutput::merge()" << endl;
throw runtime_error("Not implemented");
}
// ---------------------------- PRIVATE HELPERS -----------------------------
}
+176
View File
@@ -0,0 +1,176 @@
#pragma once
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace std;
/**
* Public interface for libmonero-cpp library.
*/
namespace monero {
/**
* Base struct which can be serialized.
*
* TODO: move this to MoneroUtils?
*/
struct SerializableStruct {
/**
* Serializes the struct to a json string.
*
* @return the struct serialized to a json string
*/
string serialize() const;
/**
* Convert the struct to a property tree.
*
* @return the converted property tree
*/
virtual boost::property_tree::ptree toPropertyTree() const = 0;
};
/**
* Enumerates Monero network types.
*/
enum MoneroNetworkType : uint8_t {
MAINNET = 0,
TESTNET,
STAGENET
};
/**
* Models a connection to a daemon.
*
* TODO: switch to boost::optional<string>
*/
struct MoneroRpcConnection {
string uri;
string username;
string password;
//MoneroRpcConnection() : uri(""), username(""), password("")) {}
MoneroRpcConnection(const string& uri = "", const string& username = "", const string& password = "") : uri(uri), username(username), password(password) {}
};
// forward declarations
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;
void merge(const shared_ptr<MoneroBlockHeader>& self, const shared_ptr<MoneroBlockHeader>& other);
};
/**
* 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;
void merge(const shared_ptr<MoneroBlockHeader>& self, const shared_ptr<MoneroBlockHeader>& other);
};
/**
* Models a Monero transaction on the blockchain.
*/
struct MoneroTx : public SerializableStruct {
static const string DEFAULT_PAYMENT_ID; // default payment id "0000000000000000"
boost::optional<shared_ptr<MoneroBlock>> block;
boost::optional<string> id;
boost::optional<string> version;
boost::optional<bool> isCoinbase;
boost::optional<string> paymentId;
boost::optional<uint64_t> fee;
boost::optional<uint32_t> mixin;
boost::optional<bool> doNotRelay;
boost::optional<bool> isRelayed;
boost::optional<bool> isConfirmed;
boost::optional<bool> inTxPool;
boost::optional<uint64_t> numConfirmations;
boost::optional<uint64_t> unlockTime;
boost::optional<uint64_t> lastRelayedTimestamp;
boost::optional<uint64_t> receivedTimestamp;
boost::optional<bool> isDoubleSpend;
boost::optional<string> key;
boost::optional<string> fullHex;
boost::optional<string> prunedHex;
boost::optional<string> prunableHex;
boost::optional<string> prunableHash;
boost::optional<uint32_t> size;
boost::optional<uint32_t> weight;
vector<shared_ptr<MoneroOutput>> vins;
vector<shared_ptr<MoneroOutput>> vouts;
vector<uint32_t> outputIndices;
boost::optional<string> metadata;
boost::optional<string> commonTxSets;
vector<uint32_t> extra;
boost::optional<string> rctSignatures; // TODO: implement
boost::optional<string> rctSigPrunable; // TODO: implement
boost::optional<bool> isKeptByBlock;
boost::optional<bool> isFailed;
boost::optional<uint32_t> lastFailedHeight;
boost::optional<string> lastFailedId;
boost::optional<uint32_t> maxUsedBlockHeight;
boost::optional<string> maxUsedBlockId;
vector<string> signatures;
boost::property_tree::ptree toPropertyTree() const;
boost::optional<uint64_t> getHeight() const {
if (block == boost::none) return boost::none;
return *((*block)->height);
}
void merge(const shared_ptr<MoneroTx>& self, const shared_ptr<MoneroTx>& other);
};
/**
* Models a Monero key image.
*/
struct MoneroKeyImage {
boost::optional<string> hex;
boost::optional<string> signature;
void merge(const shared_ptr<MoneroKeyImage>& self, const shared_ptr<MoneroKeyImage>& other);
};
/**
* Models a Monero transaction output.
*/
struct MoneroOutput {
shared_ptr<MoneroTx> tx;
boost::optional<shared_ptr<MoneroKeyImage>> keyImage;
boost::optional<uint64_t> amount;
boost::optional<uint32_t> index;
vector<uint32_t> ringOutputIndices;
boost::optional<string> stealthPublicKey;
void merge(const shared_ptr<MoneroOutput>& self, const shared_ptr<MoneroOutput>& other);
};
}
+2 -104
View File
@@ -1,4 +1,4 @@
#include "wallet/MoneroWallet.h"
#include "MoneroWallet.h"
#include "utils/MoneroUtils.h"
#include <stdio.h>
@@ -11,112 +11,10 @@ using namespace cryptonote;
using namespace epee;
/**
* Public interface for libmonero-cpp library.
* Public library interface.
*/
namespace monero {
// -------------------------- MODEL SERIALIZATION ---------------------------
boost::property_tree::ptree MoneroAccount::toPropertyTree() const {
//cout << "MoneroAccount::toPropertyTree(node)" << endl;
boost::property_tree::ptree node;
if (index != boost::none) node.put("index", *index);
if (primaryAddress != boost::none) node.put("primaryAddress", *primaryAddress);
if (balance != boost::none) node.put("balance", *balance);
if (unlockedBalance != boost::none) node.put("unlockedBalance", *unlockedBalance);
if (!subaddresses.empty()) node.add_child("subaddresses", MoneroUtils::toPropertyTree(subaddresses));
// if (!subaddresses.empty()) {
// boost::property_tree::ptree subaddressesNode;
// for (const MoneroSubaddress& subaddress : subaddresses) {
// subaddressesNode.push_back(std::make_pair("", subaddress.toPropertyTree()));
// }
// node.add_child("subaddresses", subaddressesNode);
// }
return node;
}
boost::property_tree::ptree MoneroSubaddress::toPropertyTree() const {
//cout << "MoneroSubaddress::toPropertyTree(node)" << endl;
boost::property_tree::ptree node;
if (accountIndex != boost::none) node.put("accountIndex", *accountIndex);
if (index != boost::none) node.put("index", *index);
if (address != boost::none) node.put("address", *address);
if (label != boost::none) node.put("label", *label);
if (balance != boost::none) node.put("balance", *balance);
if (unlockedBalance != boost::none) node.put("unlockedBalance", *unlockedBalance);
if (numUnspentOutputs != boost::none) node.put("numUnspentOutputs", *numUnspentOutputs);
if (isUsed != boost::none) node.put("isUsed", *isUsed);
if (numBlocksToUnlock != boost::none) node.put("numBlocksToUnlock", *numBlocksToUnlock);
return node;
}
boost::property_tree::ptree MoneroTxWallet::toPropertyTree() const {
//cout << "MoneroTxWallet::toPropertyTree(node)" << endl;
boost::property_tree::ptree node = MoneroTx::toPropertyTree();
if (!vouts.empty()) throw runtime_error("vouts not implemented");
if (!incomingTransfers.empty()) node.add_child("incomingTransfers", MoneroUtils::toPropertyTree(incomingTransfers));
if (outgoingTransfer != boost::none) throw runtime_error("outgoingTransfers not implemented");
if (note != boost::none) node.put("note", *note);
return node;
}
boost::property_tree::ptree MoneroTxRequest::toPropertyTree() const {
//cout << "MoneroTxRequest::toPropertyTree(node)" << endl;
throw runtime_error("Not implemented");
}
boost::property_tree::ptree MoneroTransfer::toPropertyTree() const {
//cout << "MoneroTransfer::toPropertyTree(node)" << endl;
boost::property_tree::ptree node;
if (amount != boost::none) node.put("amount", *amount);
if (accountIndex != boost::none) node.put("accountIndex", *accountIndex);
if (numSuggestedConfirmations != boost::none) node.put("numSuggestedConfirmations", *numSuggestedConfirmations);
return node;
}
boost::property_tree::ptree MoneroIncomingTransfer::toPropertyTree() const {
//cout << "MoneroIncomingTransfer::toPropertyTree(node)" << endl;
boost::property_tree::ptree node = MoneroTransfer::toPropertyTree();
if (subaddressIndex != boost::none) node.put("subaddressIndex", *subaddressIndex);
if (address != boost::none) node.put("address", *address);
return node;
}
boost::property_tree::ptree MoneroOutgoingTransfer::toPropertyTree() const {
//cout << "MoneroOutgoingTransfer::toPropertyTree(node)" << endl;
boost::property_tree::ptree node = MoneroTransfer::toPropertyTree();
if (!subaddressIndices.empty()) throw runtime_error("subaddressIndices not implemented");
if (!addresses.empty()) throw runtime_error("addresses not implemented");
if (!destinations.empty()) throw runtime_error("destinations not implemented");
return node;
}
//boost::property_tree::ptree MoneroUtils::txWalletToPropertyTree(const MoneroTxWallet& tx) {
// cout << "txWalletToPropertyTree(tx)" << endl;
// boost::property_tree::ptree txNode = txToPropertyTree(tx);
// if (!tx.vouts.empty()) throw runtime_error("not implemented");
// if (!tx.incomingTransfers.empty()) throw runtime_error("not implemented");
// if (tx.outgoingTransfer != boost::none) throw runtime_error("not implemented");
// if (tx.numSuggestedConfirmations != boost::none) txNode.put("numSuggestedConfirmations", *tx.numSuggestedConfirmations);
// if (tx.note != boost::none) txNode.put("note", *tx.note);
// return txNode;
//}
//
//boost::property_tree::ptree MoneroUtils::txRequestToPropertyTree(const MoneroTxRequest& tx) {
// cout << "txWalletToPropertyTree(tx)" << endl;
// boost::property_tree::ptree txNode = txWalletToPropertyTree(tx);
// if (tx.isOutgoing != boost::none) txNode.put("isOutgoing", *tx.isOutgoing);
// if (tx.isIncoming != boost::none) txNode.put("isIncoming", *tx.isIncoming);
// if (!tx.txIds.empty()) throw runtime_error("not implemented");
// if (tx.hasPaymentId != boost::none) txNode.put("hasPaymentId", *tx.hasPaymentId);
// if (!tx.paymentIds.empty()) throw runtime_error("not implemented");
// if (tx.minHeight != boost::none) txNode.put("minHeight", *tx.minHeight);
// if (tx.maxHeight != boost::none) txNode.put("maxHeight", *tx.maxHeight);
// if (tx.includeOutputs != boost::none) txNode.put("includeOutputs", *tx.includeOutputs);
// if (tx.transferRequest != boost::none) throw runtime_error("not implemented");
// return txNode;
//}
// ----------------------- UNDECLARED PRIVATE HELPERS -----------------------
// TODO: static?
+5 -221
View File
@@ -1,6 +1,6 @@
#pragma once
#include "daemon/MoneroDaemon.h"
#include "MoneroWalletModel.h"
#include "wallet/wallet2.h"
using namespace std;
@@ -8,196 +8,10 @@ using namespace crypto;
using namespace monero;
/**
* Public interface for libmonero-cpp library.
* Public library interface.
*/
namespace monero {
struct Wallet2Listener;
// ----------------------------------- MODEL --------------------------------
/**
* Models a result of syncing a wallet.
*/
struct MoneroSyncResult {
uint64_t numBlocksFetched;
bool receivedMoney;
MoneroSyncResult() {}
MoneroSyncResult(const uint64_t numBlocksFetched, const bool receivedMoney) : numBlocksFetched(numBlocksFetched), receivedMoney(receivedMoney) {}
};
/**
* Models a Monero subaddress.
*/
struct MoneroSubaddress : public SerializableStruct {
boost::optional<uint32_t> accountIndex;
boost::optional<uint32_t> index;
boost::optional<string> address;
boost::optional<string> label;
boost::optional<uint64_t> balance;
boost::optional<uint64_t> unlockedBalance;
boost::optional<uint32_t> numUnspentOutputs;
boost::optional<bool> isUsed;
boost::optional<uint32_t> numBlocksToUnlock;
// BEGIN_KV_SERIALIZE_MAP()
// KV_SERIALIZE(accountIndex)
// KV_SERIALIZE(index)
// KV_SERIALIZE(address)
// KV_SERIALIZE(label)
// KV_SERIALIZE(balance)
// KV_SERIALIZE(unlockedBalance)
// KV_SERIALIZE(numUnspentOutputs)
// KV_SERIALIZE(isUsed)
// KV_SERIALIZE(numBlocksToUnlock)
// END_KV_SERIALIZE_MAP()
boost::property_tree::ptree toPropertyTree() const;
//void merge(const shared_ptr<MoneroSubaddress>& self, const shared_ptr<MoneroSubaddress>& other);
};
/**
* Models a Monero account.
*/
struct MoneroAccount : public SerializableStruct {
boost::optional<uint32_t> index;
boost::optional<string> primaryAddress;
boost::optional<string> label;
boost::optional<uint64_t> balance;
boost::optional<uint64_t> unlockedBalance;
boost::optional<string> tag;
vector<MoneroSubaddress> subaddresses;
// BEGIN_KV_SERIALIZE_MAP()
// KV_SERIALIZE(index)
// KV_SERIALIZE(primaryAddress)
// KV_SERIALIZE(label)
// KV_SERIALIZE(balance)
// KV_SERIALIZE(unlockedBalance)
// KV_SERIALIZE(tag)
// KV_SERIALIZE(subaddresses)
// END_KV_SERIALIZE_MAP()
boost::property_tree::ptree toPropertyTree() const;
};
// forward declarations
struct MoneroTxWallet;
struct MoneroTxRequest;
/**
* Models an outgoing transfer destination.
*/
struct MoneroDestination {
boost::optional<string> address;
boost::optional<uint64_t> amount;
};
/**
* Models a base transfer of funds to or from the wallet.
*/
struct MoneroTransfer : SerializableStruct {
shared_ptr<MoneroTxWallet> tx;
boost::optional<bool> isIncoming;
boost::optional<uint64_t> amount;
boost::optional<uint32_t> accountIndex;
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);
}
};
/**
* Models an incoming transfer of funds to the wallet.
*/
struct MoneroIncomingTransfer : public MoneroTransfer {
boost::optional<uint32_t> subaddressIndex;
boost::optional<string> address;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Models an outgoing transfer of funds from the wallet.
*/
struct MoneroOutgoingTransfer : public MoneroTransfer {
vector<uint32_t> subaddressIndices;
vector<string> addresses;
vector<shared_ptr<MoneroDestination>> destinations;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Models a Monero output with wallet extensions.
*/
struct MoneroOutputWallet : public MoneroOutput {
boost::optional<uint32_t> accountIndex;
boost::optional<uint32_t> subaddressIndex;
boost::optional<bool> isSpent;
boost::optional<bool> isUnlocked;
boost::optional<bool> isFrozen;
};
/**
* Models a Monero transaction in the context of a wallet.
*/
struct MoneroTxWallet : public MoneroTx {
vector<shared_ptr<MoneroIncomingTransfer>> incomingTransfers;
boost::optional<shared_ptr<MoneroOutgoingTransfer>> outgoingTransfer;
boost::optional<string> note;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Configures a request to retrieve transfers.
*
* All transfers are returned except those that do not meet the criteria defined in this request.
*/
struct MoneroTransferRequest : public MoneroTransfer {
boost::optional<bool> isIncoming;
boost::optional<string> address;
vector<string> addresses;
boost::optional<uint32_t> subaddressIndex;
vector<uint32_t> subaddressIndices;
vector<shared_ptr<MoneroDestination>> destinations;
boost::optional<bool> hasDestinations;
boost::optional<shared_ptr<MoneroTxRequest>> txRequest;
};
/**
* Configures a request to retrieve transactions.
*
* All transactions are returned except those that do not meet the criteria defined in this request.
*/
struct MoneroTxRequest : public MoneroTxWallet {
boost::optional<bool> isOutgoing;
boost::optional<bool> isIncoming;
vector<string> txIds;
boost::optional<bool> hasPaymentId;
vector<string> paymentIds;
boost::optional<uint64_t> minHeight;
boost::optional<uint64_t> maxHeight;
boost::optional<uint64_t> includeOutputs;
boost::optional<shared_ptr<MoneroTransferRequest>> transferRequest;
boost::optional<uint64_t> getHeight() { return block == boost::none ? boost::none : (*block)->height; }
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Configures a request to retrieve wallet outputs (i.e. outputs that the wallet has or had the
* ability to spend).
*
* All outputs are returned except those that do not meet the criteria defined in this request.
*/
struct MoneroOutputRequest : public MoneroOutput {
vector<uint32_t> subaddressIndices;
boost::optional<shared_ptr<MoneroTxRequest>> txRequest;
};
// --------------------------------- LISTENERS ------------------------------
// class i_wallet2_callback
@@ -260,6 +74,9 @@ namespace monero {
virtual void onNewBlock(MoneroBlock& block) {};
};
// forward declaration of internal wallet2 listener
struct Wallet2Listener;
// ---------------------------- WALLET INTERFACE ----------------------------
/**
@@ -1271,36 +1088,3 @@ namespace monero {
shared_ptr<MoneroTx> buildTxWithIncomingTransfer(const crypto::hash &txid, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd) const;
};
}
//// --------------------------- MODEL SERIALIZATION ----------------------------
//
//BOOST_CLASS_VERSION(monero::MoneroWallet, 0)
//BOOST_CLASS_VERSION(monero::MoneroAccount, 0)
//BOOST_CLASS_VERSION(monero::MoneroSubaddress, 0)
//
//namespace boost {
// namespace serialization {
// template <class Archive>
// inline void serialize(Archive &a, monero::MoneroWallet& x, const boost::serialization::version_type ver)
// {
//// a & x.m_L;
//// a & x.m_R;
// }
//
// template <class Archive>
// inline void serialize(Archive &a, monero::MoneroAccount& x, const boost::serialization::version_type ver)
// {
//// a & x.m_signer;
//// a & x.m_LR;
//// a & x.m_partial_key_images;
// }
//
// template <class Archive>
// inline void serialize(Archive &a, monero::MoneroSubaddress& x, const boost::serialization::version_type ver)
// {
//// a & x.m_signer;
//// a & x.m_LR;
//// a & x.m_partial_key_images;
// }
// } // namepsace serialization
//} // namespace boost
+120
View File
@@ -0,0 +1,120 @@
#include "MoneroWallet.h"
#include "utils/MoneroUtils.h"
#include <stdio.h>
#include <iostream>
using namespace std;
using namespace cryptonote; // TODO: delete?
using namespace epee; // TODO: delete?
/**
* Public library interface.
*/
namespace monero {
// -------------------------- MODEL SERIALIZATION ---------------------------
boost::property_tree::ptree MoneroAccount::toPropertyTree() const {
//cout << "MoneroAccount::toPropertyTree(node)" << endl;
boost::property_tree::ptree node;
if (index != boost::none) node.put("index", *index);
if (primaryAddress != boost::none) node.put("primaryAddress", *primaryAddress);
if (balance != boost::none) node.put("balance", *balance);
if (unlockedBalance != boost::none) node.put("unlockedBalance", *unlockedBalance);
if (!subaddresses.empty()) node.add_child("subaddresses", MoneroUtils::toPropertyTree(subaddresses));
// if (!subaddresses.empty()) {
// boost::property_tree::ptree subaddressesNode;
// for (const MoneroSubaddress& subaddress : subaddresses) {
// subaddressesNode.push_back(std::make_pair("", subaddress.toPropertyTree()));
// }
// node.add_child("subaddresses", subaddressesNode);
// }
return node;
}
boost::property_tree::ptree MoneroSubaddress::toPropertyTree() const {
//cout << "MoneroSubaddress::toPropertyTree(node)" << endl;
boost::property_tree::ptree node;
if (accountIndex != boost::none) node.put("accountIndex", *accountIndex);
if (index != boost::none) node.put("index", *index);
if (address != boost::none) node.put("address", *address);
if (label != boost::none) node.put("label", *label);
if (balance != boost::none) node.put("balance", *balance);
if (unlockedBalance != boost::none) node.put("unlockedBalance", *unlockedBalance);
if (numUnspentOutputs != boost::none) node.put("numUnspentOutputs", *numUnspentOutputs);
if (isUsed != boost::none) node.put("isUsed", *isUsed);
if (numBlocksToUnlock != boost::none) node.put("numBlocksToUnlock", *numBlocksToUnlock);
return node;
}
boost::property_tree::ptree MoneroTxWallet::toPropertyTree() const {
//cout << "MoneroTxWallet::toPropertyTree(node)" << endl;
boost::property_tree::ptree node = MoneroTx::toPropertyTree();
if (!vouts.empty()) throw runtime_error("vouts not implemented");
if (!incomingTransfers.empty()) node.add_child("incomingTransfers", MoneroUtils::toPropertyTree(incomingTransfers));
if (outgoingTransfer != boost::none) throw runtime_error("outgoingTransfers not implemented");
if (note != boost::none) node.put("note", *note);
return node;
}
boost::property_tree::ptree MoneroTxRequest::toPropertyTree() const {
//cout << "MoneroTxRequest::toPropertyTree(node)" << endl;
throw runtime_error("Not implemented");
}
boost::property_tree::ptree MoneroTransfer::toPropertyTree() const {
//cout << "MoneroTransfer::toPropertyTree(node)" << endl;
boost::property_tree::ptree node;
if (amount != boost::none) node.put("amount", *amount);
if (accountIndex != boost::none) node.put("accountIndex", *accountIndex);
if (numSuggestedConfirmations != boost::none) node.put("numSuggestedConfirmations", *numSuggestedConfirmations);
return node;
}
boost::property_tree::ptree MoneroIncomingTransfer::toPropertyTree() const {
//cout << "MoneroIncomingTransfer::toPropertyTree(node)" << endl;
boost::property_tree::ptree node = MoneroTransfer::toPropertyTree();
if (subaddressIndex != boost::none) node.put("subaddressIndex", *subaddressIndex);
if (address != boost::none) node.put("address", *address);
return node;
}
boost::property_tree::ptree MoneroOutgoingTransfer::toPropertyTree() const {
//cout << "MoneroOutgoingTransfer::toPropertyTree(node)" << endl;
boost::property_tree::ptree node = MoneroTransfer::toPropertyTree();
if (!subaddressIndices.empty()) throw runtime_error("subaddressIndices not implemented");
if (!addresses.empty()) throw runtime_error("addresses not implemented");
if (!destinations.empty()) throw runtime_error("destinations not implemented");
return node;
}
//boost::property_tree::ptree MoneroUtils::txWalletToPropertyTree(const MoneroTxWallet& tx) {
// cout << "txWalletToPropertyTree(tx)" << endl;
// boost::property_tree::ptree txNode = txToPropertyTree(tx);
// if (!tx.vouts.empty()) throw runtime_error("not implemented");
// if (!tx.incomingTransfers.empty()) throw runtime_error("not implemented");
// if (tx.outgoingTransfer != boost::none) throw runtime_error("not implemented");
// if (tx.numSuggestedConfirmations != boost::none) txNode.put("numSuggestedConfirmations", *tx.numSuggestedConfirmations);
// if (tx.note != boost::none) txNode.put("note", *tx.note);
// return txNode;
//}
//
//boost::property_tree::ptree MoneroUtils::txRequestToPropertyTree(const MoneroTxRequest& tx) {
// cout << "txWalletToPropertyTree(tx)" << endl;
// boost::property_tree::ptree txNode = txWalletToPropertyTree(tx);
// if (tx.isOutgoing != boost::none) txNode.put("isOutgoing", *tx.isOutgoing);
// if (tx.isIncoming != boost::none) txNode.put("isIncoming", *tx.isIncoming);
// if (!tx.txIds.empty()) throw runtime_error("not implemented");
// if (tx.hasPaymentId != boost::none) txNode.put("hasPaymentId", *tx.hasPaymentId);
// if (!tx.paymentIds.empty()) throw runtime_error("not implemented");
// if (tx.minHeight != boost::none) txNode.put("minHeight", *tx.minHeight);
// if (tx.maxHeight != boost::none) txNode.put("maxHeight", *tx.maxHeight);
// if (tx.includeOutputs != boost::none) txNode.put("includeOutputs", *tx.includeOutputs);
// if (tx.transferRequest != boost::none) throw runtime_error("not implemented");
// return txNode;
//}
// ----------------------- UNDECLARED PRIVATE HELPERS -----------------------
}
+194
View File
@@ -0,0 +1,194 @@
#pragma once
#include "daemon/MoneroDaemonModel.h"
using namespace std;
using namespace monero;
/**
* Public library interface.
*/
namespace monero {
/**
* Models a result of syncing a wallet.
*/
struct MoneroSyncResult {
uint64_t numBlocksFetched;
bool receivedMoney;
MoneroSyncResult() {}
MoneroSyncResult(const uint64_t numBlocksFetched, const bool receivedMoney) : numBlocksFetched(numBlocksFetched), receivedMoney(receivedMoney) {}
};
/**
* Models a Monero subaddress.
*/
struct MoneroSubaddress : public SerializableStruct {
boost::optional<uint32_t> accountIndex;
boost::optional<uint32_t> index;
boost::optional<string> address;
boost::optional<string> label;
boost::optional<uint64_t> balance;
boost::optional<uint64_t> unlockedBalance;
boost::optional<uint32_t> numUnspentOutputs;
boost::optional<bool> isUsed;
boost::optional<uint32_t> numBlocksToUnlock;
// BEGIN_KV_SERIALIZE_MAP()
// KV_SERIALIZE(accountIndex)
// KV_SERIALIZE(index)
// KV_SERIALIZE(address)
// KV_SERIALIZE(label)
// KV_SERIALIZE(balance)
// KV_SERIALIZE(unlockedBalance)
// KV_SERIALIZE(numUnspentOutputs)
// KV_SERIALIZE(isUsed)
// KV_SERIALIZE(numBlocksToUnlock)
// END_KV_SERIALIZE_MAP()
boost::property_tree::ptree toPropertyTree() const;
//void merge(const shared_ptr<MoneroSubaddress>& self, const shared_ptr<MoneroSubaddress>& other);
};
/**
* Models a Monero account.
*/
struct MoneroAccount : public SerializableStruct {
boost::optional<uint32_t> index;
boost::optional<string> primaryAddress;
boost::optional<string> label;
boost::optional<uint64_t> balance;
boost::optional<uint64_t> unlockedBalance;
boost::optional<string> tag;
vector<MoneroSubaddress> subaddresses;
// BEGIN_KV_SERIALIZE_MAP()
// KV_SERIALIZE(index)
// KV_SERIALIZE(primaryAddress)
// KV_SERIALIZE(label)
// KV_SERIALIZE(balance)
// KV_SERIALIZE(unlockedBalance)
// KV_SERIALIZE(tag)
// KV_SERIALIZE(subaddresses)
// END_KV_SERIALIZE_MAP()
boost::property_tree::ptree toPropertyTree() const;
};
// forward declarations
struct MoneroTxWallet;
struct MoneroTxRequest;
/**
* Models an outgoing transfer destination.
*/
struct MoneroDestination {
boost::optional<string> address;
boost::optional<uint64_t> amount;
};
/**
* Models a base transfer of funds to or from the wallet.
*/
struct MoneroTransfer : SerializableStruct {
shared_ptr<MoneroTx> tx; // TODO *** switch to MoneroTxWallet ***
boost::optional<bool> isIncoming;
boost::optional<uint64_t> amount;
boost::optional<uint32_t> accountIndex;
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);
}
};
/**
* Models an incoming transfer of funds to the wallet.
*/
struct MoneroIncomingTransfer : public MoneroTransfer {
boost::optional<uint32_t> subaddressIndex;
boost::optional<string> address;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Models an outgoing transfer of funds from the wallet.
*/
struct MoneroOutgoingTransfer : public MoneroTransfer {
vector<uint32_t> subaddressIndices;
vector<string> addresses;
vector<shared_ptr<MoneroDestination>> destinations;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Models a Monero output with wallet extensions.
*/
struct MoneroOutputWallet : public MoneroOutput {
boost::optional<uint32_t> accountIndex;
boost::optional<uint32_t> subaddressIndex;
boost::optional<bool> isSpent;
boost::optional<bool> isUnlocked;
boost::optional<bool> isFrozen;
};
/**
* Models a Monero transaction in the context of a wallet.
*/
struct MoneroTxWallet : public MoneroTx {
vector<shared_ptr<MoneroIncomingTransfer>> incomingTransfers;
boost::optional<shared_ptr<MoneroOutgoingTransfer>> outgoingTransfer;
boost::optional<string> note;
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Configures a request to retrieve transfers.
*
* All transfers are returned except those that do not meet the criteria defined in this request.
*/
struct MoneroTransferRequest : public MoneroTransfer {
boost::optional<bool> isIncoming;
boost::optional<string> address;
vector<string> addresses;
boost::optional<uint32_t> subaddressIndex;
vector<uint32_t> subaddressIndices;
vector<shared_ptr<MoneroDestination>> destinations;
boost::optional<bool> hasDestinations;
boost::optional<shared_ptr<MoneroTxRequest>> txRequest;
};
/**
* Configures a request to retrieve transactions.
*
* All transactions are returned except those that do not meet the criteria defined in this request.
*/
struct MoneroTxRequest : public MoneroTxWallet {
boost::optional<bool> isOutgoing;
boost::optional<bool> isIncoming;
vector<string> txIds;
boost::optional<bool> hasPaymentId;
vector<string> paymentIds;
boost::optional<uint64_t> minHeight;
boost::optional<uint64_t> maxHeight;
boost::optional<uint64_t> includeOutputs;
boost::optional<shared_ptr<MoneroTransferRequest>> transferRequest;
boost::optional<uint64_t> getHeight() { return block == boost::none ? boost::none : (*block)->height; }
boost::property_tree::ptree toPropertyTree() const;
};
/**
* Configures a request to retrieve wallet outputs (i.e. outputs that the wallet has or had the
* ability to spend).
*
* All outputs are returned except those that do not meet the criteria defined in this request.
*/
struct MoneroOutputRequest : public MoneroOutput {
vector<uint32_t> subaddressIndices;
boost::optional<shared_ptr<MoneroTxRequest>> txRequest;
};
}