bitcoin_core_sv2 supports multiple versions of Bitcoin Core (v30.x + v31.x)#548
bitcoin_core_sv2 supports multiple versions of Bitcoin Core (v30.x + v31.x)#548plebhash wants to merge 13 commits into
bitcoin_core_sv2 supports multiple versions of Bitcoin Core (v30.x + v31.x)#548Conversation
14a8b80 to
c3bf3b1
Compare
df3ce2a to
9a17e32
Compare
9a17e32 to
d757e22
Compare
d757e22 to
e0f2a39
Compare
I asked
IIUC this PR is already increasing the build artifact footprint due to:
then #553 increased it further with the addition of and now the combination of both started pushing the github runners over the limit |
|
also getting similar disk-out-of-space errors after merging #531:
so maybe f4a88f8 is not enough, and we might continue to get flaky PITA over this.... let's see |
GitGab19
left a comment
There was a problem hiding this comment.
Besides of my last comments, which are only about the msrv.yaml workflow changes, I just tested with both v30.2 and v31, and everything worked fine!
tACK
a721748 to
61d1eaf
Compare
Shourya742
left a comment
There was a problem hiding this comment.
Some suggestions and questions
|
|
||
| - name: Check test compilation for jd-server | ||
| run: cargo test --manifest-path=pool-apps/jd-server/Cargo.toml --no-run | ||
|
|
There was a problem hiding this comment.
this makes sense, can you do the same in ci,yaml and lockfile.yaml
|
|
||
| let bitcoin_core_cancellation_token = CancellationToken::new(); | ||
| let bitcoin_core_config = BitcoinCoreSv2TDPConfig { | ||
| version: version.to_bitcoin_core_version(), |
There was a problem hiding this comment.
why we have two different versioning shouldn't they be the same?
There was a problem hiding this comment.
I also don't love the duplication of stratum-apps::tp_type::BitcoinCoreIpcVersion vs bitcoin_core_sv2::common::BitcoinCoreVersion
we can get rid of stratum-apps::tp_type::BitcoinCoreIpcVersion in favor of bitcoin_core_sv2::common::BitcoinCoreVersion, but with the tradeoff of having stratum-apps::tp_type::TemplateProviderType::BitcoinCoreIpc variant behind bitcoin-core-sv2 feature gate
tbh, that feels like a reasonable tradeoff, implementing it
| #[cfg(feature = "bitcoin-core-sv2")] | ||
| pub fn to_bitcoin_core_version(self) -> bitcoin_core_sv2::common::BitcoinCoreVersion { | ||
| bitcoin_core_sv2::common::BitcoinCoreVersion::try_from(self.as_major()) | ||
| .expect("BitcoinCoreIpcVersion and BitcoinCoreVersion majors must stay aligned") | ||
| } |
There was a problem hiding this comment.
Shouldn't this be a from instead of try_from, considering we already converted from config to BitcoinCoreIpcVersion enum and after than any conversion should be lossless.
There was a problem hiding this comment.
based on the adaptations from #548 (comment), this is no longer relevant
| } | ||
| } | ||
|
|
||
| impl TryFrom<u16> for BitcoinCoreIpcVersion { |
There was a problem hiding this comment.
based on the adaptations from #548 (comment), this is no longer relevant
| #[async_trait::async_trait(?Send)] | ||
| pub trait Sv2TemplateDistributionProtocol { | ||
| async fn run(&mut self); | ||
| } | ||
|
|
||
| /// Version-agnostic TDP runtime handle. | ||
| /// | ||
| /// Instances are created with [`new`], which selects the concrete backend for the requested | ||
| /// [`BitcoinCoreVersion`]. | ||
| pub type BitcoinCoreSv2TDP = Box<dyn Sv2TemplateDistributionProtocol>; |
There was a problem hiding this comment.
We can model it via enums having a common interface, something like this:
pub enum BitcoinCoreSv2TDP {
V30X(v30x::template_distribution_protocol::BitcoinCoreSv2TDP),
V31X(v31x::template_distribution_protocol::BitcoinCoreSv2TDP),
}
impl BitcoinCoreSv2TDP {
pub async fn run(&mut self) {
match self {
Self::V30X(runtime) => runtime.run().await,
Self::V31X(runtime) => runtime.run().await,
}
}
}There was a problem hiding this comment.
Would help in removal of async_trait and vtable lookup
There was a problem hiding this comment.
when I originally wrote the scope of #516 I explicitly mentioned the introduction of traits on the common module, which would serve the purpose of establishing clear interfaces for which all different version implementations would follow
but the implementation converged towards a very thin trait interface (limited to a single run method), which honestly makes it not so much valuable anymore
I think this suggestion makes sense, since we'd still be following the same run pattern, while enforcing it inside the match
so yeah thanks for the suggestion @Shourya742 implementing it
| async fn run(&mut self) { | ||
| BitcoinCoreSv2TDP::run(self).await; | ||
| } | ||
| } |
There was a problem hiding this comment.
This can removed with enum dispatch.
| #[async_trait::async_trait(?Send)] | ||
| pub trait Sv2JobDeclarationProtocol { | ||
| async fn run(&self); | ||
| } | ||
|
|
||
| /// Version-agnostic JDP runtime handle. | ||
| /// | ||
| /// Instances are created with [`new`], which selects the concrete backend for the requested | ||
| /// [`BitcoinCoreVersion`]. | ||
| pub type BitcoinCoreSv2JDP = Box<dyn Sv2JobDeclarationProtocol>; |
There was a problem hiding this comment.
The enum variant for this can be very similar?
pub enum BitcoinCoreSv2JDP {
V30X(v30x::job_declaration_protocol::BitcoinCoreSv2JDP),
V31X(v31x::job_declaration_protocol::BitcoinCoreSv2JDP),
}
impl BitcoinCoreSv2JDP {
pub async fn run(&self) {
match self {
Self::V30X(runtime) => runtime.run().await,
Self::V31X(runtime) => runtime.run().await,
}
}
}| #[derive(Debug)] | ||
| pub struct BitcoinCoreSv2JDPError { | ||
| version: BitcoinCoreVersion, | ||
| details: String, | ||
| } | ||
|
|
||
| impl fmt::Display for BitcoinCoreSv2JDPError { | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| write!( | ||
| f, | ||
| "failed to initialize bitcoin_core_sv2 JDP for v{}: {}", | ||
| self.version.as_major(), | ||
| self.details | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| impl std::error::Error for BitcoinCoreSv2JDPError {} |
There was a problem hiding this comment.
We can abstract it out with common Error from common module
| impl BitcoinCoreVersion { | ||
| pub const fn as_major(self) -> u8 { | ||
| match self { | ||
| Self::V30X => 30, | ||
| Self::V31X => 31, | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Maybe the new methods can become part of the version fields itself, instead of us having to pass version in the new constructor:
pub async fn new_jdp<P>(
self,
bitcoin_core_unix_socket_path: P,
incoming_requests: async_channel::Receiver<job_declaration_protocol::io::JdRequest>,
cancellation_token: tokio_util::sync::CancellationToken,
ready_tx: tokio::sync::oneshot::Sender<()>,
) -> Result<job_declaration_protocol::BitcoinCoreSv2JDP, BitcoinCoreSv2Error>
where
P: AsRef<std::path::Path>,
{
...
}
/// Builds a TDP runtime for this Bitcoin Core IPC schema family.
#[allow(clippy::too_many_arguments)]
pub async fn new_tdp<P>(
self,
bitcoin_core_unix_socket_path: P,
fee_threshold: u64,
min_interval: u8,
incoming_messages: async_channel::Receiver<
stratum_core::parsers_sv2::TemplateDistribution<'static>,
>,
outgoing_messages: async_channel::Sender<
stratum_core::parsers_sv2::TemplateDistribution<'static>,
>,
global_cancellation_token: tokio_util::sync::CancellationToken,
) -> Result<template_distribution_protocol::BitcoinCoreSv2TDP, BitcoinCoreSv2Error>
where
P: AsRef<std::path::Path>,
{
...
}specific version association attached to version itself.
There was a problem hiding this comment.
I experimented with this but I didn't like the result... adding a new_jdp/new_tdp constructors to BitcoinCoreVersion feels like we're mixing abstractions
keeping as-is
| @@ -0,0 +1,126 @@ | |||
| //! Local mempool mirror for Bitcoin Core v31.x Sv2 Job Declaration Protocol via capnp over UNIX | |||
There was a problem hiding this comment.
Can we move the common module at the same level as versioning module?
There was a problem hiding this comment.
I think its the same file as v30x?
There was a problem hiding this comment.
that's similar to what's already been discussed here: #548 (comment)
Can we move the common module at the same level as versioning module?
tbh if we were to do this, we should apply the same pattern across the entire crate, which is the scope of #574
There was a problem hiding this comment.
I just read the issue, with the current structuring it won't be easy for us to remove duplication. I am now thinking whether it will be viable to have version based distinct implementation, like in a method, based on version we can have different implementation (via match). What you think of this?
There was a problem hiding this comment.
when I discussed this with @GitGab19 the consensus was to leave code de-duplication as something to be solved later.
I also don't fully understand what you're trying to say on the comment above.
with the current structuring it won't be easy for us to remove duplication.
by "current structuring" do you mean what is being done on this PR or what's proposed on #574?
I am now thinking whether it will be viable to have version based distinct implementation, like in a method, based on version we can have different implementation (via match). What you think of this?
assuming this suggestion is meant to be taken as an alternative approach to #574, I first need to understand what you understand as a problem with what was proposed there
and also, do you think this is something that needs to be addressed now?
if not, we should discuss it under #574 and not here
798d191 to
c89290e
Compare
c89290e to
91a3d9e
Compare
868fd8a to
c9ea2b7
Compare
close #516
in summary:
bitcoin_core_sv2now supports both Bitcoin Core IPC v30.x and v31.x via one common API with versioned backends.template_provider_type.BitcoinCoreIpc.versionis now required (30or31) and wired through Pool/JDC/JDS runtime selection.POOL_BITCOIN_CORE_IPC_VERSIONJDC_BITCOIN_CORE_IPC_VERSIONnote: should be merged after #545