merge(self, other) with base shared_ptrs to suppoert merge inheritance

This commit is contained in:
woodser
2019-06-16 09:48:44 -04:00
parent 9b181df21c
commit d646894707
4 changed files with 193 additions and 187 deletions
+164 -164
View File
@@ -98,183 +98,183 @@ namespace monero {
// -------------------------- MODEL IMPLEMENTATION --------------------------
void MoneroBlockHeader::merge(const MoneroBlockHeader& header) {
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);
// 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 MoneroBlock& block) {
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;
// 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 MoneroTx& tx) {
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
}
// 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 MoneroKeyImage& keyImage) {
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 MoneroOutput& output) {
void MoneroOutput::merge(const shared_ptr<MoneroOutput>& self, const shared_ptr<MoneroOutput>& other) {
cout << "MoneroOutput::merge()" << endl;
throw runtime_error("Not implemented");
}
+5 -5
View File
@@ -82,7 +82,7 @@ namespace monero {
boost::optional<string> powHash;
boost::property_tree::ptree toPropertyTree() const;
void merge(const MoneroBlockHeader& header);
void merge(const shared_ptr<MoneroBlockHeader>& header);
};
/**
@@ -95,7 +95,7 @@ namespace monero {
vector<string> txIds;
boost::property_tree::ptree toPropertyTree() const;
void merge(const MoneroBlock& block);
void merge(const shared_ptr<MoneroBlockHeader>& block);
};
/**
@@ -147,7 +147,7 @@ namespace monero {
if (block == boost::none) return boost::none;
return *((*block)->height);
}
void merge(const MoneroTx& tx);
void merge(const shared_ptr<MoneroTx>& self, const shared_ptr<MoneroTx>& other);
};
/**
@@ -157,7 +157,7 @@ namespace monero {
boost::optional<string> hex;
boost::optional<string> signature;
void merge(const MoneroKeyImage& keyImage);
void merge(const shared_ptr<MoneroKeyImage>& self, const shared_ptr<MoneroKeyImage>& other);
};
/**
@@ -171,7 +171,7 @@ namespace monero {
vector<uint32_t> ringOutputIndices;
boost::optional<string> stealthPublicKey;
void merge(const MoneroOutput& output);
void merge(const shared_ptr<MoneroOutput>& self, const shared_ptr<MoneroOutput>& other);
};
}