Skip to content

PoX 2 Unlock #3260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Sep 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
7 changes: 3 additions & 4 deletions .github/actions/bitcoin-int-tests/Dockerfile.code-cov
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ WORKDIR /build

ENV CARGO_MANIFEST_DIR="$(pwd)"

RUN rustup override set nightly-2022-01-14 && \
rustup component add llvm-tools-preview && \
RUN rustup component add llvm-tools-preview && \
cargo install grcov

ENV RUSTFLAGS="-Zinstrument-coverage" \
ENV RUSTFLAGS="-Cinstrument-coverage" \
LLVM_PROFILE_FILE="stacks-blockchain-%p-%m.profraw"

COPY . .

RUN cargo build --workspace && \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ COPY . .

WORKDIR /src/testnet/stacks-node

RUN rustup override set nightly-2022-01-14 && \
rustup component add llvm-tools-preview && \
RUN rustup component add llvm-tools-preview && \
cargo install grcov

ENV RUSTFLAGS="-Zinstrument-coverage" \
ENV RUSTFLAGS="-Cinstrument-coverage" \
LLVM_PROFILE_FILE="stacks-blockchain-%p-%m.profraw"

RUN cargo test --no-run && \
Expand Down
5 changes: 2 additions & 3 deletions .github/actions/bitcoin-int-tests/Dockerfile.large-genesis
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ RUN cd / && tar -xvzf bitcoin-0.20.0-x86_64-linux-gnu.tar.gz

RUN ln -s /bitcoin-0.20.0/bin/bitcoind /bin/

RUN rustup override set nightly-2022-01-14 && \
rustup component add llvm-tools-preview && \
RUN rustup component add llvm-tools-preview && \
cargo install grcov

ENV RUSTFLAGS="-Zinstrument-coverage" \
ENV RUSTFLAGS="-Cinstrument-coverage" \
LLVM_PROFILE_FILE="stacks-blockchain-%p-%m.profraw"

RUN cargo test --no-run --workspace && \
Expand Down
8 changes: 8 additions & 0 deletions clarity/src/vm/clarity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ pub trait ClarityConnection {
}

pub trait TransactionConnection: ClarityConnection {
/// Do something with this connection's Clarity environment that can be aborted
/// with `abort_call_back`.
/// This returns the return value of `to_do`:
/// * the generic term `R`
/// * the asset changes during `to_do` in an `AssetMap`
/// * the Stacks events during the transaction
/// and a `bool` value which is `true` if the `abort_call_back` caused the changes to abort
/// If `to_do` returns an `Err` variant, then the changes are aborted.
fn with_abort_callback<F, A, R, E>(
&mut self,
to_do: F,
Expand Down
32 changes: 31 additions & 1 deletion clarity/src/vm/contexts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1061,11 +1061,41 @@ impl<'a, 'b> Environment<'a, 'b> {
}

pub fn execute_contract(
&mut self,
contract: &QualifiedContractIdentifier,
tx_name: &str,
args: &[SymbolicExpression],
read_only: bool,
) -> Result<Value> {
self.inner_execute_contract(contract, tx_name, args, read_only, false)
}

/// This method is exposed for callers that need to invoke a private method directly.
/// For example, this is used by the Stacks chainstate for invoking private methods
/// on the pox-2 contract. This should not be called by user transaction processing.
pub fn execute_contract_allow_private(
&mut self,
contract: &QualifiedContractIdentifier,
tx_name: &str,
args: &[SymbolicExpression],
read_only: bool,
) -> Result<Value> {
self.inner_execute_contract(contract, tx_name, args, read_only, true)
}

/// This method handles actual execution of contract-calls on a contract.
///
/// `allow_private` should always be set to `false` for user transactions:
/// this ensures that only `define-public` and `define-read-only` methods can
/// be invoked. The `allow_private` mode should only be used by
/// `Environment::execute_contract_allow_private`.
fn inner_execute_contract(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can add a note on this function directly that specifies that allow_private must always be false when doing user tx processing

&mut self,
contract_identifier: &QualifiedContractIdentifier,
tx_name: &str,
args: &[SymbolicExpression],
read_only: bool,
allow_private: bool,
) -> Result<Value> {
let contract_size = self
.global_context
Expand All @@ -1080,7 +1110,7 @@ impl<'a, 'b> Environment<'a, 'b> {

let func = contract.contract_context.lookup_function(tx_name)
.ok_or_else(|| { CheckErrors::UndefinedFunction(tx_name.to_string()) })?;
if !func.is_public() {
if !allow_private && !func.is_public() {
return Err(CheckErrors::NoSuchPublicFunction(contract_identifier.to_string(), tx_name.to_string()).into());
} else if read_only && !func.is_read_only() {
return Err(CheckErrors::PublicFunctionNotReadOnly(contract_identifier.to_string(), tx_name.to_string()).into());
Expand Down
1 change: 1 addition & 0 deletions clarity/src/vm/database/clarity_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,7 @@ impl<'a> ClarityDatabase<'a> {
self.fetch_entry(contract_identifier, map_name, key_value, &descriptor)
}

/// Returns a Clarity optional type wrapping a found or not found result
pub fn fetch_entry(
&mut self,
contract_identifier: &QualifiedContractIdentifier,
Expand Down
26 changes: 26 additions & 0 deletions clarity/src/vm/database/structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,32 @@ impl<'db, 'conn> STXBalanceSnapshot<'db, 'conn> {
};
}

/// If this snapshot is locked, then alter the lock height to be
/// the next burn block (i.e., `self.burn_block_height + 1`)
pub fn accelerate_unlock(&mut self) {
let unlocked = self.unlock_available_tokens_if_any();
if unlocked > 0 {
debug!("Consolidated after account-token-lock");
}

let new_unlock_height = self.burn_block_height + 1;
self.balance = match self.balance {
STXBalance::Unlocked { amount } => STXBalance::Unlocked { amount },
STXBalance::LockedPoxOne { .. } => {
unreachable!("Attempted to accelerate the unlock of a lockup created by PoX-1")
}
STXBalance::LockedPoxTwo {
amount_unlocked,
amount_locked,
..
} => STXBalance::LockedPoxTwo {
amount_unlocked,
amount_locked,
unlock_height: new_unlock_height,
},
};
}

/// Unlock any tokens that are unlockable at the current
/// burn block height, and return the amount newly unlocked
fn unlock_available_tokens_if_any(&mut self) -> u128 {
Expand Down
20 changes: 19 additions & 1 deletion src/burnchains/burnchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use crate::burnchains::{
BurnchainStateTransition, BurnchainStateTransitionOps, BurnchainTransaction,
Error as burnchain_error, PoxConstants,
};
use crate::chainstate::burn::db::sortdb::SortitionHandle;
use crate::chainstate::burn::db::sortdb::{SortitionDB, SortitionHandleConn, SortitionHandleTx};
use crate::chainstate::burn::distribution::BurnSamplePoint;
use crate::chainstate::burn::operations::{
Expand All @@ -72,11 +73,11 @@ use crate::util_lib::db::Error as db_error;
use stacks_common::address::public_keys_to_address_hash;
use stacks_common::address::AddressHashMode;
use stacks_common::deps_common::bitcoin::util::hash::Sha256dHash as BitcoinSha256dHash;
use stacks_common::util::{get_epoch_time_ms, sleep_ms};
use stacks_common::util::get_epoch_time_secs;
use stacks_common::util::hash::to_hex;
use stacks_common::util::log;
use stacks_common::util::vrf::VRFPublicKey;
use stacks_common::util::{get_epoch_time_ms, sleep_ms};

use crate::burnchains::bitcoin::indexer::BitcoinIndexer;
use crate::chainstate::stacks::boot::POX_2_MAINNET_CODE;
Expand Down Expand Up @@ -491,6 +492,23 @@ impl Burnchain {
)
}

/// Is this block either the first block in a reward cycle or
/// right before the reward phase starts? This is the mod 0 or mod 1
/// block. Reward cycle start events (like auto-unlocks) process *after*
/// the first reward block, so this function is used to determine when
/// that has passed.
pub fn is_before_reward_cycle(
first_block_ht: u64,
burn_ht: u64,
reward_cycle_length: u64,
) -> bool {
let effective_height = burn_ht
.checked_sub(first_block_ht)
.expect("FATAL: attempted to check reward cycle start before first block height");
// first block of the new reward cycle
(effective_height % reward_cycle_length) <= 1
}

pub fn static_is_in_prepare_phase(
first_block_height: u64,
reward_cycle_length: u64,
Expand Down
Loading