Merge bitcoin/bitcoin#35251: wallet: Fix for duplicate external signers case

f05b1a3532 rpc: Fix for duplicate external signers case (optout)

Pull request description:

  A straightforward fix for a minor bug in a low-probability case; when there are multiple signers with the same fingerprint, the signers following the duplicate are also thrown away (due to a `break` instead of `continue`).

  Background. Bitcoin core can work with _external signers_. They can be configured using the `-signer=<cmd>` argument. The `enumeratesigners` RPC can be used to retrieve the available signers.

  Precondition A minor bug was found in a special case:

  - multiple external signers are detected, and
  - at least two of them are duplicate, i.e., have identical fingerprint, and
  - the duplicates are followed by at least one additional signer (that is, the last one is not a duplicate),

  Current behavior: Only one of the duplicates is kept, however all subsequent signers are also ignored. This last part is probably unintended, thus it's a minor bug.
  To put it in another way, the set of fingerprints returned depends on the actual order in which the devices are returned by the external tool, which may be arbitrary.

  Expected behavior: De-duplicate the found signers by fingerprint:

  - keep one signer for each fingerprint
  - keep all non-duplicates.

  Fix: The early `break` of the loop of signers upon duplication has been changed to `continue`.

  Test added/extended: `RPCSignerTest` in `test/functional/rpc_signer.py` has been extended with a case of multiple duplicates.

ACKs for top commit:
  l0rinc:
    ACK f05b1a3532
  achow101:
    ACK f05b1a3532
  polespinasa:
    code review ACK f05b1a3532
  naiyoma:
    ACK  f05b1a3532

Tree-SHA512: ac685e233192ecaf5bd535dc66badeb84d78212b3242df71f11c682828955a40167438e16fccc667cd8beef574bc4137a586f44b0f119d7574422c70bb078293
This commit is contained in:
Ava Chow
2026-05-25 17:39:03 -07:00
2 changed files with 14 additions and 1 deletions

View File

@@ -72,6 +72,19 @@ class RPCSignerTest(BitcoinTestFramework):
)
self.clear_mock_result(self.nodes[1])
# Duplicate fingerprints
self.set_mock_result(self.nodes[1],
'0 ['
'{"fingerprint": "00000001", "type": "trezor", "model": "trezor_t"}, '
'{"fingerprint": "00000001", "type": "trezor", "model": "trezor_t"}, '
'{"fingerprint": "00000002", "type": "trezor", "model": "trezor_one"}'
']')
assert_equal(self.nodes[1].enumeratesigners(), {"signers": [
{"fingerprint": "00000001", "name": "trezor_t"},
{"fingerprint": "00000002", "name": "trezor_one"},
]})
self.clear_mock_result(self.nodes[1])
assert_equal({'fingerprint': '00000001', 'name': 'trezor_t'} in self.nodes[1].enumeratesigners()['signers'], True)
if __name__ == '__main__':