Skip to content

Commit 319188a

Browse files
giaki3003claude
andcommitted
fix: get_block_template can assemble over-weight blocks (M6 suffix not weight-budgeted)
Bug: s3-r10 (primary) Finding: Severity: Medium Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 49a73a5 commit 319188a

2 files changed

Lines changed: 36 additions & 20 deletions

File tree

lib/cusf_block_producer.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ pub trait CusfBlockProducer: CusfEnforcer {
8080

8181
type SuffixTxsError: std::error::Error + Send + Sync + 'static;
8282

83-
/// Add outputs / txs to a block template, after filling with proposed txs
83+
/// Suffix outputs / txs, appended after the proposed txs in the assembled
84+
/// block. Generated before the proposed txs are selected so that the
85+
/// suffix weight can be reserved in the block weight budget; `template`
86+
/// therefore only contains the prefix txs, not the proposed mempool txs.
8487
fn block_template_suffix<const COINBASE_TXN: bool>(
8588
&self,
8689
parent_block_hash: &BlockHash,

lib/server.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -472,9 +472,38 @@ async fn block_txs<const COINBASE_TXN: bool, BP>(
472472
.sum();
473473
let initial_block_template_weight =
474474
coinbase_txouts_weight + prefix_txs_weight;
475-
let mempool_txs = mempool.propose_txs(Some(
476-
mempool::MAX_USABLE_BLOCK_WEIGHT - initial_block_template_weight,
477-
))?;
475+
// The block template suffix (e.g. M6 withdrawal txns) is appended after the
476+
// proposed mempool txs, so its weight must be reserved before selecting
477+
// mempool txs. Otherwise the proposed txs can consume the entire remaining
478+
// weight budget and the appended suffix pushes the block over the limit.
479+
tracing::debug!("Adding block template suffix");
480+
let template_suffix = block_producer
481+
.block_template_suffix(
482+
parent_block_hash,
483+
typewit::MakeTypeWitness::MAKE,
484+
&initial_block_template,
485+
)
486+
.await
487+
.map_err(BuildBlockError::SuffixTxs)?;
488+
let suffix_coinbase_txouts_weight = match typewit::MakeTypeWitness::MAKE {
489+
typewit::const_marker::BoolWit::True(wit) => {
490+
let wit = wit.map(cusf_block_producer::CoinbaseTxouts);
491+
wit.in_ref()
492+
.to_right(&template_suffix.coinbase_txouts)
493+
.iter()
494+
.map(|tx_out| tx_out.weight())
495+
.sum()
496+
}
497+
typewit::const_marker::BoolWit::False(_) => Weight::ZERO,
498+
};
499+
let suffix_txs_weight =
500+
template_suffix.txs.iter().map(|(tx, _)| tx.weight()).sum();
501+
let suffix_weight = suffix_coinbase_txouts_weight + suffix_txs_weight;
502+
let mempool_txs = mempool.propose_txs(Some(Weight::from_wu(
503+
mempool::MAX_USABLE_BLOCK_WEIGHT.to_wu().saturating_sub(
504+
initial_block_template_weight.to_wu() + suffix_weight.to_wu(),
505+
),
506+
)))?;
478507
{
479508
let proposed_txids: String = {
480509
use std::fmt::Write;
@@ -504,22 +533,6 @@ async fn block_txs<const COINBASE_TXN: bool, BP>(
504533
};
505534
tracing::debug!(%proposed_txids, "Proposed txs for inclusion in block");
506535
}
507-
initial_block_template
508-
.prefix_txs
509-
.extend(mempool_txs.iter().map(|tx| {
510-
let fee = tx.fee.unsigned_abs();
511-
let tx = bitcoin::consensus::deserialize(&tx.data).unwrap();
512-
(tx, fee)
513-
}));
514-
tracing::debug!("Adding block template suffix");
515-
let template_suffix = block_producer
516-
.block_template_suffix(
517-
parent_block_hash,
518-
typewit::MakeTypeWitness::MAKE,
519-
&initial_block_template,
520-
)
521-
.await
522-
.map_err(BuildBlockError::SuffixTxs)?;
523536
let mut res_coinbase_txouts = initial_block_template.coinbase_txouts;
524537
match typewit::MakeTypeWitness::MAKE {
525538
typewit::const_marker::BoolWit::True(wit) => {

0 commit comments

Comments
 (0)