-
Notifications
You must be signed in to change notification settings - Fork 6
feat!: Add Electrum protocol v1.6 method support #11
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -235,17 +235,50 @@ impl Request for HeadersWithCheckpoint { | |
| /// fee rate (in BTC per kilobyte) required to be included within the specified number of blocks. | ||
| /// | ||
| /// See: <https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#blockchain-estimatefee> | ||
| /// The fee estimation mode passed to the server's `estimatesmartfee` RPC. | ||
| /// | ||
| /// Added in Electrum protocol v1.6. | ||
| /// | ||
| /// See: <https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#blockchain-estimatefee> | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
| pub enum EstimateFeeMode { | ||
| /// Conservative fee estimation (less likely to underestimate). | ||
| Conservative, | ||
| /// Economical fee estimation (may underestimate for faster inclusion). | ||
| Economical, | ||
| } | ||
|
|
||
| impl EstimateFeeMode { | ||
| fn as_str(&self) -> &'static str { | ||
| match self { | ||
| Self::Conservative => "CONSERVATIVE", | ||
| Self::Economical => "ECONOMICAL", | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
| pub struct EstimateFee { | ||
| /// The number of blocks to target for confirmation. | ||
| pub number: usize, | ||
|
|
||
| /// An optional estimation mode passed to the server's `estimatesmartfee` RPC. | ||
| /// | ||
| /// If `None`, the server uses its default mode. | ||
| /// | ||
| /// Added in Electrum protocol v1.6. | ||
| pub mode: Option<EstimateFeeMode>, | ||
| } | ||
|
|
||
| impl Request for EstimateFee { | ||
| type Response = response::EstimateFeeResp; | ||
|
|
||
| fn to_method_and_params(&self) -> MethodAndParams { | ||
| ("blockchain.estimatefee".into(), vec![self.number.into()]) | ||
| let mut params: Vec<serde_json::Value> = vec![self.number.into()]; | ||
| if let Some(mode) = &self.mode { | ||
| params.push(mode.as_str().into()); | ||
| } | ||
| ("blockchain.estimatefee".into(), params) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -271,6 +304,9 @@ impl Request for HeadersSubscribe { | |
| /// This corresponds to the `"server.relayfee"` Electrum RPC method. It returns the minimum | ||
| /// fee rate (in BTC per kilobyte) that the server will accept for relaying transactions. | ||
| /// | ||
| /// Removed in Electrum protocol v1.6 — use [`GetMempoolInfo`] (`mempool.get_info`) when | ||
| /// targeting v1.6+ servers. | ||
| /// | ||
| /// See: <https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#server-relayfee> | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
| pub struct RelayFee; | ||
|
|
@@ -589,6 +625,37 @@ impl Request for GetTxidFromPos { | |
| } | ||
| } | ||
|
|
||
| /// A request to broadcast a package of transactions to the network. | ||
| /// | ||
| /// This corresponds to the `"blockchain.transaction.broadcast_package"` Electrum RPC method, | ||
| /// which submits a package of related transactions (e.g., for CPFP or package relay). | ||
| /// | ||
| /// Added in Electrum protocol v1.6. | ||
| /// | ||
| /// See: <https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#blockchain-transaction-broadcast-package> | ||
| #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
| pub struct BroadcastPackage(pub Vec<bitcoin::Transaction>); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was looking at the documentation of this method and saw it requires two params
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good, thanks for raising this! I don't think it's an issues to ignore the |
||
|
|
||
| impl Request for BroadcastPackage { | ||
| type Response = response::BroadcastPackageResp; | ||
|
|
||
| fn to_method_and_params(&self) -> MethodAndParams { | ||
| let txs: Vec<serde_json::Value> = self | ||
| .0 | ||
| .iter() | ||
| .map(|tx| { | ||
| let mut tx_bytes = Vec::<u8>::new(); | ||
| tx.consensus_encode(&mut tx_bytes).expect("must encode"); | ||
| tx_bytes.to_lower_hex_string().into() | ||
| }) | ||
| .collect(); | ||
|
Comment on lines
+643
to
+651
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason to not use the rust-bitcoin's (e.g |
||
| ( | ||
| "blockchain.transaction.broadcast_package".into(), | ||
| vec![txs.into()], | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| /// A request for the current mempool fee histogram. | ||
| /// | ||
| /// This corresponds to the `"mempool.get_fee_histogram"` Electrum RPC method. It returns a compact | ||
|
|
@@ -607,6 +674,61 @@ impl Request for GetFeeHistogram { | |
| } | ||
| } | ||
|
|
||
| /// A request to negotiate the protocol version with the Electrum server. | ||
| /// | ||
| /// This corresponds to the `"server.version"` Electrum RPC method. It identifies the client and | ||
| /// negotiates a compatible protocol version with the server. According to the Electrum protocol | ||
| /// specification, this should be the first message sent after connecting. | ||
| /// | ||
| /// The server will select the highest protocol version that both client and server support. | ||
| /// | ||
| /// See: <https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#server-version> | ||
| #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
| pub struct ServerVersion { | ||
| /// A string identifying the client software (e.g., `"electrum_streaming_client/0.5"`). | ||
| pub client_name: CowStr, | ||
|
|
||
| /// The protocol version or version range the client supports. | ||
| /// | ||
| /// Can be a single version string (e.g., `"1.6"`) or an array-style string for a range. | ||
| pub protocol_version: CowStr, | ||
| } | ||
|
|
||
| impl Request for ServerVersion { | ||
| type Response = response::ServerVersionResp; | ||
|
|
||
| fn to_method_and_params(&self) -> MethodAndParams { | ||
| ( | ||
| "server.version".into(), | ||
| vec![ | ||
| self.client_name.as_ref().into(), | ||
| self.protocol_version.as_ref().into(), | ||
| ], | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| /// A request for general mempool information from the Electrum server. | ||
| /// | ||
| /// This corresponds to the `"mempool.get_info"` Electrum RPC method. It returns fee-related | ||
| /// parameters including `mempoolminfee`, `minrelaytxfee`, and `incrementalrelayfee`. | ||
| /// | ||
| /// This replaces the `blockchain.relayfee` method, which was removed in v1.6. | ||
| /// | ||
| /// Added in Electrum protocol v1.6. | ||
| /// | ||
| /// See: <https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#mempool-get-info> | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
| pub struct GetMempoolInfo; | ||
|
|
||
| impl Request for GetMempoolInfo { | ||
| type Response = response::MempoolInfoResp; | ||
|
|
||
| fn to_method_and_params(&self) -> MethodAndParams { | ||
| ("mempool.get_info".into(), vec![]) | ||
| } | ||
| } | ||
|
|
||
| /// A request for the Electrum server's banner message. | ||
| /// | ||
| /// This corresponds to the `"server.banner"` Electrum RPC method, which returns a server-defined | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,20 @@ use bitcoin::{ | |
|
|
||
| use crate::DoubleSHA; | ||
|
|
||
| /// Response to the `"server.version"` method. | ||
| /// | ||
| /// Returns the server's software version and the negotiated protocol version. | ||
| /// | ||
| /// See: <https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#server-version> | ||
| #[derive(Debug, Clone, serde::Deserialize)] | ||
| pub struct ServerVersionResp { | ||
| /// The server's software version string. | ||
| pub server_software: String, | ||
|
|
||
| /// The negotiated protocol version string. | ||
| pub protocol_version: String, | ||
| } | ||
|
|
||
| /// Response to the `"blockchain.block.header"` method (without checkpoint). | ||
| #[derive(Debug, Clone, serde::Deserialize, PartialEq, Eq)] | ||
| #[serde(transparent)] | ||
|
|
@@ -38,36 +52,44 @@ pub struct HeaderWithProofResp { | |
| } | ||
|
|
||
| /// Response to the `"blockchain.block.headers"` method (without checkpoint). | ||
| /// | ||
| /// Supports both the pre-1.6 format (concatenated hex in `"hex"` field) and the v1.6 format | ||
| /// (array of hex strings in `"headers"` field). | ||
| #[derive(Debug, Clone, serde::Deserialize)] | ||
| pub struct HeadersResp { | ||
| /// The number of headers returned. | ||
| pub count: usize, | ||
|
|
||
| /// The deserialized headers returned by the server. | ||
| #[serde( | ||
| rename = "hex", | ||
| deserialize_with = "crate::custom_serde::from_cancat_consensus_hex" | ||
| alias = "hex", | ||
| alias = "headers", | ||
| deserialize_with = "crate::custom_serde::headers_from_hex_or_list" | ||
| )] | ||
| pub headers: Vec<bitcoin::block::Header>, | ||
|
|
||
| /// The server’s maximum allowed headers per request. | ||
| /// The server's maximum allowed headers per request. | ||
| pub max: usize, | ||
| } | ||
|
|
||
| /// Response to the `"blockchain.block.headers"` method with a `cp_height` parameter. | ||
| /// | ||
| /// Supports both the pre-1.6 format (concatenated hex in `"hex"` field) and the v1.6 format | ||
| /// (array of hex strings in `"headers"` field). | ||
| #[derive(Debug, Clone, serde::Deserialize)] | ||
| pub struct HeadersWithCheckpointResp { | ||
| /// The number of headers returned. | ||
| pub count: usize, | ||
|
|
||
| /// The deserialized headers returned by the server. | ||
| #[serde( | ||
| rename = "hex", | ||
| deserialize_with = "crate::custom_serde::from_cancat_consensus_hex" | ||
| alias = "hex", | ||
| alias = "headers", | ||
| deserialize_with = "crate::custom_serde::headers_from_hex_or_list" | ||
| )] | ||
| pub headers: Vec<bitcoin::block::Header>, | ||
|
|
||
| /// The server’s maximum allowed headers per request. | ||
| /// The server's maximum allowed headers per request. | ||
| pub max: usize, | ||
|
|
||
| /// The Merkle root of all headers up to the checkpoint height. | ||
|
|
@@ -281,6 +303,35 @@ pub struct FeePair { | |
| pub weight: bitcoin::Weight, | ||
| } | ||
|
|
||
| /// Response to the `"blockchain.transaction.broadcast_package"` method (non-verbose mode). | ||
| /// | ||
| /// See: <https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#blockchain-transaction-broadcast-package> | ||
| #[derive(Debug, Clone, serde::Deserialize)] | ||
| pub struct BroadcastPackageResp { | ||
| /// Whether the package was accepted by the server. | ||
| pub success: bool, | ||
| } | ||
|
Comment on lines
+310
to
+313
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, it's missing the |
||
|
|
||
| /// Response to the `"mempool.get_info"` method. | ||
| /// | ||
| /// Provides fee-related information about the server's mempool. All fee rates are in BTC/kvB. | ||
| /// | ||
| /// See: <https://electrum-protocol.readthedocs.io/en/latest/protocol-methods.html#mempool-get-info> | ||
| #[derive(Debug, Clone, serde::Deserialize)] | ||
| pub struct MempoolInfoResp { | ||
| /// The minimum fee rate (BTC/kvB) for a transaction to be accepted into the mempool. | ||
| #[serde(deserialize_with = "crate::custom_serde::feerate_opt_from_btc_per_kb")] | ||
| pub mempoolminfee: Option<bitcoin::FeeRate>, | ||
|
|
||
| /// The minimum relay fee rate (BTC/kvB). | ||
| #[serde(deserialize_with = "crate::custom_serde::feerate_opt_from_btc_per_kb")] | ||
| pub minrelaytxfee: Option<bitcoin::FeeRate>, | ||
|
|
||
| /// The incremental relay fee rate (BTC/kvB). | ||
| #[serde(deserialize_with = "crate::custom_serde::feerate_opt_from_btc_per_kb")] | ||
| pub incrementalrelayfee: Option<bitcoin::FeeRate>, | ||
| } | ||
|
|
||
| /// Response to the `"server.features"` method. | ||
| #[derive(Debug, Clone, serde::Deserialize)] | ||
| pub struct ServerFeatures { | ||
|
|
||
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.
The link here doesn't point to the right method anymore given it's removed.
Maybe should be changed to https://electrum-protocol.readthedocs.io/en/latest/protocol-removed.html#blockchain.relayfee
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.
or link to the git repo and reference a tag/commit, e.g. https://github.com/spesmilo/electrum-protocol/blob/1.4.3/docs/protocol-methods.rst?plain=1#L237
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.
Agree, it's best to update it to: https://electrum-protocol.readthedocs.io/en/latest/protocol-removed.html#blockchain-relayfee, as suggested above.