Skip to content
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

feat: secret service #28

Draft
wants to merge 30 commits into
base: main
Choose a base branch
from
Draft

feat: secret service #28

wants to merge 30 commits into from

Conversation

Zk2u
Copy link

@Zk2u Zk2u commented Jan 31, 2025

Description

This PR implements a secret service system consisting of 3 library crates, server, proto and client, and 1 binary that acts as the server implementor. The client can be used by the other bridge binaries.

The "server" is responsible for keeping secrets used in strata bridge. The "clients" are the sequencer/operator binaries for their respective duties. They communicate using a QUIC connection with a binary-based rkyv wire protocol. Security is handled through mutually authenticated TLS 1.3 as part of QUIC.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature/Enhancement (non-breaking change which adds functionality or enhances an existing one)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactor
  • New or updated tests
  • Dependency Update

Notes to Reviewers

Checklist

  • I have performed a self-review of my code.
  • I have commented my code where necessary.
  • I have updated the documentation if needed.
  • My changes do not introduce new warnings.
  • I have added tests that prove my changes are effective or that my feature works.
  • New and existing tests pass with my changes.

Related Issues

STR-934

@Zk2u Zk2u requested review from Rajil1213 and storopoli January 31, 2025 11:53
@Zk2u Zk2u self-assigned this Jan 31, 2025
@Zk2u Zk2u added the enhancement New feature or request label Jan 31, 2025
@codecov-commenter
Copy link

codecov-commenter commented Jan 31, 2025

Codecov Report

Attention: Patch coverage is 30.08615% with 1055 lines in your changes missing coverage. Please review.

Project coverage is 63.09%. Comparing base (3682555) to head (278fb83).

Files with missing lines Patch % Lines
crates/secret-service-server/src/lib.rs 34.49% 207 Missing ⚠️
crates/secret-service-client/src/musig2.rs 0.00% 170 Missing ⚠️
crates/secret-service/src/disk/musig2.rs 0.00% 150 Missing ⚠️
...es/secret-service-server/src/musig2_session_mgr.rs 4.89% 136 Missing ⚠️
...rates/secret-service-proto/src/v1/rkyv_wrappers.rs 0.00% 64 Missing ⚠️
crates/secret-service/src/disk/wots.rs 0.00% 52 Missing ⚠️
crates/secret-service/src/tls.rs 0.00% 44 Missing ⚠️
crates/secret-service-proto/src/v1/wire.rs 4.65% 41 Missing ⚠️
crates/secret-service-client/src/wots.rs 0.00% 35 Missing ⚠️
crates/secret-service/src/main.rs 0.00% 35 Missing ⚠️
... and 9 more
@@            Coverage Diff             @@
##             main      #28      +/-   ##
==========================================
- Coverage   66.74%   63.09%   -3.66%     
==========================================
  Files          89      111      +22     
  Lines       13646    15155    +1509     
==========================================
+ Hits         9108     9562     +454     
- Misses       4538     5593    +1055     
Files with missing lines Coverage Δ
crates/secret-service-proto/src/wire.rs 100.00% <100.00%> (ø)
crates/secret-service/src/disk/operator.rs 100.00% <100.00%> (ø)
crates/secret-service/src/disk/p2p.rs 100.00% <100.00%> (ø)
crates/secret-service-client/src/p2p.rs 90.00% <90.00%> (ø)
crates/secret-service-proto/src/v1/traits.rs 0.00% <0.00%> (ø)
crates/secret-service-client/src/operator.rs 89.47% <89.47%> (ø)
crates/secret-service-client/src/lib.rs 89.28% <89.28%> (ø)
crates/secret-service-server/src/bool_arr.rs 90.08% <90.08%> (ø)
crates/secret-service/src/tests.rs 87.61% <87.61%> (ø)
crates/secret-service-client/src/stakechain.rs 0.00% <0.00%> (ø)
... and 12 more

Copy link
Collaborator

@Rajil1213 Rajil1213 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, it feels like this is still very much in the scaffolding stage rather than in the concrete implementation. The only concrete implementation I see is in the client-server parts of the secret service rather than what it's supposed to be doing.

I can also see that the types have been laid out such that the server also does the musig2 session book-keeping but the actual implementation for this book-keeping/signing/aggregating has not been written out yet. Another thing missing is where all this data is stored. If this service is going to handle the musig2 signing session as well, it will need this information to be persistent and recoverable.

One more thing I don't see is a wallet-like functionality, specifically an API to retrieve unspent UTXOs.

I would recommend working on the concrete parts of the implementation:

  • musig2 signing/aggregating
  • wots signing/aggregating
  • p2p signing
  • pre-image generation
  • wallet integration

...before moving on to the binary/client implementation.

The reason I bring this up is that the way it currently stands, at least some of the interfaces and designs might change and bitcoin-core being what it is, I can easily see these taking a full sprint which is far from ideal.

@Zk2u
Copy link
Author

Zk2u commented Feb 3, 2025

@Rajil1213

I can also see that the types have been laid out such that the server also does the musig2 session book-keeping but the actual implementation for this book-keeping/signing/aggregating has not been written out yet

Check the secret-service-server crate for the musig2 in-memory session management. The implementor (secret-service) is responsible for handling persistence.

Another thing missing is where all this data is stored. If this service is going to handle the musig2 signing session as well, it will need this information to be persistent and recoverable.

Correct. This will be handled via sled in the implementor. Server is going to have some minor changes so session recovery happens on boot. This bit is relatively trivial compared to the rest of it.

PS: whaddya mean by bitcoin core? None of the secret service touches or depends on core.

@Rajil1213
Copy link
Collaborator

Rajil1213 commented Feb 3, 2025

Check the secret-service-server crate for the musig2 in-memory session management. The implementor (secret-service) is responsible for handling persistence.

Is the implementor also in scope for this PR?

PS: whaddya mean by bitcoin core? None of the secret service touches or depends on core.

Right but when you write tests for all the trait implementors, you will need to eventually broadcast a signed transaction. And debugging those can be a pain.

PS: I also see that you've brought the entire musig2 crate. If this is just for serialization, you should just create newtype wrappers. But let me know if there is some other reason.

Copy link
Member

@storopoli storopoli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The direction is good, but it needs ton of polishing:

  1. Get rid of the musig2 code and do tuple wrapper structs in the same fashion as how we did for musig2 stuff for Borsh in strata, see Just do the same to what we did on strata for the musig2 stuff for Borsh.
    See https://github.com/alpenlabs/strata/blob/a0d413d711bb3af5ce312544f45600806f3f18bb/crates/primitives/src/bridge.rs#L225-L263 for examples.
  2. Needs to be better organized, the crates are huge lib.rs files and the binary should be moved to a bin/ subdir somewhere.
  3. Needs also @Rajil1213's clippy lints secret sauce config for the Cargo.tomls.

Comment on lines +1 to +4
[package]
name = "secret-service"
version = "0.1.0"
edition = "2021"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be moved to bin/ directory maybe.
Cc @Rajil1213.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, anything that has a main function should go into the bin/ directory.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocked by #44

@Zk2u
Copy link
Author

Zk2u commented Feb 5, 2025

Is the implementor also in scope for this PR?

Yes, I'm working on it at the moment. The other crates are mostly functionally complete but need tidying once I'm done

Copy link
Collaborator

@Rajil1213 Rajil1213 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a second pass of this PR. I've left some comments on the client implementation but those are really for the traits that they are implementing.

Comment on lines +1 to +4
[package]
name = "secret-service"
version = "0.1.0"
edition = "2021"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, anything that has a main function should go into the bin/ directory.

@Zk2u Zk2u force-pushed the feat/mi6 branch 2 times, most recently from f0f64bb to 17a4cda Compare February 16, 2025 18:51
Copy link
Member

@storopoli storopoli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!
Some overview comments from a quick review

Copy link
Collaborator

@Rajil1213 Rajil1213 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this PR is in the testing/documentation phase right now, could you add the following section to the Cargo.toml file in each of the crates?

[lints]
rust.missing_debug_implementations = "warn"
rust.rust_2018_idioms = { level = "deny", priority = -1 }
rust.unreachable_pub = "warn"
rust.unused_crate_dependencies = "deny"
rust.unused_must_use = "deny"
rust.unsafe_op_in_unsafe_fn = "warn"
rust.missing_docs = "warn"
rustdoc.all = "warn"

These are mostly for stricter automatic checks for documentation. There is also a lint for unsafe code since I saw some unsafe blocks in this PR (which will be warn by default in the next rust edition anyway).

Zk2u and others added 5 commits February 23, 2025 16:48
* doc: secret-service-client

* doc: secret-service-proto wire

* doc: secret-service-proto traits

* doc: secret-service-proto rhyv_wrappers

* doc: secret-service-server

* doc: secret-service

* doc: S2 is too ambiguous...

* Apply suggestions from code review

Co-authored-by: azz <[email protected]>

* doc: rebase

* doc: add spaces

---------

Co-authored-by: azz <[email protected]>
@Zk2u Zk2u requested review from Rajil1213 and storopoli February 24, 2025 13:07
@Zk2u Zk2u marked this pull request as ready for review February 24, 2025 13:08
@Zk2u Zk2u dismissed stale reviews from Rajil1213 and storopoli February 24, 2025 13:08

Lints added

@Zk2u Zk2u enabled auto-merge February 24, 2025 13:09
@Rajil1213
Copy link
Collaborator

Rajil1213 commented Feb 24, 2025

Looks like the Cargo.lock was regenerated at some point in this PR which updated all the unpinned dependencies including ark-std and strata. I have pinned these down to specific commits and the build seems to be working.

Note that we'll need to update the strata deps to their release version at some point during the integration.

CC: @ProofOfKeags @prajwolrg

@Zk2u
Copy link
Author

Zk2u commented Feb 25, 2025

@Rajil1213 is this just waiting for an approval then?

@Rajil1213
Copy link
Collaborator

is this just waiting for an approval then?

The docs are still failing. So that needs fixing. Will review it after the CI is green. But it should be good to go and we should be able to punt any changes down the line.

@Zk2u
Copy link
Author

Zk2u commented Feb 25, 2025

@Rajil1213 @storopoli ci is passing now

Copy link
Member

@storopoli storopoli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few nits.

Ideally we would also mock a MuSig2 first round and second round,
check the tests vectors in BIP-327

If you have time for that that would be great!

Comment on lines 62 to 86
// operator signer
let op_signer = client.operator_signer();
let pubkey = op_signer.pubkey().await.expect("good response");

let handles = (0..1000)
.map(|_| {
let secp_ctx = Secp256k1::verification_only();
let op_signer = op_signer.clone();
tokio::spawn(async move {
let to_sign = thread_rng().gen();
let sig = op_signer.sign(&to_sign).await.expect("good response");
assert!(secp_ctx
.verify_schnorr(&sig, &Message::from_digest(to_sign), &pubkey)
.is_ok());
})
})
.collect::<Vec<_>>();
for handle in handles {
handle.await.unwrap();
}

// p2p signer
let p2p_signer = client.p2p_signer();
p2p_signer.secret_key().await.expect("good response");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also test a stake preimage, a wots 160 and 256 secret keys, and a secret nonce?

@Zk2u
Copy link
Author

Zk2u commented Feb 25, 2025

Yes ok will add these this afternoon.

Copy link
Collaborator

@Rajil1213 Rajil1213 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The musig2 stuff might need a few changes. Other than that, the secret service crate should also be broken down. It contains a library part that handles the actual logic and a binary part main.rs that runs the binary. This should be split out so that the library part of it is what remains inside the crates directory while the main.rs should be moved to separate binary in the bin directory. This library part should also be fully tested (given its nature, I think this is doable). I also think the disk module is a bit of a misnomer at this point.

if !pubkeys.contains(&my_pub_key) {
pubkeys.push(my_pub_key);
}
pubkeys.sort();
Copy link
Collaborator

@Rajil1213 Rajil1213 Feb 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pubkeys are not sorted like this in our impl. The order of the keys is determined by the the operator indexes. We could switch over to this sorting logic but that requires changes in multiple places. For now, you can just assume that the order in which the keys are received is their canonical ordering so far as key aggregation is concerned. You can also assume that this signer's public key will be present in the list of public keys provided so it does not need to be mutable. You could add a sanity check though -- if this signer's key is not part of the list of public keys, it's a catastrophic issue because it would mean that the operator's pubkey is not present in the strata chain state.

@Zk2u Zk2u disabled auto-merge February 25, 2025 17:41
@Zk2u Zk2u marked this pull request as draft February 25, 2025 17:42
@Zk2u
Copy link
Author

Zk2u commented Feb 25, 2025

Having some weird issues with the musig2 setup so waiting for some help from Aaron and wiill fix (will also cover the pubkey stuff from @Rajil1213).

Also @Rajil1213 I agree the disk module naming could be clearer. Will rename that. But I think we should keep the implementation inside that crate for the moment. We can totally add unit tests inside the individual modules and keep it a binary.

@Rajil1213
Copy link
Collaborator

But I think we should keep the implementation inside that crate for the moment. We can totally add unit tests inside the individual modules and keep it a binary.

That's probably fine because there's not much going on there at the moment. However, at some point, that is where most of the non-trivial logic will live (musig2 session-management, etc.). Plus it's also doing a bunch of key-derivation. I feel like it's better to have that kind of thing in a separate crate (similar to how it is in strata).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants