Skip to content

Commit 0431376

Browse files
authored
Merge pull request #5509 from stacks-network/clarity-wasm-merge-develop
Merge develop onto clarity wasm
2 parents 939c650 + dea78d2 commit 0431376

File tree

176 files changed

+18610
-7563
lines changed

Some content is hidden

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

176 files changed

+18610
-7563
lines changed

.github/actions/dockerfiles/Dockerfile.debian-source

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ RUN --mount=type=tmpfs,target=${BUILD_DIR} cp -R /src/. ${BUILD_DIR}/ \
2424
&& cp -R ${BUILD_DIR}/target/${TARGET}/release/. /out
2525

2626
FROM --platform=${TARGETPLATFORM} debian:bookworm
27-
COPY --from=build /out/stacks-node /out/stacks-signer /bin/
27+
COPY --from=build /out/stacks-node /out/stacks-signer /out/stacks-inspect /bin/
2828
CMD ["stacks-node", "mainnet"]

.github/workflows/bitcoin-tests.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ jobs:
9999
- tests::signer::v0::forked_tenure_okay
100100
- tests::signer::v0::forked_tenure_invalid
101101
- tests::signer::v0::empty_sortition
102+
- tests::signer::v0::empty_sortition_before_approval
103+
- tests::signer::v0::empty_sortition_before_proposal
102104
- tests::signer::v0::bitcoind_forking_test
103105
- tests::signer::v0::multiple_miners
104106
- tests::signer::v0::mock_sign_epoch_25
@@ -112,6 +114,7 @@ jobs:
112114
- tests::signer::v0::locally_accepted_blocks_overriden_by_global_rejection
113115
- tests::signer::v0::locally_rejected_blocks_overriden_by_global_acceptance
114116
- tests::signer::v0::reorg_locally_accepted_blocks_across_tenures_succeeds
117+
- tests::signer::v0::reorg_locally_accepted_blocks_across_tenures_fails
115118
- tests::signer::v0::miner_recovers_when_broadcast_block_delay_across_tenures_occurs
116119
- tests::signer::v0::multiple_miners_with_nakamoto_blocks
117120
- tests::signer::v0::partial_tenure_fork
@@ -120,6 +123,10 @@ jobs:
120123
- tests::signer::v0::signing_in_0th_tenure_of_reward_cycle
121124
- tests::signer::v0::continue_after_tenure_extend
122125
- tests::signer::v0::multiple_miners_with_custom_chain_id
126+
- tests::signer::v0::block_commit_delay
127+
- tests::signer::v0::continue_after_fast_block_no_sortition
128+
- tests::signer::v0::block_validation_response_timeout
129+
- tests::signer::v0::tenure_extend_after_bad_commit
123130
- tests::nakamoto_integrations::burn_ops_integration_test
124131
- tests::nakamoto_integrations::check_block_heights
125132
- tests::nakamoto_integrations::clarity_burn_state
@@ -133,6 +140,10 @@ jobs:
133140
- tests::nakamoto_integrations::utxo_check_on_startup_panic
134141
- tests::nakamoto_integrations::utxo_check_on_startup_recover
135142
- tests::nakamoto_integrations::v3_signer_api_endpoint
143+
- tests::nakamoto_integrations::test_shadow_recovery
144+
- tests::nakamoto_integrations::signer_chainstate
145+
- tests::nakamoto_integrations::clarity_cost_spend_down
146+
- tests::nakamoto_integrations::v3_blockbyheight_api_endpoint
136147
# TODO: enable these once v1 signer is supported by a new nakamoto epoch
137148
# - tests::signer::v1::dkg
138149
# - tests::signer::v1::sign_request_rejected

.github/workflows/p2p-tests.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ jobs:
4242
- net::tests::convergence::test_walk_star_15_pingback
4343
- net::tests::convergence::test_walk_star_15_org_biased
4444
- net::tests::convergence::test_walk_inbound_line_15
45+
- net::api::tests::postblock_proposal::test_try_make_response
46+
- net::server::tests::test_http_10_threads_getinfo
47+
- net::server::tests::test_http_10_threads_getblock
48+
- net::server::tests::test_http_too_many_clients
49+
- net::server::tests::test_http_slow_client
4550
steps:
4651
## Setup test environment
4752
- name: Setup Test Environment

CHANGELOG.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,48 @@ 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+
19+
### Changed
20+
- Add index for StacksBlockId to nakamoto block headers table (improves node performance)
21+
- Remove the panic for reporting DB deadlocks (just error and continue waiting)
22+
- Add index to `metadata_table` in Clarity DB on `blockhash`
23+
- Add `block_commit_delay_ms` to the config file to control the time to wait after seeing a new burn block, before submitting a block commit, to allow time for the first Nakamoto block of the new tenure to be mined, allowing this miner to avoid the need to RBF the block commit.
24+
- Add `tenure_cost_limit_per_block_percentage` to the miner config file to control the percentage remaining tenure cost limit to consume per nakamoto block.
25+
- Add `/v3/blocks/height/:block_height` rpc endpoint
26+
- 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)
27+
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+
37+
## [3.0.0.0.1]
38+
39+
### Changed
40+
- Add index for StacksBlockId to nakamoto block headers table (improves node performance)
41+
- Remove the panic for reporting DB deadlocks (just error and continue waiting)
42+
- Various test fixes for CI (5353, 5368, 5372, 5371, 5380, 5378, 5387, 5396, 5390, 5394)
43+
- Various log fixes:
44+
- don't say proceeding to mine blocks if not a miner
45+
- misc. warns downgraded to debugs
46+
- 5391: Update default block proposal timeout to 10 minutes
47+
- 5406: After block rejection, miner pauses
48+
- Docs fixes
49+
- Fix signer docs link
50+
- Specify burn block in clarity docs
51+
1052
## [3.0.0.0.0]
1153

1254
### Added

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ rand = "0.8"
2222
rand_chacha = "0.3.1"
2323
tikv-jemallocator = "0.5.4"
2424
rusqlite = { version = "0.31.0", features = ["blob", "serde_json", "i128_blob", "bundled", "trace"] }
25+
thiserror = { version = "1.0.65" }
2526

2627
# Use a bit more than default optimization for
2728
# dev builds to speed up test execution

clarity/src/vm/costs/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,7 @@ impl LimitedCostTracker {
904904
Self::Free => ExecutionCost::max_value(),
905905
}
906906
}
907+
907908
pub fn get_memory(&self) -> u64 {
908909
match self {
909910
Self::Limited(TrackerData { memory, .. }) => *memory,
@@ -1178,6 +1179,7 @@ pub trait CostOverflowingMath<T> {
11781179
fn cost_overflow_mul(self, other: T) -> Result<T>;
11791180
fn cost_overflow_add(self, other: T) -> Result<T>;
11801181
fn cost_overflow_sub(self, other: T) -> Result<T>;
1182+
fn cost_overflow_div(self, other: T) -> Result<T>;
11811183
}
11821184

11831185
impl CostOverflowingMath<u64> for u64 {
@@ -1193,6 +1195,10 @@ impl CostOverflowingMath<u64> for u64 {
11931195
self.checked_sub(other)
11941196
.ok_or_else(|| CostErrors::CostOverflow)
11951197
}
1198+
fn cost_overflow_div(self, other: u64) -> Result<u64> {
1199+
self.checked_div(other)
1200+
.ok_or_else(|| CostErrors::CostOverflow)
1201+
}
11961202
}
11971203

11981204
impl ExecutionCost {
@@ -1301,6 +1307,15 @@ impl ExecutionCost {
13011307
Ok(())
13021308
}
13031309

1310+
pub fn divide(&mut self, divisor: u64) -> Result<()> {
1311+
self.runtime = self.runtime.cost_overflow_div(divisor)?;
1312+
self.read_count = self.read_count.cost_overflow_div(divisor)?;
1313+
self.read_length = self.read_length.cost_overflow_div(divisor)?;
1314+
self.write_length = self.write_length.cost_overflow_div(divisor)?;
1315+
self.write_count = self.write_count.cost_overflow_div(divisor)?;
1316+
Ok(())
1317+
}
1318+
13041319
/// Returns whether or not this cost exceeds any dimension of the
13051320
/// other cost.
13061321
pub fn exceeds(&self, other: &ExecutionCost) -> bool {

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."

0 commit comments

Comments
 (0)