mirror of
https://github.com/SeedSigner/seedsigner.git
synced 2026-10-05 23:18:25 +00:00
A multisig output whose committed script holds this seed's key can
still belong to a different wallet: a 2-of-3 over {p1,p2,p4} when the
inputs spend {p1,p2,p3}. When the psbt supplies global xpubs and fully
annotates the output, _get_cosigners resolves a cosigner list for the
inputs and one for the output, and lists that differ mean the output
pays a quorum other than the one being spent from. That output is now
counted as an external spend. It stays presumed change when the lists
match or when either side's cosigners are unresolved.
This is hygiene, not a security control. The global xpubs are optional
and unauthenticated, so a coordinator that omits them skips the check,
and a mismatch demotes rather than raises because a transfer into a
second multisig this seed belongs to is legitimate. No surveyed
coordinator produces the shape the check fires on: every one except
Bitcoin Core annotates only its own wallet's outputs, and Core, which
annotates any output a descriptor in its wallet file can solve, writes
no global xpubs at all. Settling which wallet a multisig output pays
still needs the user's own descriptor.
The comparison sits after the ownership checks rather than at the
policy shape gate, so a psbt whose output cosigners fail to resolve
still faces every ownership check.
_get_cosigners' sorted() is what makes the two lists comparable: two of
the three multisig fixtures order the same wallet's keys differently on
the input and on its change output. Its docstring now separates what
is claim from what is checked and what the result does and does not
establish, its loop carries the procedure inline, and two early-outs
name the omitted-xpubs and omitted-derivations cases before the loop
(behaviour-neutral: both already raised from inside it). Tests pin the
sort, the different-quorum spend, and the no-xpubs presumed-change
fallback.
Running Tests
The tests are designed to be run on non-Raspi hardware.
Setup
On your testing machine you'll have to install:
# general dependencies
pip3 install -r requirements.txt
# test suite dependencies
pip3 install -r tests/requirements.txt
Then make the seedsigner python module visible/importable to the tests by installing it:
pip3 install -e .
Running all tests, calculating overall test coverage
tldr: just run the convenience script from the project root:
./tests/run_full_coverage.sh
Running tests manually
Run the whole test suite:
pytest
Run a specific test file:
pytest tests/test_this_file.py
Run a specific test:
pytest tests/test_this_file.py::test_this_specific_test
Force pytest to show logging output:
pytest tests/test_this_file.py::test_this_specific_test -o log_cli=1
# or (same result)
pytest tests/test_this_file.py::test_this_specific_test --log-cli-level=DEBUG
Annoying complications:
- If you want to see
print()statements that are in a test file, add-s - Better idea: use a proper logger in the test file and use one of the above options to display logs
Screenshot generator
The screenshot generator is meant to mostly be a utility and not really part of the test suite. However,
it is actually implemented to be run by pytest.
see: Screenshot generator README
Generate coverage manually
Run tests and generate test coverage
coverage run -m pytest
The screenshots can generate their own separate coverage report:
coverage run -m pytest tests/screenshot_generator/generator.py --locale es
Show the resulting test coverage details:
coverage report
Generate the interactive html report:
coverage html