git / moonbite-core / src/mweb/mweb_miner.cpp · raw
#include <mweb/mweb_miner.h>#include <script/standard.h>#include <consensus/consensus.h>#include <consensus/tx_verify.h>#include <policy/policy.h>#include <validation.h>#include <logging.h>#include <key_io.h>#include <miner.h>using namespace MWEB;void Miner::NewBlock(const uint64_t nHeight){ mweb_builder = std::make_shared<mw::BlockBuilder>(nHeight, ::ChainstateActive().CoinsTip().GetMWEBView()); hogex_fees = 0; hogex_sigops = 0; mweb_amount_change = 0; hogex_inputs.clear(); hogex_outputs.clear();}int64_t Miner::GetHogExSigOpCost(const CTransaction& tx){ int64_t sigops = 0; for (const PegOutCoin& pegout : tx.mweb_tx.GetPegOuts()) { sigops += WITNESS_SCALE_FACTOR * pegout.GetScriptPubKey().GetSigOpCount(false); } return sigops;}bool Miner::AddMWEBTransaction(CTxMemPool::txiter iter){ CTransactionRef pTx = iter->GetSharedTx(); // // Pegin // std::vector<CTxIn> vin; CAmount pegin_amount = 0; std::vector<PegInCoin> pegins = pTx->mweb_tx.GetPegIns(); if (!ValidatePegIns(pTx, pegins)) { LogPrintf("Peg-in Mismatch\n"); return false; } for (size_t nOut = 0; nOut < pTx->vout.size(); nOut++) { if (IsPegInOutput(pTx->GetOutput(nOut))) { vin.push_back(CTxIn{pTx->GetHash(), (uint32_t)nOut}); assert(MoneyRange(pTx->vout[nOut].nValue)); pegin_amount += pTx->vout[nOut].nValue; if (!MoneyRange(pegin_amount)) { LogPrintf("Invalid total peg-in amount\n"); return false; } } } // // Pegout // std::vector<CTxOut> vout; CAmount pegout_amount = 0; std::vector<PegOutCoin> pegouts = pTx->mweb_tx.GetPegOuts(); for (const PegOutCoin& pegout : pegouts) { CAmount amount(pegout.GetAmount()); assert(MoneyRange(amount)); vout.push_back(CTxOut{amount, pegout.GetScriptPubKey()}); pegout_amount += amount; if (!MoneyRange(pegout_amount)) { LogPrintf("Invalid total peg-out amount\n"); return false; } } // Validate fee amount range const auto tx_fee = pTx->mweb_tx.GetFee(); if (!tx_fee || !MoneyRange(*tx_fee)) { LogPrintf("Invalid MWEB fee amount\n"); return false; } // // Add transaction to MWEB // if (!mweb_builder->AddTransaction(pTx->mweb_tx.m_transaction, pegins)) { LogPrintf("Failed to add MWEB transaction\n"); return false; } hogex_inputs.insert(hogex_inputs.end(), vin.cbegin(), vin.cend()); hogex_outputs.insert(hogex_outputs.end(), vout.cbegin(), vout.cend()); mweb_amount_change += (CAmount(pegin_amount) - CAmount(pegout_amount + *tx_fee)); hogex_fees += *tx_fee; hogex_sigops += GetHogExSigOpCost(*pTx); return true;}namespace std {template <>struct hash<PegInCoin> { size_t operator()(const PegInCoin& pegin) const { return boost::hash_value(pegin.GetKernelID().vec()) + boost::hash_value(pegin.GetAmount()); }};} // namespace stdbool Miner::ValidatePegIns(const CTransactionRef& pTx, const std::vector<PegInCoin>& pegins) const{ std::unordered_set<PegInCoin> pegin_set(pegins.cbegin(), pegins.cend()); for (const CTxOut& output : pTx->vout) { mw::Hash kernel_id; if (output.scriptPubKey.IsMWEBPegin(&kernel_id)) { PegInCoin pegin(output.nValue, std::move(kernel_id)); if (pegin_set.erase(pegin) != 1) { return false; } } } if (!pegin_set.empty()) { return false; } return true;}void Miner::AddHogExTransaction(const CBlockIndex* pIndexPrev, CBlock* pblock, CBlockTemplate* pblocktemplate, CAmount& nFees){ CMutableTransaction hogExTransaction; hogExTransaction.m_hogEx = true; CAmount previous_amount = 0; // // Add previous HogAddr as new HogEx input // if (pIndexPrev->mweb_header != nullptr) { previous_amount = pIndexPrev->mweb_amount; CTxIn prevHogExIn(pIndexPrev->hogex_hash, 0); hogExTransaction.vin.push_back(std::move(prevHogExIn)); } // // Add Peg-in inputs // hogExTransaction.vin.insert(hogExTransaction.vin.end(), hogex_inputs.cbegin(), hogex_inputs.cend()); // // Add New HogAddr // mw::Block::Ptr mweb_block = mweb_builder->BuildBlock(); CTxOut hogAddr; hogAddr.scriptPubKey = CScript() << OP_8 << mweb_block->GetHash().vec(); hogAddr.nValue = previous_amount + mweb_amount_change; assert(MoneyRange(hogAddr.nValue)); hogExTransaction.vout.push_back(std::move(hogAddr)); // // Add Peg-out outputs // hogExTransaction.vout.insert(hogExTransaction.vout.end(), hogex_outputs.cbegin(), hogex_outputs.cend()); // // Update block & template // pblock->vtx.emplace_back(MakeTransactionRef(std::move(hogExTransaction))); pblock->mweb_block = MWEB::Block(mweb_block); pblocktemplate->vTxFees.push_back(hogex_fees); pblocktemplate->vTxSigOpsCost.push_back(hogex_sigops);}