Skip to content

Commit b9d3b90

Browse files
committed
Merge branch 'develop' of https://github.com/stacks-network/stacks-core into chore/fix-multiple-miners
2 parents 4752a90 + 038f9e4 commit b9d3b90

File tree

5 files changed

+107
-25
lines changed

5 files changed

+107
-25
lines changed

stackslib/src/chainstate/burn/operations/leader_block_commit.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ use crate::net::Error as net_error;
4848

4949
// return type from parse_data below
5050
#[derive(Debug)]
51-
struct ParsedData {
51+
pub struct ParsedData {
5252
block_header_hash: BlockHeaderHash,
5353
new_seed: VRFSeed,
5454
parent_block_ptr: u32,
5555
parent_vtxindex: u16,
5656
key_block_ptr: u32,
5757
key_vtxindex: u16,
58-
burn_parent_modulus: u8,
58+
pub burn_parent_modulus: u8,
5959
memo: u8,
6060
}
6161

@@ -201,7 +201,7 @@ impl LeaderBlockCommitOp {
201201
StacksBlockId(self.block_header_hash.0.clone())
202202
}
203203

204-
fn parse_data(data: &Vec<u8>) -> Option<ParsedData> {
204+
pub fn parse_data(data: &[u8]) -> Option<ParsedData> {
205205
/*
206206
Wire format:
207207
0 2 3 35 67 71 73 77 79 80

stackslib/src/chainstate/stacks/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use stacks_common::address::AddressHashMode;
3636
use stacks_common::codec::{
3737
read_next, write_next, Error as codec_error, StacksMessageCodec, MAX_MESSAGE_LEN,
3838
};
39+
use stacks_common::deps_common::bitcoin::util::hash::Sha256dHash;
3940
use stacks_common::types::chainstate::{
4041
BlockHeaderHash, BurnchainHeaderHash, StacksAddress, StacksBlockId, StacksWorkScore, TrieHash,
4142
TRIEHASH_ENCODED_SIZE,
@@ -385,6 +386,14 @@ impl Txid {
385386
pub fn from_sighash_bytes(txdata: &[u8]) -> Txid {
386387
Txid::from_stacks_tx(txdata)
387388
}
389+
390+
/// Create a Txid from the tx hash bytes used in bitcoin.
391+
/// This just reverses the inner bytes of the input.
392+
pub fn from_bitcoin_tx_hash(tx_hash: &Sha256dHash) -> Txid {
393+
let mut txid_bytes = tx_hash.0.clone();
394+
txid_bytes.reverse();
395+
Self(txid_bytes)
396+
}
388397
}
389398

390399
/// How a transaction may be appended to the Stacks blockchain

testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub struct BitcoinRegtestController {
106106

107107
#[derive(Clone)]
108108
pub struct OngoingBlockCommit {
109-
payload: LeaderBlockCommitOp,
109+
pub payload: LeaderBlockCommitOp,
110110
utxos: UTXOSet,
111111
fees: LeaderBlockCommitFees,
112112
txids: Vec<Txid>,

testnet/stacks-node/src/tests/nakamoto_integrations.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,11 +592,22 @@ pub fn next_block_and<F>(
592592
) -> Result<(), String>
593593
where
594594
F: FnMut() -> Result<bool, String>,
595+
{
596+
next_block_and_controller(btc_controller, timeout_secs, |_| check())
597+
}
598+
599+
pub fn next_block_and_controller<F>(
600+
btc_controller: &mut BitcoinRegtestController,
601+
timeout_secs: u64,
602+
mut check: F,
603+
) -> Result<(), String>
604+
where
605+
F: FnMut(&mut BitcoinRegtestController) -> Result<bool, String>,
595606
{
596607
eprintln!("Issuing bitcoin block");
597608
btc_controller.build_next_block(1);
598609
let start = Instant::now();
599-
while !check()? {
610+
while !check(btc_controller)? {
600611
if start.elapsed() > Duration::from_secs(timeout_secs) {
601612
error!("Timed out waiting for block to process, trying to continue test");
602613
return Err("Timed out".into());

testnet/stacks-node/src/tests/signer/v0.rs

Lines changed: 82 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ use libsigner::v0::messages::{
2727
};
2828
use libsigner::{BlockProposal, SignerSession, StackerDBSession};
2929
use stacks::address::AddressHashMode;
30+
use stacks::burnchains::Txid;
3031
use stacks::chainstate::burn::db::sortdb::SortitionDB;
32+
use stacks::chainstate::burn::operations::LeaderBlockCommitOp;
3133
use stacks::chainstate::nakamoto::{NakamotoBlock, NakamotoBlockHeader, NakamotoChainState};
3234
use stacks::chainstate::stacks::address::PoxAddress;
3335
use stacks::chainstate::stacks::boot::MINERS_NAME;
@@ -68,15 +70,16 @@ use crate::nakamoto_node::sign_coordinator::TEST_IGNORE_SIGNERS;
6870
use crate::neon::Counters;
6971
use crate::run_loop::boot_nakamoto;
7072
use crate::tests::nakamoto_integrations::{
71-
boot_to_epoch_25, boot_to_epoch_3_reward_set, next_block_and, setup_epoch_3_reward_set,
72-
wait_for, POX_4_DEFAULT_STACKER_BALANCE, POX_4_DEFAULT_STACKER_STX_AMT,
73+
boot_to_epoch_25, boot_to_epoch_3_reward_set, next_block_and, next_block_and_controller,
74+
setup_epoch_3_reward_set, wait_for, POX_4_DEFAULT_STACKER_BALANCE,
75+
POX_4_DEFAULT_STACKER_STX_AMT,
7376
};
7477
use crate::tests::neon_integrations::{
7578
get_account, get_chain_info, get_chain_info_opt, next_block_and_wait,
7679
run_until_burnchain_height, submit_tx, submit_tx_fallible, test_observer,
7780
};
7881
use crate::tests::{self, make_stacks_transfer};
79-
use crate::{nakamoto_node, BurnchainController, Config, Keychain};
82+
use crate::{nakamoto_node, BitcoinRegtestController, BurnchainController, Config, Keychain};
8083

8184
impl SignerTest<SpawnedSigner> {
8285
/// Run the test until the first epoch 2.5 reward cycle.
@@ -1221,6 +1224,33 @@ fn bitcoind_forking_test() {
12211224
let miner_address = Keychain::default(conf.node.seed.clone())
12221225
.origin_address(conf.is_mainnet())
12231226
.unwrap();
1227+
let miner_pk = signer_test
1228+
.running_nodes
1229+
.btc_regtest_controller
1230+
.get_mining_pubkey()
1231+
.as_deref()
1232+
.map(Secp256k1PublicKey::from_hex)
1233+
.unwrap()
1234+
.unwrap();
1235+
1236+
let get_unconfirmed_commit_data = |btc_controller: &mut BitcoinRegtestController| {
1237+
let unconfirmed_utxo = btc_controller
1238+
.get_all_utxos(&miner_pk)
1239+
.into_iter()
1240+
.find(|utxo| utxo.confirmations == 0)?;
1241+
let unconfirmed_txid = Txid::from_bitcoin_tx_hash(&unconfirmed_utxo.txid);
1242+
let unconfirmed_tx = btc_controller.get_raw_transaction(&unconfirmed_txid);
1243+
let unconfirmed_tx_opreturn_bytes = unconfirmed_tx.output[0].script_pubkey.as_bytes();
1244+
info!(
1245+
"Unconfirmed tx bytes: {}",
1246+
stacks::util::hash::to_hex(unconfirmed_tx_opreturn_bytes)
1247+
);
1248+
let data = LeaderBlockCommitOp::parse_data(
1249+
&unconfirmed_tx_opreturn_bytes[unconfirmed_tx_opreturn_bytes.len() - 77..],
1250+
)
1251+
.unwrap();
1252+
Some(data)
1253+
};
12241254

12251255
signer_test.boot_to_epoch_3();
12261256
info!("------------------------- Reached Epoch 3.0 -------------------------");
@@ -1253,27 +1283,43 @@ fn bitcoind_forking_test() {
12531283
.build_next_block(1);
12541284

12551285
info!("Wait for block off of shallow fork");
1256-
thread::sleep(Duration::from_secs(15));
12571286

12581287
// we need to mine some blocks to get back to being considered a frequent miner
12591288
for i in 0..3 {
1289+
let current_burn_height = get_chain_info(&signer_test.running_nodes.conf).burn_block_height;
12601290
info!(
1261-
"Mining block {} of 3 to be considered a frequent miner",
1262-
i + 1
1291+
"Mining block #{i} to be considered a frequent miner";
1292+
"current_burn_height" => current_burn_height,
12631293
);
12641294
let commits_count = signer_test
12651295
.running_nodes
12661296
.commits_submitted
12671297
.load(Ordering::SeqCst);
1268-
next_block_and(
1298+
next_block_and_controller(
12691299
&mut signer_test.running_nodes.btc_regtest_controller,
12701300
60,
1271-
|| {
1272-
Ok(signer_test
1301+
|btc_controller| {
1302+
let commits_submitted = signer_test
12731303
.running_nodes
12741304
.commits_submitted
1275-
.load(Ordering::SeqCst)
1276-
> commits_count)
1305+
.load(Ordering::SeqCst);
1306+
if commits_submitted <= commits_count {
1307+
// wait until a commit was submitted
1308+
return Ok(false)
1309+
}
1310+
let Some(payload) = get_unconfirmed_commit_data(btc_controller) else {
1311+
warn!("Commit submitted, but bitcoin doesn't see it in the unconfirmed UTXO set, will try to wait.");
1312+
return Ok(false)
1313+
};
1314+
let burn_parent_modulus = payload.burn_parent_modulus;
1315+
let current_modulus = u8::try_from((current_burn_height + 1) % 5).unwrap();
1316+
info!(
1317+
"Ongoing Commit Operation check";
1318+
"burn_parent_modulus" => burn_parent_modulus,
1319+
"current_modulus" => current_modulus,
1320+
"payload" => ?payload,
1321+
);
1322+
Ok(burn_parent_modulus == current_modulus)
12771323
},
12781324
)
12791325
.unwrap();
@@ -1312,28 +1358,44 @@ fn bitcoind_forking_test() {
13121358
.btc_regtest_controller
13131359
.build_next_block(4);
13141360

1315-
info!("Wait for block off of deeper fork");
1316-
thread::sleep(Duration::from_secs(15));
1361+
info!("Wait for block off of deep fork");
13171362

13181363
// we need to mine some blocks to get back to being considered a frequent miner
13191364
for i in 0..3 {
1365+
let current_burn_height = get_chain_info(&signer_test.running_nodes.conf).burn_block_height;
13201366
info!(
1321-
"Mining block {} of 3 to be considered a frequent miner",
1322-
i + 1
1367+
"Mining block #{i} to be considered a frequent miner";
1368+
"current_burn_height" => current_burn_height,
13231369
);
13241370
let commits_count = signer_test
13251371
.running_nodes
13261372
.commits_submitted
13271373
.load(Ordering::SeqCst);
1328-
next_block_and(
1374+
next_block_and_controller(
13291375
&mut signer_test.running_nodes.btc_regtest_controller,
13301376
60,
1331-
|| {
1332-
Ok(signer_test
1377+
|btc_controller| {
1378+
let commits_submitted = signer_test
13331379
.running_nodes
13341380
.commits_submitted
1335-
.load(Ordering::SeqCst)
1336-
> commits_count)
1381+
.load(Ordering::SeqCst);
1382+
if commits_submitted <= commits_count {
1383+
// wait until a commit was submitted
1384+
return Ok(false)
1385+
}
1386+
let Some(payload) = get_unconfirmed_commit_data(btc_controller) else {
1387+
warn!("Commit submitted, but bitcoin doesn't see it in the unconfirmed UTXO set, will try to wait.");
1388+
return Ok(false)
1389+
};
1390+
let burn_parent_modulus = payload.burn_parent_modulus;
1391+
let current_modulus = u8::try_from((current_burn_height + 1) % 5).unwrap();
1392+
info!(
1393+
"Ongoing Commit Operation check";
1394+
"burn_parent_modulus" => burn_parent_modulus,
1395+
"current_modulus" => current_modulus,
1396+
"payload" => ?payload,
1397+
);
1398+
Ok(burn_parent_modulus == current_modulus)
13371399
},
13381400
)
13391401
.unwrap();

0 commit comments

Comments
 (0)