-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Stratum v2 Noise Protocol #29346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stratum v2 Noise Protocol #29346
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
8a5cd72
to
a392a4c
Compare
4bb5f77
to
e612cb5
Compare
I moved the static constants into classes and renamed them a bit. Expanded the fuzzer to send multiple messages back and forth (like the BIP324 fuzzer). I dropped the 1 hour wiggle room in certificate timestamps, because it adds complexity and I don't expect this to cause any issues in practice. A self-signed certificate is generated when the TemplateProvider loads, which is unlikely the same second someone connects to it. The fuzzer found a bug where I forgot to defragment messages larger than the chunk size. Since the Template Provider generally only sends large messages, this (probably) wasn't caught in testing.
[it's currently in a broken state, second ECDH handshake gives different result, maybe due to bad memory management] |
e612cb5
to
71380de
Compare
Alright, code is back in working state. I dropped a bunch of spurious Also switched to the new logging convention, mostly (fuzzing for a few hours now, will submit a draft corpus if it doesn't find anything) |
71380de
to
f2ef03f
Compare
f2ef03f
to
1b91655
Compare
This latest push improves support for mock time (which the parent PR needs). It's still using the deprecated It also changes the protocol name to |
1b91655
to
ec207fe
Compare
Updated and simplified the description to account for the new parent PR. I'm leaving this in draft status pending |
ec207fe
to
af8e738
Compare
Possibly relevant: the test introduced here, and not modified later, failed at least once in the parent PR: #29432 (comment) |
Added a CMake build flag |
c1cf1e9
to
a2a5a04
Compare
a2a5a04
to
f1db3bd
Compare
The macOS 14 native failure is spurious, see #30922. |
Co-Authored-By: Christopher Coverdale <chris.coverdale24@gmail.com>
f1db3bd
to
b588ff8
Compare
TODO: move to bitcoin#29346
TODO: move to bitcoin#29346
🐙 This pull request conflicts with the target branch and needs rebase. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK b588ff8. went through the noise protocol spec. also sharing a pictorial represantion of the NX handshake if it's useful to other reviewers.
46, 180, 120, 129, 32, 142, 158, 238, 31, 102, 159, 103, 198, 110, 231, 14, | ||
169, 234, 136, 9, 13, 80, 63, 232, 48, 220, 75, 200, 62, 41, 191, 16}; | ||
|
||
// The double hash of protocol name "Noise_NX_EllSwiftXonly_ChaChaPoly_SHA256". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b588ff8: shouldn't this be "Noise_NX_Secp256k1+EllSwift_ChaChaPoly_SHA256" (from spec)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should match the spec. I'm guessing the comment is wrong, because otherwise it wouldn't work against SRI, but will check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which says Noise_NX_Secp256k1+EllSwift_ChaChaPoly_SHA256
. I adjusted the second comment.
I also briefly sanity checked the numerical values with some online tools.
return false; | ||
} | ||
|
||
LogTrace(BCLog::SV2, "Mix hash: %s\n", HexStr(m_symmetric_state.GetHashOutput())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b588ff8: nit: could move the MixHash log up (after DecryptAndHash
)and before Validate log for more clarity.
Assume(output.size() == Sv2Cipher::EncryptedMessageSize(input.size())); | ||
|
||
if (m_initiator) { | ||
if (!m_cs1.EncryptMessage(input, output)) return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b588ff8: (micro nit/feel free to ignore) could return m_cs1.EncryptMessage
to keep it consistent with how it's done in DecryptMessage
.
* and certificate in the buffer: <- e, ee, s, es, SIGNATURE_NOISE_MESSAGE | ||
*/ | ||
void WriteMsgES(Span<std::byte> msg); | ||
/** During handshake step 2, read the remote ephmeral key, static key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b588ff8: typo - s/ephmeral/ephemeral in a few places.
since the template provider behaves as the server and only performs the responder handshake flow, it might be useful to mention initiator handshake flow is just for tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's only used in tests, but I think we should review the code in both directions under the assumption that they'll be used in production.
@@ -236,6 +238,7 @@ if(BUILD_FOR_FUZZING) | |||
set(ENABLE_EXTERNAL_SIGNER OFF) | |||
set(WITH_MINIUPNPC OFF) | |||
set(WITH_ZMQ OFF) | |||
set(WITH_SV2 OFF) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d08a2eb: sv2 is OFF when fuzzing - so we need to turn it ON here to fuzz locally. Also the sv2 fuzz tests aren't run on the CI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like I dropped this in a recent update. WITH_SV2
is now on by default and not turned off by the fuzzer CI. I think...
XOnlyPubKey(bob_static_key.GetPubKey()), bob_authority_key); | ||
|
||
bool valid_certificate = version == 0 && | ||
(valid_from <= now) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b588ff8: (valid_from < now) && (valid_to > now)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an edge case, but valid_from == now
and valid_to == now
should be allowed.
This should probably be a draft then. Re more conceptual review, I think it's been made (fairly?) clear by multiple contributors (and from the progress of the sidecar PRs from #29432) which approach is favoured, and it doesn't seem to be the one involving this PR, and implementing all the SV2 logic inside Core. |
I moved this to Sjors#66 so we can focus on building an interface for external applications to use, and getting multiprocess in a release. I plan to open a tracking issue for that. The followup PRs #30315 and #29432 will also be moved shortly. @stratospher I will apply your feedback on the moved PR later. |
Parent PR #29432. Followed by #30315.
This is the first part of the Stratum v2 Template Provider change that can be a standalone pull request.
It introduces a CMake build flag
-DWITH_SV2
that isOFF
by default (butON
for CI).The Noise Protocol Framework is defined here: https://noiseprotocol.org/noise.html
It's quite similar to BIP324. The main differences are explained here, including why Stratum v2 can't use BIP234 (yet): https://delvingbitcoin.org/t/stratum-v2-noise-protocol-bip324-nuggets/413
The implementation is based on revision 38, 2018-07-11 (most recent at the time of writing).
The Stratum v2 spec defines the specific choice of ciphers: https://github.com/stratum-mining/sv2-spec/blob/main/04-Protocol-Security.md
This protocol has been implemented in the Stratum Reference Implementation (SRI, using rust-bitcoin). https://github.com/stratum-mining/stratum
It has also been (independently) implemented in BraiinsOS. This part is currently not open source, and it's behind on some recent changes.
The classes in
sv2_noise.h
attempt to stay close to the paper, whereas the test and fuzzer code borrow heavily from BIP324.It's ready for review, but not for merge: