Skip to content

bug: return instead of continue in signer message loop silently drops valid messages #6977

@huth-stacks

Description

@huth-stacks

Bug Description

In stacks-signer/src/v0/signer.rs, the handle_event_match function processes batches of signer messages in a for loop. When a message from an unknown signer is encountered, the code executes return instead of continue, which exits the entire function — silently dropping all remaining valid signer messages in the batch.

File: stacks-signer/src/v0/signer.rs:523-541

// try and gather signatures
for (signer_public_key, message) in messages {
    let signer_address = StacksAddress::p2pkh(self.mainnet, signer_public_key);
    if !self.is_valid_signer(&signer_address) {
        debug!("{self}: Received a message from an unknown signer. Ignoring...";
            "signer_public_key" => ?signer_public_key,
            "signer_address" => %signer_address,
            "message" => ?message,
        );
        return;  // BUG: exits entire function, should be `continue`
    }
    match message {
        SignerMessage::BlockResponse(block_response) => self.handle_block_response(
            stacks_client,
            block_response,
            sortition_state,
        ),
        SignerMessage::StateMachineUpdate(update) => self
            .handle_state_machine_update(signer_public_key, update, received_time),
        // ...
    }
}

Impact

If any single message from an unknown signer appears anywhere in a batch, all subsequent valid messages (block responses, state machine updates, pre-commits) from legitimate signers are silently lost. This could:

  • Delay or prevent blocks from reaching signer consensus
  • Cause network stalls during periods of high signer activity
  • Create hard-to-diagnose consensus failures since the message loss is completely silent (only a debug! log)

The bug is ordering-dependent: a batch [valid, valid, unknown, valid, valid] loses the last two valid messages.

Recommended Fix

Change return; to continue; on line 531. This skips only the unknown signer's message while allowing the loop to process all remaining valid messages.

-        return;
+        continue;

Suggested Test

Create a test that sends a batch of SignerEvent::SignerMessages where the first message is from an unknown signer and the second is from a valid signer with a StateMachineUpdate. After processing, assert that the valid signer's update was persisted to the signer DB. This test fails on master and passes with the fix.


Agent Prompt
Fix the signer message batch processing bug in stacks-signer/src/v0/signer.rs.

In the handle_event_match function, the SignerEvent::SignerMessages arm iterates
over messages in a for loop (line 523). When an unknown signer is encountered at
line 531, `return;` exits the entire function instead of `continue;`, dropping all
remaining valid messages in the batch.

Fix:
1. Change `return;` to `continue;` on line 531
2. Add a regression test that:
   - Creates a Signer with a known valid signer address
   - Constructs a batch with an unknown signer message first, then a valid
     signer's StateMachineUpdate second
   - Calls handle_event_match
   - Asserts that the valid signer's StateMachineUpdate was stored in signer_db
     via get_signer_state_machine_updates()
3. Run `cargo test -p stacks-signer` to verify

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

Status

Status: 🆕 New

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions