Skip to main content

mina_tx_type/
coinbase.rs

1//! Coinbase transaction types for Mina Protocol.
2//!
3//! This module defines the coinbase transaction structures used for
4//! block rewards and fee transfers in the Mina Protocol.
5//!
6//! # Overview
7//!
8//! In Mina, each block can include a coinbase transaction that:
9//! - Rewards the block producer with newly minted tokens
10//! - Optionally transfers a portion of the reward as a fee to a SNARK worker
11
12use crate::currency::{Amount, Fee, Magnitude};
13use mina_signer::CompressedPubKey;
14
15/// A fee transfer within a coinbase transaction.
16///
17/// When a SNARK worker contributes proofs to a block, they may receive
18/// a portion of the coinbase reward as compensation. This structure
19/// represents that fee transfer.
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct CoinbaseFeeTransfer {
22    receiver_pk: CompressedPubKey,
23    fee: Fee,
24}
25
26impl CoinbaseFeeTransfer {
27    /// Creates a new coinbase fee transfer.
28    ///
29    /// # Arguments
30    ///
31    /// * `receiver_pk` - The compressed public key of the fee recipient
32    /// * `fee` - The fee amount to transfer
33    #[must_use]
34    pub const fn new(receiver_pk: CompressedPubKey, fee: Fee) -> Self {
35        Self { receiver_pk, fee }
36    }
37
38    /// Returns the public key of the fee recipient.
39    #[must_use]
40    pub const fn receiver_pk(&self) -> &CompressedPubKey {
41        &self.receiver_pk
42    }
43
44    /// Returns the fee amount.
45    #[must_use]
46    pub const fn fee(&self) -> Fee {
47        self.fee
48    }
49}
50
51/// A coinbase transaction for block rewards.
52///
53/// The coinbase transaction is included in each block to:
54/// 1. Credit the block producer with the coinbase reward
55/// 2. Optionally transfer a fee to a SNARK worker who contributed proofs
56///
57/// The `amount` represents the total coinbase reward for the block.
58/// If a `fee_transfer` is present, the fee is deducted from the amount
59/// before crediting the receiver.
60#[derive(Debug, Clone, PartialEq, Eq)]
61pub struct Coinbase {
62    receiver: CompressedPubKey,
63    amount: Amount,
64    fee_transfer: Option<CoinbaseFeeTransfer>,
65}
66
67impl Coinbase {
68    /// Creates a new coinbase transaction without a fee transfer.
69    ///
70    /// # Arguments
71    ///
72    /// * `receiver` - The compressed public key of the block producer
73    /// * `amount` - The coinbase reward amount
74    #[must_use]
75    pub const fn new(receiver: CompressedPubKey, amount: Amount) -> Self {
76        Self {
77            receiver,
78            amount,
79            fee_transfer: None,
80        }
81    }
82
83    /// Creates a new coinbase transaction with a fee transfer.
84    ///
85    /// # Arguments
86    ///
87    /// * `receiver` - The compressed public key of the block producer
88    /// * `amount` - The coinbase reward amount
89    /// * `fee_transfer` - The fee transfer to a SNARK worker
90    #[must_use]
91    pub const fn with_fee_transfer(
92        receiver: CompressedPubKey,
93        amount: Amount,
94        fee_transfer: CoinbaseFeeTransfer,
95    ) -> Self {
96        Self {
97            receiver,
98            amount,
99            fee_transfer: Some(fee_transfer),
100        }
101    }
102
103    /// Returns the coinbase receiver (block producer).
104    #[must_use]
105    pub const fn receiver(&self) -> &CompressedPubKey {
106        &self.receiver
107    }
108
109    /// Returns the total coinbase amount.
110    #[must_use]
111    pub const fn amount(&self) -> Amount {
112        self.amount
113    }
114
115    /// Returns the optional fee transfer.
116    #[must_use]
117    pub const fn fee_transfer(&self) -> Option<&CoinbaseFeeTransfer> {
118        self.fee_transfer.as_ref()
119    }
120
121    /// Returns `true` if this coinbase has a fee transfer.
122    #[must_use]
123    pub const fn has_fee_transfer(&self) -> bool {
124        self.fee_transfer.is_some()
125    }
126
127    /// Returns the net amount credited to the block producer.
128    ///
129    /// This is the coinbase amount minus any fee transfer.
130    /// Returns `None` if the fee exceeds the amount (which should not
131    /// happen in valid transactions).
132    #[must_use]
133    pub fn net_amount(&self) -> Option<Amount> {
134        self.fee_transfer.as_ref().map_or(Some(self.amount), |ft| {
135            let fee_as_amount: Amount = ft.fee().into();
136            self.amount.checked_sub(fee_as_amount)
137        })
138    }
139}