Open plebhash opened 8 months ago
Here is a proposed structure for the repo:
stratum
├── bin
│ ├── Cargo.toml (workspace)
│ ├── jd-client
│ ├── jd-server
│ ├── mining-proxy
│ ├── pool
│ ├── test-utils
│ └── translator
└── lib
├── Cargo.toml (workspace)
├── examples
│ ├── interop-cpp
│ ├── interop-cpp-no-cargo
│ ├── ping-pong-with-noise
│ ├── ping-pong-without-noise
│ ├── sv1-client-and-server
│ ├── sv2-proxy
│ └── template-provider-test
├── protocols
│ ├── fuzz-tests
│ ├── v1
│ └── v2
│ ├── binary-sv2
│ ├── codec-sv2
│ ├── const-sv2
│ ├── framing-sv2
│ ├── noise-sv2
│ ├── roles-logic-sv2
│ ├── subprotocols
│ └── sv2-ffi
└── roles
├── jd-client
├── jd-server
├── mining-proxy
├── pool
└── translator
However I'm not sure where to place the following directories:
benches
common
experimental
test
utils
vendored
maybe @Fi3 has some suggestions?
If we are going to separete workspaces to have differnet policies for external dependecies. More permissive in roles and less in in protocols. This part of the tree:
└── roles
├── jd-client
├── jd-server
├── mining-proxy
├── pool
└── translator
Should stay in the bin workspaces, cause we will import things here, where for the lib workspace we can likely reduce everything to: (1) serde (under a feature flag), (2) few other crypto thing for noise as well under a feature flag and (3) bitcoin-rust that we assume safe. In the roles we want to use more "fancy" things.
Another option could be to have roles as now*, but they are crates that have 2 entry-point one main and one lib so we can keep them together. Not sure what option make more sense btw.
About other directories:
Btw I excepect that finding the optimal solution will require some try and a lot of discussion, this are juts very raw guildelines.
* that we could just call roles workspace
* that we could just call protocols or core workspace
* not separating lib a bin crate
@Fi3 what is the plan for removing vendored/rust-jsonrpc
?
it seems only jd-server
uses it.
I see two alternatives:
jd-server
point to https://github.com/apoelstra/rust-jsonrpc as an external dependencyjd-server
point to thatis there some other alternative?
@lorbax is implementing a reduced bitcoin rpc library based on hyper.
ok, I started splitting the root workspace into three separate new workspaces:
roles
protocols
utils
I'm leaving test
, benches
and examples
living as separate entities without being part of any workspace.
you can check the modifications here: https://github.com/plebhash/stratum/commit/c1d8c61d0a1cf08e51a6be4cc7a3389aa172611e
@Fi3 how about moving the main.rs
implementations from roles/*
into examples
?
protocols
and roles
would live as separate workspaces and still follow the dependency policies you mentioned above (permissive for roles
, strict for protocols
), but both would be 100% libs.
if the user wants to know how to use the APIs to implement a specific role, they can look into examples
for reference. The advantage of this project layout would be making it explicitly clear that SRI allows for custom decisions on e.g.: opinionated pool design.
What is still not clear to me is whether this would make sense for every role, or only few ones like pool. Or in other words: is there room for custom implementations of proxy, translator and jdc/jds?
There is room for custom implementation on every roles, sv2 spec say only what a role main task it but there a lot of ways to achieve it, not talk to about endless kinds of translators and general proxies. Examples right now contains very trivial examples about how to use the libraries. Roles are supposed to be prod ready software used by pool and miners, not sure if they should fit in the same category. Another issue with it is that you increase the development feedback time (I guess one of the most important metric). If you have 3 work-spaces like that a -> b -> c and you work on a but you need to change something in c, in order to have the changes in a you need to: (1) change and compile c (2) clean and compile b (3) clean and compile a. So adding I'm general against adding an hop in something that we modify frequently if there is no a very good reason. Last point was true last time that I checked maybe now is not anymore like that.
ok undersood, we should keep all roles
crates as bin
+lib
.
If you have 3 work-spaces like that a -> b -> c and you work on a but you need to change something in c, in order to have the changes in a you need to: (1) change and compile c (2) clean and compile b (3) clean and compile a.
this comment confused me a bit.
is this an argument against having protocols
, roles
and utils
as separate workspaces?
I'm confused because on a previous comment you also said:
utils we have thing that are used by crates under protocols and things that are used by crates under roles, and thing like the message generator that is used by no one. I think that make sense to put them in their workspace. Now the MG is not included in then main workspace for compile issues, I think that have one workspace for utils would solve this.
that was the main motivation for creating a separate workspace for utils
.
what i mean is that having roles libraries and roles binaries in 2 separate workspace have disadvantage one of that could be the time that a developer have to wait between modifying something in the code and seeing the effects of it. in the case of the "core" part of SRI this is counterbalanced by the fact that we can use 2 different policy of what we import in work-spaces.
what i mean is that having roles libraries and roles binaries in 2 separate workspace ...
as stated in https://github.com/stratum-mining/stratum/issues/702#issuecomment-1865317310, I'm currently splitting workspaces in terms of:
roles
protocols
utils
and not lib
+ bin
. I guess I should also update the original issue description to reflect that, apologies for the confusion there.
disadvantage one of that could be the time that a developer have to wait between modifying something in the code and seeing the effects of it.
I don't think this really happens in practice. Here's some instructions so you can see it for yourself:
workspace-split
branch of my forkpool_sv2
executable:
$ cd roles/pool
$ cargo build
pool_sv
from the other workspace. For example, rename binary_sv2
:
--- a/protocols/v2/binary-sv2/binary-sv2/Cargo.toml
+++ b/protocols/v2/binary-sv2/binary-sv2/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "binary_sv2"
+name = "binary_sv2_with_a_different_name"
version = "0.1.6"
$ cargo build
error: no matching package named `binary_sv2` found
location searched: /home/bear/develop/stratum/protocols/v2/binary-sv2/binary-sv2
this means the developer can simply rebuild whatever roles
crate they're working on, while making direct modifications to some protocols
dependency crate, and never having to rebuild protocols
as an extra step
or am I missing something? if that is the case, could you please give a practical example of some specific workflow where having this specific workspace split (roles + protocols + utils
, not bin + lib
) would become prohibitive?
Not sure i will double check changing the dep name invalidate the cache i guess
ok I double checked changing the code of something in a different workspace without changing the name of the crate and cargo see it so no issue here.
SRI stands for Stratum Reference Implementation, and is meant to act as the building blocks for the Bitcoin mining infrastructure.
Now imagine someone wants to write a SV2-enabled pool based on SRI. There are infinite different directions they could go. Right now, SRI has implementation for
roles
crates, which do include a "demo" pool. But this is just a dummy project which only exists for the purpose of showcasing how to wire the low-level libraries together (e.g.: crates underprotocols
,commons
andutils
).If someone wants to leverage the low-level libs while writing a pool from scratch under a different architecture, that is already doable. We believe these low-level crate libs are relatively mature, which is why they are all set as
v1.0.0
. And they can use this demo pool as a reference. This is also likely a path to most pools that already have some codebase, but only wish to integrate SV2 low level crates in a modular way (most likely via FFI).But putting low-level libraries together implies heavy-lifting. That could be time-consuming and somewhat prohibitive to small teams that wish to leverage Rust to write a pool from scratch. That is why it is also desirable that SRI provide high-level libraries with building blocks for custom implementations on the application level.
These building blocks would be opinionated with regards to threading model, error handling, socket handling and many other general aspects of software architecture. But the pool team could still implement their own opinionated strategies for coinbase management and share accounting, without necessarilty spending thousands of man-hours on wiring together the low-level APIs.