-
Notifications
You must be signed in to change notification settings - Fork 658
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
Feat/bitcoin wire format rigidity #3126
Conversation
…given burnchain header hash, which we will use to pull out a window of previously-mined on-burnchain stacks transactions
…ks to find all on-burnchain blocks that haven't yet been processed in this Stacks fork. Process them all, instead of the ones that just happen to land in this stacks block's burnchain block.
…given the index block hash of a Stacks block.
… Stacks block (keyed by index block hash), so we can quickly load them up when searching for *un*processed burnchain-hosted transactions when processing a new Stacks block.
… can be mined and processed in Stacks blocks even if the burnchain block that contains them does not have a sortition with a stacks block
Codecov Report
@@ Coverage Diff @@
## next #3126 +/- ##
==========================================
+ Coverage 83.63% 84.00% +0.37%
==========================================
Files 268 268
Lines 209655 210798 +1143
==========================================
+ Hits 175338 177077 +1739
+ Misses 34317 33721 -596
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clarification: Why/when are TransferSTX
and StackSTX
written to the burnchain? I actually didn't realize that was happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
@@ -331,4 +331,33 @@ impl StacksChainState { | |||
.map_err(|e| Error::DBError(db_error::SqliteError(e)))? | |||
.is_some()) | |||
} | |||
|
|||
/// Load up the past N ancestors' index block hashes of a given block, *including* the given |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
past N ancestors'... not including
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is correct. The given argument index_block_hash
is included in the returned list of StacksBlockId
s.
@@ -11080,6 +11233,557 @@ pub mod test { | |||
); | |||
} | |||
|
|||
fn make_transfer_op( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add cfg[test]?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already in a mod test { ... }
block decorated with #[cfg(test)]
.
src/chainstate/stacks/db/blocks.rs
Outdated
peer_config.initial_balances = vec![(addr.to_account_principal(), initial_balance)]; | ||
peer_config.epochs = Some(StacksEpoch::unit_test_2_1(0)); | ||
|
||
let recv_addr = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
src/chainstate/stacks/db/blocks.rs
Outdated
peer_config.initial_balances = vec![(addr.to_account_principal(), initial_balance)]; | ||
peer_config.epochs = Some(StacksEpoch::unit_test_2_1(0)); | ||
|
||
let recv_addr = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also unused
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
transfer_op | ||
} | ||
|
||
#[test] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
short description of test would be good, ditto for the next test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
// mine it | ||
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed); | ||
|
||
// let's fire off our transfer op that will not land in a sortition pre-2.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment could be worded more clearly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
Per SIP-007, these operations exist in order to ensure that Stacks miners will pay a high price to attempt to censor them. If these operations did not exist, then Stacks miners could simply choose to ignore these transactions in the Stacks mempool. But because a Stacks block is only valid if it includes the burnchain transactions in the same burnchain that sortitioned it, the cost of censoring these transactions is the cost of foregoing a Stacks block reward (which is much higher than the cost of the BTC transaction). The reason we're worried about miner censorship is because there are scenarios where miners can be incentivized to block them. Miners are not only potential stackers, whose income from PoX is influenced to other stackers' stacking, but also are able to take bribes from other stackers in order to keep the stacking minimum down (and thus accrue more BTC). By making censorship very expensive for miners, we make it costly for miners to deviate from honest mining behavior in this matter. This PR not only makes on-burnchain transfer and stacking operations less brittle and more likely to get confirmed by the network, but also significantly increases the cost of censorship by doing so. Miners would need to forego 6x the block reward to block an on-burnchain stack-stx or transfer-stx operation. |
…consideration window in our tests
@kantai @gregorycoppola Need at least one of you to review please :) |
src/chainstate/stacks/db/blocks.rs
Outdated
@@ -4599,6 +4601,8 @@ impl StacksChainState { | |||
"txid" => %txid, | |||
"burn_block" => %burn_header_hash, | |||
"contract_call_ecode" => %resp.data); | |||
} else { | |||
debug!("Processed StackStx burn op for {} uSTX for {} cycles starting at {} from {} to pay out to {}", stacked_ustx, num_cycles, block_height, &sender, &reward_addr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of those fields should be k-v entries:
debug!("Processed StackStx burn op for {} uSTX for {} cycles starting at {} from {} to pay out to {}", stacked_ustx, num_cycles, block_height, &sender, &reward_addr); | |
debug!("Processed StackStx burnchain op"; "amount_ustx" => stacked_ustx, "num_cycles" => num_cycles, "burn_block_height" => block_height, "sender" => %sender, "reward_addr" => %reward_addr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be useful to add the txid
as well
src/chainstate/stacks/db/blocks.rs
Outdated
debug!( | ||
"Processed TransferStx {} uSTX from {} to {}", | ||
transfered_ustx, &sender, &recipient | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above: this should be a k-v log, with txid.
src/chainstate/stacks/db/blocks.rs
Outdated
if processed_burnchain_txids.contains(&stacking_op.txid) { | ||
continue; | ||
} | ||
all_stacking_burn_ops.push(stacking_op); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The control flow is simpler if the if
statement checks for exclusion:
if processed_burnchain_txids.contains(&stacking_op.txid) { | |
continue; | |
} | |
all_stacking_burn_ops.push(stacking_op); | |
if !processed_burnchain_txids.contains(&stacking_op.txid) { | |
all_stacking_burn_ops.push(stacking_op); | |
} |
src/chainstate/stacks/db/blocks.rs
Outdated
fn get_stacking_and_transfer_burn_ops_v210<'b>( | ||
chainstate_tx: &'b mut ChainstateTx, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the lifetime generic is necessary here: rust can almost always figure out the lifetimes for references that don't land in the return type.
src/chainstate/stacks/db/blocks.rs
Outdated
fn get_stacking_and_transfer_burn_ops<'b>( | ||
chainstate_tx: &'b mut ChainstateTx, | ||
parent_index_hash: &StacksBlockId, | ||
sortdb_conn: &Connection, | ||
burn_tip: &BurnchainHeaderHash, | ||
burn_tip_height: u64, | ||
) -> Result<(Vec<StackStxOp>, Vec<TransferStxOp>), Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the lifetime generic is necessary here: rust can almost always figure out the lifetimes for references that don't land in the return type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks great to me -- just superficial comments!
…m/stacks-network/stacks-blockchain into feat/bitcoin-wire-format-rigidity
…et to the first_block_height before spawning p2p
This PR addresses #2094 by making it so that when we process a Stacks block, we search the 6 prior burnchain blocks for unprocessed
TransferStx
andStackStx
transactions and try to apply them in this block. This tracking is handled by mapping each Stacks block's index block hash to the list of burnchain transaction IDs it handled. Then, to process a new Stacks block, we simply do the following: