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
14 changes: 14 additions & 0 deletions clarity/src/vm/database/clarity_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub trait ClarityBackingStore {
/// used to implement time-shifted evaluation.
/// returns the previous block header hash on success
fn set_block_hash(&mut self, bhh: StacksBlockId) -> Result<StacksBlockId>;
fn get_block_hash(&self) -> StacksBlockId;

/// Is None if `block_height` >= the "currently" under construction Stacks block height.
fn get_block_at_height(&mut self, height: u32) -> Option<StacksBlockId>;
Expand Down Expand Up @@ -141,6 +142,15 @@ pub trait ClarityBackingStore {
}
}

pub trait ClarityBackingStoreTransaction: ClarityBackingStore {
fn rollback_block(self: Box<Self>);
fn rollback_unconfirmed(self: Box<Self>) -> Result<()>;
fn commit_to(self: Box<Self>, final_bhh: &StacksBlockId) -> Result<()>;
fn commit_unconfirmed(self: Box<Self>);
fn commit_mined_block(self: Box<Self>, will_move_to: &StacksBlockId) -> Result<()>;
fn seal(&mut self) -> TrieHash;
}

// TODO: Figure out where this belongs
pub fn make_contract_hash_key(contract: &QualifiedContractIdentifier) -> String {
format!("clarity-contract::{contract}")
Expand Down Expand Up @@ -202,6 +212,10 @@ impl ClarityBackingStore for NullBackingStore {
panic!("NullBackingStore can't set block hash")
}

fn get_block_hash(&self) -> StacksBlockId {
panic!("NullBackingStore can't get block hash")
}

fn get_data(&mut self, _key: &str) -> Result<Option<String>> {
panic!("NullBackingStore can't retrieve data")
}
Expand Down
4 changes: 3 additions & 1 deletion clarity/src/vm/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ pub use self::clarity_db::{
BurnStateDB, ClarityDatabase, HeadersDB, StoreType, NULL_BURN_STATE_DB, NULL_HEADER_DB,
STORE_CONTRACT_SRC_INTERFACE,
};
pub use self::clarity_store::{ClarityBackingStore, SpecialCaseHandler};
pub use self::clarity_store::{
ClarityBackingStore, ClarityBackingStoreTransaction, SpecialCaseHandler,
};
pub use self::key_value_wrapper::{RollbackWrapper, RollbackWrapperPersistedLog};
#[cfg(feature = "rusqlite")]
pub use self::sqlite::SqliteConnection;
Expand Down
4 changes: 4 additions & 0 deletions clarity/src/vm/database/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,10 @@ impl ClarityBackingStore for MemoryBackingStore {
Err(RuntimeErrorType::UnknownBlockHeaderHash(BlockHeaderHash(bhh.0)).into())
}

fn get_block_hash(&self) -> StacksBlockId {
panic!("MemoryBackingStore can't get block hash")
}

fn get_data(&mut self, key: &str) -> Result<Option<String>> {
SqliteConnection::get(self.get_side_store(), key)
}
Expand Down
4 changes: 4 additions & 0 deletions stackslib/src/clarity_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use std::path::PathBuf;
use std::{fs, io};

use clarity::vm::coverage::CoverageReporter;
use clarity::vm::database::ClarityBackingStoreTransaction;
use lazy_static::lazy_static;
use rand::Rng;
use rusqlite::{Connection, OpenFlags};
Expand Down Expand Up @@ -352,6 +353,7 @@ where
let (headers_return, result) = {
let marf_tx = marf_kv.begin(&from, &to);
let (headers_return, marf_return, result) = f(headers_db, marf_tx);
let marf_return: Box<dyn ClarityBackingStoreTransaction> = Box::new(marf_return);
marf_return
.commit_to(&to)
.expect("FATAL: failed to commit block");
Expand All @@ -374,6 +376,7 @@ where

let marf_tx = marf_kv.begin(&from, &to);
let (marf_return, result) = f(marf_tx);
let marf_return: Box<dyn ClarityBackingStoreTransaction> = Box::new(marf_return);
marf_return.rollback_block();
result
}
Expand All @@ -389,6 +392,7 @@ where

let marf_tx = marf_kv.begin(&from, &to);
let (marf_return, result) = f(marf_tx);
let marf_return: Box<dyn ClarityBackingStoreTransaction> = Box::new(marf_return);
marf_return.rollback_block();
result
}
Expand Down
50 changes: 26 additions & 24 deletions stackslib/src/clarity_vm/clarity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ pub use clarity::vm::clarity::{ClarityConnection, Error};
use clarity::vm::contexts::{AssetMap, OwnedEnvironment};
use clarity::vm::costs::{CostTracker, ExecutionCost, LimitedCostTracker};
use clarity::vm::database::{
BurnStateDB, ClarityBackingStore, ClarityDatabase, HeadersDB, RollbackWrapper,
RollbackWrapperPersistedLog, STXBalance, NULL_BURN_STATE_DB, NULL_HEADER_DB,
BurnStateDB, ClarityBackingStore, ClarityBackingStoreTransaction, ClarityDatabase, HeadersDB,
RollbackWrapper, RollbackWrapperPersistedLog, STXBalance, NULL_BURN_STATE_DB, NULL_HEADER_DB,
};
use clarity::vm::errors::Error as InterpreterError;
use clarity::vm::events::{STXEventType, STXMintEventData};
Expand All @@ -53,7 +53,7 @@ use crate::chainstate::stacks::{
Error as ChainstateError, StacksMicroblockHeader, StacksTransaction, TransactionPayload,
TransactionSmartContract, TransactionVersion,
};
use crate::clarity_vm::database::marf::{MarfedKV, ReadOnlyMarfStore, WritableMarfStore};
use crate::clarity_vm::database::marf::MarfedKV;
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};
use crate::util_lib::db::Error as DatabaseError;
Expand Down Expand Up @@ -101,15 +101,15 @@ pub struct ClarityInstance {
/// issuring event dispatches, before the Clarity database commits.
///
pub struct PreCommitClarityBlock<'a> {
datastore: WritableMarfStore<'a>,
datastore: Box<dyn ClarityBackingStoreTransaction + 'a>,
commit_to: StacksBlockId,
}

///
/// A high-level interface for Clarity VM interactions within a single block.
///
pub struct ClarityBlockConnection<'a, 'b> {
datastore: WritableMarfStore<'a>,
datastore: Box<dyn ClarityBackingStoreTransaction + 'a>,
header_db: &'b dyn HeadersDB,
burn_state_db: &'b dyn BurnStateDB,
cost_track: Option<LimitedCostTracker>,
Expand Down Expand Up @@ -160,7 +160,7 @@ impl<'a, 'b> ClarityTransactionConnection<'a, 'b> {
}

pub struct ClarityReadOnlyConnection<'a> {
datastore: ReadOnlyMarfStore<'a>,
datastore: Box<dyn ClarityBackingStore + 'a>,
header_db: &'a dyn HeadersDB,
burn_state_db: &'a dyn BurnStateDB,
epoch: StacksEpochId,
Expand Down Expand Up @@ -196,13 +196,13 @@ macro_rules! using {
impl ClarityBlockConnection<'_, '_> {
#[cfg(test)]
pub fn new_test_conn<'a, 'b>(
datastore: WritableMarfStore<'a>,
datastore: super::database::marf::WritableMarfStore<'a>,
header_db: &'b dyn HeadersDB,
burn_state_db: &'b dyn BurnStateDB,
epoch: StacksEpochId,
) -> ClarityBlockConnection<'a, 'b> {
ClarityBlockConnection {
datastore,
datastore: Box::new(datastore),
header_db,
burn_state_db,
cost_track: Some(LimitedCostTracker::new_free()),
Expand Down Expand Up @@ -251,7 +251,7 @@ impl ClarityBlockConnection<'_, '_> {
&mut self,
burn_state_db: &dyn BurnStateDB,
) -> Result<StacksEpochId, Error> {
let mut db = self.datastore.as_clarity_db(self.header_db, burn_state_db);
let mut db = ClarityDatabase::new(self.datastore.as_mut(), self.header_db, burn_state_db);
// NOTE: the begin/roll_back shouldn't be necessary with how this gets used in practice,
// but is put here defensively.
db.begin();
Expand Down Expand Up @@ -328,7 +328,7 @@ impl ClarityInstance {
};

ClarityBlockConnection {
datastore,
datastore: Box::new(datastore),
header_db,
burn_state_db,
cost_track,
Expand All @@ -352,7 +352,7 @@ impl ClarityInstance {
let cost_track = Some(LimitedCostTracker::new_free());

ClarityBlockConnection {
datastore,
datastore: Box::new(datastore),
header_db,
burn_state_db,
cost_track,
Expand All @@ -378,7 +378,7 @@ impl ClarityInstance {
let cost_track = Some(LimitedCostTracker::new_free());

let mut conn = ClarityBlockConnection {
datastore: writable,
datastore: Box::new(writable),
header_db,
burn_state_db,
cost_track,
Expand Down Expand Up @@ -477,7 +477,7 @@ impl ClarityInstance {
let cost_track = Some(LimitedCostTracker::new_free());

let mut conn = ClarityBlockConnection {
datastore: writable,
datastore: Box::new(writable),
header_db,
burn_state_db,
cost_track,
Expand Down Expand Up @@ -559,6 +559,7 @@ impl ClarityInstance {

pub fn drop_unconfirmed_state(&mut self, block: &StacksBlockId) -> Result<(), Error> {
let datastore = self.datastore.begin_unconfirmed(block);
let datastore: Box<dyn ClarityBackingStoreTransaction> = Box::new(datastore);
datastore.rollback_unconfirmed()?;
Ok(())
}
Expand Down Expand Up @@ -588,7 +589,7 @@ impl ClarityInstance {
};

ClarityBlockConnection {
datastore,
datastore: Box::new(datastore),
header_db,
burn_state_db,
cost_track,
Expand Down Expand Up @@ -628,7 +629,7 @@ impl ClarityInstance {
}?;

Ok(ClarityReadOnlyConnection {
datastore,
datastore: Box::new(datastore),
header_db,
burn_state_db,
epoch,
Expand Down Expand Up @@ -677,7 +678,8 @@ impl ClarityConnection for ClarityBlockConnection<'_, '_> {
where
F: FnOnce(ClarityDatabase) -> (R, ClarityDatabase),
{
let mut db = ClarityDatabase::new(&mut self.datastore, self.header_db, self.burn_state_db);
let mut db =
ClarityDatabase::new(self.datastore.as_mut(), self.header_db, self.burn_state_db);
db.begin();
let (result, mut db) = to_do(db);
db.roll_back()
Expand All @@ -689,7 +691,7 @@ impl ClarityConnection for ClarityBlockConnection<'_, '_> {
where
F: FnOnce(&mut AnalysisDatabase) -> R,
{
let mut db = AnalysisDatabase::new(&mut self.datastore);
let mut db = AnalysisDatabase::new(self.datastore.as_mut());
db.begin();
let result = to_do(&mut db);
db.roll_back()
Expand All @@ -708,9 +710,8 @@ impl ClarityConnection for ClarityReadOnlyConnection<'_> {
where
F: FnOnce(ClarityDatabase) -> (R, ClarityDatabase),
{
let mut db = self
.datastore
.as_clarity_db(self.header_db, self.burn_state_db);
let mut db =
ClarityDatabase::new(self.datastore.as_mut(), self.header_db, self.burn_state_db);
db.begin();
let (result, mut db) = to_do(db);
db.roll_back()
Expand All @@ -722,7 +723,7 @@ impl ClarityConnection for ClarityReadOnlyConnection<'_> {
where
F: FnOnce(&mut AnalysisDatabase) -> R,
{
let mut db = self.datastore.as_analysis_db();
let mut db = AnalysisDatabase::new(self.datastore.as_mut());
db.begin();
let result = to_do(&mut db);
db.roll_back()
Expand Down Expand Up @@ -773,7 +774,8 @@ impl<'a> ClarityBlockConnection<'a, '_> {
#[cfg(test)]
pub fn commit_block(self) -> LimitedCostTracker {
debug!("Commit Clarity datastore");
self.datastore.test_commit();
let bhh = self.datastore.get_block_hash();
self.datastore.commit_to(&bhh).unwrap();

self.cost_track.unwrap()
}
Expand Down Expand Up @@ -1709,7 +1711,7 @@ impl<'a> ClarityBlockConnection<'a, '_> {

pub fn start_transaction_processing(&mut self) -> ClarityTransactionConnection<'_, '_> {
ClarityTransactionConnection::new(
&mut self.datastore,
self.datastore.as_mut(),
self.header_db,
self.burn_state_db,
&mut self.cost_track,
Expand Down Expand Up @@ -1761,7 +1763,7 @@ impl<'a> ClarityBlockConnection<'a, '_> {
self.datastore.seal()
}

pub fn destruct(self) -> WritableMarfStore<'a> {
pub fn destruct(self) -> Box<dyn ClarityBackingStoreTransaction + 'a> {
self.datastore
}

Expand Down
Loading