Skip to content

Commit 8f662ef

Browse files
authored
Merge pull request #2233 from blockstack/feat/pox-fixes
PoX - Adjustments
2 parents fd71c6a + badd707 commit 8f662ef

File tree

13 files changed

+129
-121
lines changed

13 files changed

+129
-121
lines changed

src/burnchains/burnchain.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ impl Burnchain {
430430
),
431431
("bitcoin", "regtest") => (
432432
BurnchainParameters::bitcoin_regtest(),
433-
PoxConstants::testnet_default(),
433+
PoxConstants::regtest_default(),
434434
),
435435
(_, _) => {
436436
return Err(burnchain_error::UnsupportedBurnchain);
@@ -453,6 +453,10 @@ impl Burnchain {
453453
})
454454
}
455455

456+
pub fn is_mainnet(&self) -> bool {
457+
self.network_id == NETWORK_ID_MAINNET
458+
}
459+
456460
/// the expected sunset burn is:
457461
/// total_commit * (progress through sunset phase) / (sunset phase duration)
458462
pub fn expected_sunset_burn(&self, burn_height: u64, total_commit: u64) -> u64 {
@@ -487,15 +491,10 @@ impl Burnchain {
487491
.expect("Overflowed u64 in calculating expected sunset_burn")
488492
}
489493

490-
pub fn is_reward_cycle_start(&self, block_height: u64) -> bool {
491-
if block_height <= (self.first_block_height + 1) {
492-
// not a reward cycle start if we're the first block after genesis.
493-
false
494-
} else {
495-
let effective_height = block_height - self.first_block_height;
496-
// first block of the new reward cycle
497-
(effective_height % (self.pox_constants.reward_cycle_length as u64)) == 1
498-
}
494+
pub fn is_reward_cycle_start(&self, burn_height: u64) -> bool {
495+
let effective_height = burn_height - self.first_block_height;
496+
// first block of the new reward cycle
497+
(effective_height % (self.pox_constants.reward_cycle_length as u64)) == 1
499498
}
500499

501500
pub fn reward_cycle_to_block_height(&self, reward_cycle: u64) -> u64 {

src/burnchains/mod.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,15 +392,27 @@ impl PoxConstants {
392392

393393
pub fn testnet_default() -> PoxConstants {
394394
PoxConstants::new(
395-
150, // 120 reward slots; 30 prepare-phase slots
396-
30,
397-
20,
395+
50, // 40 reward slots; 10 prepare-phase slots
396+
10,
397+
6,
398398
3333333333333333,
399-
5,
399+
1,
400400
BITCOIN_TESTNET_FIRST_BLOCK_HEIGHT + POX_SUNSET_START,
401401
BITCOIN_TESTNET_FIRST_BLOCK_HEIGHT + POX_SUNSET_END,
402402
) // total liquid supply is 40000000000000000 µSTX
403403
}
404+
405+
pub fn regtest_default() -> PoxConstants {
406+
PoxConstants::new(
407+
5,
408+
1,
409+
1,
410+
3333333333333333,
411+
1,
412+
BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT + POX_SUNSET_START,
413+
BITCOIN_REGTEST_FIRST_BLOCK_HEIGHT + POX_SUNSET_END,
414+
)
415+
}
404416
}
405417

406418
/// Structure for encoding our view of the network

src/chainstate/burn/db/sortdb.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,31 +1755,30 @@ impl<'a> SortitionHandleConn<'a> {
17551755
warn!("Missing parent"; "burn_header_hash" => %prepare_end_bhh);
17561756
BurnchainError::MissingParentBlock
17571757
})?;
1758-
let my_height = SortitionDB::get_block_height(self.deref(), &prepare_end_sortid)?
1758+
let block_height = SortitionDB::get_block_height(self.deref(), &prepare_end_sortid)?
17591759
.expect("CORRUPTION: SortitionID known, but no block height in SQL store");
17601760

17611761
// if this block is the _end_ of a prepare phase,
1762-
if !(my_height % pox_consts.reward_cycle_length == 0) {
1763-
test_debug!(
1764-
"My height = {}, reward cycle length == {}",
1765-
my_height,
1766-
pox_consts.reward_cycle_length
1762+
let effective_height = block_height - self.context.first_block_height as u32;
1763+
let position_in_cycle = effective_height % pox_consts.reward_cycle_length;
1764+
if position_in_cycle != 0 {
1765+
debug!(
1766+
"effective_height = {}, reward cycle length == {}",
1767+
effective_height, pox_consts.reward_cycle_length
17671768
);
17681769
return Err(CoordinatorError::NotPrepareEndBlock);
17691770
}
17701771

1771-
let prepare_end = my_height;
1772-
// if this block isn't greater than prepare_length, then this shouldn't be the end of a prepare block
1773-
if prepare_end < pox_consts.prepare_length {
1774-
test_debug!(
1775-
"prepare_end = {}, pox_consts.prepare_length = {}",
1776-
prepare_end,
1777-
pox_consts.prepare_length
1772+
if effective_height == 0 {
1773+
debug!(
1774+
"effective_height = {}, reward cycle length == {}",
1775+
effective_height, pox_consts.reward_cycle_length
17781776
);
1779-
return Err(CoordinatorError::NotPrepareEndBlock);
1777+
return Ok(None);
17801778
}
17811779

1782-
let prepare_begin = prepare_end - pox_consts.prepare_length;
1780+
let prepare_end = block_height;
1781+
let prepare_begin = prepare_end.saturating_sub(pox_consts.prepare_length);
17831782

17841783
let mut candidate_anchors = HashMap::new();
17851784
let mut memoized_candidates: HashMap<_, (Txid, u64)> = HashMap::new();

src/chainstate/burn/operations/leader_block_commit.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,20 @@ impl LeaderBlockCommitOp {
555555
let expect_pox_descendant = if self.all_outputs_burn() {
556556
false
557557
} else {
558-
if self.commit_outs.len() != reward_set_info.recipients.len() {
558+
let mut check_recipients: Vec<_> = reward_set_info
559+
.recipients
560+
.iter()
561+
.map(|(addr, _)| addr.clone())
562+
.collect();
563+
564+
if check_recipients.len() == 1 {
565+
// If the number of recipients in the set was even, we need to pad
566+
// with a burn address
567+
check_recipients
568+
.push(StacksAddress::burn_address(burnchain.is_mainnet()))
569+
}
570+
571+
if self.commit_outs.len() != check_recipients.len() {
559572
warn!(
560573
"Invalid block commit: expected {} PoX transfers, but commit has {}",
561574
reward_set_info.recipients.len(),
@@ -566,11 +579,6 @@ impl LeaderBlockCommitOp {
566579

567580
// sort check_recipients and commit_outs so that we can perform an
568581
// iterative equality check
569-
let mut check_recipients: Vec<_> = reward_set_info
570-
.recipients
571-
.iter()
572-
.map(|(addr, _)| addr.clone())
573-
.collect();
574582
check_recipients.sort();
575583
let mut commit_outs = self.commit_outs.clone();
576584
commit_outs.sort();

src/chainstate/coordinator/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,14 +581,15 @@ impl<'a, T: BlockEventDispatcher, N: CoordinatorNotices, U: RewardSetProvider>
581581
&mut self,
582582
burn_header: &BurnchainBlockHeader,
583583
) -> Result<Option<RewardCycleInfo>, Error> {
584-
let sortition_tip = self
584+
let sortition_tip_id = self
585585
.canonical_sortition_tip
586586
.as_ref()
587587
.expect("FATAL: Processing anchor block, but no known sortition tip");
588+
588589
get_reward_cycle_info(
589590
burn_header.block_height,
590591
&burn_header.parent_block_hash,
591-
sortition_tip,
592+
sortition_tip_id,
592593
&self.burnchain,
593594
&mut self.chain_state_db,
594595
&self.sortition_db,

src/chainstate/coordinator/tests.rs

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -462,11 +462,15 @@ fn make_genesis_block_with_recipients(
462462
builder.epoch_finish(epoch_tx);
463463

464464
let commit_outs = if let Some(recipients) = recipients {
465-
recipients
465+
let mut commit_outs = recipients
466466
.recipients
467467
.iter()
468468
.map(|(a, _)| a.clone())
469-
.collect()
469+
.collect::<Vec<StacksAddress>>();
470+
if commit_outs.len() == 1 {
471+
commit_outs.push(StacksAddress::burn_address(false))
472+
}
473+
commit_outs
470474
} else {
471475
vec![]
472476
};
@@ -668,11 +672,16 @@ fn make_stacks_block_with_input(
668672
builder.epoch_finish(epoch_tx);
669673

670674
let commit_outs = if let Some(recipients) = recipients {
671-
recipients
675+
let mut commit_outs = recipients
672676
.recipients
673677
.iter()
674678
.map(|(a, _)| a.clone())
675-
.collect()
679+
.collect::<Vec<StacksAddress>>();
680+
if commit_outs.len() == 1 {
681+
// Padding with burn address if required
682+
commit_outs.push(StacksAddress::burn_address(false))
683+
}
684+
commit_outs
676685
} else if post_sunset_burn || burnchain.is_in_prepare_phase(parent_height + 1) {
677686
test_debug!("block-commit in {} will burn", parent_height + 1);
678687
vec![StacksAddress::burn_address(false)]
@@ -992,7 +1001,7 @@ fn missed_block_commits() {
9921001
let ic = sort_db.index_handle_at_tip();
9931002
let pox_id = ic.get_pox_id().unwrap();
9941003
assert_eq!(&pox_id.to_string(),
995-
"11111111111",
1004+
"111111111111",
9961005
"PoX ID should reflect the 5 reward cycles _with_ a known anchor block, plus the 'initial' known reward cycle at genesis");
9971006
}
9981007
}
@@ -1152,7 +1161,7 @@ fn test_simple_setup() {
11521161
let ic = sort_db.index_handle_at_tip();
11531162
let pox_id = ic.get_pox_id().unwrap();
11541163
assert_eq!(&pox_id.to_string(),
1155-
"11111111111",
1164+
"111111111111",
11561165
"PoX ID should reflect the 10 reward cycles _with_ a known anchor block, plus the 'initial' known reward cycle at genesis");
11571166
}
11581167

@@ -1161,7 +1170,7 @@ fn test_simple_setup() {
11611170
let pox_id = ic.get_pox_id().unwrap();
11621171
assert_eq!(
11631172
&pox_id.to_string(),
1164-
"10000000000",
1173+
"110000000000",
11651174
"PoX ID should reflect the initial 'known' reward cycle at genesis"
11661175
);
11671176
}
@@ -1189,10 +1198,11 @@ fn test_simple_setup() {
11891198
pox_id_string.push('1');
11901199
}
11911200

1201+
println!("=> {}", pox_id_string);
11921202
assert_eq!(
11931203
pox_id_at_tip.to_string(),
11941204
// right-pad pox_id_string to 11 characters
1195-
format!("{:0<11}", pox_id_string)
1205+
format!("1{:0<11}", pox_id_string)
11961206
);
11971207
}
11981208
}
@@ -1449,7 +1459,7 @@ fn test_sortition_with_reward_set() {
14491459
let ic = sort_db.index_handle_at_tip();
14501460
let pox_id = ic.get_pox_id().unwrap();
14511461
assert_eq!(&pox_id.to_string(),
1452-
"11111111111",
1462+
"111111111111",
14531463
"PoX ID should reflect the 10 reward cycles _with_ a known anchor block, plus the 'initial' known reward cycle at genesis");
14541464
}
14551465
}
@@ -1680,7 +1690,7 @@ fn test_sortition_with_burner_reward_set() {
16801690
let ic = sort_db.index_handle_at_tip();
16811691
let pox_id = ic.get_pox_id().unwrap();
16821692
assert_eq!(&pox_id.to_string(),
1683-
"11111111111",
1693+
"111111111111",
16841694
"PoX ID should reflect the 10 reward cycles _with_ a known anchor block, plus the 'initial' known reward cycle at genesis");
16851695
}
16861696
}
@@ -1940,7 +1950,7 @@ fn test_pox_btc_ops() {
19401950
let ic = sort_db.index_handle_at_tip();
19411951
let pox_id = ic.get_pox_id().unwrap();
19421952
assert_eq!(&pox_id.to_string(),
1943-
"11111111111",
1953+
"111111111111",
19441954
"PoX ID should reflect the 5 reward cycles _with_ a known anchor block, plus the 'initial' known reward cycle at genesis");
19451955
}
19461956
}
@@ -2236,7 +2246,7 @@ fn test_stx_transfer_btc_ops() {
22362246
let ic = sort_db.index_handle_at_tip();
22372247
let pox_id = ic.get_pox_id().unwrap();
22382248
assert_eq!(&pox_id.to_string(),
2239-
"11111111111",
2249+
"111111111111",
22402250
"PoX ID should reflect the 5 reward cycles _with_ a known anchor block, plus the 'initial' known reward cycle at genesis");
22412251
}
22422252
}
@@ -2724,7 +2734,7 @@ fn test_sortition_with_sunset() {
27242734
let ic = sort_db.index_handle_at_tip();
27252735
let pox_id = ic.get_pox_id().unwrap();
27262736
assert_eq!(&pox_id.to_string(),
2727-
"11111111111111111",
2737+
"111111111111111111",
27282738
"PoX ID should reflect the 10 reward cycles _with_ a known anchor block, plus the 'initial' known reward cycle at genesis");
27292739
}
27302740
}
@@ -3159,13 +3169,13 @@ fn test_pox_no_anchor_selected() {
31593169
{
31603170
let ic = sort_db.index_handle_at_tip();
31613171
let pox_id = ic.get_pox_id().unwrap();
3162-
assert_eq!(&pox_id.to_string(), "111");
3172+
assert_eq!(&pox_id.to_string(), "1111");
31633173
}
31643174

31653175
{
31663176
let ic = sort_db_blind.index_handle_at_tip();
31673177
let pox_id = ic.get_pox_id().unwrap();
3168-
assert_eq!(&pox_id.to_string(), "101");
3178+
assert_eq!(&pox_id.to_string(), "1101");
31693179
}
31703180

31713181
for (sort_id, block) in stacks_blocks.iter() {
@@ -3181,7 +3191,7 @@ fn test_pox_no_anchor_selected() {
31813191
{
31823192
let ic = sort_db_blind.index_handle_at_tip();
31833193
let pox_id = ic.get_pox_id().unwrap();
3184-
assert_eq!(&pox_id.to_string(), "111");
3194+
assert_eq!(&pox_id.to_string(), "1111");
31853195
}
31863196

31873197
let block_height = eval_at_chain_tip(path_blinded, &sort_db_blind, "block-height");
@@ -3357,13 +3367,13 @@ fn test_pox_fork_out_of_order() {
33573367
{
33583368
let ic = sort_db.index_handle_at_tip();
33593369
let pox_id = ic.get_pox_id().unwrap();
3360-
assert_eq!(&pox_id.to_string(), "1111");
3370+
assert_eq!(&pox_id.to_string(), "11111");
33613371
}
33623372

33633373
{
33643374
let ic = sort_db_blind.index_handle_at_tip();
33653375
let pox_id = ic.get_pox_id().unwrap();
3366-
assert_eq!(&pox_id.to_string(), "1000");
3376+
assert_eq!(&pox_id.to_string(), "11000");
33673377
}
33683378

33693379
// now, we reveal to the blinded coordinator, but out of order.
@@ -3386,7 +3396,7 @@ fn test_pox_fork_out_of_order() {
33863396
{
33873397
let ic = sort_db_blind.index_handle_at_tip();
33883398
let pox_id = ic.get_pox_id().unwrap();
3389-
assert_eq!(&pox_id.to_string(), "1110");
3399+
assert_eq!(&pox_id.to_string(), "11110");
33903400
}
33913401

33923402
let block_height = eval_at_chain_tip(path_blinded, &sort_db_blind, "block-height");
@@ -3417,7 +3427,7 @@ fn test_pox_fork_out_of_order() {
34173427
{
34183428
let ic = sort_db_blind.index_handle_at_tip();
34193429
let pox_id = ic.get_pox_id().unwrap();
3420-
assert_eq!(&pox_id.to_string(), "1110");
3430+
assert_eq!(&pox_id.to_string(), "11110");
34213431
}
34223432

34233433
let block_height = eval_at_chain_tip(path_blinded, &sort_db_blind, "block-height");
@@ -3478,7 +3488,7 @@ fn test_pox_fork_out_of_order() {
34783488
{
34793489
let ic = sort_db_blind.index_handle_at_tip();
34803490
let pox_id = ic.get_pox_id().unwrap();
3481-
assert_eq!(&pox_id.to_string(), "1111");
3491+
assert_eq!(&pox_id.to_string(), "11111");
34823492
}
34833493

34843494
let block_height = eval_at_chain_tip(path_blinded, &sort_db_blind, "block-height");

0 commit comments

Comments
 (0)