From 4840cf2ee0cc9e80fcd761a8579511bae1b77b1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jose=CC=81=20A=2EP?=
<53834183+Jossec101@users.noreply.github.com>
Date: Mon, 5 Oct 2026 12:46:45 +0200
Subject: [PATCH 1/4] Pin PSBT signer output byte-for-byte before dependency
changes
Signatures are deterministic (RFC 6979), so the six existing signing vectors
get golden outputs recorded with NBitcoin 10.0.9. Any later bump or refactor
must reproduce them exactly. Tests that set MF_ env vars share one xUnit
collection so they don't race.
---
.../Fixtures/golden-psbt-signatures.json | 44 +++++++++++
RemoteSigner.Tests/FunctionTest.cs | 1 +
RemoteSigner.Tests/GoldenSignatureTests.cs | 73 +++++++++++++++++++
RemoteSigner.Tests/RemoteSigner.Tests.csproj | 3 +
4 files changed, 121 insertions(+)
create mode 100644 RemoteSigner.Tests/Fixtures/golden-psbt-signatures.json
create mode 100644 RemoteSigner.Tests/GoldenSignatureTests.cs
diff --git a/RemoteSigner.Tests/Fixtures/golden-psbt-signatures.json b/RemoteSigner.Tests/Fixtures/golden-psbt-signatures.json
new file mode 100644
index 0000000..2b17b16
--- /dev/null
+++ b/RemoteSigner.Tests/Fixtures/golden-psbt-signatures.json
@@ -0,0 +1,44 @@
+[
+ {
+ "name": "p2wsh-2of3-all",
+ "psbt": "cHNidP8BAF4BAAAAAcbYkt1iwOa6IsI8lrNx1DWQCCg/y7\u002BfQTlfEhDIKOWVAAAAAAD/////AeiN9QUAAAAAIgAgg\u002BaofANl6wKKByTgFl5yBnqUK8f7sn4ULhAAIJb1C0cAAAAATwEENYfPAy8RJCyAAAAB/DvuQjoBjOttImoGYyiO0Pte4PqdeQqzcNAw4Ecw5sgDgI4uHNSCvdBxlpQ8WoEz0WmvhgIra7A4F3FkTsB0RNcQH8zk3jAAAIABAACAAQAAgE8BBDWHzwNWrAP0gAAAAfkIrkpmsP\u002BhqxS1WvDOSPKnAiXLkBCQLWkBr5C5Po\u002BBAlGvFeBbuLfqwYlbP19H/\u002B/s2DIaAu8iKY\u002BJ0KIDffBgEGDzoLMwAACAAQAAgAEAAIBPAQQ1h88DfblGjYAAAAH1InDHaHo6\u002BzUe9PG5owwQ87bTkhcGg66pSIwTmhHJmAMiI4UjOOpn\u002B/2Nw1KrJiXnmid2RiEja/HAITCQ00ienxDtAhDIMAAAgAEAAIABAACAAAEBK2SQ9QUAAAAAIgAguNLINpkV//IIFd1ti2ig15\u002B6mPOhNWykV0mwsneO9FciAgMnQqNaMT2Yz47ME\u002BCqhsEMK9fB1sQRGvbBQkPau524BkcwRAIgPcwj6yaA6RZn\u002B4YSHi4S1WE5ziHEt0IZO5KqDE5B0zMCID6cSLumR2AbgwqMTI3/Z3szEyMQauxtzvBpY8Z4oSp8AgEDBAIAAAABBWlSIQMnQqNaMT2Yz47ME\u002BCqhsEMK9fB1sQRGvbBQkPau524BiEDgTQLkhqca3brBTunNmjIsb4WEsFryTwd3BH/ZPS4KkohA91uD9EYRlzIBT6yNU2S2L/wvOA0/em4ocaM//veOtN2U64iBgMnQqNaMT2Yz47ME\u002BCqhsEMK9fB1sQRGvbBQkPau524BhgfzOTeMAAAgAEAAIABAACAAQAAAAAAAAAiBgOBNAuSGpxrdusFO6c2aMixvhYSwWvJPB3cEf9k9LgqShjtAhDIMAAAgAEAAIABAACAAQAAAAAAAAAiBgPdbg/RGEZcyAU\u002BsjVNkti/8LzgNP3puKHGjP/73jrTdhhg86CzMAAAgAEAAIABAACAAQAAAAAAAAAAAA==",
+ "sigHash": "All",
+ "network": "Regtest",
+ "expected": "cHNidP8BAF4BAAAAAcbYkt1iwOa6IsI8lrNx1DWQCCg/y7\u002BfQTlfEhDIKOWVAAAAAAD/////AeiN9QUAAAAAIgAgg\u002BaofANl6wKKByTgFl5yBnqUK8f7sn4ULhAAIJb1C0cAAAAATwEENYfPAy8RJCyAAAAB/DvuQjoBjOttImoGYyiO0Pte4PqdeQqzcNAw4Ecw5sgDgI4uHNSCvdBxlpQ8WoEz0WmvhgIra7A4F3FkTsB0RNcQH8zk3jAAAIABAACAAQAAgE8BBDWHzwNWrAP0gAAAAfkIrkpmsP\u002BhqxS1WvDOSPKnAiXLkBCQLWkBr5C5Po\u002BBAlGvFeBbuLfqwYlbP19H/\u002B/s2DIaAu8iKY\u002BJ0KIDffBgEGDzoLMwAACAAQAAgAEAAIBPAQQ1h88DfblGjYAAAAH1InDHaHo6\u002BzUe9PG5owwQ87bTkhcGg66pSIwTmhHJmAMiI4UjOOpn\u002B/2Nw1KrJiXnmid2RiEja/HAITCQ00ienxDtAhDIMAAAgAEAAIABAACAAAEBK2SQ9QUAAAAAIgAguNLINpkV//IIFd1ti2ig15\u002B6mPOhNWykV0mwsneO9FciAgMnQqNaMT2Yz47ME\u002BCqhsEMK9fB1sQRGvbBQkPau524BkcwRAIgPcwj6yaA6RZn\u002B4YSHi4S1WE5ziHEt0IZO5KqDE5B0zMCID6cSLumR2AbgwqMTI3/Z3szEyMQauxtzvBpY8Z4oSp8AiICA4E0C5IanGt26wU7pzZoyLG\u002BFhLBa8k8HdwR/2T0uCpKRzBEAiBFGR\u002BvauPZsjnrTMioqL3pSpWJwNdLxl4O84IrB/NajgIge3JAi2Yynykj2USpjdTQu2/Da/Vv2FuvG20RKrd/\u002B3ABAQMEAQAAAAEFaVIhAydCo1oxPZjPjswT4KqGwQwr18HWxBEa9sFCQ9q7nbgGIQOBNAuSGpxrdusFO6c2aMixvhYSwWvJPB3cEf9k9LgqSiED3W4P0RhGXMgFPrI1TZLYv/C84DT96bihxoz/\u002B94603ZTriIGAydCo1oxPZjPjswT4KqGwQwr18HWxBEa9sFCQ9q7nbgGGB/M5N4wAACAAQAAgAEAAIABAAAAAAAAACIGA4E0C5IanGt26wU7pzZoyLG\u002BFhLBa8k8HdwR/2T0uCpKGO0CEMgwAACAAQAAgAEAAIABAAAAAAAAACIGA91uD9EYRlzIBT6yNU2S2L/wvOA0/em4ocaM//veOtN2GGDzoLMwAACAAQAAgAEAAIABAAAAAAAAAAAA"
+ },
+ {
+ "name": "p2wsh-2of3-none",
+ "psbt": "cHNidP8BAF4BAAAAAcbYkt1iwOa6IsI8lrNx1DWQCCg/y7\u002BfQTlfEhDIKOWVAAAAAAD/////AeiN9QUAAAAAIgAgg\u002BaofANl6wKKByTgFl5yBnqUK8f7sn4ULhAAIJb1C0cAAAAATwEENYfPAy8RJCyAAAAB/DvuQjoBjOttImoGYyiO0Pte4PqdeQqzcNAw4Ecw5sgDgI4uHNSCvdBxlpQ8WoEz0WmvhgIra7A4F3FkTsB0RNcQH8zk3jAAAIABAACAAQAAgE8BBDWHzwNWrAP0gAAAAfkIrkpmsP\u002BhqxS1WvDOSPKnAiXLkBCQLWkBr5C5Po\u002BBAlGvFeBbuLfqwYlbP19H/\u002B/s2DIaAu8iKY\u002BJ0KIDffBgEGDzoLMwAACAAQAAgAEAAIBPAQQ1h88DfblGjYAAAAH1InDHaHo6\u002BzUe9PG5owwQ87bTkhcGg66pSIwTmhHJmAMiI4UjOOpn\u002B/2Nw1KrJiXnmid2RiEja/HAITCQ00ienxDtAhDIMAAAgAEAAIABAACAAAEBK2SQ9QUAAAAAIgAguNLINpkV//IIFd1ti2ig15\u002B6mPOhNWykV0mwsneO9FciAgMnQqNaMT2Yz47ME\u002BCqhsEMK9fB1sQRGvbBQkPau524BkcwRAIgPcwj6yaA6RZn\u002B4YSHi4S1WE5ziHEt0IZO5KqDE5B0zMCID6cSLumR2AbgwqMTI3/Z3szEyMQauxtzvBpY8Z4oSp8AgEDBAIAAAABBWlSIQMnQqNaMT2Yz47ME\u002BCqhsEMK9fB1sQRGvbBQkPau524BiEDgTQLkhqca3brBTunNmjIsb4WEsFryTwd3BH/ZPS4KkohA91uD9EYRlzIBT6yNU2S2L/wvOA0/em4ocaM//veOtN2U64iBgMnQqNaMT2Yz47ME\u002BCqhsEMK9fB1sQRGvbBQkPau524BhgfzOTeMAAAgAEAAIABAACAAQAAAAAAAAAiBgOBNAuSGpxrdusFO6c2aMixvhYSwWvJPB3cEf9k9LgqShjtAhDIMAAAgAEAAIABAACAAQAAAAAAAAAiBgPdbg/RGEZcyAU\u002BsjVNkti/8LzgNP3puKHGjP/73jrTdhhg86CzMAAAgAEAAIABAACAAQAAAAAAAAAAAA==",
+ "sigHash": "None",
+ "network": "Regtest",
+ "expected": "cHNidP8BAF4BAAAAAcbYkt1iwOa6IsI8lrNx1DWQCCg/y7\u002BfQTlfEhDIKOWVAAAAAAD/////AeiN9QUAAAAAIgAgg\u002BaofANl6wKKByTgFl5yBnqUK8f7sn4ULhAAIJb1C0cAAAAATwEENYfPAy8RJCyAAAAB/DvuQjoBjOttImoGYyiO0Pte4PqdeQqzcNAw4Ecw5sgDgI4uHNSCvdBxlpQ8WoEz0WmvhgIra7A4F3FkTsB0RNcQH8zk3jAAAIABAACAAQAAgE8BBDWHzwNWrAP0gAAAAfkIrkpmsP\u002BhqxS1WvDOSPKnAiXLkBCQLWkBr5C5Po\u002BBAlGvFeBbuLfqwYlbP19H/\u002B/s2DIaAu8iKY\u002BJ0KIDffBgEGDzoLMwAACAAQAAgAEAAIBPAQQ1h88DfblGjYAAAAH1InDHaHo6\u002BzUe9PG5owwQ87bTkhcGg66pSIwTmhHJmAMiI4UjOOpn\u002B/2Nw1KrJiXnmid2RiEja/HAITCQ00ienxDtAhDIMAAAgAEAAIABAACAAAEBK2SQ9QUAAAAAIgAguNLINpkV//IIFd1ti2ig15\u002B6mPOhNWykV0mwsneO9FciAgMnQqNaMT2Yz47ME\u002BCqhsEMK9fB1sQRGvbBQkPau524BkcwRAIgPcwj6yaA6RZn\u002B4YSHi4S1WE5ziHEt0IZO5KqDE5B0zMCID6cSLumR2AbgwqMTI3/Z3szEyMQauxtzvBpY8Z4oSp8AiICA4E0C5IanGt26wU7pzZoyLG\u002BFhLBa8k8HdwR/2T0uCpKRzBEAiBFGR\u002BvauPZsjnrTMioqL3pSpWJwNdLxl4O84IrB/NajgIge3JAi2Yynykj2USpjdTQu2/Da/Vv2FuvG20RKrd/\u002B3ABAQMEAgAAAAEFaVIhAydCo1oxPZjPjswT4KqGwQwr18HWxBEa9sFCQ9q7nbgGIQOBNAuSGpxrdusFO6c2aMixvhYSwWvJPB3cEf9k9LgqSiED3W4P0RhGXMgFPrI1TZLYv/C84DT96bihxoz/\u002B94603ZTriIGAydCo1oxPZjPjswT4KqGwQwr18HWxBEa9sFCQ9q7nbgGGB/M5N4wAACAAQAAgAEAAIABAAAAAAAAACIGA4E0C5IanGt26wU7pzZoyLG\u002BFhLBa8k8HdwR/2T0uCpKGO0CEMgwAACAAQAAgAEAAIABAAAAAAAAACIGA91uD9EYRlzIBT6yNU2S2L/wvOA0/em4ocaM//veOtN2GGDzoLMwAACAAQAAgAEAAIABAAAAAAAAAAAA"
+ },
+ {
+ "name": "p2wpkh-3in-all",
+ "psbt": "cHNidP8BAKQBAAAAAwXAGAr1uq/i06r\u002BEW2SjFMKQp3Pg0q\u002BeJcqQ9iWKLrMAAAAAAD/////E9fa5RGuwTHL6xLgYpdDDXz2piFg7F9UWPZXyAZdM8kAAAAAAP////9YszwapNpRRrI7LFJglswjr9SLkao\u002BywZq/AtjZMDChAAAAAAA/////wGsJgMGAAAAABYAFJO3OqgJq4Mr3qWsDV1YUNj0aDHQAAAAAE8BBDWHzwN9uUaNAAAAAIDetxqi8U7tfzci9EleGtB59Z/A84PlsnvZ229emSEgA6/rPqXCpw3EqihylkpeL/EXKvNGahv\u002B0Dm2JmVJf8VGEO0CEMgwAACAAQAAgAAAAAAAAQEfjGkeAAAAAAAWABQCmza03sKejExNXjBVHR8UyJJWpgEDBAIAAAAiBgIUCFqogmf/kpcaV\u002B42XlzRzx4OWdqxWDesHZkVuK70sBjtAhDIMAAAgAEAAIAAAAAAAAAAAD0AAAAAAQEfyFrXBQAAAAAWABR9cTsoys8smwP2qmjSQM06tKj4fwEDBAIAAAAiBgPzpHxMZtZ1f3rW4L0yyV4gPS45MGMDooXHpvIhAGbvtBjtAhDIMAAAgAEAAIAAAAAAAQAAAC8AAAAAAQEfMGYNAAAAAAAWABRmqBq5qDk2/37GDEq0zM5HXigXjwEDBAIAAAAiBgJr4vl26F2PI9F3JT63vX1qltyDoaAOZ/D212UNJ3u1XhjtAhDIMAAAgAEAAIAAAAAAAQAAADQAAAAAAA==",
+ "sigHash": "All",
+ "network": "Regtest",
+ "expected": "cHNidP8BAKQBAAAAAwXAGAr1uq/i06r\u002BEW2SjFMKQp3Pg0q\u002BeJcqQ9iWKLrMAAAAAAD/////E9fa5RGuwTHL6xLgYpdDDXz2piFg7F9UWPZXyAZdM8kAAAAAAP////9YszwapNpRRrI7LFJglswjr9SLkao\u002BywZq/AtjZMDChAAAAAAA/////wGsJgMGAAAAABYAFJO3OqgJq4Mr3qWsDV1YUNj0aDHQAAAAAE8BBDWHzwN9uUaNAAAAAIDetxqi8U7tfzci9EleGtB59Z/A84PlsnvZ229emSEgA6/rPqXCpw3EqihylkpeL/EXKvNGahv\u002B0Dm2JmVJf8VGEO0CEMgwAACAAQAAgAAAAAAAAQEfjGkeAAAAAAAWABQCmza03sKejExNXjBVHR8UyJJWpiICAhQIWqiCZ/\u002BSlxpX7jZeXNHPHg5Z2rFYN6wdmRW4rvSwRzBEAiBuE2ST1E17NZdYPAV/4UA5rextY1RdM\u002BGKHXNR\u002BBJOwQIgSDC/XEww6tjC0n9/9\u002BMJlZVtOQGAEMJamIG1fSXgt4kBAQMEAQAAACIGAhQIWqiCZ/\u002BSlxpX7jZeXNHPHg5Z2rFYN6wdmRW4rvSwGO0CEMgwAACAAQAAgAAAAAAAAAAAPQAAAAABAR/IWtcFAAAAABYAFH1xOyjKzyybA/aqaNJAzTq0qPh/IgID86R8TGbWdX961uC9MsleID0uOTBjA6KFx6byIQBm77RHMEQCIGegAS50pocdDBKqq9A7CzQ9L8tIZ6d49KIji5uWDUesAiBv0rzp\u002BzbKX4Nv9ERH5LzqoLv6Nsu/qZEMozwmblwWtgEBAwQBAAAAIgYD86R8TGbWdX961uC9MsleID0uOTBjA6KFx6byIQBm77QY7QIQyDAAAIABAACAAAAAAAEAAAAvAAAAAAEBHzBmDQAAAAAAFgAUZqgauag5Nv9\u002BxgxKtMzOR14oF48iAgJr4vl26F2PI9F3JT63vX1qltyDoaAOZ/D212UNJ3u1XkcwRAIgAy3\u002Bo\u002BcTPwG77GTmDGEXmCLZ6Yb\u002BLh8w5yEvDi6uFsoCIE7T/74Wa4Dsc1JpIsQtoJd5N7BiMtCAape40rBFTjz3AQEDBAEAAAAiBgJr4vl26F2PI9F3JT63vX1qltyDoaAOZ/D212UNJ3u1XhjtAhDIMAAAgAEAAIAAAAAAAQAAADQAAAAAAA=="
+ },
+ {
+ "name": "p2wpkh-3in-none",
+ "psbt": "cHNidP8BAKQBAAAAAwXAGAr1uq/i06r\u002BEW2SjFMKQp3Pg0q\u002BeJcqQ9iWKLrMAAAAAAD/////E9fa5RGuwTHL6xLgYpdDDXz2piFg7F9UWPZXyAZdM8kAAAAAAP////9YszwapNpRRrI7LFJglswjr9SLkao\u002BywZq/AtjZMDChAAAAAAA/////wGsJgMGAAAAABYAFJO3OqgJq4Mr3qWsDV1YUNj0aDHQAAAAAE8BBDWHzwN9uUaNAAAAAIDetxqi8U7tfzci9EleGtB59Z/A84PlsnvZ229emSEgA6/rPqXCpw3EqihylkpeL/EXKvNGahv\u002B0Dm2JmVJf8VGEO0CEMgwAACAAQAAgAAAAAAAAQEfjGkeAAAAAAAWABQCmza03sKejExNXjBVHR8UyJJWpgEDBAIAAAAiBgIUCFqogmf/kpcaV\u002B42XlzRzx4OWdqxWDesHZkVuK70sBjtAhDIMAAAgAEAAIAAAAAAAAAAAD0AAAAAAQEfyFrXBQAAAAAWABR9cTsoys8smwP2qmjSQM06tKj4fwEDBAIAAAAiBgPzpHxMZtZ1f3rW4L0yyV4gPS45MGMDooXHpvIhAGbvtBjtAhDIMAAAgAEAAIAAAAAAAQAAAC8AAAAAAQEfMGYNAAAAAAAWABRmqBq5qDk2/37GDEq0zM5HXigXjwEDBAIAAAAiBgJr4vl26F2PI9F3JT63vX1qltyDoaAOZ/D212UNJ3u1XhjtAhDIMAAAgAEAAIAAAAAAAQAAADQAAAAAAA==",
+ "sigHash": "None",
+ "network": "Regtest",
+ "expected": "cHNidP8BAKQBAAAAAwXAGAr1uq/i06r\u002BEW2SjFMKQp3Pg0q\u002BeJcqQ9iWKLrMAAAAAAD/////E9fa5RGuwTHL6xLgYpdDDXz2piFg7F9UWPZXyAZdM8kAAAAAAP////9YszwapNpRRrI7LFJglswjr9SLkao\u002BywZq/AtjZMDChAAAAAAA/////wGsJgMGAAAAABYAFJO3OqgJq4Mr3qWsDV1YUNj0aDHQAAAAAE8BBDWHzwN9uUaNAAAAAIDetxqi8U7tfzci9EleGtB59Z/A84PlsnvZ229emSEgA6/rPqXCpw3EqihylkpeL/EXKvNGahv\u002B0Dm2JmVJf8VGEO0CEMgwAACAAQAAgAAAAAAAAQEfjGkeAAAAAAAWABQCmza03sKejExNXjBVHR8UyJJWpiICAhQIWqiCZ/\u002BSlxpX7jZeXNHPHg5Z2rFYN6wdmRW4rvSwRzBEAiBuE2ST1E17NZdYPAV/4UA5rextY1RdM\u002BGKHXNR\u002BBJOwQIgSDC/XEww6tjC0n9/9\u002BMJlZVtOQGAEMJamIG1fSXgt4kBAQMEAgAAACIGAhQIWqiCZ/\u002BSlxpX7jZeXNHPHg5Z2rFYN6wdmRW4rvSwGO0CEMgwAACAAQAAgAAAAAAAAAAAPQAAAAABAR/IWtcFAAAAABYAFH1xOyjKzyybA/aqaNJAzTq0qPh/IgID86R8TGbWdX961uC9MsleID0uOTBjA6KFx6byIQBm77RHMEQCIGegAS50pocdDBKqq9A7CzQ9L8tIZ6d49KIji5uWDUesAiBv0rzp\u002BzbKX4Nv9ERH5LzqoLv6Nsu/qZEMozwmblwWtgEBAwQCAAAAIgYD86R8TGbWdX961uC9MsleID0uOTBjA6KFx6byIQBm77QY7QIQyDAAAIABAACAAAAAAAEAAAAvAAAAAAEBHzBmDQAAAAAAFgAUZqgauag5Nv9\u002BxgxKtMzOR14oF48iAgJr4vl26F2PI9F3JT63vX1qltyDoaAOZ/D212UNJ3u1XkcwRAIgAy3\u002Bo\u002BcTPwG77GTmDGEXmCLZ6Yb\u002BLh8w5yEvDi6uFsoCIE7T/74Wa4Dsc1JpIsQtoJd5N7BiMtCAape40rBFTjz3AQEDBAIAAAAiBgJr4vl26F2PI9F3JT63vX1qltyDoaAOZ/D212UNJ3u1XhjtAhDIMAAAgAEAAIAAAAAAAQAAADQAAAAAAA=="
+ },
+ {
+ "name": "p2wpkh-samepath-all",
+ "psbt": "cHNidP8BAIUBAAAAA5AuveJtsmh34KQCGn2QjTVgYZeAP0wBbFfk5ZOGpl0OAAAAAAD/////0qsBGBoCPD41OUI73G9W8Q1hv3z8MkaGRgWlTiutSFwAAAAAAP////\u002B7IC\u002BzZyJI1BBQ/ghKrJi18xK\u002BL7VVg1Q/B4ohnnMFsAEAAAAA/////wAAAAAATwEENYfPA325Ro0AAAABg9H86IDUttPPFss\u002B9te\u002B0DByQgbeD7RPXNuVH9mh1qIDnMEWyKA\u002BkvyG038on8\u002BHxI\u002B9AD8r6ZI1dNIDSGC8824Q7QIQyDAAAIABAACAAQAAAAABAR\u002BghgEAAAAAABYAFBQptc6zAas/qjlmx6MhONjyd11nAQMEAgAAACIGAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiGO0CEMgwAACAAQAAgAEAAAAAAAAAMwAAAAABAR\u002BghgEAAAAAABYAFBQptc6zAas/qjlmx6MhONjyd11nAQMEAgAAACIGAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiGO0CEMgwAACAAQAAgAEAAAAAAAAAMwAAAAABAR\u002BghgEAAAAAABYAFBQptc6zAas/qjlmx6MhONjyd11nAQMEAgAAACIGAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiGO0CEMgwAACAAQAAgAEAAAAAAAAAMwAAAAA=",
+ "sigHash": "All",
+ "network": "Regtest",
+ "expected": "cHNidP8BAIUBAAAAA5AuveJtsmh34KQCGn2QjTVgYZeAP0wBbFfk5ZOGpl0OAAAAAAD/////0qsBGBoCPD41OUI73G9W8Q1hv3z8MkaGRgWlTiutSFwAAAAAAP////\u002B7IC\u002BzZyJI1BBQ/ghKrJi18xK\u002BL7VVg1Q/B4ohnnMFsAEAAAAA/////wAAAAAATwEENYfPA325Ro0AAAABg9H86IDUttPPFss\u002B9te\u002B0DByQgbeD7RPXNuVH9mh1qIDnMEWyKA\u002BkvyG038on8\u002BHxI\u002B9AD8r6ZI1dNIDSGC8824Q7QIQyDAAAIABAACAAQAAAAABAR\u002BghgEAAAAAABYAFBQptc6zAas/qjlmx6MhONjyd11nIgIC8VHrR43do2EE/b9zhwf2K1hb5QUCrsXVsN8W/jSatGJHMEQCICzxabvK1oB8RUMHyd5pCg5jnOaAM70BuiKN\u002BoLJhhs8AiAW6D9va0tjfvk/HccVzYx6tTnCziZZnsG4OOHAZElD1AEBAwQBAAAAIgYC8VHrR43do2EE/b9zhwf2K1hb5QUCrsXVsN8W/jSatGIY7QIQyDAAAIABAACAAQAAAAAAAAAzAAAAAAEBH6CGAQAAAAAAFgAUFCm1zrMBqz\u002BqOWbHoyE42PJ3XWciAgLxUetHjd2jYQT9v3OHB/YrWFvlBQKuxdWw3xb\u002BNJq0YkcwRAIgZ5FQCVtOe8P5tBamiWC3rXZ8vL3xmKicHWaNy2jL3ScCIEYkW4Bdhp\u002BuFkga/AiZafMYzi7y/rlA2M52rQjCjLeGAQEDBAEAAAAiBgLxUetHjd2jYQT9v3OHB/YrWFvlBQKuxdWw3xb\u002BNJq0YhjtAhDIMAAAgAEAAIABAAAAAAAAADMAAAAAAQEfoIYBAAAAAAAWABQUKbXOswGrP6o5ZsejITjY8nddZyICAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiRzBEAiA1M\u002BMgTmvnqdi2JnE540v5E1L6jyshtwUy991Ws3FtFAIgWdjj75lK4X5EPV8SqAASzKhuPYd\u002BOxZ946FTrS\u002BqHIUBAQMEAQAAACIGAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiGO0CEMgwAACAAQAAgAEAAAAAAAAAMwAAAAA="
+ },
+ {
+ "name": "p2wpkh-samepath-none",
+ "psbt": "cHNidP8BAIUBAAAAA5AuveJtsmh34KQCGn2QjTVgYZeAP0wBbFfk5ZOGpl0OAAAAAAD/////0qsBGBoCPD41OUI73G9W8Q1hv3z8MkaGRgWlTiutSFwAAAAAAP////\u002B7IC\u002BzZyJI1BBQ/ghKrJi18xK\u002BL7VVg1Q/B4ohnnMFsAEAAAAA/////wAAAAAATwEENYfPA325Ro0AAAABg9H86IDUttPPFss\u002B9te\u002B0DByQgbeD7RPXNuVH9mh1qIDnMEWyKA\u002BkvyG038on8\u002BHxI\u002B9AD8r6ZI1dNIDSGC8824Q7QIQyDAAAIABAACAAQAAAAABAR\u002BghgEAAAAAABYAFBQptc6zAas/qjlmx6MhONjyd11nAQMEAgAAACIGAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiGO0CEMgwAACAAQAAgAEAAAAAAAAAMwAAAAABAR\u002BghgEAAAAAABYAFBQptc6zAas/qjlmx6MhONjyd11nAQMEAgAAACIGAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiGO0CEMgwAACAAQAAgAEAAAAAAAAAMwAAAAABAR\u002BghgEAAAAAABYAFBQptc6zAas/qjlmx6MhONjyd11nAQMEAgAAACIGAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiGO0CEMgwAACAAQAAgAEAAAAAAAAAMwAAAAA=",
+ "sigHash": "None",
+ "network": "Regtest",
+ "expected": "cHNidP8BAIUBAAAAA5AuveJtsmh34KQCGn2QjTVgYZeAP0wBbFfk5ZOGpl0OAAAAAAD/////0qsBGBoCPD41OUI73G9W8Q1hv3z8MkaGRgWlTiutSFwAAAAAAP////\u002B7IC\u002BzZyJI1BBQ/ghKrJi18xK\u002BL7VVg1Q/B4ohnnMFsAEAAAAA/////wAAAAAATwEENYfPA325Ro0AAAABg9H86IDUttPPFss\u002B9te\u002B0DByQgbeD7RPXNuVH9mh1qIDnMEWyKA\u002BkvyG038on8\u002BHxI\u002B9AD8r6ZI1dNIDSGC8824Q7QIQyDAAAIABAACAAQAAAAABAR\u002BghgEAAAAAABYAFBQptc6zAas/qjlmx6MhONjyd11nIgIC8VHrR43do2EE/b9zhwf2K1hb5QUCrsXVsN8W/jSatGJHMEQCICzxabvK1oB8RUMHyd5pCg5jnOaAM70BuiKN\u002BoLJhhs8AiAW6D9va0tjfvk/HccVzYx6tTnCziZZnsG4OOHAZElD1AEBAwQCAAAAIgYC8VHrR43do2EE/b9zhwf2K1hb5QUCrsXVsN8W/jSatGIY7QIQyDAAAIABAACAAQAAAAAAAAAzAAAAAAEBH6CGAQAAAAAAFgAUFCm1zrMBqz\u002BqOWbHoyE42PJ3XWciAgLxUetHjd2jYQT9v3OHB/YrWFvlBQKuxdWw3xb\u002BNJq0YkcwRAIgZ5FQCVtOe8P5tBamiWC3rXZ8vL3xmKicHWaNy2jL3ScCIEYkW4Bdhp\u002BuFkga/AiZafMYzi7y/rlA2M52rQjCjLeGAQEDBAIAAAAiBgLxUetHjd2jYQT9v3OHB/YrWFvlBQKuxdWw3xb\u002BNJq0YhjtAhDIMAAAgAEAAIABAAAAAAAAADMAAAAAAQEfoIYBAAAAAAAWABQUKbXOswGrP6o5ZsejITjY8nddZyICAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiRzBEAiA1M\u002BMgTmvnqdi2JnE540v5E1L6jyshtwUy991Ws3FtFAIgWdjj75lK4X5EPV8SqAASzKhuPYd\u002BOxZ946FTrS\u002BqHIUBAQMEAgAAACIGAvFR60eN3aNhBP2/c4cH9itYW\u002BUFAq7F1bDfFv40mrRiGO0CEMgwAACAAQAAgAEAAAAAAAAAMwAAAAA="
+ }
+]
diff --git a/RemoteSigner.Tests/FunctionTest.cs b/RemoteSigner.Tests/FunctionTest.cs
index a3388e5..b5dd05b 100644
--- a/RemoteSigner.Tests/FunctionTest.cs
+++ b/RemoteSigner.Tests/FunctionTest.cs
@@ -7,6 +7,7 @@
namespace RemoteSigner.Tests;
+[Collection(SignerEnvironment.Collection)]
public class FunctionTest : IDisposable
{
private const string awsKmsKeyId = "mrk-51c7f523a83442718f2f71a986b7c7fb";
diff --git a/RemoteSigner.Tests/GoldenSignatureTests.cs b/RemoteSigner.Tests/GoldenSignatureTests.cs
new file mode 100644
index 0000000..e91d73f
--- /dev/null
+++ b/RemoteSigner.Tests/GoldenSignatureTests.cs
@@ -0,0 +1,73 @@
+using System.Text.Json;
+using FluentAssertions;
+using NBitcoin;
+using Xunit;
+
+namespace RemoteSigner.Tests;
+
+///
+/// Byte-for-byte pins of the PSBT signer's output. ECDSA signatures are deterministic (RFC 6979),
+/// so a dependency bump (NBitcoin) or a refactor of the request path must reproduce exactly these
+/// PSBTs. Regenerate only on purpose: GOLDEN_UPDATE=1 dotnet test --filter GoldenSignatureTests.
+///
+[Collection(SignerEnvironment.Collection)]
+public class GoldenSignatureTests : IDisposable
+{
+ // SignPSBT only signs inputs whose fingerprint has an MF_ entry; the seed comes from the delegate.
+ public GoldenSignatureTests() => Environment.SetEnvironmentVariable("MF_ed0210c8", "{}");
+
+ public void Dispose() => Environment.SetEnvironmentVariable("MF_ed0210c8", null);
+
+ private const string Mnemonic =
+ "middle teach digital prefer fiscal theory syrup enter crash muffin easily anxiety ill barely eagle swim volume consider dynamic unaware deputy middle into physical";
+
+ private static readonly string FixturePath = Path.Combine(AppContext.BaseDirectory, "Fixtures", "golden-psbt-signatures.json");
+
+ public static IEnumerable