diff --git a/changes/node/changed/document-non-ledger-transactions-rustdoc.md b/changes/node/changed/document-non-ledger-transactions-rustdoc.md new file mode 100644 index 000000000..297f352bb --- /dev/null +++ b/changes/node/changed/document-non-ledger-transactions-rustdoc.md @@ -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 diff --git a/metadata/static/midnight_metadata.scale b/metadata/static/midnight_metadata.scale index 7c4ab497c..84db73c02 100644 Binary files a/metadata/static/midnight_metadata.scale and b/metadata/static/midnight_metadata.scale differ diff --git a/metadata/static/midnight_metadata_2.0.0.scale b/metadata/static/midnight_metadata_2.0.0.scale index 7c4ab497c..84db73c02 100644 Binary files a/metadata/static/midnight_metadata_2.0.0.scale and b/metadata/static/midnight_metadata_2.0.0.scale differ diff --git a/pallets/c2m-bridge/src/lib.rs b/pallets/c2m-bridge/src/lib.rs index fb3c1e986..f93cb325c 100644 --- a/pallets/c2m-bridge/src/lib.rs +++ b/pallets/c2m-bridge/src/lib.rs @@ -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)] diff --git a/pallets/cnight-observation/src/lib.rs b/pallets/cnight-observation/src/lib.rs index 7e40033f8..0ec66a358 100644 --- a/pallets/cnight-observation/src/lib.rs +++ b/pallets/cnight-observation/src/lib.rs @@ -639,6 +639,20 @@ pub mod pallet { #[pallet::call] impl Pallet { + /// 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::::get().saturating_mul(UTXO_PER_TX_OVERESTIMATE)), DispatchClass::Mandatory))] pub fn process_tokens( diff --git a/pallets/midnight-system/src/lib.rs b/pallets/midnight-system/src/lib.rs index 6d37834c3..f166eb03c 100644 --- a/pallets/midnight-system/src/lib.rs +++ b/pallets/midnight-system/src/lib.rs @@ -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; @@ -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, } @@ -115,6 +144,22 @@ pub mod pallet { #[pallet::call] impl Pallet { + /// 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::::get(), DispatchClass::Operational))] pub fn send_mn_system_transaction( diff --git a/pallets/midnight/src/lib.rs b/pallets/midnight/src/lib.rs index b1cefa549..ce47bbe50 100644 --- a/pallets/midnight/src/lib.rs +++ b/pallets/midnight/src/lib.rs @@ -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: -/// // Re-export pallet items so that they can be accessed from the crate namespace. pub use pallet::*; @@ -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 Pallet { + /// 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::::get_tx_weight(midnight_tx))] pub fn send_mn_transaction(_origin: OriginFor, midnight_tx: Vec) -> DispatchResult { diff --git a/primitives/midnight/src/lib.rs b/primitives/midnight/src/lib.rs index c71d36c79..335c072f1 100644 --- a/primitives/midnight/src/lib.rs +++ b/primitives/midnight/src/lib.rs @@ -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; @@ -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, ) -> Result; } +/// 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` (the decoded ledger transaction if decoding succeeded), the V2 +/// vocabulary carries a `Result` 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, Option), + /// 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, Result), + /// 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, } @@ -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,