Skip to content

Commit 4ea5b0f

Browse files
committed
Fixup: Provide suffix txs in initial template
1 parent 65e8e6b commit 4ea5b0f

4 files changed

Lines changed: 159 additions & 141 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ async-trait = "0.1.81"
1515
bitcoin = "0.32.100"
1616
chrono = "0.4.44"
1717
clap = "4.6.1"
18-
educe = "0.6.0"
18+
educe = { version = "0.6.0", default-features = false }
1919
either = "1.16.0"
2020
futures = "0.3.32"
2121
hashlink = "0.12.0"

lib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ async-trait = { workspace = true }
1212
bitcoin-jsonrpsee = { workspace = true, features = ["tracing"] }
1313
bitcoin = { workspace = true }
1414
chrono = { workspace = true }
15-
educe = { workspace = true }
15+
educe = { workspace = true, features = ["Clone", "Debug", "Default"] }
1616
either = { workspace = true }
1717
futures = { workspace = true }
1818
hashlink = { workspace = true }

lib/cusf_block_producer.rs

Lines changed: 134 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
use std::{
2-
collections::HashSet, convert::Infallible, fmt::Debug, future::Future,
3-
};
1+
use std::{convert::Infallible, fmt::Debug, future::Future};
42

5-
use bitcoin::{BlockHash, Transaction, TxOut, Txid};
3+
use bitcoin::{BlockHash, TxOut};
64
use either::Either;
75

86
use crate::cusf_enforcer::{self, CusfEnforcer};
@@ -40,27 +38,105 @@ where
4038
type Output = <typewit::const_marker::Bool<COINBASE_TXN> as CoinbaseTxn>::CoinbaseTxouts;
4139
}
4240

43-
#[derive(Clone, Debug, Default)]
44-
pub struct InitialBlockTemplate<const COINBASE_TXN: bool>
41+
pub mod initial_block_template {
42+
use std::collections::HashSet;
43+
44+
use bitcoin::{Transaction, Txid};
45+
46+
use crate::cusf_block_producer::CoinbaseTxn;
47+
48+
pub type TxsItem = (Transaction, bitcoin::Amount);
49+
50+
#[derive(Clone, Debug)]
51+
pub enum SuffixTxsItem {
52+
/// Transaction is already generated
53+
Tx(TxsItem),
54+
/// Reserved, tx will be generated after mempool txs are selected
55+
Reserved { weight: bitcoin::Weight },
56+
}
57+
58+
impl SuffixTxsItem {
59+
pub fn weight(&self) -> bitcoin::Weight {
60+
match self {
61+
Self::Tx((tx, _)) => tx.weight(),
62+
Self::Reserved { weight } => *weight,
63+
}
64+
}
65+
}
66+
67+
#[derive(Clone, Debug, Default)]
68+
pub struct Template<const COINBASE_TXN: bool>
69+
where typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn
70+
{
71+
pub coinbase_txouts: <typewit::const_marker::Bool<COINBASE_TXN> as CoinbaseTxn>::CoinbaseTxouts,
72+
/// Prefix txs, with absolute fee
73+
pub prefix_txs: Vec<TxsItem>,
74+
/// Suffix txs
75+
pub suffix_txs: Vec<SuffixTxsItem>,
76+
/// prefix/suffix txs do not need to be included here
77+
pub exclude_mempool_txs: HashSet<Txid>,
78+
}
79+
}
80+
pub use initial_block_template::Template as InitialBlockTemplate;
81+
82+
#[derive(educe::Educe)]
83+
#[educe(Clone, Debug, Default)]
84+
pub struct FilledBlockTemplate<const COINBASE_TXN: bool>
4585
where typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn
4686
{
47-
pub coinbase_txouts: <typewit::const_marker::Bool<COINBASE_TXN> as CoinbaseTxn>::CoinbaseTxouts,
87+
pub(crate) coinbase_txouts: <typewit::const_marker::Bool<COINBASE_TXN> as CoinbaseTxn>::CoinbaseTxouts,
4888
/// Prefix txs, with absolute fee
49-
pub prefix_txs: Vec<(Transaction, bitcoin::Amount)>,
50-
/// Suffix txs, with absolute fee
51-
pub suffix_txs: Vec<(Transaction, bitcoin::Amount)>,
52-
/// prefix/suffix txs do not need to be included here
53-
pub exclude_mempool_txs: HashSet<Txid>,
89+
pub(crate) prefix_txs: Vec<initial_block_template::TxsItem>,
90+
/// Suffix txs
91+
pub(crate) suffix_txs: Vec<initial_block_template::TxsItem>,
5492
}
5593

56-
#[derive(Clone, Debug, Default)]
57-
pub struct BlockTemplateSuffix<const COINBASE_TXN: bool>
58-
where typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn
94+
impl<const COINBASE_TXN: bool> FilledBlockTemplate<COINBASE_TXN>
95+
where
96+
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn,
97+
{
98+
pub fn coinbase_txouts(&mut self) -> &mut <typewit::const_marker::Bool<COINBASE_TXN> as CoinbaseTxn>::CoinbaseTxouts{
99+
&mut self.coinbase_txouts
100+
}
101+
102+
/// Prefix txs, with absolute fee
103+
pub fn prefix_txs(&self) -> &Vec<initial_block_template::TxsItem> {
104+
&self.prefix_txs
105+
}
106+
107+
/// Suffix txs
108+
pub fn suffix_txs(&mut self) -> &mut Vec<initial_block_template::TxsItem> {
109+
&mut self.suffix_txs
110+
}
111+
}
112+
113+
impl<const COINBASE_TXN: bool> From<InitialBlockTemplate<COINBASE_TXN>>
114+
for FilledBlockTemplate<COINBASE_TXN>
115+
where
116+
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn,
59117
{
60-
/// Suffix coinbase txouts
61-
pub coinbase_txouts: <typewit::const_marker::Bool<COINBASE_TXN> as CoinbaseTxn>::CoinbaseTxouts,
62-
/// Suffix txs, with absolute fee
63-
pub txs: Vec<(Transaction, bitcoin::Amount)>,
118+
fn from(template: InitialBlockTemplate<COINBASE_TXN>) -> Self {
119+
let InitialBlockTemplate {
120+
coinbase_txouts,
121+
prefix_txs,
122+
suffix_txs,
123+
exclude_mempool_txs: _,
124+
} = template;
125+
let suffix_txs = suffix_txs
126+
.into_iter()
127+
.filter_map(|suffix_txs_item| match suffix_txs_item {
128+
initial_block_template::SuffixTxsItem::Tx(tx_item) => {
129+
Some(tx_item)
130+
}
131+
initial_block_template::SuffixTxsItem::Reserved { .. } => None,
132+
})
133+
.collect();
134+
Self {
135+
coinbase_txouts,
136+
prefix_txs,
137+
suffix_txs,
138+
}
139+
}
64140
}
65141

66142
pub trait CusfBlockProducer: CusfEnforcer {
@@ -70,30 +146,21 @@ pub trait CusfBlockProducer: CusfEnforcer {
70146
&self,
71147
parent_block_hash: &BlockHash,
72148
coinbase_txn_wit: typewit::const_marker::BoolWit<COINBASE_TXN>,
73-
template: InitialBlockTemplate<COINBASE_TXN>,
74-
) -> impl Future<
75-
Output = Result<
76-
InitialBlockTemplate<COINBASE_TXN>,
77-
Self::InitialBlockTemplateError,
78-
>,
79-
> + Send
149+
template: &mut InitialBlockTemplate<COINBASE_TXN>,
150+
) -> impl Future<Output = Result<(), Self::InitialBlockTemplateError>> + Send
80151
where
81152
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn;
82153

83-
type SuffixTxsError: std::error::Error + Send + Sync + 'static;
154+
type FinalizeBlockTemplateError: std::error::Error + Send + Sync + 'static;
84155

85-
/// Add outputs / txs to a block template, after filling with proposed txs
86-
fn block_template_suffix<const COINBASE_TXN: bool>(
156+
/// Finalize coinbase outputs / suffix txs for a block template, after
157+
/// filling with proposed txs
158+
fn finalize_block_template<const COINBASE_TXN: bool>(
87159
&self,
88160
parent_block_hash: &BlockHash,
89161
coinbase_txn_wit: typewit::const_marker::BoolWit<COINBASE_TXN>,
90-
template: &InitialBlockTemplate<COINBASE_TXN>,
91-
) -> impl Future<
92-
Output = Result<
93-
BlockTemplateSuffix<COINBASE_TXN>,
94-
Self::SuffixTxsError,
95-
>,
96-
> + Send
162+
template: &mut FilledBlockTemplate<COINBASE_TXN>,
163+
) -> impl Future<Output = Result<(), Self::FinalizeBlockTemplateError>> + Send
97164
where
98165
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn;
99166
}
@@ -110,16 +177,12 @@ where
110177
&self,
111178
parent_block_hash: &BlockHash,
112179
coinbase_txn_wit: typewit::const_marker::BoolWit<COINBASE_TXN>,
113-
mut template: InitialBlockTemplate<COINBASE_TXN>,
114-
) -> Result<
115-
InitialBlockTemplate<COINBASE_TXN>,
116-
Self::InitialBlockTemplateError,
117-
>
180+
template: &mut InitialBlockTemplate<COINBASE_TXN>,
181+
) -> Result<(), Self::InitialBlockTemplateError>
118182
where
119183
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn,
120184
{
121-
template = self
122-
.0
185+
self.0
123186
.initial_block_template(
124187
parent_block_hash,
125188
coinbase_txn_wit,
@@ -137,64 +200,37 @@ where
137200
.map_err(Either::Right)
138201
}
139202

140-
type SuffixTxsError = Either<C0::SuffixTxsError, C1::SuffixTxsError>;
203+
type FinalizeBlockTemplateError =
204+
Either<C0::FinalizeBlockTemplateError, C1::FinalizeBlockTemplateError>;
141205

142-
async fn block_template_suffix<const COINBASE_TXN: bool>(
206+
async fn finalize_block_template<const COINBASE_TXN: bool>(
143207
&self,
144208
parent_block_hash: &BlockHash,
145209
coinbase_txn_wit: typewit::const_marker::BoolWit<COINBASE_TXN>,
146-
template: &InitialBlockTemplate<COINBASE_TXN>,
147-
) -> Result<BlockTemplateSuffix<COINBASE_TXN>, Self::SuffixTxsError>
210+
template: &mut FilledBlockTemplate<COINBASE_TXN>,
211+
) -> Result<(), Self::FinalizeBlockTemplateError>
148212
where
149213
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn,
150214
{
151-
let suffix_left = self
215+
let () = self
152216
.0
153-
.block_template_suffix(
217+
.finalize_block_template(
154218
parent_block_hash,
155219
coinbase_txn_wit,
156220
template,
157221
)
158222
.await
159223
.map_err(Either::Left)?;
160-
let mut template = template.clone();
161-
match coinbase_txn_wit {
162-
typewit::const_marker::BoolWit::True(wit) => {
163-
let wit = wit.map(CoinbaseTxouts);
164-
let coinbase_txouts: &mut Vec<_> =
165-
wit.in_mut().to_right(&mut template.coinbase_txouts);
166-
coinbase_txouts.extend(
167-
wit.in_ref()
168-
.to_right(&suffix_left.coinbase_txouts)
169-
.iter()
170-
.cloned(),
171-
);
172-
}
173-
typewit::const_marker::BoolWit::False(_) => (),
174-
}
175-
template.suffix_txs.extend(suffix_left.txs.iter().cloned());
176-
let suffix_right = self
224+
let () = self
177225
.1
178-
.block_template_suffix(
226+
.finalize_block_template(
179227
parent_block_hash,
180228
coinbase_txn_wit,
181-
&template,
229+
template,
182230
)
183231
.await
184232
.map_err(Either::Right)?;
185-
let mut res = suffix_left;
186-
match coinbase_txn_wit {
187-
typewit::const_marker::BoolWit::True(wit) => {
188-
let wit = wit.map(CoinbaseTxouts);
189-
let coinbase_txouts: &mut Vec<_> =
190-
wit.in_mut().to_right(&mut res.coinbase_txouts);
191-
coinbase_txouts
192-
.extend(wit.to_right(suffix_right.coinbase_txouts));
193-
}
194-
typewit::const_marker::BoolWit::False(_) => (),
195-
}
196-
res.txs.extend(suffix_right.txs);
197-
Ok(res)
233+
Ok(())
198234
}
199235
}
200236

@@ -205,29 +241,26 @@ impl CusfBlockProducer for cusf_enforcer::DefaultEnforcer {
205241
&self,
206242
_parent_block_hash: &BlockHash,
207243
_coinbase_txn_wit: typewit::const_marker::BoolWit<COINBASE_TXN>,
208-
template: InitialBlockTemplate<COINBASE_TXN>,
209-
) -> Result<
210-
InitialBlockTemplate<COINBASE_TXN>,
211-
Self::InitialBlockTemplateError,
212-
>
244+
_template: &mut InitialBlockTemplate<COINBASE_TXN>,
245+
) -> Result<(), Self::InitialBlockTemplateError>
213246
where
214247
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn,
215248
{
216-
Ok(template)
249+
Ok(())
217250
}
218251

219-
type SuffixTxsError = Infallible;
252+
type FinalizeBlockTemplateError = Infallible;
220253

221-
async fn block_template_suffix<const COINBASE_TXN: bool>(
254+
async fn finalize_block_template<const COINBASE_TXN: bool>(
222255
&self,
223256
_parent_block_hash: &BlockHash,
224257
_coinbase_txn_wit: typewit::const_marker::BoolWit<COINBASE_TXN>,
225-
_template: &InitialBlockTemplate<COINBASE_TXN>,
226-
) -> Result<BlockTemplateSuffix<COINBASE_TXN>, Self::SuffixTxsError>
258+
_template: &mut FilledBlockTemplate<COINBASE_TXN>,
259+
) -> Result<(), Self::FinalizeBlockTemplateError>
227260
where
228261
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn,
229262
{
230-
Ok(BlockTemplateSuffix::default())
263+
Ok(())
231264
}
232265
}
233266

@@ -243,11 +276,8 @@ where
243276
&self,
244277
parent_block_hash: &BlockHash,
245278
coinbase_txn_wit: typewit::const_marker::BoolWit<COINBASE_TXN>,
246-
template: InitialBlockTemplate<COINBASE_TXN>,
247-
) -> Result<
248-
InitialBlockTemplate<COINBASE_TXN>,
249-
Self::InitialBlockTemplateError,
250-
>
279+
template: &mut InitialBlockTemplate<COINBASE_TXN>,
280+
) -> Result<(), Self::InitialBlockTemplateError>
251281
where
252282
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn,
253283
{
@@ -271,28 +301,29 @@ where
271301
}
272302
}
273303

274-
type SuffixTxsError = Either<C0::SuffixTxsError, C1::SuffixTxsError>;
304+
type FinalizeBlockTemplateError =
305+
Either<C0::FinalizeBlockTemplateError, C1::FinalizeBlockTemplateError>;
275306

276-
async fn block_template_suffix<const COINBASE_TXN: bool>(
307+
async fn finalize_block_template<const COINBASE_TXN: bool>(
277308
&self,
278309
parent_block_hash: &BlockHash,
279310
coinbase_txn_wit: typewit::const_marker::BoolWit<COINBASE_TXN>,
280-
template: &InitialBlockTemplate<COINBASE_TXN>,
281-
) -> Result<BlockTemplateSuffix<COINBASE_TXN>, Self::SuffixTxsError>
311+
template: &mut FilledBlockTemplate<COINBASE_TXN>,
312+
) -> Result<(), Self::FinalizeBlockTemplateError>
282313
where
283314
typewit::const_marker::Bool<COINBASE_TXN>: CoinbaseTxn,
284315
{
285316
match self {
286317
Self::Left(left) => left
287-
.block_template_suffix(
318+
.finalize_block_template(
288319
parent_block_hash,
289320
coinbase_txn_wit,
290321
template,
291322
)
292323
.await
293324
.map_err(Either::Left),
294325
Self::Right(right) => right
295-
.block_template_suffix(
326+
.finalize_block_template(
296327
parent_block_hash,
297328
coinbase_txn_wit,
298329
template,

0 commit comments

Comments
 (0)