Skip to content

Commit ec500ba

Browse files
committed
Check if a vote has failed inside the contract and trigger a new one if it has
Signed-off-by: Jacinta Ferrant <[email protected]>
1 parent 99973d1 commit ec500ba

File tree

1 file changed

+65
-36
lines changed

1 file changed

+65
-36
lines changed

stacks-signer/src/signer.rs

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,49 +1230,78 @@ impl Signer {
12301230
}
12311231
return Ok(());
12321232
};
1233-
let coordinator_id = self.get_coordinator(current_reward_cycle).0;
1234-
if Some(self.signer_id) == coordinator_id && self.state == State::Idle {
1235-
debug!("{self}: Checking if old vote transaction exists in StackerDB...");
1236-
// Have I already voted and have a pending transaction? Check stackerdb for the same round number and reward cycle vote transaction
1237-
// Only get the account nonce of THIS signer as we only care about our own votes, not other signer votes
1238-
let signer_address = stacks_client.get_signer_address();
1239-
let account_nonces = self.get_account_nonces(stacks_client, &[*signer_address]);
1240-
let old_transactions = self.get_signer_transactions(&account_nonces).map_err(|e| {
1233+
if self.state != State::Idle
1234+
|| Some(self.signer_id) != self.get_coordinator(current_reward_cycle).0
1235+
{
1236+
// We are not the coordinator or we are in the middle of an operation. Do not attempt to queue DKG
1237+
return Ok(());
1238+
}
1239+
debug!("{self}: Checking if old DKG vote transaction exists in StackerDB...");
1240+
// Have I already voted, but the vote is still pending in StackerDB? Check stackerdb for the same round number and reward cycle vote transaction
1241+
// Only get the account nonce of THIS signer as we only care about our own votes, not other signer votes
1242+
let signer_address = stacks_client.get_signer_address();
1243+
let account_nonces = self.get_account_nonces(stacks_client, &[*signer_address]);
1244+
let old_transactions = self.get_signer_transactions(&account_nonces).map_err(|e| {
12411245
warn!("{self}: Failed to get old signer transactions: {e:?}. May trigger DKG unnecessarily");
12421246
}).unwrap_or_default();
1243-
// Check if we have an existing vote transaction for the same round and reward cycle
1244-
for transaction in old_transactions.iter() {
1245-
let params =
1247+
// Check if we have an existing vote transaction for the same round and reward cycle
1248+
for transaction in old_transactions.iter() {
1249+
let params =
12461250
NakamotoSigners::parse_vote_for_aggregate_public_key(transaction).unwrap_or_else(|| panic!("BUG: {self}: Received an invalid {SIGNERS_VOTING_FUNCTION_NAME} transaction in an already filtered list: {transaction:?}"));
1247-
if Some(params.aggregate_key) == self.coordinator.aggregate_public_key
1248-
&& params.voting_round == self.coordinator.current_dkg_id
1249-
&& reward_cycle == self.reward_cycle
1250-
{
1251-
debug!("{self}: Not triggering a DKG round. Already have a pending vote transaction.";
1252-
"txid" => %transaction.txid(),
1253-
"aggregate_key" => %params.aggregate_key,
1254-
"voting_round" => params.voting_round
1255-
);
1256-
return Ok(());
1257-
}
1258-
}
1259-
if stacks_client
1260-
.get_vote_for_aggregate_public_key(
1261-
self.coordinator.current_dkg_id,
1262-
self.reward_cycle,
1263-
*stacks_client.get_signer_address(),
1264-
)?
1265-
.is_some()
1251+
if Some(params.aggregate_key) == self.coordinator.aggregate_public_key
1252+
&& params.voting_round == self.coordinator.current_dkg_id
1253+
&& reward_cycle == self.reward_cycle
12661254
{
1267-
// TODO Check if the vote failed and we need to retrigger the DKG round not just if we have already voted...
1268-
// TODO need logic to trigger another DKG round if a certain amount of time passes and we still have no confirmed DKG vote
1269-
debug!("{self}: Not triggering a DKG round. Already voted and we may need to wait for more votes to arrive.");
1255+
debug!("{self}: Not triggering a DKG round. Already have a pending vote transaction.";
1256+
"txid" => %transaction.txid(),
1257+
"aggregate_key" => %params.aggregate_key,
1258+
"voting_round" => params.voting_round
1259+
);
12701260
return Ok(());
12711261
}
1272-
if self.commands.front() != Some(&Command::Dkg) {
1273-
info!("{self} is the current coordinator and must trigger DKG. Queuing DKG command...");
1274-
self.commands.push_front(Command::Dkg);
1262+
}
1263+
if let Some(aggregate_key) = stacks_client.get_vote_for_aggregate_public_key(
1264+
self.coordinator.current_dkg_id,
1265+
self.reward_cycle,
1266+
*stacks_client.get_signer_address(),
1267+
)? {
1268+
let Some(round_weight) = stacks_client
1269+
.get_round_vote_weight(self.reward_cycle, self.coordinator.current_dkg_id)?
1270+
else {
1271+
// This only will happen if soemhow we registered as a signer and were granted no weight which should not really ever happen.
1272+
error!("{self}: already voted for DKG, but no round vote weight found. We either have no voting power or the contract is corrupted.";
1273+
"voting_round" => self.coordinator.current_dkg_id,
1274+
"aggregate_key" => %aggregate_key
1275+
);
1276+
return Ok(());
1277+
};
1278+
let threshold_weight = stacks_client.get_vote_threshold_weight(self.reward_cycle)?;
1279+
if round_weight < threshold_weight {
1280+
// The threshold weight has not been met yet. We should wait for more votes to arrive.
1281+
// TODO: this should be on a timeout of some kind. We should not wait forever for the threshold to be met.
1282+
// See https://github.com/stacks-network/stacks-core/issues/4568
1283+
debug!("{self}: Not triggering a DKG round. Weight threshold has not been met yet. Waiting for more votes to arrive.";
1284+
"voting_round" => self.coordinator.current_dkg_id,
1285+
"aggregate_key" => %aggregate_key,
1286+
"round_weight" => round_weight,
1287+
"threshold_weight" => threshold_weight
1288+
);
1289+
return Ok(());
12751290
}
1291+
debug!("{self}: Vote for DKG failed. Triggering a DKG round.";
1292+
"voting_round" => self.coordinator.current_dkg_id,
1293+
"aggregate_key" => %aggregate_key,
1294+
"round_weight" => round_weight,
1295+
"threshold_weight" => threshold_weight
1296+
);
1297+
} else {
1298+
debug!("{self}: Triggering a DKG round.");
1299+
}
1300+
if self.commands.front() != Some(&Command::Dkg) {
1301+
info!("{self} is the current coordinator and must trigger DKG. Queuing DKG command...");
1302+
self.commands.push_front(Command::Dkg);
1303+
} else {
1304+
debug!("{self}: DKG command already queued...");
12761305
}
12771306
Ok(())
12781307
}

0 commit comments

Comments
 (0)