diff --git a/Cargo.lock b/Cargo.lock index eae89f6c4e..08a824f335 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -734,7 +734,7 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "job_declaration_sv2" -version = "7.1.0" +version = "8.0.0" dependencies = [ "binary_sv2", ] diff --git a/stratum-core/Cargo.toml b/stratum-core/Cargo.toml index c491ac440a..21f6bd42d6 100644 --- a/stratum-core/Cargo.toml +++ b/stratum-core/Cargo.toml @@ -24,7 +24,7 @@ channels_sv2 = { path = "../sv2/channels-sv2", version = "^6.0.0" } common_messages_sv2 = { path = "../sv2/subprotocols/common-messages", version = "^7.2.0" } mining_sv2 = { path = "../sv2/subprotocols/mining", version = "^10.0.0" } template_distribution_sv2 = { path = "../sv2/subprotocols/template-distribution", version = "^5.1.0" } -job_declaration_sv2 = { path = "../sv2/subprotocols/job-declaration", version = "^7.1.0" } +job_declaration_sv2 = { path = "../sv2/subprotocols/job-declaration", version = "^8.0.0" } sv1_api = { path = "../sv1", version = "^4.0.0", optional = true } stratum_translation = { path = "stratum-translation", version = "^0.3.0", optional = true } bitcoin = { workspace = true } diff --git a/sv2/handlers-sv2/Cargo.toml b/sv2/handlers-sv2/Cargo.toml index 0e618c7af1..564a26d044 100644 --- a/sv2/handlers-sv2/Cargo.toml +++ b/sv2/handlers-sv2/Cargo.toml @@ -18,6 +18,6 @@ common_messages_sv2 = { path = "../subprotocols/common-messages", version = "^7. framing_sv2 = { path = "../framing-sv2", version = "^6.0.0" } mining_sv2 = { path = "../subprotocols/mining", version = "^10.0.0" } template_distribution_sv2 = { path = "../subprotocols/template-distribution", version = "^5.1.0" } -job_declaration_sv2 = { path = "../subprotocols/job-declaration", version = "^7.1.0" } +job_declaration_sv2 = { path = "../subprotocols/job-declaration", version = "^8.0.0" } extensions_sv2 = { path = "../extensions-sv2", version = "^0.1.0" } trait-variant = { workspace = true } diff --git a/sv2/parsers-sv2/Cargo.toml b/sv2/parsers-sv2/Cargo.toml index e852925529..4573655b14 100644 --- a/sv2/parsers-sv2/Cargo.toml +++ b/sv2/parsers-sv2/Cargo.toml @@ -17,7 +17,7 @@ framing_sv2 = { path = "../framing-sv2", version = "^6.0.0" } common_messages_sv2 = { path = "../subprotocols/common-messages", version = "^7.2.0" } mining_sv2 = { path = "../subprotocols/mining", version = "^10.0.0" } template_distribution_sv2 = { path = "../subprotocols/template-distribution", version = "^5.1.0" } -job_declaration_sv2 = { path = "../subprotocols/job-declaration", version = "^7.1.0" } +job_declaration_sv2 = { path = "../subprotocols/job-declaration", version = "^8.0.0" } extensions_sv2 = { path = "../extensions-sv2", version = "^0.1.0" } [dev-dependencies] diff --git a/sv2/parsers-sv2/src/lib.rs b/sv2/parsers-sv2/src/lib.rs index c51d058cb6..eaeec856a7 100644 --- a/sv2/parsers-sv2/src/lib.rs +++ b/sv2/parsers-sv2/src/lib.rs @@ -1748,14 +1748,18 @@ impl<'a> TryFrom> for MiningDeviceMessages<'a> { #[cfg(test)] mod test { - use crate::{AnyMessage, Extensions, ExtensionsNegotiation, Mining}; + use crate::{AnyMessage, Extensions, ExtensionsNegotiation, JobDeclaration, Mining}; + use alloc::string::String; use alloc::vec; use alloc::vec::Vec; - use binary_sv2::{Seq064K, Sv2Option, U256}; + use binary_sv2::{Seq0255, Seq064K, Str0255, Sv2Option, B0255, B032, B064K, U256}; use codec_sv2::StandardSv2Frame; use core::convert::{TryFrom, TryInto}; use extensions_sv2::{RequestExtensions, EXTENSION_TYPE_EXTENSIONS_NEGOTIATION}; - use mining_sv2::NewMiningJob; + use job_declaration_sv2::PushSolution; + use mining_sv2::{ + NewMiningJob, SetCustomMiningJob, SetCustomMiningJobError, SetCustomMiningJobSuccess, + }; pub type Message = AnyMessage<'static>; pub type StdFrame = StandardSv2Frame; @@ -1807,6 +1811,71 @@ mod test { message_serialization_check(mining_message, CORRECTLY_SERIALIZED_MSG); } + #[test] + fn set_custom_mining_job_messages_use_channel_msg_bit() { + let messages = [ + Mining::SetCustomMiningJob(SetCustomMiningJob { + channel_id: 1, + request_id: 2, + token: B0255::try_from(vec![3]).unwrap(), + version: 4, + prev_hash: U256::try_from((5_u8..37).collect::>()).unwrap(), + min_ntime: 38, + nbits: 39, + coinbase_tx_version: 40, + coinbase_prefix: B0255::try_from(vec![41]).unwrap(), + coinbase_tx_input_n_sequence: 42, + coinbase_tx_outputs: B064K::try_from(vec![43]).unwrap(), + coinbase_tx_locktime: 44, + merkle_path: Seq0255::new(Vec::new()).unwrap(), + }), + Mining::SetCustomMiningJobSuccess(SetCustomMiningJobSuccess { + channel_id: 1, + request_id: 2, + job_id: 3, + }), + Mining::SetCustomMiningJobError(SetCustomMiningJobError { + channel_id: 1, + request_id: 2, + error_code: Str0255::try_from(String::from("invalid-channel-id")).unwrap(), + }), + ]; + + for message in messages { + let frame = StdFrame::try_from(AnyMessage::Mining(message)).unwrap(); + let mut buffer = [0; 0xffff]; + let encoded_frame_length = frame.encoded_length(); + frame.serialize(&mut buffer).unwrap(); + + assert!( + is_channel_msg(&buffer[..encoded_frame_length]), + "SetCustomMiningJob messages must set channel_msg" + ); + } + } + + #[test] + fn push_solution_serialization() { + let mut correctly_serialized_msg = vec![0, 0, 0x60, 53, 0, 0, 4, 1, 2, 3, 4]; + correctly_serialized_msg.extend(5_u8..37); + correctly_serialized_msg.extend(0x11223344_u32.to_le_bytes()); + correctly_serialized_msg.extend(0x55667788_u32.to_le_bytes()); + correctly_serialized_msg.extend(0x99aabbcc_u32.to_le_bytes()); + correctly_serialized_msg.extend(0xddeeff00_u32.to_le_bytes()); + + let job_declaration_message = + AnyMessage::JobDeclaration(JobDeclaration::PushSolution(PushSolution { + extranonce: B032::try_from(vec![1, 2, 3, 4]).unwrap(), + prev_hash: U256::try_from((5_u8..37).collect::>()).unwrap(), + nonce: 0x11223344, + ntime: 0x55667788, + nbits: 0x99aabbcc, + version: 0xddeeff00, + })); + + message_serialization_check(job_declaration_message, &correctly_serialized_msg); + } + fn message_serialization_check(message: AnyMessage<'static>, expected_result: &[u8]) { let frame = StdFrame::try_from(message).unwrap(); let encoded_frame_length = frame.encoded_length(); diff --git a/sv2/subprotocols/job-declaration/Cargo.toml b/sv2/subprotocols/job-declaration/Cargo.toml index 1c326d37b3..a60c4466ed 100644 --- a/sv2/subprotocols/job-declaration/Cargo.toml +++ b/sv2/subprotocols/job-declaration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "job_declaration_sv2" -version = "7.1.0" +version = "8.0.0" authors = ["The Stratum V2 Developers"] edition = "2021" readme = "README.md" diff --git a/sv2/subprotocols/job-declaration/src/lib.rs b/sv2/subprotocols/job-declaration/src/lib.rs index c31ea71f60..724dd327a7 100644 --- a/sv2/subprotocols/job-declaration/src/lib.rs +++ b/sv2/subprotocols/job-declaration/src/lib.rs @@ -36,8 +36,7 @@ pub const MESSAGE_TYPE_DECLARE_MINING_JOB_SUCCESS: u8 = 0x58; pub const MESSAGE_TYPE_DECLARE_MINING_JOB_ERROR: u8 = 0x59; pub const MESSAGE_TYPE_PUSH_SOLUTION: u8 = 0x60; -// In the Job Declaration protocol, the `channel_msg` bit is always unset, -// except for `PUSH_SOLUTION`, which requires a specific channel reference. +// In the Job Declaration protocol, the `channel_msg` bit is always unset. pub const CHANNEL_BIT_ALLOCATE_MINING_JOB_TOKEN: bool = false; pub const CHANNEL_BIT_ALLOCATE_MINING_JOB_TOKEN_SUCCESS: bool = false; pub const CHANNEL_BIT_DECLARE_MINING_JOB: bool = false; @@ -45,7 +44,7 @@ pub const CHANNEL_BIT_DECLARE_MINING_JOB_SUCCESS: bool = false; pub const CHANNEL_BIT_DECLARE_MINING_JOB_ERROR: bool = false; pub const CHANNEL_BIT_PROVIDE_MISSING_TRANSACTIONS: bool = false; pub const CHANNEL_BIT_PROVIDE_MISSING_TRANSACTIONS_SUCCESS: bool = false; -pub const CHANNEL_BIT_PUSH_SOLUTION: bool = true; +pub const CHANNEL_BIT_PUSH_SOLUTION: bool = false; // Commonly used DeclareMiningJobError error_code values. pub const ERROR_CODE_DECLARE_MINING_JOB_INVALID_MINING_JOB_TOKEN: &str = "invalid-mining-job-token"; diff --git a/sv2/subprotocols/job-declaration/src/push_solution.rs b/sv2/subprotocols/job-declaration/src/push_solution.rs index 25db4d7351..1d5951f303 100644 --- a/sv2/subprotocols/job-declaration/src/push_solution.rs +++ b/sv2/subprotocols/job-declaration/src/push_solution.rs @@ -19,10 +19,10 @@ pub struct PushSolution<'decoder> { pub extranonce: B032<'decoder>, /// Previous block hash. pub prev_hash: U256<'decoder>, - /// Contains the time the block was constructed as a Unix timestamp. - pub ntime: u32, /// Nonce of the block. pub nonce: u32, + /// Contains the time the block was constructed as a Unix timestamp. + pub ntime: u32, /// The bits field is compact representation of the target at the time the block was mined. pub nbits: u32, /// The version field in a Bitcoin header initially indicated protocol rule changes. [`BIP9`] @@ -40,11 +40,11 @@ impl fmt::Display for PushSolution<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "PushSolution(extranonce: {}, prev_hash: {}, ntime: {}, nonce: 0x{:08x}, nbits: 0x{:08x}, version: 0x{:08x})", + "PushSolution(extranonce: {}, prev_hash: {}, nonce: 0x{:08x}, ntime: {}, nbits: 0x{:08x}, version: 0x{:08x})", self.extranonce, self.prev_hash, - self.ntime, self.nonce, + self.ntime, self.nbits, self.version ) diff --git a/sv2/subprotocols/mining/src/lib.rs b/sv2/subprotocols/mining/src/lib.rs index c4dc234d2e..1b09d233d7 100644 --- a/sv2/subprotocols/mining/src/lib.rs +++ b/sv2/subprotocols/mining/src/lib.rs @@ -87,9 +87,9 @@ pub const CHANNEL_BIT_OPEN_EXTENDED_MINING_CHANNEL_SUCCESS: bool = false; pub const CHANNEL_BIT_OPEN_MINING_CHANNEL_ERROR: bool = false; pub const CHANNEL_BIT_OPEN_STANDARD_MINING_CHANNEL: bool = false; pub const CHANNEL_BIT_OPEN_STANDARD_MINING_CHANNEL_SUCCESS: bool = false; -pub const CHANNEL_BIT_SET_CUSTOM_MINING_JOB: bool = false; -pub const CHANNEL_BIT_SET_CUSTOM_MINING_JOB_ERROR: bool = false; -pub const CHANNEL_BIT_SET_CUSTOM_MINING_JOB_SUCCESS: bool = false; +pub const CHANNEL_BIT_SET_CUSTOM_MINING_JOB: bool = true; +pub const CHANNEL_BIT_SET_CUSTOM_MINING_JOB_ERROR: bool = true; +pub const CHANNEL_BIT_SET_CUSTOM_MINING_JOB_SUCCESS: bool = true; pub const CHANNEL_BIT_SET_EXTRANONCE_PREFIX: bool = true; pub const CHANNEL_BIT_SET_GROUP_CHANNEL: bool = false; pub const CHANNEL_BIT_MINING_SET_NEW_PREV_HASH: bool = true;