From 86a6640984d3f280e49d3a6274084b4648dd688c Mon Sep 17 00:00:00 2001 From: Luna <96448399+DaOneLuna@users.noreply.github.com> Date: Tue, 9 Apr 2024 18:45:37 -0700 Subject: [PATCH] Added ability to define protocol version when serializing (#34) * Added ability to define protocol version when serializing * Switched default protocol version. Expanding RPC Server Capabilities * RPC server changes * Fixed Missing Import for metrics build * Fixed coin selection, changed from static refs to Arcs and cleaned up proof of space code * Version Bump to 2.0.3 --- cli/Cargo.toml | 15 +- cli/src/cli/mod.rs | 38 + cli/src/main.rs | 87 +- cli/src/wallets/memory_wallet.rs | 20 +- cli/src/wallets/mod.rs | 4 +- clients/Cargo.toml | 12 +- clients/src/api/pool.rs | 4 +- clients/src/websocket/farmer/mod.rs | 5 +- .../websocket/farmer/request_signed_values.rs | 22 +- clients/src/websocket/farmer/signage_point.rs | 45 +- .../harvester/harvester_handshake.rs | 14 +- .../harvester/new_signage_point_harvester.rs | 20 +- .../websocket/harvester/request_signatures.rs | 13 +- clients/src/websocket/mod.rs | 28 +- core/Cargo.toml | 6 +- core/src/blockchain/full_block.rs | 2 +- core/src/blockchain/proof_of_space.rs | 13 +- core/src/blockchain/sized_bytes.rs | 5 +- core/src/blockchain/spend_bundle.rs | 4 +- core/src/blockchain/unsized_bytes.rs | 13 +- core/src/clvm/sexp.rs | 3 +- core/src/consensus/constants.rs | 484 +++++----- core/src/pool.rs | 4 +- core/src/protocols/farmer.rs | 246 +++-- core/src/protocols/full_node.rs | 122 +-- core/src/protocols/harvester.rs | 318 +++--- core/src/protocols/introducer.rs | 4 +- core/src/protocols/mod.rs | 21 +- core/src/protocols/pool.rs | 102 +- core/src/protocols/shared.rs | 15 +- core/src/protocols/timelord.rs | 72 +- core/src/protocols/wallet.rs | 169 ++-- keys/Cargo.toml | 6 +- macros/Cargo.toml | 2 +- macros/src/lib.rs | 12 +- proof_of_space/Cargo.toml | 6 +- puzzles/Cargo.toml | 6 +- puzzles/src/clvm_puzzles.rs | 25 +- serialize/Cargo.toml | 3 +- serialize/src/lib.rs | 129 ++- servers/Cargo.toml | 15 +- servers/src/rpc/mod.rs | 387 +++++++- servers/src/websocket/farmer/handshake.rs | 25 +- servers/src/websocket/farmer/mod.rs | 13 +- .../websocket/farmer/new_proof_or_space.rs | 913 +++++++++--------- .../websocket/farmer/respond_signatures.rs | 31 +- servers/src/websocket/harvester/handshake.rs | 18 +- servers/src/websocket/harvester/mod.rs | 15 +- servers/src/websocket/mod.rs | 41 +- tests/Cargo.toml | 18 +- tests/src/clients/full_node.rs | 3 +- 51 files changed, 2223 insertions(+), 1375 deletions(-) diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 8fc48c9..b69e291 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_cli" -version = "2.0.2" +version = "2.0.3" edition = "2021" authors = ["James Hoerr"] description = "CLI Utilities for the Chia Blockchain" @@ -22,12 +22,13 @@ bip39 = {version= "2.0.0", features=["rand"] } blst = { version = "0.3.11", features = ["portable"] } clap = { version = "4.5.1", features = ["derive"] } dashmap = "5.5.3" -dg_xch_clients = {path = "../clients", version="2.0.2"} -dg_xch_core = {path = "../core", version = "2.0.2", default-features = false} -dg_xch_keys = {path = "../keys", version="2.0.2"} -dg_xch_pos = {path = "../proof_of_space", version="2.0.2"} -dg_xch_puzzles = {path = "../puzzles", version="2.0.2"} -dg_xch_serialize= {path = "../serialize", version="2.0.2"} +dialoguer = "0.11.0" +dg_xch_clients = {path = "../clients", version="2.0.3"} +dg_xch_core = {path = "../core", version = "2.0.3", default-features = false} +dg_xch_keys = {path = "../keys", version="2.0.3"} +dg_xch_pos = {path = "../proof_of_space", version="2.0.3"} +dg_xch_puzzles = {path = "../puzzles", version="2.0.3"} +dg_xch_serialize= {path = "../serialize", version="2.0.3"} hex = "0.4.3" lazy_static = "1.4.0" log = "0.4.20" diff --git a/cli/src/cli/mod.rs b/cli/src/cli/mod.rs index a4e80f9..8829734 100644 --- a/cli/src/cli/mod.rs +++ b/cli/src/cli/mod.rs @@ -1,5 +1,10 @@ +use bip39::Mnemonic; use clap::{Parser, Subcommand}; use dg_xch_core::blockchain::sized_bytes::Bytes32; +use dialoguer::theme::ColorfulTheme; +use dialoguer::Input; +use std::io::{Error, ErrorKind}; +use std::str::FromStr; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -25,6 +30,12 @@ pub struct Cli { #[derive(Debug, Subcommand)] pub enum RootCommands { + //START OF FULLNODE API + #[command(about = "Get the current BlockchainState", long_about = None)] + PrintPlottingInfo { + #[arg(long)] + launcher_id: Option, + }, //START OF FULLNODE API #[command(about = "Get the current BlockchainState", long_about = None)] GetBlockchainState, @@ -313,3 +324,30 @@ pub enum WalletAction { #[command(about = "Creates a Cold wallet", long_about = None)] Cold, } + +pub fn prompt_for_mnemonic() -> Result { + Mnemonic::from_str( + &Input::::with_theme(&ColorfulTheme::default()) + .with_prompt("Please Input Your Mnemonic: ") + .validate_with(|input: &String| -> Result<(), &str> { + if Mnemonic::from_str(input).is_ok() { + Ok(()) + } else { + Err("You did not input a valid Mnemonic, Please try again.") + } + }) + .interact_text() + .map_err(|e| { + Error::new( + ErrorKind::InvalidInput, + format!("Failed to read user Input for Mnemonic: {e:?}"), + ) + })?, + ) + .map_err(|e| { + Error::new( + ErrorKind::InvalidInput, + format!("Failed to parse Mnemonic: {e:?}"), + ) + }) +} diff --git a/cli/src/main.rs b/cli/src/main.rs index bf5fb95..477ea35 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -6,18 +6,25 @@ use cli::*; use dg_xch_cli::wallet_commands::{ create_cold_wallet, get_plotnft_ready_state, migrate_plot_nft, migrate_plot_nft_with_owner_key, }; +use dg_xch_cli::wallets::plotnft_utils::{get_plotnft_by_launcher_id, scrounge_for_plotnfts}; use dg_xch_clients::api::full_node::{FullnodeAPI, FullnodeExtAPI}; use dg_xch_clients::api::pool::create_pool_login_url; use dg_xch_clients::rpc::full_node::FullnodeClient; use dg_xch_clients::ClientSSLConfig; -use dg_xch_core::blockchain::sized_bytes::Bytes32; +use dg_xch_core::blockchain::sized_bytes::{Bytes32, Bytes48}; use dg_xch_core::blockchain::spend_bundle::SpendBundle; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_keys::{ + encode_puzzle_hash, key_from_mnemonic, master_sk_to_farmer_sk, master_sk_to_pool_sk, + master_sk_to_wallet_sk, master_sk_to_wallet_sk_unhardened, +}; +use dg_xch_puzzles::clvm_puzzles::launcher_id_to_p2_puzzle_hash; +use dg_xch_puzzles::p2_delegated_puzzle_or_hidden_puzzle::puzzle_hash_for_pk; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use hex::decode; use log::{error, info, LevelFilter}; use simple_logger::SimpleLogger; use std::env; -use std::io::{Cursor, Error}; +use std::io::{Cursor, Error, ErrorKind}; use std::sync::Arc; #[tokio::main] @@ -44,6 +51,78 @@ async fn main() -> Result<(), Error> { ssl_ca_crt_path: format!("{}/{}", v, "full_node/private_full_node.crt"), }); match cli.action { + RootCommands::PrintPlottingInfo { launcher_id } => { + let client = Arc::new(FullnodeClient::new(&host, port, timeout, ssl, &None)); + let master_key = key_from_mnemonic(&prompt_for_mnemonic()?)?; + let mut page = 0; + let mut plotnfts = vec![]; + if let Some(launcher_id) = launcher_id { + info!("Searching for NFT with LauncherID: {launcher_id}"); + if let Some(plotnft) = + get_plotnft_by_launcher_id(client.clone(), &launcher_id).await? + { + plotnfts.push(plotnft); + } else { + return Err(Error::new( + ErrorKind::NotFound, + "Failed to find a plotNFT with LauncherID: {launcher_id}", + )); + } + } else { + info!("No LauncherID Specified, Searching for PlotNFTs..."); + while page < 50 && plotnfts.is_empty() { + let mut puzzle_hashes = vec![]; + for index in page * 50..(page + 1) * 50 { + let wallet_sk = master_sk_to_wallet_sk_unhardened(&master_key, index) + .map_err(|e| { + Error::new( + ErrorKind::InvalidInput, + format!("Failed to parse Wallet SK: {:?}", e), + ) + })?; + let pub_key: Bytes48 = wallet_sk.sk_to_pk().to_bytes().into(); + puzzle_hashes.push(puzzle_hash_for_pk(&pub_key)?); + let hardened_wallet_sk = master_sk_to_wallet_sk(&master_key, index) + .map_err(|e| { + Error::new( + ErrorKind::InvalidInput, + format!("Failed to parse Wallet SK: {:?}", e), + ) + })?; + let pub_key: Bytes48 = hardened_wallet_sk.sk_to_pk().to_bytes().into(); + puzzle_hashes.push(puzzle_hash_for_pk(&pub_key)?); + } + plotnfts.extend(scrounge_for_plotnfts(client.clone(), &puzzle_hashes).await?); + page += 1; + } + } + let farmer_key = + Bytes48::from(master_sk_to_farmer_sk(&master_key)?.sk_to_pk().to_bytes()); + let pool_key = Bytes48::from(master_sk_to_pool_sk(&master_key)?.sk_to_pk().to_bytes()); + info!("{{"); + info!("\tFarmerPublicKey(All Plots): {},", farmer_key); + info!("\tPoolPublicKey(OG Plots): {},", pool_key); + info!("\tPlotNfts(NFT Plots): {{"); + let total = plotnfts.len(); + for (index, plot_nft) in plotnfts.into_iter().enumerate() { + info!("\t {{"); + info!("\t LauncherID: {},", plot_nft.launcher_id); + info!( + "\t ContractAddress: {}", + encode_puzzle_hash( + &launcher_id_to_p2_puzzle_hash( + &plot_nft.launcher_id, + plot_nft.delay_time as u64, + &plot_nft.delay_puzzle_hash, + )?, + "xch" + )? + ); + info!("\t }}{}", if index != total - 1 { "," } else { "" }); + } + info!("\t}}"); + info!("}}"); + } RootCommands::GetBlockchainState => { let client = FullnodeClient::new(&host, port, timeout, ssl, &None); let results = client.get_blockchain_state().await?; @@ -426,7 +505,7 @@ async fn main() -> Result<(), Error> { let mut cur = Cursor::new( decode(s).expect("String is not valid SpendBundle Hex"), ); - SpendBundle::from_bytes(&mut cur) + SpendBundle::from_bytes(&mut cur, ChiaProtocolVersion::default()) .expect("String is not valid SpendBundle Hex") } else { serde_json::from_str(&s).expect("String is not a valid SpendBundle") diff --git a/cli/src/wallets/memory_wallet.rs b/cli/src/wallets/memory_wallet.rs index f37939b..42ec4b0 100644 --- a/cli/src/wallets/memory_wallet.rs +++ b/cli/src/wallets/memory_wallet.rs @@ -208,12 +208,14 @@ impl WalletStore for MemoryWalletStore { } None => { let mut smaller_coin_sum = 0; //coins smaller than target. + let mut all_sum = 0; //coins smaller than target. let mut smaller_coins = vec![]; for coin in &valid_spendable_coins { if coin.amount < amount { smaller_coin_sum += coin.amount; + smaller_coins.push(coin.clone()); } - smaller_coins.push(coin.clone()); + all_sum += coin.amount; } if smaller_coin_sum == amount && smaller_coins.len() < max_num_coins @@ -228,7 +230,7 @@ impl WalletStore for MemoryWalletStore { debug!("Selected closest greater coin: {}", smallest_coin.name()); Ok(HashSet::from([smallest_coin])) } else { - return Err(Error::new(ErrorKind::InvalidInput, "Transaction of {amount} mojo would use more than {max_num_coins} coins. Try sending a smaller amount")); + return Err(Error::new(ErrorKind::InvalidInput, format!("Transaction of {amount} mojo is greater than available sum {all_sum} mojos."))); } } else if smaller_coin_sum > amount { let mut coin_set = knapsack_coin_algorithm( @@ -252,7 +254,7 @@ impl WalletStore for MemoryWalletStore { if let Some(greater_coin) = greater_coin { coin_set = Some(HashSet::from([greater_coin])); } else { - return Err(Error::new(ErrorKind::InvalidInput, "Transaction of {amount} mojo would use more than {max_num_coins} coins. Try sending a smaller amount")); + return Err(Error::new(ErrorKind::InvalidInput, format!("Transaction of {amount} mojo would use more than {max_num_coins} coins. Try sending a smaller amount"))); } } } @@ -350,16 +352,12 @@ fn check_for_exact_match(coin_list: &[Coin], target: u64) -> Option { } fn select_smallest_coin_over_target(target: u64, sorted_coin_list: &[Coin]) -> Option { - if sorted_coin_list[0].amount < target { - None - } else { - for coin in sorted_coin_list.iter().rev() { - if coin.amount >= target { - return Some(coin.clone()); - } + for coin in sorted_coin_list.iter() { + if coin.amount >= target { + return Some(coin.clone()); } - None } + None } fn sum_largest_coins(target: u128, sorted_coins: &[Coin]) -> Option> { diff --git a/cli/src/wallets/mod.rs b/cli/src/wallets/mod.rs index 1b323b5..d118a7b 100644 --- a/cli/src/wallets/mod.rs +++ b/cli/src/wallets/mod.rs @@ -22,7 +22,7 @@ use dg_xch_puzzles::utils::{ make_assert_puzzle_announcement, make_create_coin_announcement, make_create_coin_condition, make_create_puzzle_announcement, make_reserve_fee_condition, }; -use dg_xch_serialize::{hash_256, ChiaSerialize}; +use dg_xch_serialize::{hash_256, ChiaProtocolVersion, ChiaSerialize}; use log::{debug, info}; use num_traits::ToPrimitive; use std::cmp::max; @@ -536,7 +536,7 @@ pub trait Wallet { ); } let message = hash_256(message_list.iter().fold(vec![], |mut v, e| { - v.extend(e.to_bytes()); + v.extend(e.to_bytes(ChiaProtocolVersion::default())); v })); let coin_announcements = HashSet::from([message.clone()]); diff --git a/clients/Cargo.toml b/clients/Cargo.toml index 080246e..311502f 100644 --- a/clients/Cargo.toml +++ b/clients/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_clients" -version = "2.0.2" +version = "2.0.3" edition = "2021" authors = ["James Hoerr"] description = "RPC and Websocket Clients the Chia Blockchain" @@ -12,11 +12,11 @@ repository = "https://github.com/GalactechsLLC/dg_xch_utils" async-trait = "0.1.77" blst = "0.3.11" dashmap = "5.5.3" -dg_xch_core = {path = "../core", version = "2.0.2", default-features = false} -dg_xch_keys = {path = "../keys", version="2.0.2"} -dg_xch_macros = {path = "../macros", version="2.0.2"} -dg_xch_pos = {path = "../proof_of_space", version="2.0.2"} -dg_xch_serialize = {path = "../serialize", version="2.0.2"} +dg_xch_core = {path = "../core", version = "2.0.3", default-features = false} +dg_xch_keys = {path = "../keys", version="2.0.3"} +dg_xch_macros = {path = "../macros", version="2.0.3"} +dg_xch_pos = {path = "../proof_of_space", version="2.0.3"} +dg_xch_serialize = {path = "../serialize", version="2.0.3"} futures-util = "0.3.30" hex = "0.4.3" hyper = {version="1.1.0", features=["full"]} diff --git a/clients/src/api/pool.rs b/clients/src/api/pool.rs index 434e913..eaab89b 100644 --- a/clients/src/api/pool.rs +++ b/clients/src/api/pool.rs @@ -8,7 +8,7 @@ use dg_xch_core::protocols::pool::{ GetPoolInfoResponse, PoolError, PoolErrorCode, PostFarmerRequest, PostFarmerResponse, PostPartialRequest, PostPartialResponse, PutFarmerRequest, PutFarmerResponse, }; -use dg_xch_serialize::{hash_256, ChiaSerialize}; +use dg_xch_serialize::{hash_256, ChiaProtocolVersion, ChiaSerialize}; use log::warn; use reqwest::{Client, RequestBuilder}; use serde::de::DeserializeOwned; @@ -243,7 +243,7 @@ pub async fn create_pool_login_parts( target_puzzle_hash: pool_info.target_puzzle_hash, authentication_token: current_auth_token, }; - let to_sign = hash_256(payload.to_bytes()); + let to_sign = hash_256(payload.to_bytes(ChiaProtocolVersion::default())); let sig = sign(sec_key, &to_sign); sigs.push(sig); } diff --git a/clients/src/websocket/farmer/mod.rs b/clients/src/websocket/farmer/mod.rs index ec3e26a..e732a49 100644 --- a/clients/src/websocket/farmer/mod.rs +++ b/clients/src/websocket/farmer/mod.rs @@ -28,7 +28,8 @@ impl FarmerClient { ) -> Result { let constants = CONSENSUS_CONSTANTS_MAP .get(&client_config.network_id) - .unwrap_or(&MAINNET); + .cloned() + .unwrap_or(MAINNET.clone()); let handles = Arc::new(RwLock::new(handles(constants, shared_state.clone()))); let client = WsClient::new(client_config, NodeType::Farmer, handles, run).await?; Ok(FarmerClient { @@ -48,7 +49,7 @@ impl FarmerClient { } fn handles( - constants: &'static ConsensusConstants, + constants: Arc, shared_state: Arc>, ) -> HashMap> { HashMap::from([ diff --git a/clients/src/websocket/farmer/request_signed_values.rs b/clients/src/websocket/farmer/request_signed_values.rs index 62a0c76..e059c1e 100644 --- a/clients/src/websocket/farmer/request_signed_values.rs +++ b/clients/src/websocket/farmer/request_signed_values.rs @@ -6,7 +6,7 @@ use dg_xch_core::protocols::harvester::{ RequestSignatures, SignatureRequestSourceData, SigningDataKind, }; use dg_xch_core::protocols::{ChiaMessage, MessageHandler, PeerMap, ProtocolMessageTypes}; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use std::collections::HashMap; use std::io::{Cursor, Error, ErrorKind}; use std::sync::Arc; @@ -23,11 +23,17 @@ impl MessageHandler for RequestSignedValuesHandle { async fn handle( &self, msg: Arc, - _peer_id: Arc, - _peers: PeerMap, + peer_id: Arc, + peers: PeerMap, ) -> Result<(), Error> { let mut cursor = Cursor::new(&msg.data); - let request = RequestSignedValues::from_bytes(&mut cursor)?; + let peer = peers.read().await.get(&peer_id).cloned(); + let protocol_version = if let Some(peer) = peer.as_ref() { + *peer.protocol_version.read().await + } else { + ChiaProtocolVersion::default() + }; + let request = RequestSignedValues::from_bytes(&mut cursor, protocol_version)?; if let Some(identifier) = self .quality_to_identifiers .read() @@ -42,6 +48,7 @@ impl MessageHandler for RequestSignedValuesHandle { .get(&identifier.peer_node_id) .cloned() { + let protocol_version = *peer.protocol_version.read().await; let mut foliage_block_data = None; let mut foliage_transaction_block = None; let mut include_source_data = false; @@ -49,14 +56,14 @@ impl MessageHandler for RequestSignedValuesHandle { include_source_data = true; foliage_block_data = Some(SignatureRequestSourceData { kind: SigningDataKind::FoliageBlockData, - data: data.to_bytes(), + data: data.to_bytes(protocol_version), }); } if let Some(data) = request.foliage_transaction_block_data { include_source_data = true; foliage_transaction_block = Some(SignatureRequestSourceData { kind: SigningDataKind::FoliageTransactionBlock, - data: data.to_bytes(), + data: data.to_bytes(protocol_version), }); } let _ = peer @@ -66,6 +73,7 @@ impl MessageHandler for RequestSignedValuesHandle { .send(Message::Binary( ChiaMessage::new( ProtocolMessageTypes::RequestSignatures, + protocol_version, &RequestSignatures { plot_identifier: identifier.plot_identifier.clone(), challenge_hash: identifier.challenge_hash, @@ -83,7 +91,7 @@ impl MessageHandler for RequestSignedValuesHandle { }, None, ) - .to_bytes(), + .to_bytes(protocol_version), )) .await; } diff --git a/clients/src/websocket/farmer/signage_point.rs b/clients/src/websocket/farmer/signage_point.rs index b4c7ee5..4c82539 100644 --- a/clients/src/websocket/farmer/signage_point.rs +++ b/clients/src/websocket/farmer/signage_point.rs @@ -12,7 +12,7 @@ use dg_xch_core::protocols::harvester::{NewSignagePointHarvester, PoolDifficulty use dg_xch_core::protocols::{ ChiaMessage, MessageHandler, NodeType, PeerMap, ProtocolMessageTypes, SocketPeer, }; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use log::{debug, info, warn}; use std::collections::HashMap; use std::io::{Cursor, Error}; @@ -22,7 +22,7 @@ use tokio::sync::RwLock; use tokio_tungstenite::tungstenite::Message; pub struct NewSignagePointHandle { - pub constants: &'static ConsensusConstants, + pub constants: Arc, pub harvester_peers: PeerMap, pub signage_points: Arc>>>, pub pool_state: Arc>>, @@ -37,11 +37,17 @@ impl MessageHandler for NewSignagePointHandle { async fn handle( &self, msg: Arc, - _peer_id: Arc, - _peers: PeerMap, + peer_id: Arc, + peers: PeerMap, ) -> Result<(), Error> { let mut cursor = Cursor::new(&msg.data); - let sp = NewSignagePoint::from_bytes(&mut cursor)?; + let peer = peers.read().await.get(&peer_id).cloned(); + let protocol_version = if let Some(peer) = peer.as_ref() { + *peer.protocol_version.read().await + } else { + ChiaProtocolVersion::default() + }; + let sp = NewSignagePoint::from_bytes(&mut cursor, protocol_version)?; let mut pool_difficulties = vec![]; for (p2_singleton_puzzle_hash, pool_dict) in self.pool_state.read().await.iter() { if let Some(config) = &pool_dict.pool_config { @@ -73,16 +79,8 @@ impl MessageHandler for NewSignagePointHandle { signage_point_index: sp.signage_point_index, sp_hash: sp.challenge_chain_sp, pool_difficulties, - filter_prefix_bits: calculate_prefix_bits(self.constants, sp.peak_height), + filter_prefix_bits: calculate_prefix_bits(self.constants.as_ref(), sp.peak_height), }; - let msg = Message::Binary( - ChiaMessage::new( - ProtocolMessageTypes::NewSignagePointHarvester, - &harvester_point, - None, - ) - .to_bytes(), - ); let peers: Vec> = self .harvester_peers .read() @@ -92,7 +90,24 @@ impl MessageHandler for NewSignagePointHandle { .collect(); for peer in peers { if *peer.node_type.read().await == NodeType::Harvester { - let _ = peer.websocket.write().await.send(msg.clone()).await; + let protocol_version = *peer.protocol_version.read().await; + let _ = peer + .websocket + .write() + .await + .send( + Message::Binary( + ChiaMessage::new( + ProtocolMessageTypes::NewSignagePointHarvester, + protocol_version, + &harvester_point, + None, + ) + .to_bytes(protocol_version), + ) + .clone(), + ) + .await; } } { diff --git a/clients/src/websocket/harvester/harvester_handshake.rs b/clients/src/websocket/harvester/harvester_handshake.rs index eeb1153..e93c753 100644 --- a/clients/src/websocket/harvester/harvester_handshake.rs +++ b/clients/src/websocket/harvester/harvester_handshake.rs @@ -3,7 +3,7 @@ use dg_xch_core::blockchain::sized_bytes::Bytes32; use dg_xch_core::protocols::harvester::{HarvesterHandshake, HarvesterState}; use dg_xch_core::protocols::{ChiaMessage, MessageHandler, PeerMap}; use dg_xch_pos::PlotManagerAsync; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use log::{debug, info, warn}; use std::io::{Cursor, Error}; use std::sync::Arc; @@ -18,11 +18,17 @@ impl MessageHandler for HarvesterHandshakeHan async fn handle( &self, msg: Arc, - _peer_id: Arc, - _peers: PeerMap, + peer_id: Arc, + peers: PeerMap, ) -> Result<(), Error> { let mut cursor = Cursor::new(msg.data.clone()); - let handshake = HarvesterHandshake::from_bytes(&mut cursor)?; + let peer = peers.read().await.get(&peer_id).cloned(); + let protocol_version = if let Some(peer) = peer.as_ref() { + *peer.protocol_version.read().await + } else { + ChiaProtocolVersion::default() + }; + let handshake = HarvesterHandshake::from_bytes(&mut cursor, protocol_version)?; info!("Handshake from farmer: {:?}", handshake); if handshake.farmer_public_keys.is_empty() && handshake.pool_public_keys.is_empty() { warn!("Farmer Failed to send keys"); diff --git a/clients/src/websocket/harvester/new_signage_point_harvester.rs b/clients/src/websocket/harvester/new_signage_point_harvester.rs index e9a506d..79dadb2 100644 --- a/clients/src/websocket/harvester/new_signage_point_harvester.rs +++ b/clients/src/websocket/harvester/new_signage_point_harvester.rs @@ -11,7 +11,7 @@ use dg_xch_core::protocols::harvester::{NewProofOfSpace, NewSignagePointHarveste use dg_xch_core::protocols::{ChiaMessage, MessageHandler, PeerMap, ProtocolMessageTypes}; use dg_xch_pos::verifier::proof_to_bytes; use dg_xch_pos::PlotManagerAsync; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use futures_util::stream::FuturesUnordered; use futures_util::StreamExt; use hex::encode; @@ -50,8 +50,14 @@ impl MessageHandler for NewSignagePointHarves info!("Plots Not Ready Yet, skipping"); return Ok(()); } + let peer = peers.read().await.get(&peer_id).cloned(); + let protocol_version = if let Some(peer) = peer.as_ref() { + *peer.protocol_version.read().await + } else { + ChiaProtocolVersion::default() + }; let mut cursor = Cursor::new(msg.data.clone()); - let harvester_point = NewSignagePointHarvester::from_bytes(&mut cursor)?; + let harvester_point = NewSignagePointHarvester::from_bytes(&mut cursor, protocol_version)?; trace!("{:#?}", &harvester_point); let plot_counts = Arc::new(PlotCounts::default()); let harvester_point = Arc::new(harvester_point); @@ -145,7 +151,7 @@ impl MessageHandler for NewSignagePointHarves "File: {:?} Plot ID: {}, challenge: {sp_challenge_hash}, Quality Str: {}, proof: {:?}", path, &plot_id, - encode(quality.to_bytes()), + encode(quality.to_bytes(protocol_version)), encode(&proof_bytes) ); responses.push(( @@ -199,11 +205,13 @@ impl MessageHandler for NewSignagePointHarves .send(Message::Binary( ChiaMessage::new( ProtocolMessageTypes::NewProofOfSpace, + protocol_version, &NewProofOfSpace { challenge_hash: harvester_point.challenge_hash, sp_hash: harvester_point.sp_hash, - plot_identifier: encode(quality.to_bytes()) - + path.file_name.as_str(), + plot_identifier: encode( + quality.to_bytes(protocol_version), + ) + path.file_name.as_str(), proof, signage_point_index: harvester_point .signage_point_index, @@ -213,7 +221,7 @@ impl MessageHandler for NewSignagePointHarves }, None, ) - .to_bytes(), + .to_bytes(protocol_version), )) .await; if is_partial { diff --git a/clients/src/websocket/harvester/request_signatures.rs b/clients/src/websocket/harvester/request_signatures.rs index 7f85e29..0bccb18 100644 --- a/clients/src/websocket/harvester/request_signatures.rs +++ b/clients/src/websocket/harvester/request_signatures.rs @@ -7,7 +7,7 @@ use dg_xch_core::protocols::harvester::{RequestSignatures, RespondSignatures}; use dg_xch_core::protocols::{ChiaMessage, MessageHandler, PeerMap, ProtocolMessageTypes}; use dg_xch_keys::master_sk_to_local_sk; use dg_xch_pos::{PathInfo, PlotManagerAsync}; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use log::{debug, error}; use std::io::{Cursor, Error, ErrorKind}; use std::sync::Arc; @@ -27,7 +27,13 @@ impl MessageHandler for RequestSignaturesHand ) -> Result<(), Error> { debug!("{:?}", msg.msg_type); let mut cursor = Cursor::new(msg.data.clone()); - let request_signatures = RequestSignatures::from_bytes(&mut cursor)?; + let peer = peers.read().await.get(&peer_id).cloned(); + let protocol_version = if let Some(peer) = peer.as_ref() { + *peer.protocol_version.read().await + } else { + ChiaProtocolVersion::default() + }; + let request_signatures = RequestSignatures::from_bytes(&mut cursor, protocol_version)?; let file_name = request_signatures.plot_identifier.split_at(64).1; let memo = match self.plot_manager.read().await.plots().get(&PathInfo { path: Default::default(), @@ -64,6 +70,7 @@ impl MessageHandler for RequestSignaturesHand .send(Message::Binary( ChiaMessage::new( ProtocolMessageTypes::RespondSignatures, + protocol_version, &RespondSignatures { plot_identifier: request_signatures.plot_identifier, challenge_hash: request_signatures.challenge_hash, @@ -76,7 +83,7 @@ impl MessageHandler for RequestSignaturesHand }, msg.id, ) - .to_bytes(), + .to_bytes(protocol_version), )) .await; } else { diff --git a/clients/src/websocket/mod.rs b/clients/src/websocket/mod.rs index 7a1b42e..8ec1e89 100644 --- a/clients/src/websocket/mod.rs +++ b/clients/src/websocket/mod.rs @@ -6,9 +6,7 @@ pub mod wallet; use crate::ClientSSLConfig; use async_trait::async_trait; use dg_xch_core::blockchain::sized_bytes::{Bytes32, SizedBytes}; -use dg_xch_core::protocols::shared::{ - Handshake, NoCertificateVerification, CAPABILITIES, PROTOCOL_VERSION, -}; +use dg_xch_core::protocols::shared::{Handshake, NoCertificateVerification, CAPABILITIES}; use dg_xch_core::protocols::{ ChiaMessage, ChiaMessageFilter, ChiaMessageHandler, MessageHandler, NodeType, SocketPeer, WebsocketConnection, @@ -18,7 +16,7 @@ use dg_xch_core::ssl::{ generate_ca_signed_cert_data, load_certs, load_certs_from_bytes, load_private_key, load_private_key_from_bytes, CHIA_CA_CRT, CHIA_CA_KEY, }; -use dg_xch_serialize::{hash_256, ChiaSerialize}; +use dg_xch_serialize::{hash_256, ChiaProtocolVersion, ChiaSerialize}; use log::debug; use reqwest::header::{HeaderName, HeaderValue}; use rustls::{Certificate, ClientConfig, PrivateKey}; @@ -217,17 +215,21 @@ impl WsClient { *peer_id.as_ref(), Arc::new(SocketPeer { node_type: Arc::new(RwLock::new(NodeType::Harvester)), + protocol_version: Arc::new(RwLock::new(ChiaProtocolVersion::default())), websocket: connection.clone(), }), ); let handle_run = run.clone(); + let protocol_version = client_config.protocol_version; let ws_client = WsClient { connection, client_config, handle: tokio::spawn(async move { stream.run(handle_run).await }), run, }; - ws_client.perform_handshake(node_type).await?; + ws_client + .perform_handshake(node_type, protocol_version) + .await?; Ok(ws_client) } @@ -246,14 +248,19 @@ impl WsClient { self.handle.is_finished() } - async fn perform_handshake(&self, node_type: NodeType) -> Result { + async fn perform_handshake( + &self, + node_type: NodeType, + chia_protocol_version: ChiaProtocolVersion, + ) -> Result { oneshot::( self.connection.clone(), ChiaMessage::new( ProtocolMessageTypes::Handshake, + chia_protocol_version, &Handshake { network_id: self.client_config.network_id.to_string(), - protocol_version: PROTOCOL_VERSION.to_string(), + protocol_version: chia_protocol_version.to_string(), software_version: version(), server_port: self.client_config.port, node_type: node_type as u8, @@ -265,6 +272,7 @@ impl WsClient { None, ), Some(ProtocolMessageTypes::Handshake), + chia_protocol_version, None, Some(15000), ) @@ -279,6 +287,7 @@ pub struct WsClientConfig { pub ssl_info: Option, //Used to control software version sent to server, default is dg_xch_clients: VERSION pub software_version: Option, + pub protocol_version: ChiaProtocolVersion, pub additional_headers: Option>, } @@ -310,6 +319,7 @@ pub async fn oneshot( connection: Arc>, msg: ChiaMessage, resp_type: Option, + protocol_version: ChiaProtocolVersion, msg_id: Option, timeout: Option, ) -> Result { @@ -360,8 +370,8 @@ pub async fn oneshot( let res = res?; if let Some(v) = res { let mut cursor = Cursor::new(v); - connection.write().await.unsubscribe(handle.id).await; - R::from_bytes(&mut cursor).map_err(|e| { + connection.read().await.unsubscribe(handle.id).await; + R::from_bytes(&mut cursor, protocol_version).map_err(|e| { Error::new( ErrorKind::InvalidData, format!("Failed to parse msg: {:?}", e), diff --git a/core/Cargo.toml b/core/Cargo.toml index 18fcea4..755d858 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_core" -version = "2.0.2" +version = "2.0.3" edition = "2021" authors = ["James Hoerr"] description = "Core library containing type/error definitions, CLVM tools, Consensus and Pool definitions" @@ -16,8 +16,8 @@ bls12_381 = "0.8.0" blst = { version = "0.3.11", features = ["portable"] } bytes = "1.5.0" der = "0.7.8" -dg_xch_macros = {path = "../macros", version="2.0.2"} -dg_xch_serialize = {path = "../serialize", version="2.0.2"} +dg_xch_macros = {path = "../macros", version="2.0.3"} +dg_xch_serialize = {path = "../serialize", version="2.0.3"} futures-util = "0.3.30" hex = "0.4.3" hkdf = "0.12.4" diff --git a/core/src/blockchain/full_block.rs b/core/src/blockchain/full_block.rs index 677dbda..a93e2ba 100644 --- a/core/src/blockchain/full_block.rs +++ b/core/src/blockchain/full_block.rs @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; pub struct FullBlock { pub finished_sub_slots: Vec, pub reward_chain_block: RewardChainBlock, - pub challenge_chain_sp_proof: VdfProof, + pub challenge_chain_sp_proof: Option, pub challenge_chain_ip_proof: VdfProof, pub reward_chain_sp_proof: Option, pub reward_chain_ip_proof: VdfProof, diff --git a/core/src/blockchain/proof_of_space.rs b/core/src/blockchain/proof_of_space.rs index 3f37f68..32c8413 100644 --- a/core/src/blockchain/proof_of_space.rs +++ b/core/src/blockchain/proof_of_space.rs @@ -2,7 +2,7 @@ use crate::blockchain::sized_bytes::{prep_hex_str, Bytes32, Bytes48, SizedBytes} use crate::consensus::constants::ConsensusConstants; use blst::min_pk::{AggregatePublicKey, PublicKey, SecretKey}; use dg_xch_macros::ChiaSerial; -use dg_xch_serialize::{hash_256, ChiaSerialize}; +use dg_xch_serialize::{hash_256, ChiaProtocolVersion, ChiaSerialize}; use hex::{decode, encode}; use serde::de::Visitor; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -34,18 +34,21 @@ impl Debug for ProofBytes { } impl ChiaSerialize for ProofBytes { - fn to_bytes(&self) -> Vec + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec where Self: Sized, { - ChiaSerialize::to_bytes(&self.0) + ChiaSerialize::to_bytes(&self.0, version) } - fn from_bytes>(bytes: &mut Cursor) -> Result + fn from_bytes>( + bytes: &mut Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - Ok(Self(ChiaSerialize::from_bytes(bytes)?)) + Ok(Self(ChiaSerialize::from_bytes(bytes, version)?)) } } diff --git a/core/src/blockchain/sized_bytes.rs b/core/src/blockchain/sized_bytes.rs index 30ff7c7..0e15ccf 100644 --- a/core/src/blockchain/sized_bytes.rs +++ b/core/src/blockchain/sized_bytes.rs @@ -1,6 +1,7 @@ use crate::clvm::program::Program; use blst::min_pk::{PublicKey, SecretKey, Signature}; use bytes::Buf; +use dg_xch_serialize::ChiaProtocolVersion; use dg_xch_serialize::ChiaSerialize; use hex::FromHexError; use hex::{decode, encode}; @@ -330,10 +331,10 @@ macro_rules! impl_sized_bytes_serial { ($($name: ident, $size:expr);*) => { $( impl ChiaSerialize for $name { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self, _version: ChiaProtocolVersion) -> Vec { self.to_sized_bytes().to_vec() } - fn from_bytes>(bytes: &mut Cursor) -> Result where Self: Sized, + fn from_bytes>(bytes: &mut Cursor, _version: ChiaProtocolVersion) -> Result where Self: Sized, { if bytes.remaining() < $size { Err(Error::new(ErrorKind::InvalidInput, format!("Failed to Parse {}, expected length {}, found {}", stringify!($name), $size, bytes.remaining()))) diff --git a/core/src/blockchain/spend_bundle.rs b/core/src/blockchain/spend_bundle.rs index 79cae2d..88750cc 100644 --- a/core/src/blockchain/spend_bundle.rs +++ b/core/src/blockchain/spend_bundle.rs @@ -5,7 +5,7 @@ use crate::blockchain::sized_bytes::{Bytes32, Bytes96}; use crate::clvm::program::Program; use blst::min_pk::{AggregateSignature, Signature}; use dg_xch_macros::ChiaSerial; -use dg_xch_serialize::{hash_256, ChiaSerialize}; +use dg_xch_serialize::{hash_256, ChiaProtocolVersion, ChiaSerialize}; use serde::{Deserialize, Serialize}; use std::collections::HashSet; use std::io::{Error, ErrorKind}; @@ -17,7 +17,7 @@ pub struct SpendBundle { } impl SpendBundle { pub fn name(&self) -> Bytes32 { - Bytes32::new(&hash_256(self.to_bytes())) + Bytes32::new(&hash_256(self.to_bytes(ChiaProtocolVersion::default()))) } pub fn aggregate(bundles: Vec) -> Result { let mut coin_spends = vec![]; diff --git a/core/src/blockchain/unsized_bytes.rs b/core/src/blockchain/unsized_bytes.rs index 1e38549..10c9b4a 100644 --- a/core/src/blockchain/unsized_bytes.rs +++ b/core/src/blockchain/unsized_bytes.rs @@ -1,6 +1,6 @@ use crate::blockchain::sized_bytes::{prep_hex_str, SizedBytes}; use crate::clvm::program::Program; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use hex::{decode, encode}; use serde::de::Visitor; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -145,14 +145,17 @@ impl fmt::Debug for UnsizedBytes { } } impl ChiaSerialize for UnsizedBytes { - fn to_bytes(&self) -> Vec { - self.bytes.to_bytes() + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec { + self.bytes.to_bytes(version) } - fn from_bytes>(bytes: &mut Cursor) -> Result + fn from_bytes>( + bytes: &mut Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - let bytes: Vec = Vec::from_bytes(bytes)?; + let bytes: Vec = Vec::from_bytes(bytes, version)?; Ok(Self { bytes }) } } diff --git a/core/src/clvm/sexp.rs b/core/src/clvm/sexp.rs index c9601d2..a79f61c 100644 --- a/core/src/clvm/sexp.rs +++ b/core/src/clvm/sexp.rs @@ -3,6 +3,7 @@ use crate::blockchain::sized_bytes::*; use crate::clvm::assemble::is_hex; use crate::clvm::assemble::keywords::KEYWORD_FROM_ATOM; use crate::clvm::program::Program; +use dg_xch_serialize::ChiaProtocolVersion; use dg_xch_serialize::ChiaSerialize; use hex::encode; use num_bigint::BigInt; @@ -463,7 +464,7 @@ impl IntoSExp for Program { impl IntoSExp for ConditionOpcode { fn to_sexp(self) -> SExp { - SExp::Atom(AtomBuf::new(self.to_bytes())) + SExp::Atom(AtomBuf::new(self.to_bytes(ChiaProtocolVersion::default()))) } } diff --git a/core/src/consensus/constants.rs b/core/src/consensus/constants.rs index c9375eb..ba7ce2f 100644 --- a/core/src/consensus/constants.rs +++ b/core/src/consensus/constants.rs @@ -2,6 +2,7 @@ use crate::blockchain::sized_bytes::Bytes32; use num_bigint::BigInt; use once_cell::sync::Lazy; use std::collections::HashMap; +use std::sync::Arc; #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct ConsensusConstants { @@ -77,247 +78,266 @@ pub struct ConsensusConstants { } impl Default for ConsensusConstants { fn default() -> Self { - MAINNET.clone() + MAINNET.as_ref().clone() } } -pub static MAINNET: Lazy = Lazy::new(|| ConsensusConstants { - slot_blocks_target: 32, - min_blocks_per_challenge_block: 16, - max_sub_slot_blocks: 128, - num_sps_sub_slot: 64, - sub_slot_iters_starting: 2u64.pow(27), - difficulty_constant_factor: 2u128.pow(67), - difficulty_starting: 7, - difficulty_change_max_factor: 3, - sub_epoch_blocks: 384, - epoch_blocks: 4608, - significant_bits: BigInt::from(8), - discriminant_size_bits: BigInt::from(1024), - number_zero_bits_plot_filter: 9, - min_plot_size: 32, - max_plot_size: 50, - sub_slot_time_target: BigInt::from(600), - num_sp_intervals_extra: 3, - max_future_time: BigInt::from(5 * 60), - max_future_time2: BigInt::from(2 * 60), - number_of_timestamps: BigInt::from(11), - genesis_challenge: Bytes32::from( - "ccd5bb71183532bff220ba46c268991a3ff07eb358e8255a65c30a2dce0e5fbb", - ), - agg_sig_me_additional_data: hex::decode( - "ccd5bb71183532bff220ba46c268991a3ff07eb358e8255a65c30a2dce0e5fbb", - ) - .expect("Failed to parse known good hex"), - genesis_pre_farm_pool_puzzle_hash: Bytes32::from( - "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", - ), - genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( - "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", - ), - max_vdf_witness_size: BigInt::from(64), - mempool_block_buffer: BigInt::from(50), - max_coin_amount: BigInt::from(u64::MAX), - max_block_cost_clvm: BigInt::from(11000000000u64), - cost_per_byte: BigInt::from(12000), - weight_proof_threshold: 2, - weight_proof_recent_blocks: 1000, - max_block_count_per_requests: 32, - blocks_cache_size: 4608 + (128 * 4), - max_generator_size: 1000000, - max_generator_ref_list_size: 512, - pool_sub_slot_iters: 37600000000, - soft_fork2_height: 0, - soft_fork3_height: 4510000, - hard_fork_height: 5496000, - hard_fork_fix_height: 5496000, - plot_filter_128_height: 10542000, - plot_filter_64_height: 15592000, - plot_filter_32_height: 20643000, - bech32_prefix: String::from("xch"), - is_testnet: false, +pub static MAINNET: Lazy> = Lazy::new(|| { + Arc::new(ConsensusConstants { + slot_blocks_target: 32, + min_blocks_per_challenge_block: 16, + max_sub_slot_blocks: 128, + num_sps_sub_slot: 64, + sub_slot_iters_starting: 2u64.pow(27), + difficulty_constant_factor: 2u128.pow(67), + difficulty_starting: 7, + difficulty_change_max_factor: 3, + sub_epoch_blocks: 384, + epoch_blocks: 4608, + significant_bits: BigInt::from(8), + discriminant_size_bits: BigInt::from(1024), + number_zero_bits_plot_filter: 9, + min_plot_size: 32, + max_plot_size: 50, + sub_slot_time_target: BigInt::from(600), + num_sp_intervals_extra: 3, + max_future_time: BigInt::from(5 * 60), + max_future_time2: BigInt::from(2 * 60), + number_of_timestamps: BigInt::from(11), + genesis_challenge: Bytes32::from( + "ccd5bb71183532bff220ba46c268991a3ff07eb358e8255a65c30a2dce0e5fbb", + ), + agg_sig_me_additional_data: hex::decode( + "ccd5bb71183532bff220ba46c268991a3ff07eb358e8255a65c30a2dce0e5fbb", + ) + .expect("Failed to parse known good hex"), + genesis_pre_farm_pool_puzzle_hash: Bytes32::from( + "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", + ), + genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( + "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", + ), + max_vdf_witness_size: BigInt::from(64), + mempool_block_buffer: BigInt::from(50), + max_coin_amount: BigInt::from(u64::MAX), + max_block_cost_clvm: BigInt::from(11000000000u64), + cost_per_byte: BigInt::from(12000), + weight_proof_threshold: 2, + weight_proof_recent_blocks: 1000, + max_block_count_per_requests: 32, + blocks_cache_size: 4608 + (128 * 4), + max_generator_size: 1000000, + max_generator_ref_list_size: 512, + pool_sub_slot_iters: 37600000000, + soft_fork2_height: 0, + soft_fork3_height: 4510000, + hard_fork_height: 5496000, + hard_fork_fix_height: 5496000, + plot_filter_128_height: 10542000, + plot_filter_64_height: 15592000, + plot_filter_32_height: 20643000, + bech32_prefix: String::from("xch"), + is_testnet: false, + }) }); -pub static TESTNET_0: Lazy = Lazy::new(|| ConsensusConstants { - genesis_challenge: Bytes32::from( - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - ), - genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( - "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", - ), - genesis_pre_farm_pool_puzzle_hash: Bytes32::from( - "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", - ), - min_plot_size: 18, - bech32_prefix: String::from("txch"), - is_testnet: true, - ..Default::default() +pub static TESTNET_0: Lazy> = Lazy::new(|| { + Arc::new(ConsensusConstants { + genesis_challenge: Bytes32::from( + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + ), + genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( + "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", + ), + genesis_pre_farm_pool_puzzle_hash: Bytes32::from( + "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", + ), + min_plot_size: 18, + bech32_prefix: String::from("txch"), + is_testnet: true, + ..Default::default() + }) }); -pub static TESTNET_2: Lazy = Lazy::new(|| ConsensusConstants { - difficulty_constant_factor: 10052721566054, - genesis_challenge: Bytes32::from( - "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", - ), - genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( - "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", - ), - genesis_pre_farm_pool_puzzle_hash: Bytes32::from( - "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", - ), - min_plot_size: 18, - bech32_prefix: String::from("txch"), - is_testnet: true, - ..Default::default() +pub static TESTNET_2: Lazy> = Lazy::new(|| { + Arc::new(ConsensusConstants { + difficulty_constant_factor: 10052721566054, + genesis_challenge: Bytes32::from( + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + ), + genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( + "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", + ), + genesis_pre_farm_pool_puzzle_hash: Bytes32::from( + "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", + ), + min_plot_size: 18, + bech32_prefix: String::from("txch"), + is_testnet: true, + ..Default::default() + }) }); -pub static TESTNET_3: Lazy = Lazy::new(|| ConsensusConstants { - difficulty_constant_factor: 10052721566054, - genesis_challenge: Bytes32::from( - "ca7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015af", - ), - genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( - "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", - ), - genesis_pre_farm_pool_puzzle_hash: Bytes32::from( - "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", - ), - mempool_block_buffer: BigInt::from(10), - min_plot_size: 18, - bech32_prefix: String::from("txch"), - is_testnet: true, - ..Default::default() +pub static TESTNET_3: Lazy> = Lazy::new(|| { + Arc::new(ConsensusConstants { + difficulty_constant_factor: 10052721566054, + genesis_challenge: Bytes32::from( + "ca7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015af", + ), + genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( + "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", + ), + genesis_pre_farm_pool_puzzle_hash: Bytes32::from( + "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", + ), + mempool_block_buffer: BigInt::from(10), + min_plot_size: 18, + bech32_prefix: String::from("txch"), + is_testnet: true, + ..Default::default() + }) }); -pub static TESTNET_4: Lazy = Lazy::new(|| ConsensusConstants { - difficulty_constant_factor: 10052721566054, - difficulty_starting: 30, - epoch_blocks: 768, - genesis_challenge: Bytes32::from( - "dd7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015af", - ), - genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( - "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", - ), - genesis_pre_farm_pool_puzzle_hash: Bytes32::from( - "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", - ), - mempool_block_buffer: BigInt::from(10), - min_plot_size: 18, - bech32_prefix: String::from("txch"), - is_testnet: true, - ..Default::default() +pub static TESTNET_4: Lazy> = Lazy::new(|| { + Arc::new(ConsensusConstants { + difficulty_constant_factor: 10052721566054, + difficulty_starting: 30, + epoch_blocks: 768, + genesis_challenge: Bytes32::from( + "dd7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015af", + ), + genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( + "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", + ), + genesis_pre_farm_pool_puzzle_hash: Bytes32::from( + "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", + ), + mempool_block_buffer: BigInt::from(10), + min_plot_size: 18, + bech32_prefix: String::from("txch"), + is_testnet: true, + ..Default::default() + }) }); -pub static TESTNET_5: Lazy = Lazy::new(|| ConsensusConstants { - difficulty_constant_factor: 10052721566054, - difficulty_starting: 30, - epoch_blocks: 768, - genesis_challenge: Bytes32::from( - "ee7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015af", - ), - genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( - "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", - ), - genesis_pre_farm_pool_puzzle_hash: Bytes32::from( - "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", - ), - mempool_block_buffer: BigInt::from(10), - min_plot_size: 18, - bech32_prefix: String::from("txch"), - is_testnet: true, - ..Default::default() +pub static TESTNET_5: Lazy> = Lazy::new(|| { + Arc::new(ConsensusConstants { + difficulty_constant_factor: 10052721566054, + difficulty_starting: 30, + epoch_blocks: 768, + genesis_challenge: Bytes32::from( + "ee7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015af", + ), + genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( + "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", + ), + genesis_pre_farm_pool_puzzle_hash: Bytes32::from( + "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", + ), + mempool_block_buffer: BigInt::from(10), + min_plot_size: 18, + bech32_prefix: String::from("txch"), + is_testnet: true, + ..Default::default() + }) }); -pub static TESTNET_7: Lazy = Lazy::new(|| ConsensusConstants { - difficulty_constant_factor: 10052721566054, - difficulty_starting: 30, - epoch_blocks: 768, - genesis_challenge: Bytes32::from( - "117816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015af", - ), - genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( - "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", - ), - genesis_pre_farm_pool_puzzle_hash: Bytes32::from( - "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", - ), - mempool_block_buffer: BigInt::from(50), - min_plot_size: 18, - bech32_prefix: String::from("txch"), - is_testnet: true, - ..Default::default() +pub static TESTNET_7: Lazy> = Lazy::new(|| { + Arc::new(ConsensusConstants { + difficulty_constant_factor: 10052721566054, + difficulty_starting: 30, + epoch_blocks: 768, + genesis_challenge: Bytes32::from( + "117816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015af", + ), + genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( + "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", + ), + genesis_pre_farm_pool_puzzle_hash: Bytes32::from( + "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", + ), + mempool_block_buffer: BigInt::from(50), + min_plot_size: 18, + bech32_prefix: String::from("txch"), + is_testnet: true, + ..Default::default() + }) }); -pub static TESTNET_10: Lazy = Lazy::new(|| ConsensusConstants { - agg_sig_me_additional_data: hex::decode( - "ae83525ba8d1dd3f09b277de18ca3e43fc0af20d20c4b3e92ef2a48bd291ccb2", - ) - .expect("Failed to parse known good hex"), - difficulty_constant_factor: 10052721566054, - difficulty_starting: 30, - epoch_blocks: 768, - genesis_challenge: Bytes32::from( - "ae83525ba8d1dd3f09b277de18ca3e43fc0af20d20c4b3e92ef2a48bd291ccb2", - ), - genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( - "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", - ), - genesis_pre_farm_pool_puzzle_hash: Bytes32::from( - "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", - ), - mempool_block_buffer: BigInt::from(10), - min_plot_size: 18, - soft_fork2_height: 3000000, - soft_fork3_height: 2997292, - // planned 2.0 release is July 26, height 2965036 on testnet - //1 week later - hard_fork_height: 2997292, - // November 2023 - hard_fork_fix_height: 3426000, - // another 2 weeks later - plot_filter_128_height: 3061804, - // 3 years later - plot_filter_64_height: 8010796, - // 3 years later - plot_filter_32_height: 13056556, - bech32_prefix: String::from("txch"), - is_testnet: true, - ..Default::default() +pub static TESTNET_10: Lazy> = Lazy::new(|| { + Arc::new(ConsensusConstants { + agg_sig_me_additional_data: hex::decode( + "ae83525ba8d1dd3f09b277de18ca3e43fc0af20d20c4b3e92ef2a48bd291ccb2", + ) + .expect("Failed to parse known good hex"), + difficulty_constant_factor: 10052721566054, + difficulty_starting: 30, + epoch_blocks: 768, + genesis_challenge: Bytes32::from( + "ae83525ba8d1dd3f09b277de18ca3e43fc0af20d20c4b3e92ef2a48bd291ccb2", + ), + genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( + "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af", + ), + genesis_pre_farm_pool_puzzle_hash: Bytes32::from( + "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc", + ), + mempool_block_buffer: BigInt::from(10), + min_plot_size: 18, + soft_fork2_height: 3000000, + soft_fork3_height: 2997292, + // planned 2.0 release is July 26, height 2965036 on testnet + //1 week later + hard_fork_height: 2997292, + // November 2023 + hard_fork_fix_height: 3426000, + // another 2 weeks later + plot_filter_128_height: 3061804, + // 3 years later + plot_filter_64_height: 8010796, + // 3 years later + plot_filter_32_height: 13056556, + bech32_prefix: String::from("txch"), + is_testnet: true, + ..Default::default() + }) }); -pub static TESTNET_11: Lazy = Lazy::new(|| ConsensusConstants { - agg_sig_me_additional_data: hex::decode( - "37a90eb5185a9c4439a91ddc98bbadce7b4feba060d50116a067de66bf236615", - ) - .expect("Failed to parse known good hex"), - difficulty_constant_factor: 10052721566054, - difficulty_starting: 30, - epoch_blocks: 768, - genesis_challenge: Bytes32::from( - "37a90eb5185a9c4439a91ddc98bbadce7b4feba060d50116a067de66bf236615", - ), - genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( - "08296fc227decd043aee855741444538e4cc9a31772c4d1a9e6242d1e777e42a", - ), - genesis_pre_farm_pool_puzzle_hash: Bytes32::from( - "3ef7c233fc0785f3c0cae5992c1d35e7c955ca37a423571c1607ba392a9d12f7", - ), - mempool_block_buffer: BigInt::from(10), - min_plot_size: 18, - sub_slot_iters_starting: 67108864, - //Forks activated from the beginning on this network - hard_fork_height: 0, - hard_fork_fix_height: 0, - plot_filter_128_height: 6029568, - plot_filter_64_height: 11075328, - plot_filter_32_height: 16121088, - bech32_prefix: String::from("txch"), - is_testnet: true, - ..Default::default() -}); -pub static CONSENSUS_CONSTANTS_MAP: Lazy> = Lazy::new(|| { - HashMap::from([ - ("testnet0".to_string(), TESTNET_0.clone()), - ("testnet2".to_string(), TESTNET_2.clone()), - ("testnet3".to_string(), TESTNET_3.clone()), - ("testnet4".to_string(), TESTNET_4.clone()), - ("testnet4".to_string(), TESTNET_5.clone()), - ("testnet7".to_string(), TESTNET_7.clone()), - ("testnet10".to_string(), TESTNET_10.clone()), - ("testnet11".to_string(), TESTNET_11.clone()), - ("mainnet".to_string(), MAINNET.clone()), - ]) +pub static TESTNET_11: Lazy> = Lazy::new(|| { + Arc::new(ConsensusConstants { + agg_sig_me_additional_data: hex::decode( + "37a90eb5185a9c4439a91ddc98bbadce7b4feba060d50116a067de66bf236615", + ) + .expect("Failed to parse known good hex"), + difficulty_constant_factor: 10052721566054, + difficulty_starting: 30, + epoch_blocks: 768, + genesis_challenge: Bytes32::from( + "37a90eb5185a9c4439a91ddc98bbadce7b4feba060d50116a067de66bf236615", + ), + genesis_pre_farm_farmer_puzzle_hash: Bytes32::from( + "08296fc227decd043aee855741444538e4cc9a31772c4d1a9e6242d1e777e42a", + ), + genesis_pre_farm_pool_puzzle_hash: Bytes32::from( + "3ef7c233fc0785f3c0cae5992c1d35e7c955ca37a423571c1607ba392a9d12f7", + ), + mempool_block_buffer: BigInt::from(10), + min_plot_size: 18, + sub_slot_iters_starting: 67108864, + //Forks activated from the beginning on this network + hard_fork_height: 0, + hard_fork_fix_height: 0, + plot_filter_128_height: 6029568, + plot_filter_64_height: 11075328, + plot_filter_32_height: 16121088, + bech32_prefix: String::from("txch"), + is_testnet: true, + ..Default::default() + }) }); +pub static CONSENSUS_CONSTANTS_MAP: Lazy>> = + Lazy::new(|| { + HashMap::from([ + ("testnet0".to_string(), TESTNET_0.clone()), + ("testnet2".to_string(), TESTNET_2.clone()), + ("testnet3".to_string(), TESTNET_3.clone()), + ("testnet4".to_string(), TESTNET_4.clone()), + ("testnet4".to_string(), TESTNET_5.clone()), + ("testnet7".to_string(), TESTNET_7.clone()), + ("testnet10".to_string(), TESTNET_10.clone()), + ("testnet11".to_string(), TESTNET_11.clone()), + ("mainnet".to_string(), MAINNET.clone()), + ]) + }); diff --git a/core/src/pool.rs b/core/src/pool.rs index 290cc92..431183e 100644 --- a/core/src/pool.rs +++ b/core/src/pool.rs @@ -2,7 +2,7 @@ use crate::blockchain::coin_spend::CoinSpend; use crate::blockchain::sized_bytes::{Bytes32, Bytes48}; use crate::clvm::program::Program; use dg_xch_macros::ChiaSerial; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use num_traits::ToPrimitive; use serde::{Deserialize, Serialize}; use std::io::{Cursor, Error, ErrorKind}; @@ -65,7 +65,7 @@ impl PoolState { .as_vec() .unwrap_or_default(), ); - Self::from_bytes(&mut cursor) + Self::from_bytes(&mut cursor, ChiaProtocolVersion::default()) } } diff --git a/core/src/protocols/farmer.rs b/core/src/protocols/farmer.rs index f8ea0c3..f4c84fe 100644 --- a/core/src/protocols/farmer.rs +++ b/core/src/protocols/farmer.rs @@ -12,8 +12,8 @@ use crate::protocols::error::RecentErrors; use crate::protocols::PeerMap; use blst::min_pk::SecretKey; use dg_xch_macros::ChiaSerial; -use hyper::body::Buf; -use log::debug; +use dg_xch_serialize::ChiaProtocolVersion; + #[cfg(feature = "metrics")] use prometheus::core::{AtomicU64, GenericGauge, GenericGaugeVec}; #[cfg(feature = "metrics")] @@ -26,80 +26,98 @@ use tokio::sync::RwLock; #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct SPSubSlotSourceData { + //First in Version 0.0.36 pub cc_sub_slot: ChallengeChainSubSlot, pub rc_sub_slot: RewardChainSubSlot, } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct SPVDFSourceData { + //First in Version 0.0.36 pub cc_vdf: ClassgroupElement, pub rc_vdf: ClassgroupElement, } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct SignagePointSourceData { + //First in Version 0.0.36 pub sub_slot_data: Option, pub vdf_data: Option, } #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewSignagePoint { - pub challenge_hash: Bytes32, - pub challenge_chain_sp: Bytes32, - pub reward_chain_sp: Bytes32, - pub difficulty: u64, - pub sub_slot_iters: u64, - pub signage_point_index: u8, - pub peak_height: u32, - pub sp_source_data: Option, + pub challenge_hash: Bytes32, //Min Version 0.0.34 + pub challenge_chain_sp: Bytes32, //Min Version 0.0.34 + pub reward_chain_sp: Bytes32, //Min Version 0.0.34 + pub difficulty: u64, //Min Version 0.0.34 + pub sub_slot_iters: u64, //Min Version 0.0.34 + pub signage_point_index: u8, //Min Version 0.0.34 + pub peak_height: u32, //Min Version 0.0.35 + pub sp_source_data: Option, //Min Version 0.0.36 } impl dg_xch_serialize::ChiaSerialize for NewSignagePoint { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec { let mut bytes = vec![]; bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.challenge_hash, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.challenge_chain_sp, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.reward_chain_sp, + version, )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.difficulty)); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.sub_slot_iters, + &self.difficulty, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.signage_point_index, + &self.sub_slot_iters, + version, )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.peak_height)); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.sp_source_data, + &self.signage_point_index, + version, )); + if version >= ChiaProtocolVersion::Chia0_0_35 { + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.peak_height, + version, + )); + } + if version >= ChiaProtocolVersion::Chia0_0_36 { + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.sp_source_data, + version, + )); + } bytes } - fn from_bytes>(bytes: &mut std::io::Cursor) -> Result + fn from_bytes>( + bytes: &mut std::io::Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let challenge_chain_sp = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let reward_chain_sp = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let difficulty = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let sub_slot_iters = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let signage_point_index = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let peak_height = if bytes.remaining() >= 4 { - //Maintain Compatibility with < Chia 2.X nodes for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let challenge_chain_sp = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let reward_chain_sp = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let difficulty = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let sub_slot_iters = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let signage_point_index = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let peak_height = if version >= ChiaProtocolVersion::Chia0_0_35 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); 0u32 }; - let sp_source_data = if bytes.remaining() > 0 { - //Maintain Compatibility with Pre Chip 22 Nodes for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let sp_source_data = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version).unwrap_or_default() } else { - debug!("You are connected to an old node version, Please update your Fullnode."); None }; Ok(Self { @@ -117,74 +135,92 @@ impl dg_xch_serialize::ChiaSerialize for NewSignagePoint { #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct DeclareProofOfSpace { - pub challenge_hash: Bytes32, - pub challenge_chain_sp: Bytes32, - pub signage_point_index: u8, - pub reward_chain_sp: Bytes32, - pub proof_of_space: ProofOfSpace, - pub challenge_chain_sp_signature: Bytes96, - pub reward_chain_sp_signature: Bytes96, - pub farmer_puzzle_hash: Bytes32, - pub pool_target: Option, - pub pool_signature: Option, - pub include_signature_source_data: bool, + pub challenge_hash: Bytes32, //Min Version 0.0.34 + pub challenge_chain_sp: Bytes32, //Min Version 0.0.34 + pub signage_point_index: u8, //Min Version 0.0.34 + pub reward_chain_sp: Bytes32, //Min Version 0.0.34 + pub proof_of_space: ProofOfSpace, //Min Version 0.0.34 + pub challenge_chain_sp_signature: Bytes96, //Min Version 0.0.34 + pub reward_chain_sp_signature: Bytes96, //Min Version 0.0.34 + pub farmer_puzzle_hash: Bytes32, //Min Version 0.0.34 + pub pool_target: Option, //Min Version 0.0.34 + pub pool_signature: Option, //Min Version 0.0.34 + pub include_signature_source_data: bool, //Min Version 0.0.36 } impl dg_xch_serialize::ChiaSerialize for DeclareProofOfSpace { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec { let mut bytes = vec![]; bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.challenge_hash, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.challenge_chain_sp, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.signage_point_index, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.reward_chain_sp, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.proof_of_space, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.challenge_chain_sp_signature, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.reward_chain_sp_signature, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.farmer_puzzle_hash, + version, )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.pool_target)); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.pool_signature, + &self.pool_target, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.include_signature_source_data, + &self.pool_signature, + version, )); + if version >= ChiaProtocolVersion::Chia0_0_36 { + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.include_signature_source_data, + version, + )); + } bytes } - fn from_bytes>(bytes: &mut std::io::Cursor) -> Result + fn from_bytes>( + bytes: &mut std::io::Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let challenge_chain_sp = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let signage_point_index = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let reward_chain_sp = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let proof_of_space = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let challenge_chain_sp_signature = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let reward_chain_sp_signature = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let farmer_puzzle_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let pool_target = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let pool_signature = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let include_signature_source_data = if bytes.remaining() > 0 { - //Maintain Compatibility with < Chia 2.X nodes for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let challenge_chain_sp = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let signage_point_index = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let reward_chain_sp = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let proof_of_space = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let challenge_chain_sp_signature = + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let reward_chain_sp_signature = + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let farmer_puzzle_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let pool_target = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let pool_signature = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let include_signature_source_data = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); false }; Ok(Self { @@ -205,62 +241,68 @@ impl dg_xch_serialize::ChiaSerialize for DeclareProofOfSpace { #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestSignedValues { - pub quality_string: Bytes32, - pub foliage_block_data_hash: Bytes32, - pub foliage_transaction_block_hash: Bytes32, - pub foliage_block_data: Option, - pub foliage_transaction_block_data: Option, - pub rc_block_unfinished: Option, + pub quality_string: Bytes32, //Min Version 0.0.34 + pub foliage_block_data_hash: Bytes32, //Min Version 0.0.34 + pub foliage_transaction_block_hash: Bytes32, //Min Version 0.0.34 + pub foliage_block_data: Option, //Min Version 0.0.36 + pub foliage_transaction_block_data: Option, //Min Version 0.0.36 + pub rc_block_unfinished: Option, //Min Version 0.0.36 } impl dg_xch_serialize::ChiaSerialize for RequestSignedValues { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec { let mut bytes = vec![]; bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.quality_string, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.foliage_block_data_hash, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.foliage_transaction_block_hash, + version, )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.foliage_block_data, - )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.foliage_transaction_block_data, - )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.rc_block_unfinished, - )); + if version >= ChiaProtocolVersion::Chia0_0_36 { + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.foliage_block_data, + version, + )); + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.foliage_transaction_block_data, + version, + )); + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.rc_block_unfinished, + version, + )); + } bytes } - fn from_bytes>(bytes: &mut std::io::Cursor) -> Result + fn from_bytes>( + bytes: &mut std::io::Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - let quality_string = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let foliage_block_data_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let foliage_transaction_block_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let foliage_block_data = if bytes.remaining() > 0 { - //Maintain Compatibility with < Chia 2.X nodes for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let quality_string = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let foliage_block_data_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let foliage_transaction_block_hash = + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let foliage_block_data = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); None }; - let foliage_transaction_block_data = if bytes.remaining() > 0 { - //Maintain Compatibility with < Chia 2.X nodes for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let foliage_transaction_block_data = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); None }; - let rc_block_unfinished = if bytes.remaining() > 0 { - //Maintain Compatibility with Pre Chip 22 Nodes for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let rc_block_unfinished = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); None }; Ok(Self { @@ -276,20 +318,20 @@ impl dg_xch_serialize::ChiaSerialize for RequestSignedValues { #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct FarmingInfo { - pub challenge_hash: Bytes32, - pub sp_hash: Bytes32, - pub timestamp: u64, - pub passed: u32, - pub proofs: u32, - pub total_plots: u32, + pub challenge_hash: Bytes32, //Min Version 0.0.34 + pub sp_hash: Bytes32, //Min Version 0.0.34 + pub timestamp: u64, //Min Version 0.0.34 + pub passed: u32, //Min Version 0.0.34 + pub proofs: u32, //Min Version 0.0.34 + pub total_plots: u32, //Min Version 0.0.34 pub lookup_time: u64, } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct SignedValues { - pub quality_string: Bytes32, - pub foliage_block_data_signature: Bytes96, - pub foliage_transaction_block_signature: Bytes96, + pub quality_string: Bytes32, //Min Version 0.0.34 + pub foliage_block_data_signature: Bytes96, //Min Version 0.0.34 + pub foliage_transaction_block_signature: Bytes96, //Min Version 0.0.34 } pub type ProofsMap = Arc>>>; diff --git a/core/src/protocols/full_node.rs b/core/src/protocols/full_node.rs index f903e57..cb3e5b4 100644 --- a/core/src/protocols/full_node.rs +++ b/core/src/protocols/full_node.rs @@ -12,51 +12,51 @@ use serde::{Deserialize, Serialize}; #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewPeak { - pub header_hash: Bytes32, - pub height: u32, - pub weight: u128, - pub fork_point_with_previous_peak: u32, - pub unfinished_reward_block_hash: Bytes32, + pub header_hash: Bytes32, //Min Version 0.0.34 + pub height: u32, //Min Version 0.0.34 + pub weight: u128, //Min Version 0.0.34 + pub fork_point_with_previous_peak: u32, //Min Version 0.0.34 + pub unfinished_reward_block_hash: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewTransaction { - pub transaction_id: Bytes32, - pub cost: u64, - pub fees: u64, + pub transaction_id: Bytes32, //Min Version 0.0.34 + pub cost: u64, //Min Version 0.0.34 + pub fees: u64, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestTransaction { - pub transaction_id: Bytes32, + pub transaction_id: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondTransaction { - pub transaction: SpendBundle, + pub transaction: SpendBundle, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestProofOfWeight { - pub total_number_of_blocks: u32, - pub vtip: Bytes32, + pub total_number_of_blocks: u32, //Min Version 0.0.34 + pub tip: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondProofOfWeight { - pub wp: WeightProof, - pub tip: Bytes32, + pub wp: WeightProof, //Min Version 0.0.34 + pub tip: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestBlock { - pub height: u32, - pub include_transaction_block: bool, + pub height: u32, //Min Version 0.0.34 + pub include_transaction_block: bool, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RejectBlock { - pub height: u32, + pub height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] @@ -68,109 +68,115 @@ pub struct BlockCountMetrics { #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestBlocks { - pub start_height: u32, - pub end_height: u32, - pub include_transaction_block: bool, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 + pub include_transaction_block: bool, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondBlocks { - pub start_height: u32, - pub end_height: u32, - pub blocks: Vec, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 + pub blocks: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RejectBlocks { - pub start_height: u32, - pub end_height: u32, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondBlock { - pub block: FullBlock, + pub block: FullBlock, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewUnfinishedBlock { - pub unfinished_reward_hash: Bytes32, + pub unfinished_reward_hash: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestUnfinishedBlock { - pub unfinished_reward_hash: Bytes32, + pub unfinished_reward_hash: Bytes32, //Min Version 0.0.34 +} + +#[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] +pub struct NewUnfinishedBlock2 { + pub unfinished_reward_hash: Bytes32, //Min Version 0.0.36 + pub foliage_hash: Option, //Min Version 0.0.36 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondUnfinishedBlock { - pub unfinished_block: UnfinishedBlock, + pub unfinished_block: UnfinishedBlock, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewSignagePointOrEndOfSubSlot { - pub prev_challenge_hash: Option, - pub challenge_hash: Bytes32, - pub index_from_challenge: u8, - pub last_rc_infusion: Bytes32, + pub prev_challenge_hash: Option, //Min Version 0.0.34 + pub challenge_hash: Bytes32, //Min Version 0.0.34 + pub index_from_challenge: u8, //Min Version 0.0.34 + pub last_rc_infusion: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestSignagePointOrEndOfSubSlot { - pub challenge_hash: Bytes32, - pub index_from_challenge: u8, - pub last_rc_infusion: Bytes32, + pub challenge_hash: Bytes32, //Min Version 0.0.34 + pub index_from_challenge: u8, //Min Version 0.0.34 + pub last_rc_infusion: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondSignagePoint { - pub index_from_challenge: u8, - pub challenge_chain_vdf: VdfInfo, - pub challenge_chain_proof: VdfProof, - pub reward_chain_vdf: VdfInfo, - pub reward_chain_proof: VdfProof, + pub index_from_challenge: u8, //Min Version 0.0.34 + pub challenge_chain_vdf: VdfInfo, //Min Version 0.0.34 + pub challenge_chain_proof: VdfProof, //Min Version 0.0.34 + pub reward_chain_vdf: VdfInfo, //Min Version 0.0.34 + pub reward_chain_proof: VdfProof, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondEndOfSubSlot { - pub end_of_slot_bundle: EndOfSubSlotBundle, + pub end_of_slot_bundle: EndOfSubSlotBundle, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestMempoolTransactions { - pub filter: Vec, + pub filter: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewCompactVDF { - pub height: u32, - pub header_hash: Bytes32, - pub field_vdf: u8, - pub vdf_info: VdfInfo, + pub height: u32, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 + pub field_vdf: u8, //Min Version 0.0.34 + pub vdf_info: VdfInfo, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestCompactVDF { - pub height: u32, - pub header_hash: Bytes32, - pub field_vdf: u8, - pub vdf_info: VdfInfo, + pub height: u32, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 + pub field_vdf: u8, //Min Version 0.0.34 + pub vdf_info: VdfInfo, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondCompactVDF { - pub height: u32, - pub header_hash: Bytes32, - pub field_vdf: u8, - pub vdf_info: VdfInfo, - pub vdf_proof: VdfProof, + pub height: u32, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 + pub field_vdf: u8, //Min Version 0.0.34 + pub vdf_info: VdfInfo, //Min Version 0.0.34 + pub vdf_proof: VdfProof, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] -pub struct RequestPeers {} +pub struct RequestPeers {} //Min Version 0.0.34 #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondPeers { - pub peer_list: Vec, + pub peer_list: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Serialize, Deserialize, Debug)] diff --git a/core/src/protocols/harvester.rs b/core/src/protocols/harvester.rs index dee65f4..c50efcd 100644 --- a/core/src/protocols/harvester.rs +++ b/core/src/protocols/harvester.rs @@ -1,9 +1,7 @@ use crate::blockchain::proof_of_space::ProofOfSpace; use crate::blockchain::reward_chain_block_unfinished::RewardChainBlockUnfinished; use crate::blockchain::sized_bytes::{Bytes32, Bytes48, Bytes96}; -use bytes::Buf; use dg_xch_macros::ChiaSerial; -use log::debug; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; #[cfg(feature = "metrics")] @@ -13,31 +11,31 @@ use std::time::Instant; #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct PoolDifficulty { - pub difficulty: u64, - pub sub_slot_iters: u64, - pub pool_contract_puzzle_hash: Bytes32, + pub difficulty: u64, //Min Version 0.0.34 + pub sub_slot_iters: u64, //Min Version 0.0.34 + pub pool_contract_puzzle_hash: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct HarvesterHandshake { - pub farmer_public_keys: Vec, - pub pool_public_keys: Vec, + pub farmer_public_keys: Vec, //Min Version 0.0.34 + pub pool_public_keys: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewSignagePointHarvester { - pub challenge_hash: Bytes32, - pub difficulty: u64, - pub sub_slot_iters: u64, - pub signage_point_index: u8, - pub sp_hash: Bytes32, - pub pool_difficulties: Vec, - pub filter_prefix_bits: i8, + pub challenge_hash: Bytes32, //Min Version 0.0.34 + pub difficulty: u64, //Min Version 0.0.34 + pub sub_slot_iters: u64, //Min Version 0.0.34 + pub signage_point_index: u8, //Min Version 0.0.34 + pub sp_hash: Bytes32, //Min Version 0.0.34 + pub pool_difficulties: Vec, //Min Version 0.0.34 + pub filter_prefix_bits: i8, //Min Version 0.0.35 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct ProofOfSpaceFeeInfo { - pub applied_fee_threshold: u32, + pub applied_fee_threshold: u32, //Min Version 0.0.36 } #[derive(ChiaSerial, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] @@ -68,72 +66,85 @@ impl From for SigningDataKind { #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct SignatureRequestSourceData { - pub kind: SigningDataKind, - pub data: Vec, + pub kind: SigningDataKind, //Min Version 0.0.36 + pub data: Vec, //Min Version 0.0.36 } #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewProofOfSpace { - pub challenge_hash: Bytes32, - pub sp_hash: Bytes32, - pub plot_identifier: String, - pub proof: ProofOfSpace, - pub signage_point_index: u8, - pub include_source_signature_data: bool, - pub farmer_reward_address_override: Option, - pub fee_info: Option, + pub challenge_hash: Bytes32, //Min Version 0.0.34 + pub sp_hash: Bytes32, //Min Version 0.0.34 + pub plot_identifier: String, //Min Version 0.0.34 + pub proof: ProofOfSpace, //Min Version 0.0.34 + pub signage_point_index: u8, //Min Version 0.0.34 + pub include_source_signature_data: bool, //Min Version 0.0.36 + pub farmer_reward_address_override: Option, //Min Version 0.0.36 + pub fee_info: Option, //Min Version 0.0.36 } impl dg_xch_serialize::ChiaSerialize for NewProofOfSpace { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec { let mut bytes = vec![]; bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.challenge_hash, + version, )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.sp_hash)); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.plot_identifier, + &self.sp_hash, + version, )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.proof)); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.signage_point_index, + &self.plot_identifier, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.include_source_signature_data, + &self.proof, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.farmer_reward_address_override, + &self.signage_point_index, + version, )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.fee_info)); + if version >= ChiaProtocolVersion::Chia0_0_36 { + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.include_source_signature_data, + version, + )); + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.farmer_reward_address_override, + version, + )); + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.fee_info, + version, + )); + } bytes } - fn from_bytes>(bytes: &mut std::io::Cursor) -> Result + fn from_bytes>( + bytes: &mut std::io::Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let sp_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let plot_identifier = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let proof = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let signage_point_index = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let include_source_signature_data = if bytes.remaining() > 0 { - //Maintain Compatibility with Pre Chip 22 for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let sp_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let plot_identifier = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let proof = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let signage_point_index = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let include_source_signature_data = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); false }; - let farmer_reward_address_override = if bytes.remaining() > 0 { - //Maintain Compatibility with Pre Chip 22 for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let farmer_reward_address_override = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); None }; - let fee_info = if bytes.remaining() > 0 { - //Maintain Compatibility with Pre Chip 22 for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let fee_info = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); None }; Ok(Self { @@ -150,52 +161,63 @@ impl dg_xch_serialize::ChiaSerialize for NewProofOfSpace { } #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestSignatures { - pub plot_identifier: String, - pub challenge_hash: Bytes32, - pub sp_hash: Bytes32, - pub messages: Vec, - pub message_data: Option>>, - pub rc_block_unfinished: Option, + pub plot_identifier: String, //Min Version 0.0.34 + pub challenge_hash: Bytes32, //Min Version 0.0.34 + pub sp_hash: Bytes32, //Min Version 0.0.34 + pub messages: Vec, //Min Version 0.0.34 + pub message_data: Option>>, //Min Version 0.0.36 + pub rc_block_unfinished: Option, //Min Version 0.0.36 } impl dg_xch_serialize::ChiaSerialize for RequestSignatures { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec { let mut bytes = vec![]; bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.plot_identifier, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.challenge_hash, + version, )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.sp_hash)); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.messages)); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.message_data, + &self.sp_hash, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.rc_block_unfinished, + &self.messages, + version, )); + if version >= ChiaProtocolVersion::Chia0_0_36 { + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.message_data, + version, + )); + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.rc_block_unfinished, + version, + )); + } bytes } - fn from_bytes>(bytes: &mut std::io::Cursor) -> Result + fn from_bytes>( + bytes: &mut std::io::Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - let plot_identifier = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let sp_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let messages = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let message_data = if bytes.remaining() > 0 { - //Maintain Compatibility with Pre Chip 22 for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let plot_identifier = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let sp_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let messages = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let message_data = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); None }; - let rc_block_unfinished = if bytes.remaining() > 0 { - //Maintain Compatibility with Pre Chip 22 for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let rc_block_unfinished = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); None }; Ok(Self { @@ -211,61 +233,76 @@ impl dg_xch_serialize::ChiaSerialize for RequestSignatures { #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondSignatures { - pub plot_identifier: String, - pub challenge_hash: Bytes32, - pub sp_hash: Bytes32, - pub local_pk: Bytes48, - pub farmer_pk: Bytes48, - pub message_signatures: Vec<(Bytes32, Bytes96)>, - pub include_source_signature_data: bool, - pub farmer_reward_address_override: Option, + pub plot_identifier: String, //Min Version 0.0.34 + pub challenge_hash: Bytes32, //Min Version 0.0.34 + pub sp_hash: Bytes32, //Min Version 0.0.34 + pub local_pk: Bytes48, //Min Version 0.0.34 + pub farmer_pk: Bytes48, //Min Version 0.0.34 + pub message_signatures: Vec<(Bytes32, Bytes96)>, //Min Version 0.0.34 + pub include_source_signature_data: bool, //Min Version 0.0.36 + pub farmer_reward_address_override: Option, //Min Version 0.0.36 } impl dg_xch_serialize::ChiaSerialize for RespondSignatures { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec { let mut bytes = vec![]; bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.plot_identifier, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( &self.challenge_hash, + version, )); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.sp_hash)); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.local_pk)); - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.farmer_pk)); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.message_signatures, + &self.sp_hash, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.include_source_signature_data, + &self.local_pk, + version, )); bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( - &self.farmer_reward_address_override, + &self.farmer_pk, + version, )); + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.message_signatures, + version, + )); + if version >= ChiaProtocolVersion::Chia0_0_36 { + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.include_source_signature_data, + version, + )); + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes( + &self.farmer_reward_address_override, + version, + )); + } bytes } - fn from_bytes>(bytes: &mut std::io::Cursor) -> Result + fn from_bytes>( + bytes: &mut std::io::Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - let plot_identifier = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let sp_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let local_pk = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let farmer_pk = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let message_signatures = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; - let include_source_signature_data = if bytes.remaining() > 0 { - //Maintain Compatibility with Pre Chip 22 for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let plot_identifier = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let challenge_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let sp_hash = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let local_pk = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let farmer_pk = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let message_signatures = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)?; + let include_source_signature_data = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); false }; - let farmer_reward_address_override = if bytes.remaining() > 0 { - //Maintain Compatibility with Pre Chip 22 for now - dg_xch_serialize::ChiaSerialize::from_bytes(bytes)? + let farmer_reward_address_override = if version >= ChiaProtocolVersion::Chia0_0_36 { + dg_xch_serialize::ChiaSerialize::from_bytes(bytes, version)? } else { - debug!("You are connected to an old node version, Please update your Fullnode."); None }; Ok(Self { @@ -283,77 +320,78 @@ impl dg_xch_serialize::ChiaSerialize for RespondSignatures { #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct Plot { - pub filename: String, - pub size: u8, - pub plot_id: Bytes32, - pub pool_public_key: Option, - pub pool_contract_puzzle_hash: Option, - pub plot_public_key: Bytes48, - pub file_size: u64, - pub time_modified: u64, - pub compression_level: Option, + pub filename: String, //Min Version 0.0.34 + pub size: u8, //Min Version 0.0.34 + pub plot_id: Bytes32, //Min Version 0.0.34 + pub pool_public_key: Option, //Min Version 0.0.34 + pub pool_contract_puzzle_hash: Option, //Min Version 0.0.34 + pub plot_public_key: Bytes48, //Min Version 0.0.34 + pub file_size: u64, //Min Version 0.0.34 + pub time_modified: u64, //Min Version 0.0.34 + pub compression_level: Option, //Min Version 0.0.35 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] -pub struct RequestPlots {} +pub struct RequestPlots {} //Min Version 0.0.34 #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondPlots { - pub plots: Vec, - pub failed_to_open_filenames: Vec, - pub no_key_filenames: Vec, + pub plots: Vec, //Min Version 0.0.34 + pub failed_to_open_filenames: Vec, //Min Version 0.0.34 + pub no_key_filenames: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct PlotSyncIdentifier { - pub timestamp: u64, - pub sync_id: u64, - pub message_id: u64, + pub timestamp: u64, //Min Version 0.0.34 + pub sync_id: u64, //Min Version 0.0.34 + pub message_id: u64, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct PlotSyncStart { - pub identifier: PlotSyncIdentifier, - pub initial: bool, - pub last_sync_id: u64, - pub plot_file_count: u32, - pub harvesting_mode: u8, + pub identifier: PlotSyncIdentifier, //Min Version 0.0.34 + pub initial: bool, //Min Version 0.0.34 + pub last_sync_id: u64, //Min Version 0.0.34 + pub plot_file_count: u32, //Min Version 0.0.34 + pub harvesting_mode: u8, //Min Version 0.0.35 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct PlotSyncPathList { - pub identifier: PlotSyncIdentifier, - pub data: Vec, - pub r#final: bool, + pub identifier: PlotSyncIdentifier, //Min Version 0.0.34 + pub data: Vec, //Min Version 0.0.34 + pub r#final: bool, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct PlotSyncPlotList { - pub identifier: PlotSyncIdentifier, - pub data: Vec, - pub r#final: bool, + pub identifier: PlotSyncIdentifier, //Min Version 0.0.34 + pub data: Vec, //Min Version 0.0.34 + pub r#final: bool, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct PlotSyncDone { - pub identifier: PlotSyncIdentifier, - pub duration: u64, + pub identifier: PlotSyncIdentifier, //Min Version 0.0.34 + pub duration: u64, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct PlotSyncError { - pub code: i16, - pub message: String, - pub expected_identifier: Option, + pub code: i16, //Min Version 0.0.34 + pub message: String, //Min Version 0.0.34 + pub expected_identifier: Option, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct PlotSyncResponse { - pub identifier: PlotSyncIdentifier, - pub message_type: i16, - pub error: Option, + pub identifier: PlotSyncIdentifier, //Min Version 0.0.34 + pub message_type: i16, //Min Version 0.0.34 + pub error: Option, //Min Version 0.0.34 } +use dg_xch_serialize::ChiaProtocolVersion; #[cfg(feature = "metrics")] use prometheus::core::{AtomicU64, GenericGauge}; #[cfg(feature = "metrics")] diff --git a/core/src/protocols/introducer.rs b/core/src/protocols/introducer.rs index daf31f6..20db97d 100644 --- a/core/src/protocols/introducer.rs +++ b/core/src/protocols/introducer.rs @@ -3,9 +3,9 @@ use dg_xch_macros::ChiaSerial; use serde::{Deserialize, Serialize}; #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] -pub struct RequestPeersIntroducer {} +pub struct RequestPeersIntroducer {} //Min Version 0.0.34 #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondPeersIntroducer { - pub peer_list: Vec, + pub peer_list: Vec, //Min Version 0.0.34 } diff --git a/core/src/protocols/mod.rs b/core/src/protocols/mod.rs index b75452b..c98247b 100644 --- a/core/src/protocols/mod.rs +++ b/core/src/protocols/mod.rs @@ -12,6 +12,7 @@ use crate::blockchain::sized_bytes::Bytes32; use crate::utils::await_termination; use async_trait::async_trait; use dg_xch_macros::ChiaSerial; +use dg_xch_serialize::ChiaProtocolVersion; use dg_xch_serialize::ChiaSerialize; use futures_util::stream::{FusedStream, SplitSink, SplitStream}; use futures_util::SinkExt; @@ -463,17 +464,22 @@ pub struct ChiaMessage { pub data: Vec, } impl ChiaMessage { - pub fn new(msg_type: ProtocolMessageTypes, msg: &T, id: Option) -> Self { + pub fn new( + msg_type: ProtocolMessageTypes, + version: ChiaProtocolVersion, + msg: &T, + id: Option, + ) -> Self { ChiaMessage { msg_type, id, - data: msg.to_bytes(), + data: msg.to_bytes(version), } } } impl From for Message { fn from(val: ChiaMessage) -> Self { - Message::Binary(val.to_bytes()) + Message::Binary(val.to_bytes(ChiaProtocolVersion::default())) } } @@ -513,6 +519,7 @@ pub type PeerMap = Arc>>>; pub struct SocketPeer { pub node_type: Arc>, + pub protocol_version: Arc>, pub websocket: Arc>, } @@ -642,6 +649,12 @@ pub struct ReadStream { impl ReadStream { pub async fn run(&mut self, run: Arc) { loop { + let peer_self = self.peers.read().await.get(&self.peer_id).cloned(); + let protocol_version = if let Some(peer) = peer_self.as_ref() { + *peer.protocol_version.read().await + } else { + ChiaProtocolVersion::default() + }; select! { msg = self.read.next() => { match msg { @@ -649,7 +662,7 @@ impl ReadStream { match msg { Message::Binary(bin_data) => { let mut cursor = Cursor::new(&bin_data); - match ChiaMessage::from_bytes(&mut cursor) { + match ChiaMessage::from_bytes(&mut cursor, protocol_version) { Ok(chia_msg) => { let msg_arc: Arc = Arc::new(chia_msg); let mut matched = false; diff --git a/core/src/protocols/pool.rs b/core/src/protocols/pool.rs index 54b01a2..227bd74 100644 --- a/core/src/protocols/pool.rs +++ b/core/src/protocols/pool.rs @@ -72,112 +72,112 @@ impl From for PoolErrorCode { } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PoolError { - pub error_code: u8, - pub error_message: String, + pub error_code: u8, //Min Version 0.0.34 + pub error_message: String, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct AuthenticationPayload { - pub method_name: String, - pub launcher_id: Bytes32, - pub target_puzzle_hash: Bytes32, - pub authentication_token: u64, + pub method_name: String, //Min Version 0.0.34 + pub launcher_id: Bytes32, //Min Version 0.0.34 + pub target_puzzle_hash: Bytes32, //Min Version 0.0.34 + pub authentication_token: u64, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct GetPoolInfoResponse { - pub name: String, - pub logo_url: String, - pub minimum_difficulty: u64, - pub relative_lock_height: u32, - pub protocol_version: u8, - pub fee: String, - pub description: String, - pub target_puzzle_hash: Bytes32, - pub authentication_token_timeout: u8, + pub name: String, //Min Version 0.0.34 + pub logo_url: String, //Min Version 0.0.34 + pub minimum_difficulty: u64, //Min Version 0.0.34 + pub relative_lock_height: u32, //Min Version 0.0.34 + pub protocol_version: u8, //Min Version 0.0.34 + pub fee: String, //Min Version 0.0.34 + pub description: String, //Min Version 0.0.34 + pub target_puzzle_hash: Bytes32, //Min Version 0.0.34 + pub authentication_token_timeout: u8, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PostPartialPayload { - pub launcher_id: Bytes32, - pub authentication_token: u64, - pub proof_of_space: ProofOfSpace, - pub sp_hash: Bytes32, - pub end_of_sub_slot: bool, - pub harvester_id: Bytes32, + pub launcher_id: Bytes32, //Min Version 0.0.34 + pub authentication_token: u64, //Min Version 0.0.34 + pub proof_of_space: ProofOfSpace, //Min Version 0.0.34 + pub sp_hash: Bytes32, //Min Version 0.0.34 + pub end_of_sub_slot: bool, //Min Version 0.0.34 + pub harvester_id: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PostPartialRequest { - pub payload: PostPartialPayload, - pub aggregate_signature: Bytes96, + pub payload: PostPartialPayload, //Min Version 0.0.34 + pub aggregate_signature: Bytes96, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PostPartialResponse { - pub new_difficulty: u64, + pub new_difficulty: u64, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct GetFarmerRequest { - pub launcher_id: Bytes32, - pub authentication_token: u64, - pub signature: Bytes96, + pub launcher_id: Bytes32, //Min Version 0.0.34 + pub authentication_token: u64, //Min Version 0.0.34 + pub signature: Bytes96, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct GetFarmerResponse { - pub authentication_public_key: Bytes48, - pub payout_instructions: String, - pub current_difficulty: u64, - pub current_points: u64, + pub authentication_public_key: Bytes48, //Min Version 0.0.34 + pub payout_instructions: String, //Min Version 0.0.34 + pub current_difficulty: u64, //Min Version 0.0.34 + pub current_points: u64, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PostFarmerPayload { - pub launcher_id: Bytes32, - pub authentication_token: u64, - pub authentication_public_key: Bytes48, - pub payout_instructions: String, - pub suggested_difficulty: Option, + pub launcher_id: Bytes32, //Min Version 0.0.34 + pub authentication_token: u64, //Min Version 0.0.34 + pub authentication_public_key: Bytes48, //Min Version 0.0.34 + pub payout_instructions: String, //Min Version 0.0.34 + pub suggested_difficulty: Option, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PostFarmerRequest { - pub payload: PostFarmerPayload, - pub signature: Bytes96, + pub payload: PostFarmerPayload, //Min Version 0.0.34 + pub signature: Bytes96, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PostFarmerResponse { - pub welcome_message: String, + pub welcome_message: String, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PutFarmerPayload { - pub launcher_id: Bytes32, - pub authentication_token: u64, - pub authentication_public_key: Option, - pub payout_instructions: Option, - pub suggested_difficulty: Option, + pub launcher_id: Bytes32, //Min Version 0.0.34 + pub authentication_token: u64, //Min Version 0.0.34 + pub authentication_public_key: Option, //Min Version 0.0.34 + pub payout_instructions: Option, //Min Version 0.0.34 + pub suggested_difficulty: Option, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PutFarmerRequest { - pub payload: PutFarmerPayload, - pub signature: Bytes96, + pub payload: PutFarmerPayload, //Min Version 0.0.34 + pub signature: Bytes96, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct PutFarmerResponse { - pub authentication_public_key: Option, - pub payout_instructions: Option, - pub suggested_difficulty: Option, + pub authentication_public_key: Option, //Min Version 0.0.34 + pub payout_instructions: Option, //Min Version 0.0.34 + pub suggested_difficulty: Option, //Min Version 0.0.34 } #[derive(ChiaSerial, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct ErrorResponse { - pub error_code: u16, - pub error_message: Option, + pub error_code: u16, //Min Version 0.0.34 + pub error_message: Option, //Min Version 0.0.34 } pub fn get_current_authentication_token(timeout: u8) -> u64 { diff --git a/core/src/protocols/shared.rs b/core/src/protocols/shared.rs index bfeb1d2..6ba2731 100644 --- a/core/src/protocols/shared.rs +++ b/core/src/protocols/shared.rs @@ -4,8 +4,6 @@ use rustls::{Certificate, DigitallySignedStruct, ServerName}; use serde::{Deserialize, Serialize}; use std::time::SystemTime; -pub const PROTOCOL_VERSION: &str = "0.0.36"; - pub enum Capability { Base = 1, BlockHeaders = 2, @@ -15,12 +13,13 @@ pub enum Capability { #[derive(ChiaSerial, Serialize, Deserialize, Debug, Clone)] pub struct Handshake { - pub network_id: String, - pub protocol_version: String, - pub software_version: String, - pub server_port: u16, - pub node_type: u8, - pub capabilities: Vec<(u16, String)>, + //Same for all Versions + pub network_id: String, //Min Version 0.0.34 + pub protocol_version: String, //Min Version 0.0.34 + pub software_version: String, //Min Version 0.0.34 + pub server_port: u16, //Min Version 0.0.34 + pub node_type: u8, //Min Version 0.0.34 + pub capabilities: Vec<(u16, String)>, //Min Version 0.0.34 } pub const CAPABILITIES: [(u16, &str); 3] = [ diff --git a/core/src/protocols/timelord.rs b/core/src/protocols/timelord.rs index 1a72e88..c41b82d 100644 --- a/core/src/protocols/timelord.rs +++ b/core/src/protocols/timelord.rs @@ -11,64 +11,64 @@ use serde::{Deserialize, Serialize}; #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewPeakTimelord { - pub reward_chain_block: RewardChainBlock, - pub difficulty: u64, - pub deficit: u8, - pub sub_slot_iters: u64, - pub sub_epoch_summary: Option, - pub previous_reward_challenges: Vec<(Bytes32, u128)>, - pub last_challenge_sb_or_eos_total_iters: u128, - pub passes_ses_height_but_not_yet_included: bool, + pub reward_chain_block: RewardChainBlock, //Min Version 0.0.34 + pub difficulty: u64, //Min Version 0.0.34 + pub deficit: u8, //Min Version 0.0.34 + pub sub_slot_iters: u64, //Min Version 0.0.34 + pub sub_epoch_summary: Option, //Min Version 0.0.34 + pub previous_reward_challenges: Vec<(Bytes32, u128)>, //Min Version 0.0.34 + pub last_challenge_sb_or_eos_total_iters: u128, //Min Version 0.0.34 + pub passes_ses_height_but_not_yet_included: bool, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewUnfinishedBlockTimelord { - pub reward_chain_block: RewardChainBlockUnfinished, - pub difficulty: u64, - pub sub_slot_iters: u64, - pub foliage: Foliage, - pub sub_epoch_summary: Option, - pub rc_prev: Bytes32, + pub reward_chain_block: RewardChainBlockUnfinished, //Min Version 0.0.34 + pub difficulty: u64, //Min Version 0.0.34 + pub sub_slot_iters: u64, //Min Version 0.0.34 + pub foliage: Foliage, //Min Version 0.0.34 + pub sub_epoch_summary: Option, //Min Version 0.0.34 + pub rc_prev: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewInfusionPointVDF { - pub unfinished_reward_hash: Bytes32, - pub challenge_chain_ip_vdf: VdfInfo, - pub challenge_chain_ip_proof: VdfProof, - pub reward_chain_ip_vdf: VdfInfo, - pub reward_chain_ip_proof: VdfProof, - pub infused_challenge_chain_ip_vdf: Option, - pub infused_challenge_chain_ip_proof: Option, + pub unfinished_reward_hash: Bytes32, //Min Version 0.0.34 + pub challenge_chain_ip_vdf: VdfInfo, //Min Version 0.0.34 + pub challenge_chain_ip_proof: VdfProof, //Min Version 0.0.34 + pub reward_chain_ip_vdf: VdfInfo, //Min Version 0.0.34 + pub reward_chain_ip_proof: VdfProof, //Min Version 0.0.34 + pub infused_challenge_chain_ip_vdf: Option, //Min Version 0.0.34 + pub infused_challenge_chain_ip_proof: Option, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewSignagePointVDF { - pub index_from_challenge: u8, - pub challenge_chain_sp_vdf: VdfInfo, - pub challenge_chain_sp_proof: VdfProof, - pub reward_chain_sp_vdf: VdfInfo, - pub reward_chain_sp_proof: VdfProof, + pub index_from_challenge: u8, //Min Version 0.0.34 + pub challenge_chain_sp_vdf: VdfInfo, //Min Version 0.0.34 + pub challenge_chain_sp_proof: VdfProof, //Min Version 0.0.34 + pub reward_chain_sp_vdf: VdfInfo, //Min Version 0.0.34 + pub reward_chain_sp_proof: VdfProof, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewEndOfSubSlotVDF { - pub end_of_sub_slot_bundle: EndOfSubSlotBundle, + pub end_of_sub_slot_bundle: EndOfSubSlotBundle, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestCompactProofOfTime { - pub new_proof_of_time: VdfInfo, - pub header_hash: Bytes32, - pub height: u32, - pub field_vdf: u8, + pub new_proof_of_time: VdfInfo, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 + pub height: u32, //Min Version 0.0.34 + pub field_vdf: u8, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondCompactProofOfTime { - pub vdf_info: VdfInfo, - pub vdf_proof: VdfProof, - pub header_hash: Bytes32, - pub height: u32, - pub field_vdf: u8, + pub vdf_info: VdfInfo, //Min Version 0.0.34 + pub vdf_proof: VdfProof, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 + pub height: u32, //Min Version 0.0.34 + pub field_vdf: u8, //Min Version 0.0.34 } diff --git a/core/src/protocols/wallet.rs b/core/src/protocols/wallet.rs index a5d0c3f..aa0a950 100644 --- a/core/src/protocols/wallet.rs +++ b/core/src/protocols/wallet.rs @@ -8,227 +8,234 @@ use serde::{Deserialize, Serialize}; #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestPuzzleSolution { - pub coin_name: Bytes32, - pub height: u32, + pub coin_name: Bytes32, //Min Version 0.0.34 + pub height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct PuzzleSolutionResponse { - pub coin_name: Bytes32, - pub height: u32, - pub puzzle: SerializedProgram, - pub solution: SerializedProgram, + pub coin_name: Bytes32, //Min Version 0.0.34 + pub height: u32, //Min Version 0.0.34 + pub puzzle: SerializedProgram, //Min Version 0.0.34 + pub solution: SerializedProgram, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondPuzzleSolution { - pub response: PuzzleSolutionResponse, + pub response: PuzzleSolutionResponse, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RejectPuzzleSolution { - pub coin_name: Bytes32, - pub height: u32, + pub coin_name: Bytes32, //Min Version 0.0.34 + pub height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct SendTransaction { - pub transaction: SpendBundle, + pub transaction: SpendBundle, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct TransactionAck { - pub txid: Bytes32, - pub status: u8, - pub error: Option, + pub txid: Bytes32, //Min Version 0.0.34 + pub status: u8, //Min Version 0.0.34 + pub error: Option, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct NewPeakWallet { - pub header_hash: Bytes32, - pub height: u32, - pub weight: u128, - pub fork_point_with_previous_peak: u32, + pub header_hash: Bytes32, //Min Version 0.0.34 + pub height: u32, //Min Version 0.0.34 + pub weight: u128, //Min Version 0.0.34 + pub fork_point_with_previous_peak: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestBlockHeader { - pub height: u32, + pub height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondBlockHeader { - pub header_block: HeaderBlock, + pub header_block: HeaderBlock, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RejectHeaderRequest { - pub height: u32, + pub height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestRemovals { - pub height: u32, - pub header_hash: Bytes32, - pub coin_names: Option>, + pub height: u32, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 + pub coin_names: Option>, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondRemovals { - pub height: u32, - pub header_hash: Bytes32, - pub coins: Vec<(Bytes32, Option)>, - pub proofs: Option)>>, + pub height: u32, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 + pub coins: Vec<(Bytes32, Option)>, //Min Version 0.0.34 + pub proofs: Option)>>, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RejectRemovalsRequest { - pub height: u32, - pub header_hash: Bytes32, + pub height: u32, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestAdditions { - pub height: u32, - pub header_hash: Option, - pub puzzle_hashes: Option>, + pub height: u32, //Min Version 0.0.34 + pub header_hash: Option, //Min Version 0.0.34 + pub puzzle_hashes: Option>, //Min Version 0.0.35 } pub type Proofs = Option, Option>)>>; #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondAdditions { - pub height: u32, - pub header_hash: Bytes32, - pub coins: Vec<(Bytes32, Vec)>, - pub proofs: Proofs, + pub height: u32, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 + pub coins: Vec<(Bytes32, Vec)>, //Min Version 0.0.34 + pub proofs: Proofs, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RejectAdditionsRequest { - pub height: u32, - pub header_hash: Bytes32, + pub height: u32, //Min Version 0.0.34 + pub header_hash: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondBlockHeaders { - pub start_height: u32, - pub end_height: u32, - pub header_blocks: Vec, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 + pub header_blocks: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RejectBlockHeaders { - pub start_height: u32, - pub end_height: u32, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestBlockHeaders { - pub start_height: u32, - pub end_height: u32, - pub return_filter: bool, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 + pub return_filter: bool, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestHeaderBlocks { - pub start_height: u32, - pub end_height: u32, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RejectHeaderBlocks { - pub start_height: u32, - pub end_height: u32, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondHeaderBlocks { - pub start_height: u32, - pub end_height: u32, - pub header_blocks: Vec, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 + pub header_blocks: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RegisterForPhUpdates { - pub puzzle_hashes: Vec, - pub min_height: u32, + pub puzzle_hashes: Vec, //Min Version 0.0.34 + pub min_height: u32, //Min Version 0.0.34 +} + +#[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] +pub struct RespondToPhUpdates { + pub puzzle_hashes: Vec, //Min Version 0.0.34 + pub min_height: u32, //Min Version 0.0.34 + pub coin_states: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct CoinState { - pub coin: Coin, - pub spent_height: Option, - pub created_height: Option, + pub coin: Coin, //Min Version 0.0.34 + pub spent_height: Option, //Min Version 0.0.34 + pub created_height: Option, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RegisterForCoinUpdates { - pub coin_ids: Vec, - pub min_height: u32, + pub coin_ids: Vec, //Min Version 0.0.34 + pub min_height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondToCoinUpdates { - pub coin_ids: Vec, - pub min_height: u32, - pub coin_states: Vec, + pub coin_ids: Vec, //Min Version 0.0.34 + pub min_height: u32, //Min Version 0.0.34 + pub coin_states: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct CoinStateUpdate { - pub height: u32, - pub fork_height: u32, - pub peak_hash: Bytes32, - pub items: Vec, + pub height: u32, //Min Version 0.0.34 + pub fork_height: u32, //Min Version 0.0.34 + pub peak_hash: Bytes32, //Min Version 0.0.34 + pub items: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestChildren { - pub coin_name: Bytes32, + pub coin_name: Bytes32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondChildren { - pub coin_states: Vec, + pub coin_states: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestSESInfo { - pub start_height: u32, - pub end_height: u32, + pub start_height: u32, //Min Version 0.0.34 + pub end_height: u32, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondSESInfo { - pub reward_chain_hash: Vec, - pub heights: Vec>, + pub reward_chain_hash: Vec, //Min Version 0.0.34 + pub heights: Vec>, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RequestFeeEstimates { - pub time_targets: Vec, + pub time_targets: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct RespondFeeEstimates { - pub estimates: FeeEstimateGroup, + pub estimates: FeeEstimateGroup, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct FeeEstimate { - pub error: Option, - pub time_target: u64, - pub estimated_fee_rate: FeeRate, + pub error: Option, //Min Version 0.0.34 + pub time_target: u64, //Min Version 0.0.34 + pub estimated_fee_rate: FeeRate, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct FeeEstimateGroup { - pub error: Option, - pub estimates: Vec, + pub error: Option, //Min Version 0.0.34 + pub estimates: Vec, //Min Version 0.0.34 } #[derive(ChiaSerial, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct FeeRate { - pub mojos_per_clvm_cost: u64, + pub mojos_per_clvm_cost: u64, //Min Version 0.0.34 } diff --git a/keys/Cargo.toml b/keys/Cargo.toml index f9167e8..f1231eb 100644 --- a/keys/Cargo.toml +++ b/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_keys" -version = "2.0.2" +version = "2.0.3" edition = "2021" authors = ["James Hoerr"] description = "Key Management Utils the Chia Blockchain" @@ -12,8 +12,8 @@ repository = "https://github.com/GalactechsLLC/dg_xch_utils" bech32 = "0.9.1" blst = { version = "0.3.11", features = ["portable"] } bip39 = {version= "2.0.0", features=["rand"] } -dg_xch_core = {path = "../core", version = "2.0.2", default-features = false } -dg_xch_puzzles = {path = "../puzzles", version="2.0.2"} +dg_xch_core = {path = "../core", version = "2.0.3", default-features = false } +dg_xch_puzzles = {path = "../puzzles", version="2.0.3"} hex = "0.4.3" hkdf = "0.12.4" sha2 = "0.10.8" \ No newline at end of file diff --git a/macros/Cargo.toml b/macros/Cargo.toml index a038681..47c78f6 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_macros" -version = "2.0.2" +version = "2.0.3" edition = "2021" description = "Derive Marcos for Chia Serialization" license = "Apache-2.0" diff --git a/macros/src/lib.rs b/macros/src/lib.rs index f6dad99..f8694f3 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -13,10 +13,10 @@ pub fn derive_chia_serial(input: TokenStream) -> TokenStream { let (to_bytes, from_bytes) = create_to_bytes(input.data); let gen = quote! { impl dg_xch_serialize::ChiaSerialize for #name { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self, macro_chia_protocol_version: dg_xch_serialize::ChiaProtocolVersion) -> Vec { #to_bytes } - fn from_bytes>(bytes: &mut std::io::Cursor) -> Result + fn from_bytes>(bytes: &mut std::io::Cursor, macro_chia_protocol_version: dg_xch_serialize::ChiaProtocolVersion) -> Result where Self: Sized, { @@ -35,13 +35,13 @@ fn create_to_bytes(data: Data) -> (TokenStream2, TokenStream2) { let to_bytes = fields.named.iter().map(|f| { let name = &f.ident; quote_spanned! {f.span()=> - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.#name)); + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.#name, macro_chia_protocol_version)); } }); let names = fields.named.iter().map(|f| { let name = &f.ident; quote_spanned! {f.span()=> - let #name = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; + let #name = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, macro_chia_protocol_version)?; } }); let assign = fields.named.iter().map(|f| { @@ -68,13 +68,13 @@ fn create_to_bytes(data: Data) -> (TokenStream2, TokenStream2) { let to_bytes = fields.unnamed.iter().enumerate().map(|(i, f)| { let index = Index::from(i); quote_spanned! {f.span()=> - bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.#index)); + bytes.extend(dg_xch_serialize::ChiaSerialize::to_bytes(&self.#index, macro_chia_protocol_version)); } }); let names = fields.unnamed.iter().enumerate().map(|(i, f)| { let index = Index::from(i); quote_spanned! {f.span()=> - let #index = dg_xch_serialize::ChiaSerialize::from_bytes(bytes)?; + let #index = dg_xch_serialize::ChiaSerialize::from_bytes(bytes, macro_chia_protocol_version)?; } }); let assign = fields.unnamed.iter().enumerate().map(|(i, f)| { diff --git a/proof_of_space/Cargo.toml b/proof_of_space/Cargo.toml index 8e95e5a..35b8ce9 100644 --- a/proof_of_space/Cargo.toml +++ b/proof_of_space/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_pos" -version = "2.0.2" +version = "2.0.3" edition = "2021" authors = ["James Hoerr"] description = "Proof of Space library for the Chia Blockchain" @@ -11,8 +11,8 @@ repository = "https://github.com/GalactechsLLC/dg_xch_utils" [dependencies] async-trait = "0.1.77" blake3 = "1.5.0" -dg_xch_core = {path = "../core", version = "2.0.2", default-features = false } -dg_xch_serialize = {path = "../serialize", version="2.0.2"} +dg_xch_core = {path = "../core", version = "2.0.3", default-features = false } +dg_xch_serialize = {path = "../serialize", version="2.0.3"} futures-util = "0.3.30" hex = "0.4.3" lazy_static = "1.4.0" diff --git a/puzzles/Cargo.toml b/puzzles/Cargo.toml index 62f18e0..d6a89e3 100644 --- a/puzzles/Cargo.toml +++ b/puzzles/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_puzzles" -version = "2.0.2" +version = "2.0.3" edition = "2021" authors = ["James Hoerr"] description = "Core library for working with CLVM puzzles" @@ -10,8 +10,8 @@ repository = "https://github.com/GalactechsLLC/dg_xch_utils" [dependencies] blst = { version = "0.3.11", features = ["portable"] } -dg_xch_core = {path = "../core", version = "2.0.2", default-features = false} -dg_xch_serialize = {path = "../serialize", version="2.0.2"} +dg_xch_core = {path = "../core", version = "2.0.3", default-features = false} +dg_xch_serialize = {path = "../serialize", version="2.0.3"} hex = "0.4.3" lazy_static = "1.4.0" num-bigint = "0.4.4" diff --git a/puzzles/src/clvm_puzzles.rs b/puzzles/src/clvm_puzzles.rs index fc46b5e..6b2773a 100644 --- a/puzzles/src/clvm_puzzles.rs +++ b/puzzles/src/clvm_puzzles.rs @@ -8,7 +8,7 @@ use dg_xch_core::consensus::block_rewards::calculate_pool_reward; use dg_xch_core::consensus::coinbase::pool_parent_id; use dg_xch_core::plots::PlotNftExtraData; use dg_xch_core::pool::PoolState; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use lazy_static::lazy_static; use log::debug; use num_traits::{ToPrimitive, Zero}; @@ -350,7 +350,13 @@ pub fn create_travel_spend( )?; let inner_solution = if is_pool_member_inner_puzzle(&inner_puzzle)? { Program::to(vec![ - vec![("p".to_sexp(), SExp::Atom(AtomBuf::new(target.to_bytes())))].to_sexp(), + vec![( + "p".to_sexp(), + SExp::Atom(AtomBuf::new( + target.to_bytes(ChiaProtocolVersion::default()), + )), + )] + .to_sexp(), 0.to_sexp(), ]) } else if is_pool_waitingroom_inner_puzzle(&inner_puzzle)? { @@ -364,11 +370,17 @@ pub fn create_travel_spend( debug!( "create_travel_spend: waitingroom: target PoolState bytes:\n{:?}\nhash:{}", target, - Program::to(target.to_bytes()).tree_hash() + Program::to(target.to_bytes(ChiaProtocolVersion::default())).tree_hash() ); Program::to(vec![ 1.to_sexp(), - vec![("p".to_sexp(), SExp::Atom(AtomBuf::new(target.to_bytes())))].to_sexp(), + vec![( + "p".to_sexp(), + SExp::Atom(AtomBuf::new( + target.to_bytes(ChiaProtocolVersion::default()), + )), + )] + .to_sexp(), destination_inner.tree_hash().to_sexp(), ]) // current or target } else { @@ -538,7 +550,10 @@ pub fn pool_state_from_extra_data(extra_data: Program) -> Result { let mut cursor = Cursor::new(byte_data); - Ok(Some(PoolState::from_bytes(&mut cursor)?)) + Ok(Some(PoolState::from_bytes( + &mut cursor, + ChiaProtocolVersion::default(), + )?)) } None => Ok(None), } diff --git a/serialize/Cargo.toml b/serialize/Cargo.toml index f6a6042..6e48966 100644 --- a/serialize/Cargo.toml +++ b/serialize/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_serialize" -version = "2.0.2" +version = "2.0.3" edition = "2021" authors = ["James Hoerr"] description = "Low Level Support Package for dg_xch_utils" @@ -11,4 +11,5 @@ repository = "https://github.com/GalactechsLLC/dg_xch_utils" [dependencies] bytes = "1.5.0" log = "0.4.20" +serde = "1.0.197" sha2 = "0.10.8" \ No newline at end of file diff --git a/serialize/src/lib.rs b/serialize/src/lib.rs index 13e9229..20045b2 100644 --- a/serialize/src/lib.rs +++ b/serialize/src/lib.rs @@ -1,7 +1,10 @@ use bytes::Buf; use log::warn; use sha2::{Digest, Sha256}; +use std::convert::Infallible; +use std::fmt::{Display, Formatter}; use std::io::{Cursor, Error, ErrorKind, Read}; +use std::str::FromStr; pub fn hash_256(input: impl AsRef<[u8]>) -> Vec { let mut hasher = Sha256::new(); @@ -9,17 +12,65 @@ pub fn hash_256(input: impl AsRef<[u8]>) -> Vec { hasher.finalize().to_vec() } +#[derive( + Default, + Debug, + Copy, + Clone, + Ord, + PartialOrd, + Eq, + PartialEq, + serde::Serialize, + serde::Deserialize, +)] +pub enum ChiaProtocolVersion { + Chia0_0_34 = 34, //Pre 2.0.0 + Chia0_0_35 = 35, //2.0.0 + #[default] + Chia0_0_36 = 36, //2.2.0 +} +impl Display for ChiaProtocolVersion { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + ChiaProtocolVersion::Chia0_0_34 => f.write_str("0.0.34"), + ChiaProtocolVersion::Chia0_0_35 => f.write_str("0.0.35"), + ChiaProtocolVersion::Chia0_0_36 => f.write_str("0.0.36"), + } + } +} +impl FromStr for ChiaProtocolVersion { + type Err = Infallible; + fn from_str(s: &str) -> Result { + Ok(match s { + "0.0.34" => ChiaProtocolVersion::Chia0_0_34, + "0.0.35" => ChiaProtocolVersion::Chia0_0_35, + "0.0.36" => ChiaProtocolVersion::Chia0_0_36, + _ => { + warn!( + "Failed to detect Protocol Version: {s}, defaulting to {}", + ChiaProtocolVersion::default() + ); + ChiaProtocolVersion::default() + } + }) + } +} + pub trait ChiaSerialize { - fn to_bytes(&self) -> Vec + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec where Self: Sized; - fn from_bytes>(bytes: &mut Cursor) -> Result + fn from_bytes>( + bytes: &mut Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized; } impl ChiaSerialize for String { - fn to_bytes(&self) -> Vec + fn to_bytes(&self, _version: ChiaProtocolVersion) -> Vec where Self: Sized, { @@ -28,7 +79,10 @@ impl ChiaSerialize for String { bytes.extend(self.as_bytes()); bytes } - fn from_bytes>(bytes: &mut Cursor) -> Result + fn from_bytes>( + bytes: &mut Cursor, + _version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { @@ -50,13 +104,16 @@ impl ChiaSerialize for String { } impl ChiaSerialize for bool { - fn to_bytes(&self) -> Vec + fn to_bytes(&self, _version: ChiaProtocolVersion) -> Vec where Self: Sized, { vec![*self as u8] } - fn from_bytes>(bytes: &mut Cursor) -> Result + fn from_bytes>( + bytes: &mut Cursor, + _version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { @@ -77,7 +134,7 @@ impl ChiaSerialize for Option where T: ChiaSerialize, { - fn to_bytes(&self) -> Vec + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec where Self: Sized, { @@ -85,7 +142,7 @@ where match &self { Some(t) => { bytes.push(1u8); - bytes.extend(t.to_bytes()); + bytes.extend(t.to_bytes(version)); } None => { bytes.push(0u8); @@ -93,14 +150,17 @@ where } bytes } - fn from_bytes>(bytes: &mut Cursor) -> Result + fn from_bytes>( + bytes: &mut Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { let mut bool_buf: [u8; 1] = [0; 1]; bytes.read_exact(&mut bool_buf)?; if bool_buf[0] > 0 { - Ok(Some(T::from_bytes(bytes)?)) + Ok(Some(T::from_bytes(bytes, version)?)) } else { Ok(None) } @@ -112,21 +172,24 @@ where T: ChiaSerialize, U: ChiaSerialize, { - fn to_bytes(&self) -> Vec + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec where Self: Sized, { let mut bytes: Vec = Vec::new(); - bytes.extend(self.0.to_bytes()); - bytes.extend(self.1.to_bytes()); + bytes.extend(self.0.to_bytes(version)); + bytes.extend(self.1.to_bytes(version)); bytes } - fn from_bytes>(bytes: &mut Cursor) -> Result + fn from_bytes>( + bytes: &mut Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - let t = T::from_bytes(bytes)?; - let u = U::from_bytes(bytes)?; + let t = T::from_bytes(bytes, version)?; + let u = U::from_bytes(bytes, version)?; Ok((t, u)) } } @@ -137,23 +200,26 @@ where U: ChiaSerialize, V: ChiaSerialize, { - fn to_bytes(&self) -> Vec + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec where Self: Sized, { let mut bytes: Vec = Vec::new(); - bytes.extend(self.0.to_bytes()); - bytes.extend(self.1.to_bytes()); - bytes.extend(self.2.to_bytes()); + bytes.extend(self.0.to_bytes(version)); + bytes.extend(self.1.to_bytes(version)); + bytes.extend(self.2.to_bytes(version)); bytes } - fn from_bytes>(bytes: &mut Cursor) -> Result + fn from_bytes>( + bytes: &mut Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { - let t = T::from_bytes(bytes)?; - let u = U::from_bytes(bytes)?; - let v = V::from_bytes(bytes)?; + let t = T::from_bytes(bytes, version)?; + let u = U::from_bytes(bytes, version)?; + let v = V::from_bytes(bytes, version)?; Ok((t, u, v)) } } @@ -162,18 +228,21 @@ impl ChiaSerialize for Vec where T: ChiaSerialize, { - fn to_bytes(&self) -> Vec + fn to_bytes(&self, version: ChiaProtocolVersion) -> Vec where Self: Sized, { let mut bytes: Vec = Vec::new(); bytes.extend((self.len() as u32).to_be_bytes()); for e in self { - bytes.extend(e.to_bytes()); + bytes.extend(e.to_bytes(version)); } bytes } - fn from_bytes>(bytes: &mut Cursor) -> Result + fn from_bytes>( + bytes: &mut Cursor, + version: ChiaProtocolVersion, + ) -> Result where Self: Sized, { @@ -185,7 +254,7 @@ where warn!("Serializing Large Vec: {vec_len}") } (0..vec_len).try_fold(buf, |mut vec, _| { - vec.push(T::from_bytes(bytes)?); + vec.push(T::from_bytes(bytes, version)?); Ok(vec) }) } @@ -195,10 +264,10 @@ macro_rules! impl_primitives { ($($name: ident, $size:expr);*) => { $( impl ChiaSerialize for $name { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self, _version: ChiaProtocolVersion) -> Vec { self.to_be_bytes().to_vec() } - fn from_bytes>(bytes: &mut Cursor) -> Result where Self: Sized, + fn from_bytes>(bytes: &mut Cursor, _version: ChiaProtocolVersion) -> Result where Self: Sized, { if bytes.remaining() < $size { Err(Error::new(std::io::ErrorKind::InvalidInput, format!("Failed to Parse $name, expected length $size, found {}", bytes.remaining()))) diff --git a/servers/Cargo.toml b/servers/Cargo.toml index d34c5b0..2c41e8c 100644 --- a/servers/Cargo.toml +++ b/servers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_servers" -version = "2.0.2" +version = "2.0.3" edition = "2021" authors = ["James Hoerr"] description = "Library for Creating Servers compatible with Chia's RPC and Websocket Protocols" @@ -11,17 +11,18 @@ repository = "https://github.com/GalactechsLLC/dg_xch_utils" [dependencies] async-trait = "0.1.77" blst = { version = "0.3.11", features = ["portable"] } -dg_xch_core = {path = "../core", version = "2.0.2", default-features = false } -dg_xch_clients = {path = "../clients", version = "2.0.2" } -dg_xch_keys = {path = "../keys", version = "2.0.2" } -dg_xch_pos = {path = "../proof_of_space", version = "2.0.2" } -dg_xch_serialize = {path = "../serialize", version = "2.0.2" } +dg_xch_core = {path = "../core", version = "2.0.3", default-features = false } +dg_xch_clients = {path = "../clients", version = "2.0.3" } +dg_xch_keys = {path = "../keys", version = "2.0.3" } +dg_xch_pos = {path = "../proof_of_space", version = "2.0.3" } +dg_xch_serialize = {path = "../serialize", version = "2.0.3" } http-body-util = { version = "0.1"} hex = "0.4.3" +http = "1.0.0" hyper = {version="1.1.0", features=["full"]} hyper-tungstenite = "0.12.0" hyper-util = {version="0.1.3", features=["full"]} -log = "0.4.20" +log = "0.4.21" prometheus = {version="0.13.3", features=["protobuf"], optional = true} rustls = {version = "0.21.10", features = ["dangerous_configuration"] } serde = { version = "1.0.197", features = ["derive"] } diff --git a/servers/src/rpc/mod.rs b/servers/src/rpc/mod.rs index 5c6efcc..3b8d585 100644 --- a/servers/src/rpc/mod.rs +++ b/servers/src/rpc/mod.rs @@ -3,13 +3,20 @@ use dg_xch_core::ssl::{ generate_ca_signed_cert_data, load_certs, load_certs_from_bytes, load_private_key, load_private_key_from_bytes, AllowAny, SslInfo, CHIA_CA_CRT, CHIA_CA_KEY, }; +use http::request::Parts; +use http::{Method, StatusCode}; use http_body_util::Full; -use hyper::body::{Bytes, Incoming}; +use hyper::body::{Body, Bytes, Incoming, SizeHint}; +use hyper::header::HeaderValue; use hyper::server::conn::http1::Builder; use hyper::service::service_fn; -use hyper::{Request, Response}; +use hyper::{HeaderMap, Request, Response, Uri}; use hyper_util::rt::TokioIo; use log::error; +#[cfg(feature = "metrics")] +use prometheus::core::{AtomicU64, GenericCounterVec}; +#[cfg(feature = "metrics")] +use prometheus::{HistogramOpts, HistogramVec, Opts, Registry}; use rustls::{RootCertStore, ServerConfig}; use std::env; use std::io::{Error, ErrorKind}; @@ -18,23 +25,184 @@ use std::str::FromStr; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::Duration; +#[cfg(feature = "metrics")] +use std::time::Instant; use tokio::net::TcpListener; use tokio::select; use tokio_rustls::TlsAcceptor; #[async_trait] pub trait RpcHandler { - async fn handle(&self, req: Request) -> Result>, Error>; + async fn handle( + &self, + request: RpcRequest, + response: Response>, + address: &SocketAddr, + ) -> Result>, (Parts, HeaderMap, Error)>; +} + +pub fn extract_parts_and_drop_body(req: RpcRequest) -> (Parts, HeaderMap) { + match req.request_type { + RequestType::Stream(r) => (r.into_parts().0, req.response_headers), + RequestType::Sized(r) => (r.into_parts().0, req.response_headers), + } +} + +pub struct RpcRequest { + pub request_type: RequestType, + pub response_headers: HeaderMap, +} +impl RpcRequest { + pub fn get_best_guess_public_ip(&self, address: &SocketAddr) -> String { + if let Some(real_ip) = self.headers().get("x-real-ip") { + format!("{:?}", real_ip) + } else if let Some(forwards) = self.headers().get("x-forwarded-for") { + format!("{:?}", forwards) + } else { + address.to_string() + } + } + pub fn uri(&self) -> &Uri { + match &self.request_type { + RequestType::Sized(r) => r.uri(), + RequestType::Stream(r) => r.uri(), + } + } + pub fn headers(&self) -> &HeaderMap { + match &self.request_type { + RequestType::Sized(r) => r.headers(), + RequestType::Stream(r) => r.headers(), + } + } + pub fn method(&self) -> &Method { + match &self.request_type { + RequestType::Sized(r) => r.method(), + RequestType::Stream(r) => r.method(), + } + } + pub fn size_hint(&self) -> SizeHint { + match &self.request_type { + RequestType::Sized(r) => r.size_hint(), + RequestType::Stream(r) => r.size_hint(), + } + } +} + +pub enum RequestType { + Stream(Request), + Sized(Request>), +} + +#[cfg(feature = "metrics")] +#[non_exhaustive] +pub struct EndpointMetrics { + pub total_requests: Arc>, + pub successful_requests: Arc>, + pub failed_requests: Arc>, + pub blocked_requests: Arc>, + pub average_request_time: Arc, +} +#[cfg(feature = "metrics")] +impl EndpointMetrics { + pub fn new(registry: &Registry) -> Result { + let labels = &["code", "method", "path"]; + Ok(Self { + total_requests: Arc::new( + GenericCounterVec::new( + Opts::new("total_requests", "Total requests server has handled"), + labels, + ) + .map(|g: GenericCounterVec| { + registry.register(Box::new(g.clone())).unwrap_or(()); + g + })?, + ), + successful_requests: Arc::new( + GenericCounterVec::new( + Opts::new( + "successful_requests", + "Total successful requests server has handled", + ), + labels, + ) + .map(|g: GenericCounterVec| { + registry.register(Box::new(g.clone())).unwrap_or(()); + g + })?, + ), + failed_requests: Arc::new( + GenericCounterVec::new( + Opts::new( + "failed_requests", + "Total failed requests server has handled", + ), + labels, + ) + .map(|g: GenericCounterVec| { + registry.register(Box::new(g.clone())).unwrap_or(()); + g + })?, + ), + blocked_requests: Arc::new( + GenericCounterVec::new( + Opts::new( + "blocked_requests", + "Total blocked requests server has handled", + ), + labels, + ) + .map(|g: GenericCounterVec| { + registry.register(Box::new(g.clone())).unwrap_or(()); + g + })?, + ), + average_request_time: Arc::new({ + let opts = HistogramOpts::new("average_request_time", "Average Request Time"); + HistogramVec::new(opts, labels).map(|h: HistogramVec| { + registry.register(Box::new(h.clone())).unwrap_or(()); + h + })? + }), + }) + } +} + +#[cfg(feature = "metrics")] +pub struct RpcMetrics { + pub request_metrics: Arc, +} + +pub enum MiddleWareResult { + Continue(RpcRequest), + Bypass(RpcRequest), + Failure(Parts, Response>), +} + +#[async_trait] +pub trait MiddleWare { + async fn handle( + &self, + req: RpcRequest, + address: &SocketAddr, + ) -> Result; + + fn name(&self) -> &str; + fn set_enabled(&self, enabled: bool); + fn is_enabled(&self) -> bool; } #[derive(Default)] pub struct DefaultRpcHandler {} #[async_trait] impl RpcHandler for DefaultRpcHandler { - async fn handle(&self, _: Request) -> Result>, Error> { - Ok(Response::new(Full::new(Bytes::from( - "HTTP NOT SUPPORTED ON THIS ENDPOINT", - )))) + async fn handle( + &self, + _: RpcRequest, + mut response: Response>, + _: &SocketAddr, + ) -> Result>, (Parts, HeaderMap, Error)> { + *response.body_mut() = Full::new(Bytes::from("HTTP NOT SUPPORTED ON THIS ENDPOINT")); + Ok(response) } } @@ -48,11 +216,30 @@ pub struct RpcServer { pub socket_address: SocketAddr, pub server_config: Arc, pub handler: Arc, + pub middleware: Arc>>, + #[cfg(feature = "metrics")] + pub metrics: Arc, } impl RpcServer { pub fn new( config: &RpcServerConfig, handler: Arc, + #[cfg(feature = "metrics")] metrics: Arc, + ) -> Result { + let middleware: Vec> = vec![]; + Self::new_with_middleware( + config, + handler, + Arc::new(middleware), + #[cfg(feature = "metrics")] + metrics, + ) + } + pub fn new_with_middleware( + config: &RpcServerConfig, + handler: Arc, + middleware: Arc>>, + #[cfg(feature = "metrics")] metrics: Arc, ) -> Result { let server_config = Self::init(config) .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("Invalid Cert: {:?}", e)))?; @@ -61,6 +248,9 @@ impl RpcServer { socket_address, server_config, handler, + middleware, + #[cfg(feature = "metrics")] + metrics, }) } @@ -74,13 +264,13 @@ impl RpcServer { select!( res = listener.accept() => { match res { - Ok((stream, _)) => { + Ok((stream, address)) => { match acceptor.accept(stream).await { Ok(stream) => { let server = server.clone(); let service = service_fn(move |req| { let server = server.clone(); - connection_handler(server, req) + connection_handler(server, req, address) }); let connection = http.serve_connection(TokioIo::new(stream), service); tokio::spawn( async move { @@ -186,6 +376,183 @@ impl RpcServer { async fn connection_handler( server: Arc, req: Request, + address: SocketAddr, ) -> Result>, Error> { - server.handler.handle(req).await + #[cfg(feature = "metrics")] + let start = Instant::now(); + let mut req: RpcRequest = RpcRequest { + request_type: RequestType::Stream(req), + response_headers: Default::default(), + }; + let middleware_arc = server.middleware.clone(); + for middleware in middleware_arc.as_slice() { + if middleware.is_enabled() { + match middleware.handle(req, &address).await? { + MiddleWareResult::Bypass(r) => { + req = r; + break; + } + MiddleWareResult::Continue(r) => { + req = r; + continue; + } + MiddleWareResult::Failure(_parts, res) => { + #[cfg(feature = "metrics")] + { + match res.status() { + StatusCode::PAYLOAD_TOO_LARGE | StatusCode::TOO_MANY_REQUESTS => { + set_blocked_metrics( + server.clone(), + res.status().as_str(), + _parts.method.as_str(), + _parts.uri.path(), + start, + ); + } + _ => { + set_failed_metrics( + server.clone(), + res.status().as_str(), + _parts.method.as_str(), + _parts.uri.path(), + start, + ); + } + } + } + return Ok(res); + } + } + } + } + #[cfg(feature = "metrics")] + let (method, path) = { (req.method().to_string(), req.uri().path().to_string()) }; + let response = Response::builder() + .header( + "Access-Control-Allow-Origin", + req.headers() + .get("origin") + .unwrap_or(&HeaderValue::from_static("*")), + ) + .header( + "Access-Control-Allow-Credentials", + HeaderValue::from_static("true"), + ) + .header( + "Access-Control-Allow-Methods", + HeaderValue::from_static("POST, GET"), + ) + .body(Full::new(Bytes::new())) + .expect("Failed to create default request"); + match server.handler.handle(req, response, &address).await { + Ok(response) => { + #[cfg(feature = "metrics")] + { + set_success_metrics( + server.clone(), + response.status().as_str(), + &method, + &path, + start, + ); + } + Ok(response) + } + Err((_parts, _headers, e)) => { + #[cfg(feature = "metrics")] + { + set_failed_metrics( + server.clone(), + StatusCode::INTERNAL_SERVER_ERROR.as_str(), + &method, + &path, + start, + ); + } + Ok(Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .header("Access-Control-Allow-Origin", "*") + .body(Full::new(Bytes::from(format!("{e:?}")))) + .expect("Failed to create 500 body")) + } + } +} + +#[cfg(feature = "metrics")] +pub fn set_failed_metrics( + server: Arc, + code: &str, + method: &str, + path: &str, + start: Instant, +) { + server + .metrics + .request_metrics + .failed_requests + .with_label_values(&[code, method, path]) + .inc(); + common_metrics(server, code, method, path, start); +} + +#[cfg(feature = "metrics")] +pub fn set_success_metrics( + server: Arc, + code: &str, + method: &str, + path: &str, + start: Instant, +) { + server + .metrics + .request_metrics + .successful_requests + .with_label_values(&[code, method, path]) + .inc(); + common_metrics(server, code, method, path, start); +} + +#[cfg(feature = "metrics")] +pub fn set_blocked_metrics( + server: Arc, + code: &str, + method: &str, + path: &str, + start: Instant, +) { + server + .metrics + .request_metrics + .blocked_requests + .with_label_values(&[code, method, path]) + .inc(); + common_metrics(server, code, method, path, start); +} + +#[cfg(feature = "metrics")] +pub fn common_metrics( + server: Arc, + code: &str, + method: &str, + path: &str, + start: Instant, +) { + server + .metrics + .request_metrics + .average_request_time + .with_label_values(&[code, method, path]) + .observe(duration_to_seconds(Instant::now().duration_since(start))); + server + .metrics + .request_metrics + .total_requests + .with_label_values(&[code, method, path]) + .inc(); +} + +#[inline] +pub fn duration_to_seconds(d: Duration) -> f64 { + let nanos = f64::from(d.subsec_nanos()) / 1e9; + d.as_secs() as f64 + nanos } diff --git a/servers/src/websocket/farmer/handshake.rs b/servers/src/websocket/farmer/handshake.rs index 27c9091..336f289 100644 --- a/servers/src/websocket/farmer/handshake.rs +++ b/servers/src/websocket/farmer/handshake.rs @@ -4,15 +4,16 @@ use async_trait::async_trait; use blst::min_pk::SecretKey; use dg_xch_core::blockchain::sized_bytes::{Bytes32, Bytes48}; use dg_xch_core::protocols::harvester::HarvesterHandshake; -use dg_xch_core::protocols::shared::{Handshake, CAPABILITIES, PROTOCOL_VERSION}; +use dg_xch_core::protocols::shared::{Handshake, CAPABILITIES}; use dg_xch_core::protocols::{ ChiaMessage, MessageHandler, NodeType, PeerMap, ProtocolMessageTypes, }; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use hyper_tungstenite::tungstenite::Message; use log::{debug, info}; use std::collections::HashMap; use std::io::{Cursor, Error}; +use std::str::FromStr; use std::sync::Arc; pub struct HandshakeHandle { @@ -29,7 +30,13 @@ impl MessageHandler for HandshakeHandle { peers: PeerMap, ) -> Result<(), Error> { let mut cursor = Cursor::new(&msg.data); - let handshake = Handshake::from_bytes(&mut cursor)?; + let peer = peers.read().await.get(&peer_id).cloned(); + let protocol_version = if let Some(peer) = peer.as_ref() { + *peer.protocol_version.read().await + } else { + ChiaProtocolVersion::default() + }; + let handshake = Handshake::from_bytes(&mut cursor, protocol_version)?; debug!("New Peer: {}", &peer_id); if let Some(peer) = peers.read().await.get(&peer_id).cloned() { let (network_id, server_port) = { @@ -37,15 +44,20 @@ impl MessageHandler for HandshakeHandle { (cfg.network.clone(), cfg.websocket.port) }; *peer.node_type.write().await = NodeType::from(handshake.node_type); + let protocol_version = ChiaProtocolVersion::from_str(&handshake.protocol_version) + .expect("ChiaProtocolVersion::from_str is Infallible"); + *peer.protocol_version.write().await = protocol_version; peer.websocket .write() .await .send(Message::Binary( ChiaMessage::new( ProtocolMessageTypes::Handshake, + protocol_version, &Handshake { network_id, - protocol_version: PROTOCOL_VERSION.to_string(), + //Server Will use version sent by peer + protocol_version: protocol_version.to_string(), software_version: version(), server_port, node_type: NodeType::Farmer as u8, @@ -56,7 +68,7 @@ impl MessageHandler for HandshakeHandle { }, msg.id, ) - .to_bytes(), + .to_bytes(protocol_version), )) .await .unwrap_or_default(); @@ -70,13 +82,14 @@ impl MessageHandler for HandshakeHandle { .send(Message::Binary( ChiaMessage::new( ProtocolMessageTypes::HarvesterHandshake, + protocol_version, &HarvesterHandshake { farmer_public_keys, pool_public_keys, }, None, ) - .to_bytes(), + .to_bytes(protocol_version), )) .await .unwrap_or_default(); diff --git a/servers/src/websocket/farmer/mod.rs b/servers/src/websocket/farmer/mod.rs index 8fa64ee..4ab53f2 100644 --- a/servers/src/websocket/farmer/mod.rs +++ b/servers/src/websocket/farmer/mod.rs @@ -1,5 +1,7 @@ use crate::websocket::farmer::new_proof_or_space::NewProofOfSpaceHandle; use crate::websocket::farmer::respond_signatures::RespondSignaturesHandle; +#[cfg(feature = "metrics")] +use crate::websocket::WebSocketMetrics; use crate::websocket::{WebsocketServer, WebsocketServerConfig}; use blst::min_pk::SecretKey; use dg_xch_clients::api::pool::PoolClient; @@ -15,7 +17,7 @@ use dg_xch_core::protocols::pool::{ }; use dg_xch_core::protocols::{ChiaMessageFilter, ChiaMessageHandler, ProtocolMessageTypes}; use dg_xch_keys::decode_puzzle_hash; -use dg_xch_serialize::{hash_256, ChiaSerialize}; +use dg_xch_serialize::{hash_256, ChiaProtocolVersion, ChiaSerialize}; use log::{error, info}; use std::collections::HashMap; use std::io::Error; @@ -49,6 +51,7 @@ impl Fa shared_state: Arc>, full_node_client: Arc>>>, additional_headers: Arc>, + #[cfg(feature = "metrics")] metrics: Arc>, ) -> Result { let config = Arc::new(config); let handles = Arc::new(RwLock::new(Self::handles( @@ -63,6 +66,8 @@ impl Fa &config.websocket, shared_state.harvester_peers.clone(), handles, + #[cfg(feature = "metrics")] + metrics, )?, shared_state, pool_client, @@ -178,7 +183,7 @@ pub async fn get_farmer( target_puzzle_hash, authentication_token, } - .to_bytes(); + .to_bytes(ChiaProtocolVersion::default()); let to_sign = hash_256(&msg); let signature = sign(authentication_sk, &to_sign); if !verify_signature(&authentication_sk.sk_to_pk(), &to_sign, &signature) { @@ -238,7 +243,7 @@ pub async fn post_farmer( )?, suggested_difficulty, }; - let to_sign = hash_256(payload.to_bytes()); + let to_sign = hash_256(payload.to_bytes(ChiaProtocolVersion::default())); let signature = sign(owner_sk, &to_sign); if !verify_signature(&owner_sk.sk_to_pk(), &to_sign, &signature) { error!("Farmer POST Failed to Validate Signature"); @@ -276,7 +281,7 @@ pub async fn put_farmer( payout_instructions: parse_payout_address(payout_instructions.to_string()).ok(), suggested_difficulty, }; - let to_sign = hash_256(payload.to_bytes()); + let to_sign = hash_256(payload.to_bytes(ChiaProtocolVersion::default())); let signature = sign(owner_sk, &to_sign); if !verify_signature(&owner_sk.sk_to_pk(), &to_sign, &signature) { error!("Local Failed to Validate Signature"); diff --git a/servers/src/websocket/farmer/new_proof_or_space.rs b/servers/src/websocket/farmer/new_proof_or_space.rs index 0bf5ff2..1f3a953 100644 --- a/servers/src/websocket/farmer/new_proof_or_space.rs +++ b/servers/src/websocket/farmer/new_proof_or_space.rs @@ -7,7 +7,7 @@ use dg_xch_clients::websocket::oneshot; use dg_xch_core::blockchain::proof_of_space::{generate_plot_public_key, generate_taproot_sk}; use dg_xch_core::blockchain::sized_bytes::{Bytes32, Bytes48, SizedBytes}; use dg_xch_core::clvm::bls_bindings::{sign, sign_prepend, AUG_SCHEME_DST}; -use dg_xch_core::consensus::constants::CONSENSUS_CONSTANTS_MAP; +use dg_xch_core::consensus::constants::{ConsensusConstants, CONSENSUS_CONSTANTS_MAP}; use dg_xch_core::consensus::pot_iterations::{ calculate_iterations_quality, calculate_sp_interval_iters, }; @@ -25,8 +25,8 @@ use dg_xch_core::protocols::pool::{ }; use dg_xch_core::protocols::{ChiaMessage, MessageHandler, PeerMap, ProtocolMessageTypes}; use dg_xch_pos::verify_and_get_quality_string; -use dg_xch_serialize::hash_256; use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{hash_256, ChiaProtocolVersion}; use hyper_tungstenite::tungstenite::Message; use log::{debug, error, info, warn}; use std::collections::HashMap; @@ -60,13 +60,11 @@ impl MessageHandler for NewProofO peer_id: Arc, peers: PeerMap, ) -> Result<(), Error> { - let exists; - { - exists = peers.read().await.get(&peer_id).is_some(); - } - if exists { + let peer = peers.read().await.get(&peer_id).cloned(); + if let Some(peer) = peer { + let protocol_version = *peer.protocol_version.read().await; let mut cursor = Cursor::new(&msg.data); - let new_pos = NewProofOfSpace::from_bytes(&mut cursor)?; + let new_pos = NewProofOfSpace::from_bytes(&mut cursor, protocol_version)?; if let Some(sps) = self.signage_points.read().await.get(&new_pos.sp_hash) { let constants = CONSENSUS_CONSTANTS_MAP .get(&self.config.network) @@ -90,480 +88,485 @@ impl MessageHandler for NewProofO if required_iters < calculate_sp_interval_iters(&constants, sp.sub_slot_iters)? { - let sp_src_data = { - if new_pos.include_source_signature_data - || new_pos.farmer_reward_address_override.is_some() - { - if let Some(sp_data) = sp.sp_source_data.as_ref() { - let (cc, rc) = if let Some(vdf) = sp_data.vdf_data.as_ref() - { - ( - SignatureRequestSourceData { - kind: SigningDataKind::ChallengeChainVdf, - data: vdf.cc_vdf.to_bytes(), - }, - SignatureRequestSourceData { - kind: SigningDataKind::RewardChainVdf, - data: vdf.rc_vdf.to_bytes(), - }, - ) - } else if let Some(vdf) = sp_data.sub_slot_data.as_ref() { - ( - SignatureRequestSourceData { - kind: SigningDataKind::ChallengeChainSubSlot, - data: vdf.cc_sub_slot.to_bytes(), - }, - SignatureRequestSourceData { - kind: SigningDataKind::RewardChainSubSlot, - data: vdf.rc_sub_slot.to_bytes(), - }, - ) - } else { - return Err(Error::new(ErrorKind::InvalidInput, "Source Signature Did not contain any data, Cannot Sign Proof")); - }; - Some(vec![Some(cc), Some(rc)]) - } else { - return Err(Error::new(ErrorKind::InvalidInput, "Source Signature Data Request But was Null, Cannot Sign Proof")); - } - } else { - None - } - }; - let request = RequestSignatures { - plot_identifier: new_pos.plot_identifier.clone(), - challenge_hash: new_pos.challenge_hash, - sp_hash: new_pos.sp_hash, - messages: vec![sp.challenge_chain_sp, sp.reward_chain_sp], - message_data: sp_src_data, - rc_block_unfinished: None, - }; - if self - .proofs_of_space - .read() + self._handle_proof( + sp, + &qs, + &new_pos, + protocol_version, + peer_id.clone(), + peers.clone(), + ) + .await? + } + if new_pos.proof.pool_contract_puzzle_hash.is_some() { + self.handle_partial( + &qs, + &new_pos, + &constants, + protocol_version, + peer_id.clone(), + peers.clone(), + ) + .await? + } else { + debug!("Not a pooling proof of space"); + } + } else { + warn!("Invalid proof of space {:?}", new_pos); + } + } + } else { + warn!( + "Received response for a signage point that we do not have {}", + &new_pos.sp_hash + ); + } + } else { + warn!("Peer Not Found {:?}", peer_id); + } + Ok(()) + } +} + +impl NewProofOfSpaceHandle { + async fn _handle_proof( + &self, + sp: &NewSignagePoint, + qs: &Bytes32, + new_pos: &NewProofOfSpace, + protocol_version: ChiaProtocolVersion, + peer_id: Arc, + peers: PeerMap, + ) -> Result<(), Error> { + let sp_src_data = { + if new_pos.include_source_signature_data + || new_pos.farmer_reward_address_override.is_some() + { + if let Some(sp_data) = sp.sp_source_data.as_ref() { + let (cc, rc) = if let Some(vdf) = sp_data.vdf_data.as_ref() { + ( + SignatureRequestSourceData { + kind: SigningDataKind::ChallengeChainVdf, + data: vdf.cc_vdf.to_bytes(protocol_version), + }, + SignatureRequestSourceData { + kind: SigningDataKind::RewardChainVdf, + data: vdf.rc_vdf.to_bytes(protocol_version), + }, + ) + } else if let Some(vdf) = sp_data.sub_slot_data.as_ref() { + ( + SignatureRequestSourceData { + kind: SigningDataKind::ChallengeChainSubSlot, + data: vdf.cc_sub_slot.to_bytes(protocol_version), + }, + SignatureRequestSourceData { + kind: SigningDataKind::RewardChainSubSlot, + data: vdf.rc_sub_slot.to_bytes(protocol_version), + }, + ) + } else { + return Err(Error::new( + ErrorKind::InvalidInput, + "Source Signature Did not contain any data, Cannot Sign Proof", + )); + }; + Some(vec![Some(cc), Some(rc)]) + } else { + return Err(Error::new( + ErrorKind::InvalidInput, + "Source Signature Data Request But was Null, Cannot Sign Proof", + )); + } + } else { + None + } + }; + let request = RequestSignatures { + plot_identifier: new_pos.plot_identifier.clone(), + challenge_hash: new_pos.challenge_hash, + sp_hash: new_pos.sp_hash, + messages: vec![sp.challenge_chain_sp, sp.reward_chain_sp], + message_data: sp_src_data, + rc_block_unfinished: None, + }; + if self + .proofs_of_space + .read() + .await + .get(&new_pos.sp_hash) + .is_none() + { + self.proofs_of_space + .write() + .await + .insert(new_pos.sp_hash, vec![]); + } + self.proofs_of_space + .write() + .await + .get_mut(&new_pos.sp_hash) + .expect("Should not happen, item created above") + .push((new_pos.plot_identifier.clone(), new_pos.proof.clone())); + self.cache_time + .write() + .await + .insert(new_pos.sp_hash, Instant::now()); + self.quality_to_identifiers.write().await.insert( + *qs, + FarmerIdentifier { + plot_identifier: new_pos.plot_identifier.clone(), + challenge_hash: new_pos.challenge_hash, + sp_hash: new_pos.sp_hash, + peer_node_id: *peer_id, + }, + ); + self.cache_time.write().await.insert(*qs, Instant::now()); + if let Some(p) = peers.read().await.get(&peer_id).cloned() { + let _ = p + .websocket + .write() + .await + .send(Message::Binary( + ChiaMessage::new( + ProtocolMessageTypes::RequestSignatures, + protocol_version, + &request, + None, + ) + .to_bytes(protocol_version), + )) + .await; + } + Ok(()) + } + + async fn handle_partial( + &self, + qs: &Bytes32, + new_pos: &NewProofOfSpace, + constants: &ConsensusConstants, + protocol_version: ChiaProtocolVersion, + peer_id: Arc, + peers: PeerMap, + ) -> Result<(), Error> { + let p2_singleton_puzzle_hash = new_pos + .proof + .pool_contract_puzzle_hash + .as_ref() + .expect("Checked in previous method"); + if self + .pool_state + .read() + .await + .get(p2_singleton_puzzle_hash) + .is_none() + { + warn!("Did not find pool info for {p2_singleton_puzzle_hash}"); + return Ok(()); + } + let (pool_url, launcher_id) = if let Some(Some(config)) = self + .pool_state + .read() + .await + .get(p2_singleton_puzzle_hash) + .map(|v| v.pool_config.as_ref()) + { + (config.pool_url.clone(), config.launcher_id) + } else { + warn!("No Pool Config for {p2_singleton_puzzle_hash}"); + return Ok(()); + }; + if pool_url.is_empty() { + return Ok(()); + } + let (required_iters, pool_dif) = if let Some(Some(pool_dif)) = self + .pool_state + .read() + .await + .get(p2_singleton_puzzle_hash) + .map(|v| v.current_difficulty) + { + ( + calculate_iterations_quality( + constants.difficulty_constant_factor, + qs, + new_pos.proof.size, + pool_dif, + &new_pos.sp_hash, + ), + pool_dif, + ) + } else { + warn!("No pool specific difficulty has been set for {p2_singleton_puzzle_hash}, check communication with the pool, skipping this partial to {}.", pool_url); + return Ok(()); + }; + if required_iters >= calculate_sp_interval_iters(constants, constants.pool_sub_slot_iters)? + { + debug!( + "Proof of space not good enough for pool {}: {:?}", + pool_url, pool_dif + ); + return Ok(()); + } + let auth_token_timeout = if let Some(Some(auth_token_timeout)) = self + .pool_state + .read() + .await + .get(p2_singleton_puzzle_hash) + .map(|v| v.authentication_token_timeout) + { + auth_token_timeout + } else { + warn!("No pool specific authentication_token_timeout has been set for {p2_singleton_puzzle_hash}, check communication with the pool."); + return Ok(()); + }; + let is_eos = new_pos.signage_point_index == 0; + let payload = PostPartialPayload { + launcher_id, + authentication_token: get_current_authentication_token(auth_token_timeout), + proof_of_space: new_pos.proof.clone(), + sp_hash: new_pos.sp_hash, + end_of_sub_slot: is_eos, + harvester_id: *peer_id, + }; + let to_sign = hash_256(payload.to_bytes(protocol_version)); + let sp_src_data = { + if new_pos.include_source_signature_data + || new_pos.farmer_reward_address_override.is_some() + { + Some(vec![Some(SignatureRequestSourceData { + kind: SigningDataKind::Partial, + data: payload.to_bytes(protocol_version), + })]) + } else { + None + } + }; + let request = RequestSignatures { + plot_identifier: new_pos.plot_identifier.clone(), + challenge_hash: new_pos.challenge_hash, + sp_hash: new_pos.sp_hash, + messages: vec![Bytes32::new(&to_sign)], + message_data: sp_src_data, + rc_block_unfinished: None, + }; + if let Some(peer) = peers.read().await.get(&peer_id).cloned() { + let msg_id = Some(ONE_SHOT_COUNTER.fetch_add(1, Ordering::SeqCst)); + let respond_sigs: RespondSignatures = oneshot( + peer.websocket.clone(), + ChiaMessage::new( + ProtocolMessageTypes::RequestSignatures, + protocol_version, + &request, + msg_id, + ), + Some(ProtocolMessageTypes::RespondSignatures), + protocol_version, + msg_id, + Some(15000), + ) + .await?; + let response_msg_sig = if let Some(f) = respond_sigs.message_signatures.first() { + Signature::from_bytes(f.1.to_sized_bytes()) + .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{:?}", e)))? + } else { + return Err(Error::new( + ErrorKind::InvalidInput, + "No Signature in Response", + )); + }; + let mut plot_sig = None; + let local_pk = PublicKey::from_bytes(respond_sigs.local_pk.to_sized_bytes()) + .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{:?}", e)))?; + for sk in self.farmer_private_keys.values() { + let pk = sk.sk_to_pk(); + if pk.to_bytes() == *respond_sigs.farmer_pk.to_sized_bytes() { + let agg_pk = generate_plot_public_key(&local_pk, &pk, true)?; + if agg_pk.to_bytes() != *new_pos.proof.plot_public_key.to_sized_bytes() { + return Err(Error::new(ErrorKind::InvalidInput, "Key Mismatch")); + } + let sig_farmer = sign_prepend(sk, &to_sign, &agg_pk); + let taproot_sk = generate_taproot_sk(&local_pk, &pk)?; + let taproot_sig = sign_prepend(&taproot_sk, &to_sign, &agg_pk); + + let p_sig = AggregateSignature::aggregate( + &[&sig_farmer, &response_msg_sig, &taproot_sig], + true, + ) + .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{:?}", e)))?; + if p_sig.to_signature().verify( + true, + to_sign.as_ref(), + AUG_SCHEME_DST, + &agg_pk.to_bytes(), + &agg_pk, + true, + ) != BLST_ERROR::BLST_SUCCESS + { + warn!( + "Failed to validate partial signature {:?}", + p_sig.to_signature() + ); + continue; + } + plot_sig = Some(p_sig); + } + } + let auth_key = if let Some(Some(owner_public_key)) = self + .pool_state + .read() + .await + .get(p2_singleton_puzzle_hash) + .map(|v| v.pool_config.as_ref().map(|c| &c.owner_public_key)) + { + self.auth_secret_keys.get(owner_public_key) + } else { + warn!("No pool specific authentication_token_timeout has been set for {p2_singleton_puzzle_hash}, check communication with the pool."); + return Ok(()); + }; + if let Some(auth_key) = auth_key { + let auth_sig = sign(auth_key, &to_sign); + if let Some(plot_sig) = plot_sig { + let agg_sig = + AggregateSignature::aggregate(&[&plot_sig.to_signature(), &auth_sig], true) + .map_err(|e| Error::new(ErrorKind::InvalidInput, format!("{:?}", e)))?; + let post_request = PostPartialRequest { + payload, + aggregate_signature: agg_sig.to_signature().to_bytes().into(), + }; + debug!( + "Submitting partial for {} to {}", + post_request.payload.launcher_id.to_string(), + pool_url.as_str() + ); + if let Some(v) = self + .pool_state + .write() + .await + .get_mut(p2_singleton_puzzle_hash) + { + v.points_found_since_start += pool_dif; + v.points_found_24h.push((Instant::now(), pool_dif)); + } + debug!("POST /partial request {:?}", &post_request); + match self + .pool_client + .post_partial( + pool_url.as_str(), + post_request, + &Some(self.headers.as_ref().clone()), + ) + .await + { + Ok(resp) => { + if let Some(v) = self + .pool_state + .write() .await - .get(&new_pos.sp_hash) - .is_none() + .get_mut(p2_singleton_puzzle_hash) { - self.proofs_of_space - .write() - .await - .insert(new_pos.sp_hash, vec![]); + v.points_acknowledged_since_start += resp.new_difficulty; + v.current_points += resp.new_difficulty; + v.points_acknowledged_24h.push((Instant::now(), pool_dif)); } - self.proofs_of_space - .write() - .await - .get_mut(&new_pos.sp_hash) - .expect("Should not happen, item created above") - .push((new_pos.plot_identifier.clone(), new_pos.proof.clone())); - self.cache_time - .write() - .await - .insert(new_pos.sp_hash, Instant::now()); - self.quality_to_identifiers.write().await.insert( - qs, - FarmerIdentifier { - plot_identifier: new_pos.plot_identifier.clone(), - challenge_hash: new_pos.challenge_hash, - sp_hash: new_pos.sp_hash, - peer_node_id: *peer_id, - }, - ); - self.cache_time.write().await.insert(qs, Instant::now()); - if let Some(p) = peers.read().await.get(&peer_id).cloned() { - let _ = p - .websocket + #[cfg(feature = "metrics")] + if let Some(r) = self.metrics.write().await.as_mut() { + use std::time::Duration; + let now = Instant::now(); + if let Some(c) = &mut r.points_acknowledged_24h { + if let Some(v) = self + .pool_state + .write() + .await + .get_mut(p2_singleton_puzzle_hash) + { + c.with_label_values( + &[&p2_singleton_puzzle_hash.to_string()], + ) + .set( + v.points_acknowledged_24h + .iter() + .filter(|v| { + now.duration_since(v.0) + < Duration::from_secs(60 * 60 * 24) + }) + .map(|v| v.1) + .sum(), + ) + } + } + } + if pool_dif != resp.new_difficulty { + info!("New Pool Difficulty: {:?} ", resp.new_difficulty); + if let Some(v) = self + .pool_state .write() .await - .send(Message::Binary( - ChiaMessage::new( - ProtocolMessageTypes::RequestSignatures, - &request, - None, - ) - .to_bytes(), - )) - .await; + .get_mut(p2_singleton_puzzle_hash) + { + v.current_difficulty = Some(resp.new_difficulty); + } } - } - if let Some(p2_singleton_puzzle_hash) = - &new_pos.proof.pool_contract_puzzle_hash - { - if self - .pool_state - .read() - .await - .get(p2_singleton_puzzle_hash) - .is_none() - { - warn!("Did not find pool info for {p2_singleton_puzzle_hash}"); - return Ok(()); + #[cfg(feature = "metrics")] + if let Some(r) = self.metrics.write().await.as_mut() { + if let Some(c) = &mut r.current_difficulty { + c.with_label_values(&[&p2_singleton_puzzle_hash.to_string()]) + .set(resp.new_difficulty); + } } - let (pool_url, launcher_id) = if let Some(Some(config)) = self + if let Some(v) = self .pool_state - .read() + .write() .await - .get(p2_singleton_puzzle_hash) - .map(|v| v.pool_config.as_ref()) + .get_mut(p2_singleton_puzzle_hash) { - (config.pool_url.clone(), config.launcher_id) - } else { - warn!("No Pool Config for {p2_singleton_puzzle_hash}"); - return Ok(()); - }; - if pool_url.is_empty() { - return Ok(()); + debug!("Current Points: {:?} ", v.current_points); } - let (required_iters, pool_dif) = if let Some(Some(pool_dif)) = self + } + Err(e) => { + error!("Error in pooling: {:?}", e); + if let Some(v) = self .pool_state - .read() + .write() .await - .get(p2_singleton_puzzle_hash) - .map(|v| v.current_difficulty) + .get_mut(p2_singleton_puzzle_hash) { - ( - calculate_iterations_quality( - constants.difficulty_constant_factor, - &qs, - new_pos.proof.size, - pool_dif, - &new_pos.sp_hash, - ), - pool_dif, - ) - } else { - warn!("No pool specific difficulty has been set for {p2_singleton_puzzle_hash}, check communication with the pool, skipping this partial to {}.", pool_url); - return Ok(()); - }; - if required_iters - >= calculate_sp_interval_iters( - &constants, - constants.pool_sub_slot_iters, - )? - { - debug!( - "Proof of space not good enough for pool {}: {:?}", - pool_url, pool_dif - ); - return Ok(()); + v.pool_errors_24h.push((Instant::now(), format!("{:?}", e))); } - let auth_token_timeout = if let Some(Some(auth_token_timeout)) = self - .pool_state - .read() - .await - .get(p2_singleton_puzzle_hash) - .map(|v| v.authentication_token_timeout) - { - auth_token_timeout - } else { - warn!("No pool specific authentication_token_timeout has been set for {p2_singleton_puzzle_hash}, check communication with the pool."); - return Ok(()); - }; - let is_eos = new_pos.signage_point_index == 0; - let payload = PostPartialPayload { - launcher_id, - authentication_token: get_current_authentication_token( + if e.error_code == PoolErrorCode::ProofNotGoodEnough as u8 { + error!("Partial not good enough, forcing pool farmer update to get our current difficulty."); + let _ = update_pool_farmer_info( + self.pool_state.clone(), + p2_singleton_puzzle_hash, auth_token_timeout, - ), - proof_of_space: new_pos.proof.clone(), - sp_hash: new_pos.sp_hash, - end_of_sub_slot: is_eos, - harvester_id: *peer_id, - }; - let to_sign = hash_256(payload.to_bytes()); - let sp_src_data = { - if new_pos.include_source_signature_data - || new_pos.farmer_reward_address_override.is_some() - { - Some(vec![Some(SignatureRequestSourceData { - kind: SigningDataKind::Partial, - data: payload.to_bytes(), - })]) - } else { - None - } - }; - let request = RequestSignatures { - plot_identifier: new_pos.plot_identifier.clone(), - challenge_hash: new_pos.challenge_hash, - sp_hash: new_pos.sp_hash, - messages: vec![Bytes32::new(&to_sign)], - message_data: sp_src_data, - rc_block_unfinished: None, - }; - if let Some(peer) = peers.read().await.get(&peer_id).cloned() { - let msg_id = Some(ONE_SHOT_COUNTER.fetch_add(1, Ordering::SeqCst)); - let respond_sigs: RespondSignatures = oneshot( - peer.websocket.clone(), - ChiaMessage::new( - ProtocolMessageTypes::RequestSignatures, - &request, - msg_id, - ), - Some(ProtocolMessageTypes::RespondSignatures), - msg_id, - Some(15000), + auth_key, + self.pool_client.clone(), + self.headers.clone(), ) - .await?; - let response_msg_sig = if let Some(f) = - respond_sigs.message_signatures.first() - { - Signature::from_bytes(f.1.to_sized_bytes()).map_err(|e| { - Error::new(ErrorKind::InvalidInput, format!("{:?}", e)) - })? - } else { - return Err(Error::new( - ErrorKind::InvalidInput, - "No Signature in Response", - )); - }; - let mut plot_sig = None; - let local_pk = - PublicKey::from_bytes(respond_sigs.local_pk.to_sized_bytes()) - .map_err(|e| { - Error::new(ErrorKind::InvalidInput, format!("{:?}", e)) - })?; - for sk in self.farmer_private_keys.values() { - let pk = sk.sk_to_pk(); - if pk.to_bytes() == *respond_sigs.farmer_pk.to_sized_bytes() { - let agg_pk = - generate_plot_public_key(&local_pk, &pk, true)?; - if agg_pk.to_bytes() - != *new_pos.proof.plot_public_key.to_sized_bytes() - { - return Err(Error::new( - ErrorKind::InvalidInput, - "Key Mismatch", - )); - } - let sig_farmer = sign_prepend(sk, &to_sign, &agg_pk); - let taproot_sk = generate_taproot_sk(&local_pk, &pk)?; - let taproot_sig = - sign_prepend(&taproot_sk, &to_sign, &agg_pk); - - let p_sig = AggregateSignature::aggregate( - &[&sig_farmer, &response_msg_sig, &taproot_sig], - true, - ) - .map_err(|e| { - Error::new(ErrorKind::InvalidInput, format!("{:?}", e)) - })?; - if p_sig.to_signature().verify( - true, - to_sign.as_ref(), - AUG_SCHEME_DST, - &agg_pk.to_bytes(), - &agg_pk, - true, - ) != BLST_ERROR::BLST_SUCCESS - { - warn!( - "Failed to validate partial signature {:?}", - p_sig.to_signature() - ); - continue; - } - plot_sig = Some(p_sig); - } - } - let auth_key = if let Some(Some(owner_public_key)) = self + .await; + } + if e.error_code == PoolErrorCode::InvalidSignature as u8 { + error!("Invalid Signature, Forcing Pool Update"); + if let Some(v) = self .pool_state - .read() + .write() .await - .get(p2_singleton_puzzle_hash) - .map(|v| v.pool_config.as_ref().map(|c| &c.owner_public_key)) + .get_mut(p2_singleton_puzzle_hash) { - self.auth_secret_keys.get(owner_public_key) - } else { - warn!("No pool specific authentication_token_timeout has been set for {p2_singleton_puzzle_hash}, check communication with the pool."); - return Ok(()); - }; - if let Some(auth_key) = auth_key { - let auth_sig = sign(auth_key, &to_sign); - if let Some(plot_sig) = plot_sig { - let agg_sig = AggregateSignature::aggregate( - &[&plot_sig.to_signature(), &auth_sig], - true, - ) - .map_err(|e| { - Error::new(ErrorKind::InvalidInput, format!("{:?}", e)) - })?; - let post_request = PostPartialRequest { - payload, - aggregate_signature: agg_sig - .to_signature() - .to_bytes() - .into(), - }; - debug!( - "Submitting partial for {} to {}", - post_request.payload.launcher_id.to_string(), - pool_url.as_str() - ); - if let Some(v) = self - .pool_state - .write() - .await - .get_mut(p2_singleton_puzzle_hash) - { - v.points_found_since_start += pool_dif; - v.points_found_24h.push((Instant::now(), pool_dif)); - } - debug!("POST /partial request {:?}", &post_request); - match self - .pool_client - .post_partial( - pool_url.as_str(), - post_request, - &Some(self.headers.as_ref().clone()), - ) - .await - { - Ok(resp) => { - if let Some(v) = self - .pool_state - .write() - .await - .get_mut(p2_singleton_puzzle_hash) - { - v.points_acknowledged_since_start += - resp.new_difficulty; - v.current_points += resp.new_difficulty; - v.points_acknowledged_24h - .push((Instant::now(), pool_dif)); - } - #[cfg(feature = "metrics")] - if let Some(r) = self.metrics.write().await.as_mut() - { - use std::time::Duration; - let now = Instant::now(); - if let Some(c) = &mut r.points_acknowledged_24h - { - if let Some(v) = self - .pool_state - .write() - .await - .get_mut(p2_singleton_puzzle_hash) - { - c.with_label_values(&[ - &p2_singleton_puzzle_hash - .to_string(), - ]) - .set( - v.points_acknowledged_24h - .iter() - .filter(|v| { - now.duration_since(v.0) - < Duration::from_secs( - 60 * 60 * 24, - ) - }) - .map(|v| v.1) - .sum(), - ) - } - } - } - if pool_dif != resp.new_difficulty { - info!( - "New Pool Difficulty: {:?} ", - resp.new_difficulty - ); - if let Some(v) = self - .pool_state - .write() - .await - .get_mut(p2_singleton_puzzle_hash) - { - v.current_difficulty = - Some(resp.new_difficulty); - } - } - #[cfg(feature = "metrics")] - if let Some(r) = self.metrics.write().await.as_mut() - { - if let Some(c) = &mut r.current_difficulty { - c.with_label_values(&[ - &p2_singleton_puzzle_hash.to_string(), - ]) - .set(resp.new_difficulty); - } - } - if let Some(v) = self - .pool_state - .write() - .await - .get_mut(p2_singleton_puzzle_hash) - { - debug!( - "Current Points: {:?} ", - v.current_points - ); - } - } - Err(e) => { - error!("Error in pooling: {:?}", e); - if let Some(v) = self - .pool_state - .write() - .await - .get_mut(p2_singleton_puzzle_hash) - { - v.pool_errors_24h - .push((Instant::now(), format!("{:?}", e))); - } - if e.error_code - == PoolErrorCode::ProofNotGoodEnough as u8 - { - error!("Partial not good enough, forcing pool farmer update to get our current difficulty."); - let _ = update_pool_farmer_info( - self.pool_state.clone(), - p2_singleton_puzzle_hash, - auth_token_timeout, - auth_key, - self.pool_client.clone(), - self.headers.clone(), - ) - .await; - } - if e.error_code - == PoolErrorCode::InvalidSignature as u8 - { - error!( - "Invalid Signature, Forcing Pool Update" - ); - if let Some(v) = self - .pool_state - .write() - .await - .get_mut(p2_singleton_puzzle_hash) - { - v.next_farmer_update = Instant::now(); - } - } - return Ok(()); - } - } - } - } else { - warn!("No authentication sk for {p2_singleton_puzzle_hash}"); - return Ok(()); + v.next_farmer_update = Instant::now(); } - } else { - warn!("No peer to sign partial"); } - } else { - debug!("Not a pooling proof of space"); + return Ok(()); } - } else { - warn!("Invalid proof of space {:?}", new_pos); } } } else { - warn!( - "Received response for a signage point that we do not have {}", - &new_pos.sp_hash - ); + warn!("No authentication sk for {p2_singleton_puzzle_hash}"); + return Ok(()); } + } else { + warn!("No peer to sign partial"); } Ok(()) } diff --git a/servers/src/websocket/farmer/respond_signatures.rs b/servers/src/websocket/farmer/respond_signatures.rs index 1ac4b47..52a25be 100644 --- a/servers/src/websocket/farmer/respond_signatures.rs +++ b/servers/src/websocket/farmer/respond_signatures.rs @@ -17,7 +17,7 @@ use dg_xch_core::protocols::farmer::{ use dg_xch_core::protocols::harvester::RespondSignatures; use dg_xch_core::protocols::{ChiaMessage, MessageHandler, PeerMap, ProtocolMessageTypes}; use dg_xch_pos::verify_and_get_quality_string; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use hyper_tungstenite::tungstenite::Message; use log::{debug, error, info, warn}; use std::collections::HashMap; @@ -46,11 +46,17 @@ impl MessageHandler for RespondSignaturesHandle { async fn handle( &self, msg: Arc, - _peer_id: Arc, - _peers: PeerMap, + peer_id: Arc, + peers: PeerMap, ) -> Result<(), Error> { let mut cursor = Cursor::new(&msg.data); - let response = RespondSignatures::from_bytes(&mut cursor)?; + let peer = peers.read().await.get(&peer_id).cloned(); + let protocol_version = if let Some(peer) = peer.as_ref() { + *peer.protocol_version.read().await + } else { + ChiaProtocolVersion::default() + }; + let response = RespondSignatures::from_bytes(&mut cursor, protocol_version)?; if let Some(sps) = self.signage_points.read().await.get(&response.sp_hash) { if sps.is_empty() { error!("Missing Signage Points for {}", &response.sp_hash); @@ -222,8 +228,11 @@ impl MessageHandler for RespondSignaturesHandle { .config .pool_rewards_payout_address, }; - let pool_target_signature = - sign(sk, &pool_target.to_bytes()); + let pool_target_signature = sign( + sk, + &pool_target + .to_bytes(ChiaProtocolVersion::default()), + ); (Some(pool_target), Some(pool_target_signature)) } else { error!("Don't have the private key for the pool key used by harvester: {pool_public_key}"); @@ -273,10 +282,13 @@ impl MessageHandler for RespondSignaturesHandle { .send(Message::Binary( ChiaMessage::new( ProtocolMessageTypes::DeclareProofOfSpace, + client.client.client_config.protocol_version, &request, None, ) - .to_bytes(), + .to_bytes( + client.client.client_config.protocol_version, + ), )) .await; info!("Declaring Proof of Space: {:?}", request); @@ -428,10 +440,13 @@ impl MessageHandler for RespondSignaturesHandle { .send(Message::Binary( ChiaMessage::new( ProtocolMessageTypes::SignedValues, + client.client.client_config.protocol_version, &request, None, ) - .to_bytes(), + .to_bytes( + client.client.client_config.protocol_version, + ), )) .await; info!("Sending Signed Values: {:?}", request); diff --git a/servers/src/websocket/harvester/handshake.rs b/servers/src/websocket/harvester/handshake.rs index 63ba67d..6f0a497 100644 --- a/servers/src/websocket/harvester/handshake.rs +++ b/servers/src/websocket/harvester/handshake.rs @@ -2,13 +2,14 @@ use crate::version; use crate::websocket::harvester::HarvesterServerConfig; use async_trait::async_trait; use dg_xch_core::blockchain::sized_bytes::Bytes32; -use dg_xch_core::protocols::shared::{Handshake, CAPABILITIES, PROTOCOL_VERSION}; +use dg_xch_core::protocols::shared::{Handshake, CAPABILITIES}; use dg_xch_core::protocols::{ ChiaMessage, MessageHandler, NodeType, PeerMap, ProtocolMessageTypes, }; -use dg_xch_serialize::ChiaSerialize; +use dg_xch_serialize::{ChiaProtocolVersion, ChiaSerialize}; use hyper_tungstenite::tungstenite::Message; use std::io::{Cursor, Error, ErrorKind}; +use std::str::FromStr; use std::sync::Arc; pub struct HandshakeHandle { @@ -22,19 +23,24 @@ impl MessageHandler for HandshakeHandle { peer_id: Arc, peers: PeerMap, ) -> Result<(), Error> { - let mut cursor = Cursor::new(&msg.data); - let handshake = Handshake::from_bytes(&mut cursor)?; if let Some(peer) = peers.read().await.get(&peer_id).cloned() { + let mut cursor = Cursor::new(&msg.data); + let handshake = + Handshake::from_bytes(&mut cursor, *peer.protocol_version.read().await)?; *peer.node_type.write().await = NodeType::from(handshake.node_type); + let protocol_version = ChiaProtocolVersion::from_str(&handshake.protocol_version) + .expect("ChiaProtocolVersion::from_str is Infallible"); + *peer.protocol_version.write().await = protocol_version; peer.websocket .write() .await .send(Message::Binary( ChiaMessage::new( ProtocolMessageTypes::Handshake, + protocol_version, &Handshake { network_id: self.config.network.clone(), - protocol_version: PROTOCOL_VERSION.to_string(), + protocol_version: protocol_version.to_string(), software_version: version(), server_port: self.config.websocket.port, node_type: NodeType::Harvester as u8, @@ -45,7 +51,7 @@ impl MessageHandler for HandshakeHandle { }, msg.id, ) - .to_bytes(), + .to_bytes(protocol_version), )) .await } else { diff --git a/servers/src/websocket/harvester/mod.rs b/servers/src/websocket/harvester/mod.rs index 86a1962..41ce3a8 100644 --- a/servers/src/websocket/harvester/mod.rs +++ b/servers/src/websocket/harvester/mod.rs @@ -1,4 +1,6 @@ use crate::websocket::harvester::handshake::HandshakeHandle; +#[cfg(feature = "metrics")] +use crate::websocket::WebSocketMetrics; use crate::websocket::{WebsocketServer, WebsocketServerConfig}; use dg_xch_core::protocols::{ChiaMessageFilter, ChiaMessageHandler, ProtocolMessageTypes}; use std::collections::HashMap; @@ -20,11 +22,20 @@ pub struct HarvesterServer { pub config: Arc, } impl HarvesterServer { - pub fn new(config: HarvesterServerConfig) -> Result { + pub fn new( + config: HarvesterServerConfig, + #[cfg(feature = "metrics")] metrics: Arc>, + ) -> Result { let config = Arc::new(config); let handles = Arc::new(RwLock::new(Self::handles(config.clone()))); Ok(Self { - server: WebsocketServer::new(&config.websocket, Default::default(), handles)?, + server: WebsocketServer::new( + &config.websocket, + Default::default(), + handles, + #[cfg(feature = "metrics")] + metrics, + )?, config, }) } diff --git a/servers/src/websocket/mod.rs b/servers/src/websocket/mod.rs index 60dcd0a..2ec01b0 100644 --- a/servers/src/websocket/mod.rs +++ b/servers/src/websocket/mod.rs @@ -9,7 +9,7 @@ use dg_xch_core::ssl::{ generate_ca_signed_cert_data, load_certs, load_certs_from_bytes, load_private_key, load_private_key_from_bytes, AllowAny, SslInfo, CHIA_CA_CRT, CHIA_CA_KEY, }; -use dg_xch_serialize::hash_256; +use dg_xch_serialize::{hash_256, ChiaProtocolVersion}; use http_body_util::Full; use hyper::body::{Bytes, Incoming}; use hyper::server::conn::http1::Builder; @@ -18,6 +18,8 @@ use hyper::{Request, Response}; use hyper_tungstenite::{is_upgrade_request, upgrade, HyperWebsocket}; use hyper_util::rt::TokioIo; use log::{debug, error}; +#[cfg(feature = "metrics")] +use prometheus::core::{AtomicU64, GenericGauge}; use rustls::{Certificate, PrivateKey, RootCertStore, ServerConfig}; use std::collections::HashMap; use std::io::{Error, ErrorKind}; @@ -40,17 +42,25 @@ pub struct WebsocketServerConfig { pub ssl_info: Option, } +#[cfg(feature = "metrics")] +pub struct WebSocketMetrics { + pub connected_clients: Arc>>, +} + pub struct WebsocketServer { pub socket_address: SocketAddr, pub server_config: Arc, pub peers: PeerMap, pub message_handlers: Arc>>>, + #[cfg(feature = "metrics")] + pub metrics: Arc>, } impl WebsocketServer { pub fn new( config: &WebsocketServerConfig, peers: PeerMap, message_handlers: Arc>>>, + #[cfg(feature = "metrics")] metrics: Arc>, ) -> Result { let (certs, key, root_certs) = if let Some(ssl_info) = &config.ssl_info { ( @@ -84,6 +94,8 @@ impl WebsocketServer { server_config, peers, message_handlers, + #[cfg(feature = "metrics")] + metrics, }) } pub fn with_ca( @@ -92,6 +104,7 @@ impl WebsocketServer { message_handlers: Arc>>>, cert_data: &str, key_data: &str, + #[cfg(feature = "metrics")] metrics: Arc>, ) -> Result { let (cert_bytes, key_bytes) = generate_ca_signed_cert_data(cert_data.as_bytes(), key_data.as_bytes())?; @@ -108,6 +121,8 @@ impl WebsocketServer { server_config, peers, message_handlers, + #[cfg(feature = "metrics")] + metrics, }) } @@ -120,12 +135,16 @@ impl WebsocketServer { let run = run.clone(); let peers = self.peers.clone(); let handlers = self.message_handlers.clone(); + #[cfg(feature = "metrics")] + let metrics = self.metrics.clone(); select!( res = listener.accept() => { match res { Ok((stream, _)) => { let peers = peers.clone(); let message_handlers = handlers.clone(); + #[cfg(feature = "metrics")] + let metrics = metrics.clone(); match acceptor.accept(stream).await { Ok(stream) => { let addr = stream.get_ref().0.peer_addr().ok(); @@ -145,7 +164,11 @@ impl WebsocketServer { message_handlers: message_handlers.clone(), run: run.clone(), }; - connection_handler(data) + connection_handler( + data, + #[cfg(feature = "metrics")] + metrics.clone() + ) }); let connection = http.serve_connection(TokioIo::new(stream), service).with_upgrades(); tokio::spawn( async move { @@ -228,6 +251,7 @@ struct ConnectionData { async fn connection_handler( mut data: ConnectionData, + #[cfg(feature = "metrics")] metrics: Arc>, ) -> Result>, tungstenite::error::Error> { if is_upgrade_request(&data.req) { let (response, websocket) = upgrade(&mut data.req, None)?; @@ -253,6 +277,12 @@ async fn connection_handler( )) })?, ); + #[cfg(feature = "metrics")] + if let Some(metrics) = metrics.as_ref() { + if let Some(gauge) = metrics.connected_clients.as_ref() { + gauge.add(1); + } + } tokio::spawn(async move { if let Err(e) = handle_connection( addr, @@ -266,6 +296,12 @@ async fn connection_handler( { error!("Error in websocket connection: {}", e); } + #[cfg(feature = "metrics")] + if let Some(metrics) = metrics.as_ref() { + if let Some(gauge) = metrics.connected_clients.as_ref() { + gauge.sub(1); + } + } }); Ok(response) } else { @@ -293,6 +329,7 @@ async fn handle_connection( *peer_id, Arc::new(SocketPeer { node_type: Arc::new(RwLock::new(NodeType::Unknown)), + protocol_version: Arc::new(RwLock::new(ChiaProtocolVersion::default())), websocket: Arc::new(RwLock::new(websocket)), }), ); diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 93e15a8..bab4b03 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dg_xch_tests" -version = "2.0.2" +version = "2.0.3" edition = "2021" authors = ["James Hoerr"] description = "Low Level Support Package for dg_xch_utils" @@ -12,14 +12,14 @@ repository = "https://github.com/GalactechsLLC/dg_xch_utils/serialize" async-trait = "0.1.77" blst = "0.3.11" bytes = "1.5.0" -dg_xch_core = {path = "../core", version = "2.0.2", features = ["paperclip"] } -dg_xch_cli = {path = "../cli", version="2.0.2"} -dg_xch_clients = {path = "../clients", version="2.0.2"} -dg_xch_keys = {path = "../keys", version="2.0.2"} -dg_xch_macros = {path = "../macros", version="2.0.2"} -dg_xch_pos = {path = "../proof_of_space", version="2.0.2"} -dg_xch_puzzles = {path = "../puzzles", version="2.0.2"} -dg_xch_serialize = {path = "../serialize", version="2.0.2"} +dg_xch_core = {path = "../core", version = "2.0.3", features = ["paperclip"] } +dg_xch_cli = {path = "../cli", version="2.0.3"} +dg_xch_clients = {path = "../clients", version="2.0.3"} +dg_xch_keys = {path = "../keys", version="2.0.3"} +dg_xch_macros = {path = "../macros", version="2.0.3"} +dg_xch_pos = {path = "../proof_of_space", version="2.0.3"} +dg_xch_puzzles = {path = "../puzzles", version="2.0.3"} +dg_xch_serialize = {path = "../serialize", version="2.0.3"} futures-util = "0.3.30" hex = "0.4.3" lazy_static = "1.4.0" diff --git a/tests/src/clients/full_node.rs b/tests/src/clients/full_node.rs index 5a4ed69..b8f506c 100644 --- a/tests/src/clients/full_node.rs +++ b/tests/src/clients/full_node.rs @@ -239,6 +239,7 @@ use uuid::Uuid; use dg_xch_core::blockchain::sized_bytes::Bytes32; use dg_xch_core::protocols::{ChiaMessage, MessageHandler, PeerMap}; +use dg_xch_serialize::ChiaProtocolVersion; pub struct NewSignagePointEcho { pub id: Uuid, @@ -253,7 +254,7 @@ impl MessageHandler for NewSignagePointEcho { ) -> Result<(), Error> { use dg_xch_serialize::ChiaSerialize; let mut cursor = Cursor::new(&msg.data); - let sp = NewSignagePoint::from_bytes(&mut cursor)?; + let sp = NewSignagePoint::from_bytes(&mut cursor, ChiaProtocolVersion::default())?; println!( "New Signage Point({}): {:?}", sp.signage_point_index, sp.challenge_hash