Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/stacks-network/stacks-core
Browse files Browse the repository at this point in the history
… into feat/clippy-ci-stacks-common
  • Loading branch information
jferrant committed Dec 20, 2024
2 parents 2bb2686 + 0ee5d7c commit 3e01ab9
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 17 deletions.
1 change: 1 addition & 0 deletions .github/workflows/bitcoin-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ jobs:
- tests::nakamoto_integrations::mock_mining
- tests::nakamoto_integrations::multiple_miners
- tests::nakamoto_integrations::follower_bootup_across_multiple_cycles
- tests::nakamoto_integrations::nakamoto_lockup_events
- tests::nakamoto_integrations::utxo_check_on_startup_panic
- tests::nakamoto_integrations::utxo_check_on_startup_recover
- tests::nakamoto_integrations::v3_signer_api_endpoint
Expand Down
103 changes: 88 additions & 15 deletions stackslib/src/chainstate/nakamoto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ use super::stacks::db::{
use super::stacks::events::{StacksTransactionReceipt, TransactionOrigin};
use super::stacks::{
Error as ChainstateError, StacksBlock, StacksBlockHeader, StacksMicroblock, StacksTransaction,
TenureChangeError, TenureChangePayload, TransactionPayload,
TenureChangeError, TenureChangePayload, TokenTransferMemo, TransactionPayload,
TransactionVersion,
};
use crate::burnchains::{Burnchain, PoxConstants, Txid};
use crate::chainstate::burn::db::sortdb::SortitionDB;
Expand Down Expand Up @@ -108,8 +109,7 @@ use crate::core::{
};
use crate::net::stackerdb::{StackerDBConfig, MINER_SLOT_COUNT};
use crate::net::Error as net_error;
use crate::util_lib::boot;
use crate::util_lib::boot::boot_code_id;
use crate::util_lib::boot::{self, boot_code_addr, boot_code_id, boot_code_tx_auth};
use crate::util_lib::db::{
query_int, query_row, query_row_columns, query_row_panic, query_rows, sqlite_open,
tx_begin_immediate, u64_to_sql, DBConn, Error as DBError, FromRow,
Expand Down Expand Up @@ -2093,7 +2093,8 @@ impl NakamotoChainState {
return Err(e);
};

let (receipt, clarity_commit, reward_set_data) = ok_opt.expect("FATAL: unreachable");
let (mut receipt, clarity_commit, reward_set_data, phantom_unlock_events) =
ok_opt.expect("FATAL: unreachable");

assert_eq!(
receipt.header.anchored_header.block_hash(),
Expand Down Expand Up @@ -2147,6 +2148,20 @@ impl NakamotoChainState {
&receipt.header.anchored_header.block_hash()
);

let tx_receipts = &mut receipt.tx_receipts;
if let Some(unlock_receipt) =
// For the event dispatcher, attach any STXMintEvents that
// could not be included in the block (e.g. because the
// block didn't have a Coinbase transaction).
Self::generate_phantom_unlock_tx(
phantom_unlock_events,
&stacks_chain_state.config(),
next_ready_block.header.chain_length,
)
{
tx_receipts.push(unlock_receipt);
}

// announce the block, if we're connected to an event dispatcher
if let Some(dispatcher) = dispatcher_opt {
let block_event = (
Expand All @@ -2157,7 +2172,7 @@ impl NakamotoChainState {
dispatcher.announce_block(
&block_event,
&receipt.header.clone(),
&receipt.tx_receipts,
&tx_receipts,
&parent_block_id,
next_ready_block_snapshot.winning_block_txid,
&receipt.matured_rewards,
Expand Down Expand Up @@ -4193,11 +4208,13 @@ impl NakamotoChainState {
applied_epoch_transition: bool,
signers_updated: bool,
coinbase_height: u64,
phantom_lockup_events: Vec<StacksTransactionEvent>,
) -> Result<
(
StacksEpochReceipt,
PreCommitClarityBlock<'a>,
Option<RewardSetData>,
Vec<StacksTransactionEvent>,
),
ChainstateError,
> {
Expand Down Expand Up @@ -4234,7 +4251,7 @@ impl NakamotoChainState {
coinbase_height,
};

return Ok((epoch_receipt, clarity_commit, None));
return Ok((epoch_receipt, clarity_commit, None, phantom_lockup_events));
}

/// Append a Nakamoto Stacks block to the Stacks chain state.
Expand All @@ -4260,6 +4277,7 @@ impl NakamotoChainState {
StacksEpochReceipt,
PreCommitClarityBlock<'a>,
Option<RewardSetData>,
Vec<StacksTransactionEvent>,
),
ChainstateError,
> {
Expand Down Expand Up @@ -4527,18 +4545,20 @@ impl NakamotoChainState {
Ok(lockup_events) => lockup_events,
};

// if any, append lockups events to the coinbase receipt
if lockup_events.len() > 0 {
// If any, append lockups events to the coinbase receipt
if let Some(receipt) = tx_receipts.get_mut(0) {
// Receipts are appended in order, so the first receipt should be
// the one of the coinbase transaction
if let Some(receipt) = tx_receipts.get_mut(0) {
if receipt.is_coinbase_tx() {
receipt.events.append(&mut lockup_events);
}
} else {
warn!("Unable to attach lockups events, block's first transaction is not a coinbase transaction")
if receipt.is_coinbase_tx() {
receipt.events.append(&mut lockup_events);
}
}

// If lockup_events still contains items, it means they weren't attached
if !lockup_events.is_empty() {
info!("Unable to attach lockup events, block's first transaction is not a coinbase transaction. Will attach as a phantom tx.");
}

// if any, append auto unlock events to the coinbase receipt
if auto_unlock_events.len() > 0 {
// Receipts are appended in order, so the first receipt should be
Expand Down Expand Up @@ -4611,6 +4631,7 @@ impl NakamotoChainState {
applied_epoch_transition,
signer_set_calc.is_some(),
coinbase_height,
lockup_events,
);
}

Expand Down Expand Up @@ -4724,7 +4745,12 @@ impl NakamotoChainState {
coinbase_height,
};

Ok((epoch_receipt, clarity_commit, reward_set_data))
Ok((
epoch_receipt,
clarity_commit,
reward_set_data,
lockup_events,
))
}

/// Create a StackerDB config for the .miners contract.
Expand Down Expand Up @@ -4885,6 +4911,53 @@ impl NakamotoChainState {
clarity.save_analysis(&contract_id, &analysis).unwrap();
})
}

/// Generate a "phantom" transaction to include STXMintEvents for
/// lockups that could not be attached to a Coinbase transaction
/// (because the block doesn't have a Coinbase transaction).
fn generate_phantom_unlock_tx(
events: Vec<StacksTransactionEvent>,
config: &ChainstateConfig,
stacks_block_height: u64,
) -> Option<StacksTransactionReceipt> {
if events.is_empty() {
return None;
}
info!("Generating phantom unlock tx");
let version = if config.mainnet {
TransactionVersion::Mainnet
} else {
TransactionVersion::Testnet
};

// Make the txid unique -- the phantom tx payload should include something block-specific otherwise
// they will always have the same txid. In this case we use the block height in the memo. This also
// happens to give some indication of the purpose of this phantom tx, for anyone looking.
let memo = TokenTransferMemo({
let str = format!("Block {} token unlocks", stacks_block_height);
let mut buf = [0u8; 34];
buf[..str.len().min(34)].copy_from_slice(&str.as_bytes()[..]);
buf
});
let boot_code_address = boot_code_addr(config.mainnet);
let boot_code_auth = boot_code_tx_auth(boot_code_address.clone());
let unlock_tx = StacksTransaction::new(
version,
boot_code_auth,
TransactionPayload::TokenTransfer(
PrincipalData::Standard(boot_code_address.into()),
0,
memo,
),
);
let unlock_receipt = StacksTransactionReceipt::from_stx_transfer(
unlock_tx,
events,
Value::okay_true(),
ExecutionCost::ZERO,
);
Some(unlock_receipt)
}
}

impl StacksMessageCodec for NakamotoBlock {
Expand Down
2 changes: 1 addition & 1 deletion stackslib/src/chainstate/stacks/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2903,7 +2903,7 @@ pub mod test {
// Just update the expected value
assert_eq!(
genesis_root_hash.to_string(),
"c771616ff6acb710051238c9f4a3c48020a6d70cda637d34b89f2311a7e27886"
"0eb3076f0635ccdfcdc048afb8dea9048c5180a2e2b2952874af1d18f06321e8"
);
}

Expand Down
1 change: 1 addition & 0 deletions stx-genesis/chainstate-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ SM1ZH700J7CEDSEHM5AJ4C4MKKWNESTS35DD3SZM5,13888889,2267
SM260QHD6ZM2KKPBKZB8PFE5XWP0MHSKTD1B7BHYR,208333333,45467
SM260QHD6ZM2KKPBKZB8PFE5XWP0MHSKTD1B7BHYR,208333333,6587
SM260QHD6ZM2KKPBKZB8PFE5XWP0MHSKTD1B7BHYR,208333333,2267
SP2CTPPV8BHBVSQR727A3MK00ZD85RNY903KAG9F3,12345678,35
-----END STX VESTING-----
2 changes: 1 addition & 1 deletion stx-genesis/chainstate-test.txt.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
014402b47d53b0716402c172fa746adf308b03a826ebea91944a5eb6a304a823
088c3caea982a8f6f74dda48ec5f06f51f7605def9760a971b1acd763ee6b7cf
Loading

0 comments on commit 3e01ab9

Please sign in to comment.