Skip to content

Commit 0bad518

Browse files
committed
crc: split fork handling into its own fn in signer_state
1 parent 8836dba commit 0bad518

File tree

1 file changed

+72
-53
lines changed

1 file changed

+72
-53
lines changed

stacks-signer/src/v0/signer_state.rs

Lines changed: 72 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,8 @@ impl LocalStateMachine {
644644
};
645645

646646
// No matter what, if we're in tx replay mode, remove the tx replay set
647+
// TODO: in later versions, we will only clear the tx replay
648+
// set when replay is completed.
647649
prior_state_machine.tx_replay_set = None;
648650

649651
let MinerState::ActiveMiner {
@@ -780,59 +782,12 @@ impl LocalStateMachine {
780782
};
781783
return Err(ClientError::InvalidResponse(err_msg).into());
782784
}
783-
if expected_burn_block.burn_block_height <= prior_state_machine.burn_block_height
784-
&& expected_burn_block.consensus_hash != prior_state_machine.burn_block
785-
// TODO: handle fork while still in replay
786-
&& tx_replay_set.is_none()
787-
{
788-
info!("Signer State: fork detected";
789-
"expected_burn_block.height" => expected_burn_block.burn_block_height,
790-
"expected_burn_block.hash" => %expected_burn_block.consensus_hash,
791-
"next_burn_block_height" => next_burn_block_height,
792-
"next_burn_block_hash" => %next_burn_block_hash,
793-
"prior_state_machine.burn_block_height" => prior_state_machine.burn_block_height,
794-
"prior_state_machine.burn_block" => %prior_state_machine.burn_block,
795-
);
796-
// Determine the tenures that were forked
797-
let mut parent_burn_block_info =
798-
db.get_burn_block_by_ch(&prior_state_machine.burn_block)?;
799-
let last_forked_tenure = prior_state_machine.burn_block;
800-
let mut first_forked_tenure = prior_state_machine.burn_block;
801-
let mut forked_tenures = vec![(
802-
prior_state_machine.burn_block,
803-
prior_state_machine.burn_block_height,
804-
)];
805-
while parent_burn_block_info.block_height > expected_burn_block.burn_block_height {
806-
parent_burn_block_info =
807-
db.get_burn_block_by_hash(&parent_burn_block_info.parent_burn_block_hash)?;
808-
first_forked_tenure = parent_burn_block_info.consensus_hash;
809-
forked_tenures.push((
810-
parent_burn_block_info.consensus_hash,
811-
parent_burn_block_info.block_height,
812-
));
813-
}
814-
let fork_info =
815-
client.get_tenure_forking_info(&first_forked_tenure, &last_forked_tenure)?;
816-
let forked_txs = fork_info
817-
.iter()
818-
.flat_map(|fork_info| {
819-
fork_info
820-
.nakamoto_blocks
821-
.iter()
822-
.flat_map(|blocks| blocks.iter())
823-
.flat_map(|block| block.txs.iter())
824-
})
825-
.filter(|tx| match tx.payload {
826-
// Don't include Coinbase, TenureChange, or PoisonMicroblock transactions
827-
TransactionPayload::TenureChange(..)
828-
| TransactionPayload::Coinbase(..)
829-
| TransactionPayload::PoisonMicroblock(..) => false,
830-
_ => true,
831-
})
832-
.cloned()
833-
.collect::<Vec<_>>();
834-
tx_replay_set = Some(forked_txs);
835-
}
785+
tx_replay_set = self.handle_possible_bitcoin_fork(
786+
db,
787+
client,
788+
&expected_burn_block,
789+
&prior_state_machine,
790+
)?;
836791
}
837792

838793
let CurrentAndLastSortition {
@@ -993,4 +948,68 @@ impl LocalStateMachine {
993948
};
994949
state.tx_replay_set.clone()
995950
}
951+
952+
/// Handle a possible bitcoin fork. If a fork is detetected,
953+
/// return the transactions that should be replayed.
954+
pub fn handle_possible_bitcoin_fork(
955+
&self,
956+
db: &SignerDb,
957+
client: &StacksClient,
958+
expected_burn_block: &NewBurnBlock,
959+
prior_state_machine: &SignerStateMachine,
960+
) -> Result<Option<Vec<StacksTransaction>>, SignerChainstateError> {
961+
if expected_burn_block.burn_block_height <= prior_state_machine.burn_block_height
962+
&& expected_burn_block.consensus_hash != prior_state_machine.burn_block
963+
// TODO: handle fork while still in replay
964+
&& prior_state_machine.tx_replay_set.is_none()
965+
{
966+
info!("Signer State: fork detected";
967+
"expected_burn_block.height" => expected_burn_block.burn_block_height,
968+
"expected_burn_block.hash" => %expected_burn_block.consensus_hash,
969+
"prior_state_machine.burn_block_height" => prior_state_machine.burn_block_height,
970+
"prior_state_machine.burn_block" => %prior_state_machine.burn_block,
971+
);
972+
// Determine the tenures that were forked
973+
let mut parent_burn_block_info =
974+
db.get_burn_block_by_ch(&prior_state_machine.burn_block)?;
975+
let last_forked_tenure = prior_state_machine.burn_block;
976+
let mut first_forked_tenure = prior_state_machine.burn_block;
977+
let mut forked_tenures = vec![(
978+
prior_state_machine.burn_block,
979+
prior_state_machine.burn_block_height,
980+
)];
981+
while parent_burn_block_info.block_height > expected_burn_block.burn_block_height {
982+
parent_burn_block_info =
983+
db.get_burn_block_by_hash(&parent_burn_block_info.parent_burn_block_hash)?;
984+
first_forked_tenure = parent_burn_block_info.consensus_hash;
985+
forked_tenures.push((
986+
parent_burn_block_info.consensus_hash,
987+
parent_burn_block_info.block_height,
988+
));
989+
}
990+
let fork_info =
991+
client.get_tenure_forking_info(&first_forked_tenure, &last_forked_tenure)?;
992+
let forked_txs = fork_info
993+
.iter()
994+
.flat_map(|fork_info| {
995+
fork_info
996+
.nakamoto_blocks
997+
.iter()
998+
.flat_map(|blocks| blocks.iter())
999+
.flat_map(|block| block.txs.iter())
1000+
})
1001+
.filter(|tx| match tx.payload {
1002+
// Don't include Coinbase, TenureChange, or PoisonMicroblock transactions
1003+
TransactionPayload::TenureChange(..)
1004+
| TransactionPayload::Coinbase(..)
1005+
| TransactionPayload::PoisonMicroblock(..) => false,
1006+
_ => true,
1007+
})
1008+
.cloned()
1009+
.collect::<Vec<_>>();
1010+
Ok(Some(forked_txs))
1011+
} else {
1012+
Ok(None)
1013+
}
1014+
}
9961015
}

0 commit comments

Comments
 (0)