mirror of
https://github.com/wownero/wownero-cpp.git
synced 2026-10-22 09:38:49 +02:00
separate models from daemon and wallet classes
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 -----------------------------
|
||||
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 -----------------------
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user