Skip to content

Commit e92fdb1

Browse files
committed
Merge branch 'develop' of https://github.com/stacks-network/stacks-core into bug/validation-queue-race-condition
2 parents d6bffcf + 7267cd0 commit e92fdb1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1963
-282
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
77

88
## [Unreleased]
99

10+
### Added
11+
12+
### Changed
13+
14+
15+
## [3.0.0.0.3]
16+
17+
### Added
18+
1019
### Changed
1120
- Add index for StacksBlockId to nakamoto block headers table (improves node performance)
1221
- Remove the panic for reporting DB deadlocks (just error and continue waiting)
@@ -16,6 +25,15 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
1625
- Add `/v3/blocks/height/:block_height` rpc endpoint
1726
- If the winning miner of a sortition is committed to the wrong parent tenure, the previous miner can immediately tenure extend and continue mining since the winning miner would never be able to propose a valid block. (#5361)
1827

28+
## [3.0.0.0.2]
29+
30+
### Added
31+
32+
### Changed
33+
- Fixes a few bugs in the relayer and networking stack
34+
- detects and deprioritizes unhealthy replicas
35+
- fixes an issue in the p2p stack which was preventing it from caching the reward set.
36+
1937
## [3.0.0.0.1]
2038

2139
### Changed

clarity/src/vm/database/clarity_db.rs

Lines changed: 120 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use stacks_common::consts::{
2323
};
2424
use stacks_common::types::chainstate::{
2525
BlockHeaderHash, BurnchainHeaderHash, ConsensusHash, SortitionId, StacksAddress, StacksBlockId,
26-
VRFSeed,
26+
TrieHash, VRFSeed,
2727
};
2828
use stacks_common::types::{Address, StacksEpoch as GenericStacksEpoch, StacksEpochId};
2929
use stacks_common::util::hash::{to_hex, Hash160, Sha256Sum, Sha512Trunc256Sum};
@@ -76,6 +76,68 @@ pub enum StoreType {
7676
PoxUnlockHeight = 0x15,
7777
}
7878

79+
impl TryFrom<&str> for StoreType {
80+
type Error = String;
81+
82+
fn try_from(value: &str) -> core::result::Result<Self, Self::Error> {
83+
use self::StoreType::*;
84+
85+
let hex_value = u8::from_str_radix(value, 10).map_err(|e| e.to_string())?;
86+
match hex_value {
87+
0x00 => Ok(DataMap),
88+
0x01 => Ok(Variable),
89+
0x02 => Ok(FungibleToken),
90+
0x03 => Ok(CirculatingSupply),
91+
0x04 => Ok(NonFungibleToken),
92+
0x05 => Ok(DataMapMeta),
93+
0x06 => Ok(VariableMeta),
94+
0x07 => Ok(FungibleTokenMeta),
95+
0x08 => Ok(NonFungibleTokenMeta),
96+
0x09 => Ok(Contract),
97+
0x10 => Ok(SimmedBlock),
98+
0x11 => Ok(SimmedBlockHeight),
99+
0x12 => Ok(Nonce),
100+
0x13 => Ok(STXBalance),
101+
0x14 => Ok(PoxSTXLockup),
102+
0x15 => Ok(PoxUnlockHeight),
103+
_ => Err("Invalid StoreType".into()),
104+
}
105+
}
106+
}
107+
108+
pub enum ContractDataVarName {
109+
Contract,
110+
ContractSize,
111+
ContractSrc,
112+
ContractDataSize,
113+
}
114+
115+
impl ContractDataVarName {
116+
pub fn as_str(&self) -> &str {
117+
match self {
118+
Self::Contract => "contract",
119+
Self::ContractSize => "contract-size",
120+
Self::ContractSrc => "contract-src",
121+
Self::ContractDataSize => "contract-data-size",
122+
}
123+
}
124+
}
125+
126+
impl TryFrom<&str> for ContractDataVarName {
127+
type Error = String;
128+
129+
fn try_from(value: &str) -> core::result::Result<Self, Self::Error> {
130+
use self::ContractDataVarName::*;
131+
match value {
132+
"contract" => Ok(Contract),
133+
"contract-size" => Ok(ContractSize),
134+
"contract-src" => Ok(ContractSrc),
135+
"contract-data-size" => Ok(ContractDataSize),
136+
_ => Err("Invalid ContractDataVarName".into()),
137+
}
138+
}
139+
}
140+
79141
pub struct ClarityDatabase<'a> {
80142
pub store: RollbackWrapper<'a>,
81143
headers_db: &'a dyn HeadersDB,
@@ -465,6 +527,13 @@ impl<'a> ClarityDatabase<'a> {
465527
self.store.get_data::<T>(key)
466528
}
467529

530+
pub fn get_data_by_hash<T>(&mut self, hash: &TrieHash) -> Result<Option<T>>
531+
where
532+
T: ClarityDeserializable<T>,
533+
{
534+
self.store.get_data_by_hash::<T>(hash)
535+
}
536+
468537
pub fn put_value(&mut self, key: &str, value: Value, epoch: &StacksEpochId) -> Result<()> {
469538
self.put_value_with_size(key, value, epoch)?;
470539
Ok(())
@@ -522,6 +591,16 @@ impl<'a> ClarityDatabase<'a> {
522591
self.store.get_data_with_proof(key)
523592
}
524593

594+
pub fn get_data_with_proof_by_hash<T>(
595+
&mut self,
596+
hash: &TrieHash,
597+
) -> Result<Option<(T, Vec<u8>)>>
598+
where
599+
T: ClarityDeserializable<T>,
600+
{
601+
self.store.get_data_with_proof_by_hash(hash)
602+
}
603+
525604
pub fn make_key_for_trip(
526605
contract_identifier: &QualifiedContractIdentifier,
527606
data: StoreType,
@@ -559,12 +638,18 @@ impl<'a> ClarityDatabase<'a> {
559638
self.store
560639
.prepare_for_contract_metadata(contract_identifier, hash)?;
561640
// insert contract-size
562-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract-size");
641+
let key = ClarityDatabase::make_metadata_key(
642+
StoreType::Contract,
643+
ContractDataVarName::ContractSize.as_str(),
644+
);
563645
self.insert_metadata(contract_identifier, &key, &(contract_content.len() as u64))?;
564646

565647
// insert contract-src
566648
if STORE_CONTRACT_SRC_INTERFACE {
567-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract-src");
649+
let key = ClarityDatabase::make_metadata_key(
650+
StoreType::Contract,
651+
ContractDataVarName::ContractSrc.as_str(),
652+
);
568653
self.insert_metadata(contract_identifier, &key, &contract_content.to_string())?;
569654
}
570655
Ok(())
@@ -574,7 +659,10 @@ impl<'a> ClarityDatabase<'a> {
574659
&mut self,
575660
contract_identifier: &QualifiedContractIdentifier,
576661
) -> Option<String> {
577-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract-src");
662+
let key = ClarityDatabase::make_metadata_key(
663+
StoreType::Contract,
664+
ContractDataVarName::ContractSrc.as_str(),
665+
);
578666
self.fetch_metadata(contract_identifier, &key)
579667
.ok()
580668
.flatten()
@@ -683,15 +771,21 @@ impl<'a> ClarityDatabase<'a> {
683771
&mut self,
684772
contract_identifier: &QualifiedContractIdentifier,
685773
) -> Result<u64> {
686-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract-size");
774+
let key = ClarityDatabase::make_metadata_key(
775+
StoreType::Contract,
776+
ContractDataVarName::ContractSize.as_str(),
777+
);
687778
let contract_size: u64 =
688779
self.fetch_metadata(contract_identifier, &key)?
689780
.ok_or_else(|| {
690781
InterpreterError::Expect(
691782
"Failed to read non-consensus contract metadata, even though contract exists in MARF."
692783
.into())
693784
})?;
694-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract-data-size");
785+
let key = ClarityDatabase::make_metadata_key(
786+
StoreType::Contract,
787+
ContractDataVarName::ContractDataSize.as_str(),
788+
);
695789
let data_size: u64 = self
696790
.fetch_metadata(contract_identifier, &key)?
697791
.ok_or_else(|| {
@@ -710,7 +804,10 @@ impl<'a> ClarityDatabase<'a> {
710804
contract_identifier: &QualifiedContractIdentifier,
711805
data_size: u64,
712806
) -> Result<()> {
713-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract-size");
807+
let key = ClarityDatabase::make_metadata_key(
808+
StoreType::Contract,
809+
ContractDataVarName::ContractSize.as_str(),
810+
);
714811
let contract_size: u64 =
715812
self.fetch_metadata(contract_identifier, &key)?
716813
.ok_or_else(|| {
@@ -720,7 +817,10 @@ impl<'a> ClarityDatabase<'a> {
720817
})?;
721818
contract_size.cost_overflow_add(data_size)?;
722819

723-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract-data-size");
820+
let key = ClarityDatabase::make_metadata_key(
821+
StoreType::Contract,
822+
ContractDataVarName::ContractDataSize.as_str(),
823+
);
724824
self.insert_metadata(contract_identifier, &key, &data_size)?;
725825
Ok(())
726826
}
@@ -730,21 +830,30 @@ impl<'a> ClarityDatabase<'a> {
730830
contract_identifier: &QualifiedContractIdentifier,
731831
contract: Contract,
732832
) -> Result<()> {
733-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract");
833+
let key = ClarityDatabase::make_metadata_key(
834+
StoreType::Contract,
835+
ContractDataVarName::Contract.as_str(),
836+
);
734837
self.insert_metadata(contract_identifier, &key, &contract)?;
735838
Ok(())
736839
}
737840

738841
pub fn has_contract(&mut self, contract_identifier: &QualifiedContractIdentifier) -> bool {
739-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract");
842+
let key = ClarityDatabase::make_metadata_key(
843+
StoreType::Contract,
844+
ContractDataVarName::Contract.as_str(),
845+
);
740846
self.store.has_metadata_entry(contract_identifier, &key)
741847
}
742848

743849
pub fn get_contract(
744850
&mut self,
745851
contract_identifier: &QualifiedContractIdentifier,
746852
) -> Result<Contract> {
747-
let key = ClarityDatabase::make_metadata_key(StoreType::Contract, "contract");
853+
let key = ClarityDatabase::make_metadata_key(
854+
StoreType::Contract,
855+
ContractDataVarName::Contract.as_str(),
856+
);
748857
let mut data: Contract = self.fetch_metadata(contract_identifier, &key)?
749858
.ok_or_else(|| InterpreterError::Expect(
750859
"Failed to read non-consensus contract metadata, even though contract exists in MARF."

clarity/src/vm/database/clarity_store.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::path::PathBuf;
1818

1919
#[cfg(feature = "canonical")]
2020
use rusqlite::Connection;
21-
use stacks_common::types::chainstate::{BlockHeaderHash, StacksBlockId, VRFSeed};
21+
use stacks_common::types::chainstate::{BlockHeaderHash, StacksBlockId, TrieHash, VRFSeed};
2222
use stacks_common::util::hash::{hex_bytes, to_hex, Hash160, Sha512Trunc256Sum};
2323

2424
use crate::vm::analysis::AnalysisDatabase;
@@ -64,9 +64,15 @@ 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>)>>;
72+
fn get_data_with_proof_from_path(
73+
&mut self,
74+
hash: &TrieHash,
75+
) -> Result<Option<(String, Vec<u8>)>>;
7076
fn has_entry(&mut self, key: &str) -> Result<bool> {
7177
Ok(self.get_data(key)?.is_some())
7278
}
@@ -209,10 +215,21 @@ impl ClarityBackingStore for NullBackingStore {
209215
panic!("NullBackingStore can't retrieve data")
210216
}
211217

218+
fn get_data_from_path(&mut self, _hash: &TrieHash) -> Result<Option<String>> {
219+
panic!("NullBackingStore can't retrieve data")
220+
}
221+
212222
fn get_data_with_proof(&mut self, _key: &str) -> Result<Option<(String, Vec<u8>)>> {
213223
panic!("NullBackingStore can't retrieve data")
214224
}
215225

226+
fn get_data_with_proof_from_path(
227+
&mut self,
228+
_hash: &TrieHash,
229+
) -> Result<Option<(String, Vec<u8>)>> {
230+
panic!("NullBackingStore can't retrieve data")
231+
}
232+
216233
#[cfg(feature = "canonical")]
217234
fn get_side_store(&mut self) -> &Connection {
218235
panic!("NullBackingStore has no side store")

clarity/src/vm/database/key_value_wrapper.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use std::hash::Hash;
1818

1919
use hashbrown::HashMap;
20-
use stacks_common::types::chainstate::StacksBlockId;
20+
use stacks_common::types::chainstate::{StacksBlockId, TrieHash};
2121
use stacks_common::types::StacksEpochId;
2222
use stacks_common::util::hash::Sha512Trunc256Sum;
2323

@@ -369,6 +369,21 @@ impl<'a> RollbackWrapper<'a> {
369369
.transpose()
370370
}
371371

372+
/// this function will only return commitment proofs for values _already_ materialized
373+
/// in the underlying store. otherwise it returns None.
374+
pub fn get_data_with_proof_by_hash<T>(
375+
&mut self,
376+
hash: &TrieHash,
377+
) -> InterpreterResult<Option<(T, Vec<u8>)>>
378+
where
379+
T: ClarityDeserializable<T>,
380+
{
381+
self.store
382+
.get_data_with_proof_from_path(hash)?
383+
.map(|(value, proof)| Ok((T::deserialize(&value)?, proof)))
384+
.transpose()
385+
}
386+
372387
pub fn get_data<T>(&mut self, key: &str) -> InterpreterResult<Option<T>>
373388
where
374389
T: ClarityDeserializable<T>,
@@ -392,6 +407,23 @@ impl<'a> RollbackWrapper<'a> {
392407
.transpose()
393408
}
394409

410+
/// DO NOT USE IN CONSENSUS CODE.
411+
///
412+
/// Load data directly from the underlying store, given its trie hash. The lookup map will not
413+
/// be used.
414+
///
415+
/// This should never be called from within the Clarity VM, or via block-processing. It's only
416+
/// meant to be used by the RPC system.
417+
pub fn get_data_by_hash<T>(&mut self, hash: &TrieHash) -> InterpreterResult<Option<T>>
418+
where
419+
T: ClarityDeserializable<T>,
420+
{
421+
self.store
422+
.get_data_from_path(hash)?
423+
.map(|x| T::deserialize(&x))
424+
.transpose()
425+
}
426+
395427
pub fn deserialize_value(
396428
value_hex: &str,
397429
expected: &TypeSignature,

clarity/src/vm/database/sqlite.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rusqlite::{
1919
params, Connection, Error as SqliteError, ErrorCode as SqliteErrorCode, OptionalExtension, Row,
2020
Savepoint,
2121
};
22-
use stacks_common::types::chainstate::{BlockHeaderHash, StacksBlockId};
22+
use stacks_common::types::chainstate::{BlockHeaderHash, StacksBlockId, TrieHash};
2323
use stacks_common::types::sqlite::NO_PARAMS;
2424
use stacks_common::util::db::tx_busy_handler;
2525
use stacks_common::util::hash::Sha512Trunc256Sum;
@@ -330,10 +330,21 @@ impl ClarityBackingStore for MemoryBackingStore {
330330
SqliteConnection::get(self.get_side_store(), key)
331331
}
332332

333+
fn get_data_from_path(&mut self, hash: &TrieHash) -> Result<Option<String>> {
334+
SqliteConnection::get(self.get_side_store(), hash.to_string().as_str())
335+
}
336+
333337
fn get_data_with_proof(&mut self, key: &str) -> Result<Option<(String, Vec<u8>)>> {
334338
Ok(SqliteConnection::get(self.get_side_store(), key)?.map(|x| (x, vec![])))
335339
}
336340

341+
fn get_data_with_proof_from_path(
342+
&mut self,
343+
hash: &TrieHash,
344+
) -> Result<Option<(String, Vec<u8>)>> {
345+
self.get_data_with_proof(&hash.to_string())
346+
}
347+
337348
fn get_side_store(&mut self) -> &Connection {
338349
&self.side_store
339350
}

0 commit comments

Comments
 (0)