Skip to content
Merged
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
14 changes: 13 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
[workspace]
members = [
"nucleus",
"programs/magic-root-interface",
"programs/v42-calculator-interface",
"solana/account",
"solana/program-runtime",
"solana/svm",
"solana/transaction-context",
"solana/transaction-view",
"solana/transaction-view"
]
resolver = "3"

Expand All @@ -20,6 +23,8 @@ version = "0.1.0"
[workspace.dependencies]
magic-root-interface = { path = "programs/magic-root-interface" }
magic-root-program = { path = "programs/magic-root-program" }
nucleus = { path = "nucleus", package = "magicblock-engine-nucleus" }
v42-calculator-interface = { path = "programs/v42-calculator-interface", default-features = false }
solana-account = { path = "solana/account" }
solana-program-runtime = { path = "solana/program-runtime" }
solana-svm = { path = "solana/svm" }
Expand All @@ -36,7 +41,11 @@ cfg-if = "1.0.4"
criterion = "0.8.2"
derive_more = "2.1.1"
env_logger = "0.11.8"
futures = { version = "0.3.32", default-features = false }
heed = { version = "0.22.1", default-features = false }
itertools = "0.13.0"
oneshot = "0.2.1"
prometheus = { version = "0.14.0", default-features = false }
qualifier_attr = "0.2.2"
rand = "0.9.2"
rustix = { version = "1.1.4" }
Expand All @@ -48,6 +57,9 @@ snedfile = "0.1"
tar = "0.4.45"
tempfile = "3"
thiserror = "2.0.17"
tokio = "1.52.1"
tokio-util = "0.7.18"
tracing = "0.1.44"
tracing-subscriber = { version = "0.3.23", features = ["env-filter", "fmt"] }
wincode = "0.5.1"
zstd = { version = "0.13.3", default-features = false }
Expand Down
86 changes: 86 additions & 0 deletions nucleus/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
[package]
name = "magicblock-engine-nucleus"

authors.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[lib]
name = "nucleus"

[features]
config = [
"dep:serde",
"dep:serde_with",
"dep:solana-keypair",
"dep:solana-pubkey",
"dep:solana-signer"
]
default = []
heed = ["dep:heed"]
ledger = ["solana-hash/copy", "solana-hash/wincode", "wincode/derive"]
metrics = ["dep:prometheus", "dep:tracing"]
notifier = ["tokio/sync"]
runtime = [
"agave-transaction-view/agave-unstable-api",
"dep:derive_more",
"dep:oneshot",
"dep:solana-svm",
"dep:solana-transaction-error",
"ledger",
"service",
"tls",
"tokio/sync"
]
service = ["metrics", "shutdown"]
shutdown = ["dep:futures", "dep:oneshot", "dep:tokio", "dep:tokio-util", "dep:tracing"]
testkit = [
"dep:solana-instruction",
"dep:solana-keypair",
"dep:solana-message",
"dep:solana-pubkey",
"dep:solana-signature",
"dep:solana-signer",
"dep:tempfile",
"dep:tracing-subscriber",
"dep:v42-calculator-interface",
"runtime",
"solana-transaction/wincode"
]
tls = ["dep:solana-instruction-error", "dep:solana-pubkey", "dep:wincode"]

[dependencies]
derive_more = { workspace = true, optional = true, features = ["deref", "from"] }
futures = { workspace = true, features = ["alloc"], optional = true }
heed = { workspace = true, optional = true }
oneshot = { workspace = true, features = ["async"], optional = true }
prometheus = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"], optional = true }
serde_with = { workspace = true, optional = true }
solana-hash = { workspace = true, optional = true }
solana-instruction-error = { workspace = true, optional = true }
tempfile = { workspace = true, optional = true }
tokio = { workspace = true, features = ["macros", "signal", "time"], optional = true }
tokio-util = { workspace = true, optional = true }
tracing = { workspace = true, optional = true }
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"], optional = true }
wincode = { workspace = true, optional = true }

agave-transaction-view = { workspace = true, optional = true }
solana-instruction = { workspace = true, optional = true }
solana-keypair = { workspace = true, optional = true }
solana-message = { workspace = true, optional = true }
solana-pubkey = { workspace = true, optional = true }
solana-signature = { workspace = true, optional = true }
solana-signer = { workspace = true, optional = true }
solana-svm = { workspace = true, optional = true }
solana-transaction = { workspace = true, optional = true }
solana-transaction-error = { workspace = true, optional = true }
v42-calculator-interface = { workspace = true, optional = true, features = ["builder"] }

[lints]
workspace = true
33 changes: 33 additions & 0 deletions nucleus/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# `magicblock-engine-nucleus`

Nucleus contains shared engine types that do not own storage or execution
policy. It also exposes byte-size constants and a Unix-time helper that returns
zero when the system clock predates the epoch. Its default feature set is empty.

## Features

- `config`: serializable authority, accountsdb, blockstore, and ledger
configuration types. Authority serialization includes the complete local
keypair; consumers must redact it before exposing serialized output.
- `heed`: LMDB transaction aliases, safe environment-bound transaction reuse
helpers, and the shared `DatabaseIndex` trait.
- `shutdown`: ordered cancellation, service handles, and termination reporting.
The pacemaker quiesces execution and terminally syncs the ledger before the
sequencer and appender tier; remaining backing services stop afterward.
Dropping the manager cancels every tier without waiting for services to stop.
- `notifier`: the one-shot, non-resetting `EventNotifier` latch.
- `ledger`: shared block-boundary metadata, including each block's locally
computed hash and parent, plus snapshot checksum/transaction seals and
blockstore positions.
- `metrics`: Prometheus metric construction, `engine_`-namespaced registration,
labels, and timers.
- `service`: the `metrics` and `shutdown` feature bundle.
- `runtime`: transaction views, execution messages, sequencer handles, and the
quiescence barrier; it also enables `ledger`, `service`, and `tls`.
- `tls`: thread-local MagicRoot authority and encoded service-message state.
- `testkit`: engine-independent fixtures, temporary directories, Legacy/V0/V1
transaction encoding, v42 instructions, transaction views, and tracing setup
used by downstream test targets. It enables `runtime` because `signed_view`
returns the runtime transaction view.

Keeper-specific harnesses remain in `keeper::testkit`.
92 changes: 92 additions & 0 deletions nucleus/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//! Shared engine configuration types.

use std::{num::NonZeroU64, path::PathBuf, sync::Arc, time::Duration};

use serde::{Deserialize, Serialize};
use solana_keypair::Keypair;
use solana_pubkey::Pubkey;
use solana_signer::Signer;

/// Local signing identity and optional authority override represented by a replica.
///
/// Serialization includes the complete local keypair as a base58 string.
/// Consumers must redact the `local` field before exposing serialized output.
#[derive(Clone, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct Authority {
/// Signer used for locally produced messages and transactions.
#[serde(with = "keypair")]
pub local: Arc<Keypair>,
/// Immediate upstream identity exposed as the engine authority when set.
#[serde(default, with = "serde_with::As::<Option<serde_with::DisplayFromStr>>")]
pub remote: Option<Pubkey>,
}

impl Authority {
/// Returns the remote authority when configured, otherwise the local identity.
pub fn pubkey(&self) -> Pubkey {
self.remote.unwrap_or(self.local.pubkey())
}
}

impl<K: Into<Arc<Keypair>>> From<K> for Authority {
fn from(local: K) -> Self {
let local = local.into();
Self { local, remote: None }
}
}

/// Account storage and recent-load cache parameters.
#[derive(Clone, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct AccountsDBParams {
/// Accounts database root directory.
pub directory: PathBuf,
/// Requested maximum number of resolved account pubkeys retained for
/// recency tracking and eviction notifications.
///
/// The cache uses at least 256 slots, rounds larger capacities up to a
/// power of two, and may evict earlier under bucket pressure.
pub lru_capacity: usize,
}

/// Block production timing used by the engine and keeper caches.
#[derive(Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct BlockstoreParams {
/// Expected wall-clock interval between produced slots.
pub blocktime: Duration,
/// Number of blocks included into each superblock.
pub superblock: NonZeroU64,
}

/// Ledger storage parameters.
#[derive(Clone, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct LedgerParams {
/// Ledger root directory.
pub directory: PathBuf,
/// Maximum used bytes allowed on the ledger filesystem before eviction runs.
pub size_limit: u64,
}

mod keypair {
use super::*;
use serde::{Deserializer, Serializer, de::Error as _};

pub(super) fn serialize<S: Serializer>(
keypair: &Arc<Keypair>,
serializer: S,
) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&keypair.to_base58_string())
}

pub(super) fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Arc<Keypair>, D::Error> {
let encoded = String::deserialize(deserializer)?;
Keypair::try_from_base58_string(&encoded)
.map(Arc::new)
.map_err(D::Error::custom)
}
}
37 changes: 37 additions & 0 deletions nucleus/src/heed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Shared heed index plumbing.

use ::heed::{Env, Result, RoTxn, RwTxn, WithTls};

/// Read-only transaction using heed thread-local storage.
pub type RoTxnTls<'e> = RoTxn<'e, WithTls>;
/// Optional write transaction used by batched updates.
pub type OptRwTxn<'t, 'e> = &'t mut Option<RwTxn<'e>>;
/// Optional read transaction used by batched reads.
pub type OptRoTxn<'t, 'e> = &'t mut Option<RoTxnTls<'e>>;

/// Common access for heed-backed indexes.
pub trait DatabaseIndex {
/// Returns the owning heed environment.
fn env(&self) -> &Env;

/// Flushes the index databases to durable storage.
fn flush(&self) -> Result<()> {
self.env().force_sync()
}
}

/// Uses the supplied write transaction or opens one against `env` on demand.
pub fn write_txn<'t, 'e>(env: &'e Env, txn: OptRwTxn<'t, 'e>) -> Result<&'t mut RwTxn<'e>> {
if let Some(txn) = txn {
return Ok(txn);
}
Ok(txn.insert(env.write_txn()?))
}

/// Uses the supplied read transaction or opens one against `env` on demand.
pub fn read_txn<'t, 'e>(env: &'e Env, txn: OptRoTxn<'t, 'e>) -> Result<&'t RoTxnTls<'e>> {
if let Some(txn) = txn {
return Ok(txn);
}
Ok(txn.insert(env.read_txn()?))
}
51 changes: 51 additions & 0 deletions nucleus/src/ledger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! Ledger block-boundary schema shared by storage-adjacent crates.

use solana_hash::Hash;
use wincode::{SchemaRead, SchemaWrite};

use crate::Slot;

/// File name of the archived accountsdb snapshot tarball inside a superblock directory.
pub const ACCOUNTSDB_SNAPSHOT_FILE: &str = "accountsdb.tar.zst";

/// A byte cursor into the ledger blockstore stream, used by the replication path
/// to mark how far a follower has consumed. Ordering is lexicographic over
/// `(superblock, offset)`, matching the on-disk append order across rotations.
#[derive(Clone, Copy, SchemaRead, SchemaWrite, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct BlockstorePosition {
/// Superblock whose blockstore file the offset indexes into.
pub superblock: u64,
/// Byte offset of the write cursor within that superblock's blockstore file.
pub offset: u64,
}

/// Block boundary entry stored after all transactions in the block.
#[derive(SchemaRead, SchemaWrite, Clone, Copy, Default, PartialEq, Eq, Debug)]
pub struct Block {
/// Slot that produced the block.
pub slot: Slot,
/// Block hash for `slot`.
pub hash: Hash,
/// Block timestamp in the producer's time base.
pub time: i64,
/// Hash of the preceding block.
pub parent: Hash,
}

impl Block {
/// Creates a block boundary whose hash-chain metadata is not yet known.
pub fn new(slot: Slot, time: i64) -> Self {
Self { slot, time, ..Default::default() }
}
}

/// Superblock boundary entry stored at the end of the blockstore stream.
#[derive(SchemaRead, SchemaWrite, Clone, Copy, Debug, PartialEq, Eq)]
pub struct SuperblockSeal {
/// Id of the superblock this seal closes.
pub id: u64,
/// Checksum of accountsdb at the moment the superblock was sealed.
pub checksum: u64,
/// Total committed transactions represented by the sealed accountsdb snapshot.
pub transactions: u64,
}
44 changes: 44 additions & 0 deletions nucleus/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#![doc = include_str!("../README.md")]

use std::time::{Duration, UNIX_EPOCH};

#[cfg(feature = "config")]
pub mod config;

#[cfg(feature = "heed")]
pub mod heed;

#[cfg(feature = "shutdown")]
pub mod shutdown;

#[cfg(feature = "notifier")]
pub mod notifier;

#[cfg(feature = "ledger")]
pub mod ledger;

#[cfg(feature = "metrics")]
pub mod metrics;

#[cfg(feature = "runtime")]
pub mod runtime;

#[cfg(feature = "testkit")]
pub mod testkit;

#[cfg(feature = "tls")]
pub mod tls;

/// Ledger slot number.
pub type Slot = u64;
/// One kibibyte in bytes.
pub const KB: usize = 1024;
/// One mebibyte in bytes.
pub const MB: usize = 1024 * KB;
/// One gibibyte in bytes.
pub const GB: usize = 1024 * MB;

/// Returns the duration since the Unix epoch, or zero if the clock predates it.
pub fn unix_time() -> Duration {
UNIX_EPOCH.elapsed().unwrap_or_default()
}
Loading