Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4349d1e
feat: add support for producing ephemeral blocks
jcnelson Aug 11, 2025
708d279
feat: add support for beginning ephemeral blocks
jcnelson Aug 11, 2025
7b0e79c
chore: API sync
jcnelson Aug 11, 2025
4fd470d
feat: support for instantiating a ClarityTx for an ephemeral block
jcnelson Aug 11, 2025
2f629b8
chore: public function to get the sqlite db path
jcnelson Aug 11, 2025
909e976
feat: new function for instantiating an ephemeral ClarityBlockConnection
jcnelson Aug 11, 2025
fa631ea
feat: redefine WritableMarfStore as an enum of a persistent MARF stor…
jcnelson Aug 11, 2025
60e1725
chore: WIP unit test coverage for ephemeral MARF store
jcnelson Aug 11, 2025
8be1135
fix: correct ephemeral open-tip height
moodmosaic Aug 11, 2025
1eb29af
Merge pull request #1 from moodmosaic/test/shadow-marf
jcnelson Aug 12, 2025
7f6b723
chore: cargo fmt
jcnelson Aug 14, 2025
a07469a
Merge remote-tracking branch 'stacks-network/develop' into feat/shado…
jcnelson Aug 14, 2025
da5f19c
Merge remote-tracking branch 'origin' into feat/shadow-marf
jcnelson Aug 21, 2025
e42ee4c
fix: revert debug verbosity and fix off-by-one error for getting a bl…
jcnelson Aug 21, 2025
22c0196
feat: add test with Nakamoto block replay
jcnelson Aug 21, 2025
b124fd4
feat: if a transaction has an unexpected vm_error, report it when pan…
jcnelson Aug 21, 2025
ae90917
Merge branch 'develop' into feat/shadow-marf
jcnelson Aug 21, 2025
2665922
Merge remote-tracking branch 'origin/develop' into feat/shadow-marf
jcnelson Aug 27, 2025
c6b8d92
feat: add ClarityMarfStore and ClarityMarfStoreTransaction traits, wh…
jcnelson Aug 29, 2025
c84a016
Merge branch 'feat/shadow-marf' of https://github.com/jcnelson/stacks…
jcnelson Aug 29, 2025
5e3df0b
Merge branch 'develop' into feat/shadow-marf
jcnelson Aug 29, 2025
93e8935
clippy: don't hide elided lifetime
jcnelson Aug 29, 2025
4d2ea3f
Merge branch 'feat/shadow-marf' of https://github.com/jcnelson/stacks…
jcnelson Aug 29, 2025
f022a87
Merge branch 'develop' into feat/shadow-marf
jcnelson Sep 4, 2025
1a85e83
Merge branch 'develop' into feat/shadow-marf
jcnelson Sep 5, 2025
87874ca
Merge remote-tracking branch 'stacks-network/develop' into feat/shado…
jcnelson Sep 11, 2025
1e8730d
Merge remote-tracking branch 'stacks-network/develop' into HEAD, and …
jcnelson Sep 11, 2025
c95eb4e
chore: remove remaining superfish and address compiler error
jcnelson Sep 11, 2025
4555d7d
Merge branch 'develop' into feat/shadow-marf
jcnelson Sep 11, 2025
4ef13fc
Merge branch 'develop' into feat/shadow-marf
jcnelson Sep 12, 2025
be799cc
Update stackslib/src/clarity_vm/database/ephemeral.rs
jcnelson Sep 16, 2025
344b869
Update stackslib/src/clarity_vm/database/marf.rs
jcnelson Sep 16, 2025
ffaf9e5
chore: address PR feedback
jcnelson Sep 16, 2025
4620135
Merge remote-tracking branch 'stacks-network/develop' into feat/shado…
jcnelson Sep 16, 2025
fba48a0
Merge branch 'develop' into feat/shadow-marf
jcnelson Sep 16, 2025
19c4b0e
Merge remote-tracking branch 'stacks-network/develop' into feat/shado…
jcnelson Sep 17, 2025
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
12 changes: 6 additions & 6 deletions stackslib/src/chainstate/nakamoto/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,10 @@ impl NakamotoBlockBuilder {
burn_dbconn,
burn_dbconn.context.first_block_height,
&burn_dbconn.context.pox_constants,
info.parent_consensus_hash,
info.parent_header_hash,
&info.parent_consensus_hash,
&info.parent_header_hash,
info.parent_burn_block_height,
info.burn_tip,
&info.burn_tip,
info.burn_tip_height,
info.cause == Some(TenureChangeCause::BlockFound),
info.coinbase_height,
Expand All @@ -444,10 +444,10 @@ impl NakamotoBlockBuilder {
burn_dbconn,
burn_dbconn.context.first_block_height,
&burn_dbconn.context.pox_constants,
info.parent_consensus_hash,
info.parent_header_hash,
&info.parent_consensus_hash,
&info.parent_header_hash,
info.parent_burn_block_height,
info.burn_tip,
&info.burn_tip,
info.burn_tip_height,
info.cause == Some(TenureChangeCause::BlockFound),
info.coinbase_height,
Expand Down
6 changes: 3 additions & 3 deletions stackslib/src/chainstate/nakamoto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3830,10 +3830,10 @@ impl NakamotoChainState {
sortition_dbconn: &'b dyn SortitionDBRef,
first_block_height: u64,
pox_constants: &PoxConstants,
parent_consensus_hash: ConsensusHash,
parent_header_hash: BlockHeaderHash,
parent_consensus_hash: &ConsensusHash,
parent_header_hash: &BlockHeaderHash,
parent_burn_height: u32,
burn_header_hash: BurnchainHeaderHash,
burn_header_hash: &BurnchainHeaderHash,
burn_header_height: u32,
new_tenure: bool,
coinbase_height: u64,
Expand Down
7 changes: 4 additions & 3 deletions stackslib/src/chainstate/stacks/boot/contract_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ use crate::chainstate::stacks::boot::{
};
use crate::chainstate::stacks::index::ClarityMarfTrieId;
use crate::chainstate::stacks::{C32_ADDRESS_VERSION_TESTNET_SINGLESIG, *};
use crate::clarity_vm::clarity::{ClarityBlockConnection, Error as ClarityError};
use crate::clarity_vm::database::marf::{
ClarityMarfStore, ClarityMarfStoreTransaction, MarfedKV, WritableMarfStore,
use crate::clarity_vm::clarity::{
ClarityBlockConnection, ClarityMarfStore, ClarityMarfStoreTransaction, Error as ClarityError,
WritableMarfStore,
};
use crate::clarity_vm::database::marf::MarfedKV;
use crate::core::{
StacksEpoch, StacksEpochId, BITCOIN_REGTEST_FIRST_BLOCK_HASH,
BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT, BITCOIN_REGTEST_FIRST_BLOCK_TIMESTAMP,
Expand Down
5 changes: 2 additions & 3 deletions stackslib/src/clarity_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@ use crate::clarity::vm::{
analysis, ast, eval_all, ClarityVersion, ContractContext, ContractName, SymbolicExpression,
Value,
};
use crate::clarity_vm::database::marf::{
ClarityMarfStore, ClarityMarfStoreTransaction, MarfedKV, PersistentWritableMarfStore,
};
use crate::clarity_vm::clarity::{ClarityMarfStore, ClarityMarfStoreTransaction};
use crate::clarity_vm::database::marf::{MarfedKV, PersistentWritableMarfStore};
use crate::clarity_vm::database::MemoryBackingStore;
use crate::core::{StacksEpochId, BLOCK_LIMIT_MAINNET_205, HELIUM_BLOCK_LIMIT_20};
use crate::util_lib::boot::{boot_code_addr, boot_code_id};
Expand Down
110 changes: 108 additions & 2 deletions stackslib/src/clarity_vm/clarity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use clarity::vm::database::{
BurnStateDB, ClarityBackingStore, ClarityDatabase, HeadersDB, RollbackWrapper,
RollbackWrapperPersistedLog, STXBalance, NULL_BURN_STATE_DB, NULL_HEADER_DB,
};
use clarity::vm::errors::Error as InterpreterError;
use clarity::vm::errors::{Error as InterpreterError, InterpreterResult};
use clarity::vm::events::{STXEventType, STXMintEventData};
use clarity::vm::representations::SymbolicExpression;
use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier, Value};
Expand All @@ -54,7 +54,7 @@ use crate::chainstate::stacks::{
TransactionSmartContract, TransactionVersion,
};
use crate::clarity_vm::database::marf::{
ClarityMarfStore, ClarityMarfStoreTransaction, MarfedKV, ReadOnlyMarfStore, WritableMarfStore,
BoxedClarityMarfStoreTransaction, MarfedKV, ReadOnlyMarfStore,
};
use crate::core::{StacksEpoch, StacksEpochId, FIRST_STACKS_BLOCK_ID, GENESIS_EPOCH};
use crate::util_lib::boot::{boot_code_acc, boot_code_addr, boot_code_id, boot_code_tx_auth};
Expand Down Expand Up @@ -136,6 +136,112 @@ pub struct ClarityTransactionConnection<'a, 'b> {
epoch: StacksEpochId,
}

/// Unified API common to all MARF stores
pub trait ClarityMarfStore: ClarityBackingStore {
/// Instantiate a `ClarityDatabase` out of this MARF store.
/// Takes a `HeadersDB` and `BurnStateDB` implementation which are both used by
/// `ClarityDatabase` to access Stacks's chainstate and sortition chainstate, respectively.
fn as_clarity_db<'b>(
&'b mut self,
headers_db: &'b dyn HeadersDB,
burn_state_db: &'b dyn BurnStateDB,
) -> ClarityDatabase<'b>
where
Self: Sized,
{
ClarityDatabase::new(self, headers_db, burn_state_db)
}

/// Instantiate an `AnalysisDatabase` out of this MARF store.
fn as_analysis_db(&mut self) -> AnalysisDatabase<'_>
where
Self: Sized,
{
AnalysisDatabase::new(self)
}
}

/// A MARF store which can be written to is both a ClarityMarfStore and a
/// ClarityMarfStoreTransaction (and thus also a ClarityBackingStore).
pub trait WritableMarfStore:
ClarityMarfStore + ClarityMarfStoreTransaction + BoxedClarityMarfStoreTransaction
{
}

/// A MARF store transaction for a chainstate block's trie.
/// This transaction instantiates a trie which builds atop an already-written trie in the
/// chainstate. Once committed, it will persist -- it may be built upon, and a subsequent attempt
/// to build the same trie will fail.
///
/// The Stacks node commits tries for one of three purposes:
/// * It processed a block, and needs to persist its trie in the chainstate proper.
/// * It mined a block, and needs to persist its trie outside of the chainstate proper. The miner
/// may build on it later.
/// * It processed an unconfirmed microblock (Stacks 2.x only), and needs to persist the
/// unconfirmed chainstate outside of the chainstate proper so that the microblock miner can
/// continue to build on it and the network can service RPC requests on its state.
///
/// These needs are each captured in distinct methods for committing this transaction.
pub trait ClarityMarfStoreTransaction {
/// Commit all inserted metadata and associate it with the block trie identified by `target`.
/// It can later be deleted via `drop_metadata_for()` if given the same taret.
/// Returns Ok(()) on success
/// Returns Err(..) on error
fn commit_metadata_for_trie(&mut self, target: &StacksBlockId) -> InterpreterResult<()>;

/// Drop metadata for a particular block trie that was stored previously via `commit_metadata_to()`.
/// This function is idempotent.
///
/// Returns Ok(()) if the metadata for the trie identified by `target` was dropped.
/// It will be possible to insert it again afterwards.
/// Returns Err(..) if the metadata was not successfully dropped.
fn drop_metadata_for_trie(&mut self, target: &StacksBlockId) -> InterpreterResult<()>;

/// Compute the ID of the trie being built.
/// In Stacks, this will only be called once all key/value pairs are inserted (and will only be
/// called at most once in this transaction's lifetime).
fn seal_trie(&mut self) -> TrieHash;

/// Drop the block trie that this transaction was creating.
/// Destroys the transaction.
fn drop_current_trie(self);

/// Drop the unconfirmed state trie that this transaction was creating.
/// Destroys the transaction.
///
/// Returns Ok(()) on successful deletion of the data
/// Returns Err(..) if the deletion failed (this usually isn't recoverable, but recovery is up
/// to the caller)
fn drop_unconfirmed(self) -> InterpreterResult<()>;

/// Store the processed block's trie that this transaction was creating.
/// The trie's ID must be `target`, so that subsequent tries can be built on it (and so that
/// subsequent queries can read from it). `target` may not be known until it is time to write
/// the trie out, which is why it is provided here.
///
/// Returns Ok(()) if the block trie was successfully persisted.
/// Returns Err(..) if there was an error in trying to persist this block trie.
fn commit_to_processed_block(self, target: &StacksBlockId) -> InterpreterResult<()>;

/// Store a mined block's trie that this transaction was creating.
/// This function is distinct from `commit_to_processed_block()` in that the stored block will
/// not be added to the chainstate. However, it must be persisted so that the node can later
/// build on it.
///
/// Returns Ok(()) if the block trie was successfully persisted.
/// Returns Err(..) if there was an error trying to persist this MARF trie.
fn commit_to_mined_block(self, target: &StacksBlockId) -> InterpreterResult<()>;

/// Persist the unconfirmed state trie so that other parts of the Stacks node can read from it
/// (such as to handle pending transactions or process RPC requests on it).
fn commit_unconfirmed(self);

/// Commit to the current chain tip.
/// Used only for testing.
#[cfg(test)]
fn test_commit(self);
}

impl<'a, 'b> ClarityTransactionConnection<'a, 'b> {
pub fn new(
store: &'b mut dyn ClarityBackingStore,
Expand Down
Loading