diff --git a/src/block_template.cpp b/src/block_template.cpp index ffcdb53..d650012 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -871,11 +871,11 @@ void BlockTemplate::select_mempool_transactions(const Mempool& mempool) size_t k = b->serialize_mainchain_data().size() + b->serialize_sidechain_data().size() - 2; // Add output and tx count real varints - writeVarint(m_shares.size(), [&k](uint8_t) { ++k; }); + writeVarint(m_shares.size() + 1, [&k](uint8_t) { ++k; }); writeVarint(m_mempoolTxs.size(), [&k](uint8_t) { ++k; }); // Add a rough upper bound estimation of outputs' size. All outputs have <= 5 bytes for each output's reward (< 0.034359738368 XMR per output) - k += m_shares.size() * (5 /* reward */ + 1 /* tx_type */ + HASH_SIZE /* stealth address */ + 1 /* viewtag */); + k += (m_shares.size() + 1) * (5 /* reward */ + 1 /* tx_type */ + HASH_SIZE /* stealth address */ + 1 /* viewtag */); // +1 for dev fee // >= 0.034359738368 XMR is required for a 6 byte varint, add 1 byte per each potential 6-byte varint { @@ -998,7 +998,7 @@ int BlockTemplate::create_miner_tx(const MinerData& data, const std::vector EXTRA_NONCE_SIZE) { if (corrected_extra_nonce_size > EXTRA_NONCE_MAX_SIZE) { LOGWARN(5, "create_miner_tx: corrected_extra_nonce_size (" << corrected_extra_nonce_size << ") is too large"); diff --git a/src/pool_block.cpp b/src/pool_block.cpp index 9789922..2ecc03c 100644 --- a/src/pool_block.cpp +++ b/src/pool_block.cpp @@ -172,6 +172,8 @@ std::vector PoolBlock::serialize_mainchain_data(size_t* header_size, si writeVarint(m_outputAmounts.size(), data); + LOGINFO(3, "serialize_mainchain_data: writing " << m_outputAmounts.size() << " outputs, offset=" << outputs_offset0); + for (size_t i = 0, n = m_outputAmounts.size(); i < n; ++i) { const TxOutput& output = m_outputAmounts[i]; diff --git a/src/pool_block_parser.inl b/src/pool_block_parser.inl index 2c2c4e5..ecbb821 100644 --- a/src/pool_block_parser.inl +++ b/src/pool_block_parser.inl @@ -184,6 +184,8 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si EXPECT_BYTE(TX_EXTRA_NONCE); READ_VARINT(m_extraNonceSize); + LOGINFO(3, "Extra nonce size: " << m_extraNonceSize << " (valid range: " << EXTRA_NONCE_SIZE << " to " << EXTRA_NONCE_MAX_SIZE << ")"); + // Sanity check if ((m_extraNonceSize < EXTRA_NONCE_SIZE) || (m_extraNonceSize > EXTRA_NONCE_MAX_SIZE)) return __LINE__; @@ -495,8 +497,11 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si if (m_sidechainId.empty()) { m_sidechainId = check; + LOGINFO(3, "Calculated sidechain ID: " << check); } else if (m_sidechainId != check) { + LOGINFO(3, "Sidechain ID mismatch! Expected: " << m_sidechainId << " Got: " << check); + LOGINFO(3, " outputs_blob_size: " << outputs_blob_size << " actual: " << outputs_actual_blob_size << " diff: " << outputs_blob_size_diff); return __LINE__; } diff --git a/src/side_chain.cpp b/src/side_chain.cpp index 759c1ef..3a0142a 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -894,40 +894,50 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v }); } - blob.reserve(n * 39 + 64); - - writeVarint(n, blob); - - block->m_ephPublicKeys.clear(); - block->m_outputAmounts.clear(); - - block->m_ephPublicKeys.reserve(n); - block->m_outputAmounts.reserve(n); - - hash eph_public_key; - for (size_t i = 0; i < n; ++i) { - // stop helper jobs when they meet with current thread - const int c = data->counter.load(); - if ((c >= 0) && (static_cast(i) >= c)) { - // this will cause all helper jobs to finish immediately - data->counter = -1; - } - - writeVarint(tmpRewards[i], blob); - - blob.emplace_back(TXOUT_TO_TAGGED_KEY); - - uint8_t view_tag; - if (!data->tmpShares[i].m_wallet->get_eph_public_key(data->txkeySec, i, eph_public_key, view_tag)) { - LOGWARN(6, "get_eph_public_key failed at index " << i); - } - blob.insert(blob.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE); - - blob.emplace_back(view_tag); - - block->m_ephPublicKeys.emplace_back(eph_public_key); - block->m_outputAmounts.emplace_back(tmpRewards[i], view_tag); - } + blob.reserve(n * 39 + 64); + writeVarint(n + 1, blob); // +1 for dev fee + + // Add dev fee output first + const uint64_t total_miner_reward = std::accumulate(tmpRewards.begin(), tmpRewards.end(), 0ULL); + const uint64_t dev_fee = static_cast(total_miner_reward * (Params::DEV_FEE_PERCENTAGE / 100.0)); + + writeVarint(dev_fee, blob); + blob.emplace_back(TXOUT_TO_TAGGED_KEY); + + hash dev_eph_public_key; + uint8_t dev_view_tag; + if (!Params::s_devFeeWallet->get_eph_public_key(data->txkeySec, 0, dev_eph_public_key, dev_view_tag)) { + LOGWARN(6, "get_eph_public_key failed for dev fee"); + } + blob.insert(blob.end(), dev_eph_public_key.h, dev_eph_public_key.h + HASH_SIZE); + blob.emplace_back(dev_view_tag); + + block->m_ephPublicKeys.clear(); + block->m_outputAmounts.clear(); + block->m_ephPublicKeys.reserve(n + 1); // +1 for dev fee + block->m_outputAmounts.reserve(n + 1); // +1 for dev fee + block->m_ephPublicKeys.emplace_back(dev_eph_public_key); + block->m_outputAmounts.emplace_back(dev_fee, dev_view_tag); + + hash eph_public_key; + for (size_t i = 0; i < n; ++i) { + // stop helper jobs when they meet with current thread + const int c = data->counter.load(); + if ((c >= 0) && (static_cast(i) >= c)) { + // this will cause all helper jobs to finish immediately + data->counter = -1; + } + writeVarint(tmpRewards[i], blob); + blob.emplace_back(TXOUT_TO_TAGGED_KEY); + uint8_t view_tag; + if (!data->tmpShares[i].m_wallet->get_eph_public_key(data->txkeySec, i + 1, eph_public_key, view_tag)) { + LOGWARN(6, "get_eph_public_key failed at index " << i); + } + blob.insert(blob.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE); + blob.emplace_back(view_tag); + block->m_ephPublicKeys.emplace_back(eph_public_key); + block->m_outputAmounts.emplace_back(tmpRewards[i], view_tag); + } block->m_ephPublicKeys.shrink_to_fit(); block->m_outputAmounts.shrink_to_fit();