Skip to content

Commit ca4d87d

Browse files
committed
Change Block::coinbase() to return &Coinbase instead of Option<&Transaction>
This change has semantic meaning: it guarantees that every checked Block has a coinbase as its first transaction. The method is now infallible for validated blocks. As a follow-up, update bip34_block_height to work with the new Coinbase type: - Removed unnecessary error handling, since coinbase() now returns &Coinbase instead of Option<&Transaction>. - Used cb.inner() to access the underlying Transaction fields for input processing.
1 parent 7c438b2 commit ca4d87d

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

bitcoin/src/blockdata/block.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use internals::{compact_size, ToU64};
1515
use io::{BufRead, Write};
1616
use units::BlockTime;
1717

18+
use super::transaction::Coinbase;
1819
use super::Weight;
1920
use crate::consensus::encode::WriteExt as _;
2021
use crate::consensus::{encode, Decodable, Encodable};
@@ -258,8 +259,11 @@ pub trait BlockCheckedExt: sealed::Sealed {
258259
/// > including base data and witness data.
259260
fn total_size(&self) -> usize;
260261

261-
/// Returns the coinbase transaction, if one is present.
262-
fn coinbase(&self) -> Option<&Transaction>;
262+
/// Returns the coinbase transaction.
263+
///
264+
/// This method is infallible for checked blocks because validation ensures
265+
/// that a valid coinbase transaction is always present.
266+
fn coinbase(&self) -> &Coinbase;
263267

264268
/// Returns the block height, as encoded in the coinbase transaction according to BIP34.
265269
fn bip34_block_height(&self) -> Result<u64, Bip34Error>;
@@ -293,8 +297,10 @@ impl BlockCheckedExt for Block<Checked> {
293297
size
294298
}
295299

296-
/// Returns the coinbase transaction, if one is present.
297-
fn coinbase(&self) -> Option<&Transaction> { self.transactions().first() }
300+
fn coinbase(&self) -> &Coinbase {
301+
let first_tx = &self.transactions()[0];
302+
Coinbase::assume_coinbase_ref(first_tx)
303+
}
298304

299305
/// Returns the block height, as encoded in the coinbase transaction according to BIP34.
300306
fn bip34_block_height(&self) -> Result<u64, Bip34Error> {
@@ -311,8 +317,8 @@ impl BlockCheckedExt for Block<Checked> {
311317
return Err(Bip34Error::Unsupported);
312318
}
313319

314-
let cb = self.coinbase().ok_or(Bip34Error::NotPresent)?;
315-
let input = cb.input.first().ok_or(Bip34Error::NotPresent)?;
320+
let cb = self.coinbase();
321+
let input = cb.first_input();
316322
let push = input
317323
.script_sig
318324
.instructions_minimal()
@@ -539,7 +545,7 @@ mod tests {
539545
let block = block.assume_checked(None);
540546

541547
let cb_txid = "d574f343976d8e70d91cb278d21044dd8a396019e6db70755a0a50e4783dba38";
542-
assert_eq!(block.coinbase().unwrap().compute_txid().to_string(), cb_txid);
548+
assert_eq!(block.coinbase().compute_txid().to_string(), cb_txid);
543549

544550
assert_eq!(block.bip34_block_height(), Ok(100_000));
545551

bitcoin/src/blockdata/transaction.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,14 @@ impl Coinbase {
11791179
Self(tx)
11801180
}
11811181

1182+
/// Returns the first input of this coinbase transaction.
1183+
///
1184+
/// This method is infallible because a valid coinbase transaction is guaranteed
1185+
/// to have exactly one input.
1186+
pub fn first_input(&self) -> &TxIn {
1187+
&self.0.input[0]
1188+
}
1189+
11821190
/// Returns a reference to the underlying transaction.
11831191
///
11841192
/// Warning: The coinbase input contains dummy prevouts that should not be treated as real prevouts.

0 commit comments

Comments
 (0)