Skip to content

Commit 2cdf090

Browse files
committed
chore: provide access to MARF'ed data via MARF::get_by_hash and ClarityBackingStore::get_data_from_path
1 parent 14535c4 commit 2cdf090

File tree

6 files changed

+120
-3
lines changed

6 files changed

+120
-3
lines changed

clarity/src/vm/database/clarity_db.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use stacks_common::types::chainstate::{
2626
VRFSeed,
2727
};
2828
use stacks_common::types::{Address, StacksEpoch as GenericStacksEpoch, StacksEpochId};
29+
use stacks_common::types::chainstate::TrieHash;
2930
use stacks_common::util::hash::{to_hex, Hash160, Sha256Sum, Sha512Trunc256Sum};
3031

3132
use super::clarity_store::SpecialCaseHandler;
@@ -464,6 +465,13 @@ impl<'a> ClarityDatabase<'a> {
464465
{
465466
self.store.get_data::<T>(key)
466467
}
468+
469+
pub fn get_data_by_hash<T>(&mut self, hash: &TrieHash) -> Result<Option<T>>
470+
where
471+
T: ClarityDeserializable<T>,
472+
{
473+
self.store.get_data_by_hash::<T>(hash)
474+
}
467475

468476
pub fn put_value(&mut self, key: &str, value: Value, epoch: &StacksEpochId) -> Result<()> {
469477
self.put_value_with_size(key, value, epoch)?;
@@ -521,6 +529,13 @@ impl<'a> ClarityDatabase<'a> {
521529
{
522530
self.store.get_data_with_proof(key)
523531
}
532+
533+
pub fn get_data_with_proof_by_hash<T>(&mut self, hash: &TrieHash) -> Result<Option<(T, Vec<u8>)>>
534+
where
535+
T: ClarityDeserializable<T>,
536+
{
537+
self.store.get_data_with_proof_by_hash(hash)
538+
}
524539

525540
pub fn make_key_for_trip(
526541
contract_identifier: &QualifiedContractIdentifier,

clarity/src/vm/database/clarity_store.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ pub trait ClarityBackingStore {
6464
fn put_all_data(&mut self, items: Vec<(String, String)>) -> Result<()>;
6565
/// fetch K-V out of the committed datastore
6666
fn get_data(&mut self, key: &str) -> Result<Option<String>>;
67+
/// fetch Hash(K)-V out of the commmitted datastore
68+
fn get_data_from_path(&mut self, hash: &TrieHash) -> Result<Option<String>>;
6769
/// fetch K-V out of the committed datastore, along with the byte representation
6870
/// of the Merkle proof for that key-value pair
6971
fn get_data_with_proof(&mut self, key: &str) -> Result<Option<(String, Vec<u8>)>>;
@@ -212,6 +214,10 @@ impl ClarityBackingStore for NullBackingStore {
212214
fn get_data(&mut self, _key: &str) -> Result<Option<String>> {
213215
panic!("NullBackingStore can't retrieve data")
214216
}
217+
218+
fn get_data_from_path(&mut self, _hash: &TrieHash) -> Result<Option<String>> {
219+
panic!("NullBackingStore can't retrieve data")
220+
}
215221

216222
fn get_data_with_proof(&mut self, _key: &str) -> Result<Option<(String, Vec<u8>)>> {
217223
panic!("NullBackingStore can't retrieve data")

clarity/src/vm/database/key_value_wrapper.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::hash::Hash;
1818

1919
use hashbrown::HashMap;
2020
use stacks_common::types::chainstate::StacksBlockId;
21+
use stacks_common::types::chainstate::TrieHash;
2122
use stacks_common::types::StacksEpochId;
2223
use stacks_common::util::hash::Sha512Trunc256Sum;
2324

@@ -368,6 +369,18 @@ impl<'a> RollbackWrapper<'a> {
368369
.map(|(value, proof)| Ok((T::deserialize(&value)?, proof)))
369370
.transpose()
370371
}
372+
373+
/// this function will only return commitment proofs for values _already_ materialized
374+
/// in the underlying store. otherwise it returns None.
375+
pub fn get_data_with_proof_by_hash<T>(&mut self, hash: &TrieHash) -> InterpreterResult<Option<(T, Vec<u8>)>>
376+
where
377+
T: ClarityDeserializable<T>,
378+
{
379+
self.store
380+
.get_data_with_proof_from_path(hash)?
381+
.map(|(value, proof)| Ok((T::deserialize(&value)?, proof)))
382+
.transpose()
383+
}
371384

372385
pub fn get_data<T>(&mut self, key: &str) -> InterpreterResult<Option<T>>
373386
where
@@ -391,6 +404,23 @@ impl<'a> RollbackWrapper<'a> {
391404
.map(|x| T::deserialize(&x))
392405
.transpose()
393406
}
407+
408+
/// DO NOT USE IN CONSENSUS CODE.
409+
///
410+
/// Load data directly from the underlying store, given its trie hash. The lookup map will not
411+
/// be used.
412+
///
413+
/// This should never be called from within the Clarity VM, or via block-processing. It's only
414+
/// meant to be used by the RPC system.
415+
pub fn get_data_by_hash<T>(&mut self, hash: &TrieHash) -> InterpreterResult<Option<T>>
416+
where
417+
T: ClarityDeserializable<T>,
418+
{
419+
self.store
420+
.get_data_from_path(hash)?
421+
.map(|x| T::deserialize(&x))
422+
.transpose()
423+
}
394424

395425
pub fn deserialize_value(
396426
value_hex: &str,

clarity/src/vm/database/sqlite.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,10 @@ impl ClarityBackingStore for MemoryBackingStore {
324324
SqliteConnection::get(self.get_side_store(), key)
325325
}
326326

327+
fn get_data_from_path(&mut self, hash: &TrieHash) -> Result<Option<String>> {
328+
SqliteConnection::get(self.get_side_store(), hash.to_string().as_str())
329+
}
330+
327331
fn get_data_with_proof(&mut self, key: &str) -> Result<Option<(String, Vec<u8>)>> {
328332
Ok(SqliteConnection::get(self.get_side_store(), key)?.map(|x| (x, vec![])))
329333
}

stackslib/src/clarity_vm/database/marf.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use stacks_common::codec::StacksMessageCodec;
2020
use stacks_common::types::chainstate::{BlockHeaderHash, StacksBlockId, TrieHash};
2121

2222
use crate::chainstate::stacks::index::marf::{MARFOpenOpts, MarfConnection, MarfTransaction, MARF};
23-
use crate::chainstate::stacks::index::node::TriePath;
2423
use crate::chainstate::stacks::index::{
2524
ClarityMarfTrieId, Error, MARFValue, MarfTrieId, TrieMerkleProof,
2625
};
@@ -477,6 +476,36 @@ impl<'a> ClarityBackingStore for ReadOnlyMarfStore<'a> {
477476
})
478477
.transpose()
479478
}
479+
480+
fn get_data_from_path(&mut self, hash: &TrieHash) -> InterpreterResult<Option<String>> {
481+
trace!("MarfedKV get_from_hash: {:?} tip={}", hash, &self.chain_tip);
482+
self.marf
483+
.get_from_hash(&self.chain_tip, hash)
484+
.or_else(|e| match e {
485+
Error::NotFoundError => {
486+
trace!(
487+
"MarfedKV get {:?} off of {:?}: not found",
488+
hash,
489+
&self.chain_tip
490+
);
491+
Ok(None)
492+
}
493+
_ => Err(e),
494+
})
495+
.map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))?
496+
.map(|marf_value| {
497+
let side_key = marf_value.to_hex();
498+
trace!("MarfedKV get side-key for {:?}: {:?}", hash, &side_key);
499+
SqliteConnection::get(self.get_side_store(), &side_key)?.ok_or_else(|| {
500+
InterpreterError::Expect(format!(
501+
"ERROR: MARF contained value_hash not found in side storage: {}",
502+
side_key
503+
))
504+
.into()
505+
})
506+
})
507+
.transpose()
508+
}
480509

481510
fn put_all_data(&mut self, _items: Vec<(String, String)>) -> InterpreterResult<()> {
482511
error!("Attempted to commit changes to read-only MARF");
@@ -656,6 +685,36 @@ impl<'a> ClarityBackingStore for WritableMarfStore<'a> {
656685
})
657686
.transpose()
658687
}
688+
689+
fn get_data_from_path(&mut self, hash: &TrieHash) -> InterpreterResult<Option<String>> {
690+
trace!("MarfedKV get_from_hash: {:?} tip={}", hash, &self.chain_tip);
691+
self.marf
692+
.get_from_hash(&self.chain_tip, hash)
693+
.or_else(|e| match e {
694+
Error::NotFoundError => {
695+
trace!(
696+
"MarfedKV get {:?} off of {:?}: not found",
697+
hash,
698+
&self.chain_tip
699+
);
700+
Ok(None)
701+
}
702+
_ => Err(e),
703+
})
704+
.map_err(|_| InterpreterError::Expect("ERROR: Unexpected MARF Failure on GET".into()))?
705+
.map(|marf_value| {
706+
let side_key = marf_value.to_hex();
707+
trace!("MarfedKV get side-key for {:?}: {:?}", hash, &side_key);
708+
SqliteConnection::get(self.marf.sqlite_tx(), &side_key)?.ok_or_else(|| {
709+
InterpreterError::Expect(format!(
710+
"ERROR: MARF contained value_hash not found in side storage: {}",
711+
side_key
712+
))
713+
.into()
714+
})
715+
})
716+
.transpose()
717+
}
659718

660719
fn get_data_with_proof(&mut self, key: &str) -> InterpreterResult<Option<(String, Vec<u8>)>> {
661720
self.marf

stackslib/src/clarity_vm/database/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,10 @@ impl ClarityBackingStore for MemoryBackingStore {
12321232
fn get_data(&mut self, key: &str) -> InterpreterResult<Option<String>> {
12331233
SqliteConnection::get(self.get_side_store(), key)
12341234
}
1235+
1236+
fn get_data_from_path(&mut self, hash: &TrieHash) -> InterpreterResult<Option<String>> {
1237+
SqliteConnection::get(self.get_side_store(), hash.to_string().as_str())
1238+
}
12351239

12361240
fn get_data_with_proof(&mut self, key: &str) -> InterpreterResult<Option<(String, Vec<u8>)>> {
12371241
Ok(SqliteConnection::get(self.get_side_store(), key)?.map(|x| (x, vec![])))
@@ -1241,8 +1245,7 @@ impl ClarityBackingStore for MemoryBackingStore {
12411245
&mut self,
12421246
key: &TrieHash,
12431247
) -> InterpreterResult<Option<(String, Vec<u8>)>> {
1244-
// Ok(SqliteConnection::get(self.get_side_store(), )?.map(|x| (x, vec![])))
1245-
Ok(SqliteConnection::get(self.get_side_store(), key)?.map(|x| (x, vec![])))
1248+
Ok(SqliteConnection::get(self.get_side_store(), key.to_string().as_str())?.map(|x| (x, vec![])))
12461249
}
12471250

12481251
fn get_side_store(&mut self) -> &Connection {

0 commit comments

Comments
 (0)