Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#node

# Document the non-ledger transaction surface in rustdoc

Adds crate- and item-level documentation across the node crates that define the
non-ledger transaction surface: `TransactionType`/`TransactionTypeV2` and their
variants in `primitives/midnight`, the `send_mn_transaction` envelope in
`pallets/midnight`, the system-transaction entry points and
`SystemTransactionApplied` event in `pallets/midnight-system`, the
`process_tokens` observation-inherent path in `pallets/cnight-observation`, and
the bridge-transfer framing in `pallets/c2m-bridge`. The docs state the
node/ledger boundary, frame the transaction classification as an off-node
vocabulary consumed via runtime metadata (not in-node dispatch), and remove a
stale FRAME-template scaffold comment and `//todo` placeholder. Documentation
only β€” no behaviour, signatures, or error codes change.

Closes: https://github.com/midnightntwrk/midnight-node/issues/1533
PR: https://github.com/midnightntwrk/midnight-node/pull/1619
Binary file modified metadata/static/midnight_metadata.scale
Binary file not shown.
Binary file modified metadata/static/midnight_metadata_2.0.0.scale
Binary file not shown.
9 changes: 9 additions & 0 deletions pallets/c2m-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
//!
//! This pallet implements the [`pallet_partner_chains_bridge::TransferHandler`] trait
//! with Midnight-specific logic.
//!
//! A bridge transfer is an inherent that produces a system transaction, not a
//! standalone transaction type. The handler validates an observed Cardano
//! transfer against the approved-transfers list and applies the resulting ledger
//! system transaction through the
//! [`MidnightSystemTransactionExecutor`](midnight_primitives::MidnightSystemTransactionExecutor)
//! seam, so the net effect on the ledger arrives as a system transaction. Each
//! handled transfer also emits a bridge [`Event`] for correlation with the
//! Cardano-side movement.

#![cfg_attr(not(feature = "std"), no_std)]

Expand Down
14 changes: 14 additions & 0 deletions pallets/cnight-observation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,20 @@ pub mod pallet {

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Record observed Cardano token movements on Midnight.
///
/// This call is the payload of the cNIGHT observation inherent: the block
/// author injects the observed UTXOs and the next Cardano position
/// through `create_inherent`, and every other node re-derives the same
/// data and compares it in `check_inherent`. The observation is therefore
/// a consensus-checked fact rather than a user-submitted transaction β€”
/// the call requires no origin and runs at most once per block.
///
/// # Errors
///
/// Returns [`Error::TooManyUtxos`] if `utxos` exceeds the per-block
/// capacity, or [`Error::InherentAlreadyExecuted`] if the inherent has
/// already run in this block.
#[pallet::call_index(0)]
#[pallet::weight((T::WeightInfo::process_tokens(CardanoTxCapacityPerBlock::<T>::get().saturating_mul(UTXO_PER_TX_OVERESTIMATE)), DispatchClass::Mandatory))]
pub fn process_tokens(
Expand Down
45 changes: 45 additions & 0 deletions pallets/midnight-system/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
//! # Midnight system transaction pallet
//!
//! Applies privileged system transactions to the Midnight ledger.
//!
//! A system transaction is a node-owned, non-ledger transaction category: it
//! changes ledger state through a privileged, audited channel rather than
//! through the user transaction pool. Two entry points reach the ledger:
//!
//! - [`Pallet::send_mn_system_transaction`] β€” a root-origin extrinsic, gated by
//! a governance allow-check, that governance uses to apply a system
//! transaction directly.
//! - The [`MidnightSystemTransactionExecutor`] implementation β€” the seam by
//! which other pallets (notably the Cardano-to-Midnight bridge) apply a
//! serialized system transaction.
//!
//! Both paths emit a [`SystemTransactionApplied`] event so an indexer can
//! correlate the effect on the ledger with the originating call. The serialized
//! system transaction is opaque to the node; the ledger decodes and interprets
//! it.
//!
//! [`MidnightSystemTransactionExecutor`]: midnight_primitives::MidnightSystemTransactionExecutor

#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;
Expand Down Expand Up @@ -31,9 +53,16 @@ pub mod pallet {
SystemTransactionApplied(SystemTransactionApplied),
}

/// Emitted when a system transaction is applied to the ledger.
///
/// Both [`Pallet::send_mn_system_transaction`] and the
/// `MidnightSystemTransactionExecutor` seam deposit this event so an indexer
/// can correlate the ledger effect with the originating call.
#[derive(Clone, Debug, PartialEq, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
pub struct SystemTransactionApplied {
/// Ledger transaction hash of the applied system transaction.
pub hash: Hash,
/// The serialized system transaction that was applied, opaque to the node.
pub serialized_system_transaction: Vec<u8>,
}

Expand Down Expand Up @@ -115,6 +144,22 @@ pub mod pallet {

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Apply a system transaction to the ledger.
///
/// `midnight_system_tx` is the opaque, serialized ledger system
/// transaction. The call requires root origin and is gated by the
/// ledger's governance allow-check, so only the system transactions
/// governance is permitted to run reach the ledger. On success it applies
/// the transaction through the ledger system-transaction path and emits a
/// [`SystemTransactionApplied`] event.
///
/// # Errors
///
/// Returns [`Error::SystemTransactionNotAllowedForGovernance`] if the
/// governance allow-check rejects the transaction, or one of the
/// ledger-derived error variants (mirrored from the ledger API) if the
/// ledger fails to apply it. The dispatch also fails if the origin is not
/// root.
#[pallet::call_index(0)]
#[pallet::weight((ConfigurableSystemTxWeight::<T>::get(), DispatchClass::Operational))]
pub fn send_mn_system_transaction(
Expand Down
44 changes: 37 additions & 7 deletions pallets/midnight/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! # Midnight pallet
//!
//! Owns the ledger-carrying transaction envelope and validates it before the
//! ledger applies it.
//!
//! [`Pallet::send_mn_transaction`] is the primary dispatchable: it carries a
//! ledger transaction as an opaque byte vector, validated through the ledger
//! API and applied to ledger state. The node frames, validates, weighs, and
//! routes the transaction; the ledger decodes and interprets the opaque
//! payload. This pallet sits on the node side of that boundary and does not
//! inspect the payload's contents.
//!
//! The crate also re-exports the [`TransactionType`] and [`TransactionTypeV2`]
//! classification vocabulary (defined in `midnight-primitives`), which off-node
//! consumers read through runtime metadata to label a decoded transaction.

#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;

/// Edit this file to define custom logic or remove it if it is not needed.
/// Learn more about FRAME and the core library of Substrate FRAME pallets:
/// <https://docs.substrate.io/reference/frame-pallets/>
// Re-export pallet items so that they can be accessed from the crate namespace.
pub use pallet::*;

Expand Down Expand Up @@ -362,12 +375,29 @@ pub mod pallet {
}
}

// Dispatchable functions allows users to interact with the pallet and invoke state changes.
// These functions materialize as "extrinsics", which are often compared to transactions.
// Dispatchable functions must be annotated with a weight and must return a DispatchResult.
//todo example of custom transaction type (extrinsic) transaction has to be signed to call it
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Apply a ledger transaction to ledger state.
///
/// `midnight_tx` is the opaque, serialized ledger transaction. The call
/// is unsigned and submitted through the transaction pool; the pallet's
/// `ValidateUnsigned` implementation gates it through the ledger API
/// before dispatch. On apply, the pallet hands the payload to the ledger
/// and emits the resulting ledger events (contract call, deploy,
/// maintain, claimed rewards, unshielded token movements, and an
/// applied-transaction marker).
///
/// This is the node-owned envelope for a ledger transaction: the node
/// frames, validates, weighs, and routes the transaction, while the
/// ledger decodes and interprets the `midnight_tx` payload. The node does
/// not inspect the payload's contents.
///
/// # Errors
///
/// Returns one of the ledger-derived [`Error`] variants if the ledger
/// rejects the transaction. Validity failures surfaced during pool
/// validation map to `InvalidTransaction` codes rather than a dispatch
/// error.
#[pallet::call_index(0)]
#[pallet::weight(Pallet::<T>::get_tx_weight(midnight_tx))]
pub fn send_mn_transaction(_origin: OriginFor<T>, midnight_tx: Vec<u8>) -> DispatchResult {
Expand Down
84 changes: 82 additions & 2 deletions primitives/midnight/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! # Midnight node primitives
//!
//! Shared types and traits that define the boundary between the Midnight node,
//! the runtime, and the Midnight ledger.
//!
//! The node frames, validates, weighs, and routes transactions; the ledger
//! decodes and interprets the opaque payload carried by a ledger transaction.
//! Everything in this crate sits on the node side of that boundary.
//!
//! The crate exposes:
//!
//! - The [`TransactionType`] and [`TransactionTypeV2`] classification
//! vocabulary, published to off-node consumers through runtime metadata.
//! - The [`MidnightSystemTransactionExecutor`] seam, by which other pallets
//! apply a serialized system transaction to the ledger.
//! - The [`LedgerStateProviderMut`] and [`LedgerBlockContextProvider`] seams
//! for reading and mutating ledger state.
//! - The [`bridge`] module's [`BridgeRecipient`] type, used by the bridge
//! inherent and the Cardano-to-Midnight bridge pallet.

#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;
Expand Down Expand Up @@ -40,24 +60,77 @@ pub trait LedgerBlockContextProvider {
fn get_block_context() -> BlockContext;
}

/// Seam by which a pallet applies a serialized system transaction to the ledger.
///
/// `pallet-midnight-system` implements this trait so that other pallets β€” notably
/// the Cardano-to-Midnight bridge β€” can apply a system transaction through the
/// privileged ledger path without depending on the system pallet directly. A
/// bridge transfer uses this seam to turn an observed Cardano transfer into a
/// system transaction.
///
/// The argument is the opaque, serialized ledger system transaction; the node
/// passes it to the ledger and does not interpret its contents.
pub trait MidnightSystemTransactionExecutor {
/// Execute a Midnight System Transaction and return a SCALE-compatible result
/// Apply a serialized system transaction and return its ledger transaction hash.
///
/// # Errors
///
/// Returns a [`DispatchError`] if the ledger rejects the system transaction
/// (for example, a deserialization or transaction error surfaced through the
/// ledger API).
fn execute_system_transaction(
serialized_system_transaction: Vec<u8>,
) -> Result<Hash, DispatchError>;
}

/// Classification vocabulary for a decoded transaction, consumed off-node.
///
/// This enumeration is a published vocabulary, exposed to off-node consumers
/// (indexers, the toolkit, and downstream tooling) through runtime metadata. It
/// labels a decoded transaction; it is **not** an in-node dispatch mechanism.
/// The node never matches on these variants to decide how to process a
/// transaction β€” dispatch happens through the FRAME pallet [`Call`] enums and
/// inherents. The variants exist so a downstream decoder can classify a
/// transaction without re-implementing the dispatch logic.
///
/// [`TransactionTypeV2`] supersedes this type: where this version carries an
/// `Option<Tx>` (the decoded ledger transaction if decoding succeeded), the V2
/// vocabulary carries a `Result<Tx, LedgerApiError>` so a consumer can see why a
/// payload failed to decode.
///
/// [`Call`]: https://docs.rs/frame-support/latest/frame_support/pallet_macros/attr.call.html
#[derive(Clone, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
pub enum TransactionType {
/// A ledger-carrying transaction: the opaque ledger payload and, if it
/// decoded, the decoded ledger transaction.
MidnightTx(Vec<u8>, Option<Tx>),
/// The block timestamp, surfaced as a first-class transaction value.
TimestampTx(u64),
/// A transaction the classifier does not recognize (for example, a future
/// or unknown variant).
UnknownTx,
}

/// Current classification vocabulary for a decoded transaction, consumed off-node.
///
/// Like [`TransactionType`], this enumeration is a published vocabulary exposed
/// to off-node consumers through runtime metadata to label a decoded
/// transaction. It is **not** an in-node dispatch mechanism β€” the node never
/// matches on these variants; dispatch happens through the FRAME pallet `Call`
/// enums and inherents.
///
/// This version supersedes [`TransactionType`] by carrying the ledger decode
/// `Result` rather than an `Option`, so a consumer can observe a decode failure
/// ([`LedgerApiError`]) instead of only the absence of a decoded transaction.
#[derive(Clone, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
pub enum TransactionTypeV2 {
/// A ledger-carrying transaction: the opaque ledger payload and the result
/// of decoding it.
MidnightTx(Vec<u8>, Result<Tx, LedgerApiError>),
/// The block timestamp, surfaced as a first-class transaction value.
TimestampTx(u64),
/// A transaction the classifier does not recognize (for example, a future
/// or unknown variant).
UnknownTx,
}

Expand Down Expand Up @@ -87,7 +160,14 @@ pub mod bridge {
TooLong,
}

/// Recipient type used by the bridge pallet and inherent data provider.
/// A Midnight recipient address carried by a bridge transfer.
///
/// The bridge pallet and the bridge inherent data provider use this type to
/// name the beneficiary of a Cardano-to-Midnight transfer. The address is
/// bounded to [`BRIDGE_RECIPIENT_MAX_BYTES`] bytes so the recipient encoded
/// in the bridge datum has a fixed maximum size and a predictable encoded
/// length; an address exceeding the bound is rejected with
/// [`BridgeRecipientError::TooLong`].
#[derive(
Clone,
PartialEq,
Expand Down
Loading