diff --git a/Cargo.lock b/Cargo.lock index 22a2f37..9c9dac8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -667,14 +667,16 @@ dependencies = [ "num", "num_cpus", "once_cell", - "parking_lot", + "parking_lot 0.11.2", "prost", "rand 0.8.4", + "semver", "serde", "serde_json", "serde_repr", "sha3", "shuttle", + "time", "tokio", "tokio-stream", "tokio-util 0.7.0", @@ -730,9 +732,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" [[package]] name = "libloading" @@ -752,10 +754,11 @@ checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] @@ -791,14 +794,15 @@ checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" [[package]] name = "mio" -version = "0.7.14" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" dependencies = [ "libc", "log", "miow", "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", "winapi 0.3.9", ] @@ -926,6 +930,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" +dependencies = [ + "libc", +] + [[package]] name = "once_cell" version = "1.9.0" @@ -965,7 +978,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.2", ] [[package]] @@ -982,6 +1005,19 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "parking_lot_core" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -1387,9 +1423,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi 0.3.9", @@ -1453,19 +1489,31 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +[[package]] +name = "time" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" +dependencies = [ + "itoa 1.0.1", + "libc", + "num_threads", +] + [[package]] name = "tokio" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ "bytes", "libc", "memchr", "mio", "num_cpus", - "parking_lot", + "parking_lot 0.12.0", "pin-project-lite", + "socket2", "tokio-macros", "winapi 0.3.9", ] @@ -1720,6 +1768,12 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "which" version = "4.2.2" @@ -1774,6 +1828,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" + +[[package]] +name = "windows_i686_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" + +[[package]] +name = "windows_i686_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + [[package]] name = "wyz" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index ceafe99..2001261 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ include = [ [dependencies] tonic = "0.6" -tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.17", features = ["macros", "rt-multi-thread"] } prost = "0.9" futures-util = "0.3" tokio-stream = {version = "0.1", features = ["net"]} @@ -48,6 +48,7 @@ async-trait = "0.1" num = "0.4" nix = "0.23" kernel32-sys = "0.2" +semver = "1.0" [features] default = ["parking_lot"] @@ -65,6 +66,7 @@ codegen-units = 1 [build-dependencies] tonic-build = { version = "0.6", default-features = false, features = ["prost", "transport"] } cc = "1" +time = { version = "0.3", features = ["formatting"] } [dev-dependencies] sha3 = { git = "https://github.com/elichai/hashes", branch = "cSHAKE" } diff --git a/README.md b/README.md index db9ea19..9feeaea 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build status](https://github.com/tmrlvi/kaspa-miner/workflows/ci/badge.svg)](https://github.com/tmrlvi/kaspa-miner/actions) [![Latest version](https://img.shields.io/crates/v/kaspa-miner.svg)](https://crates.io/crates/kaspa-miner) ![License](https://img.shields.io/crates/l/kaspa-miner.svg) -[![dependency status](https://deps.rs/repo/github/elichai/kaspa-miner/status.svg)](https://deps.rs/repo/github/elichai/kaspa-miner) +[![dependency status](https://deps.rs/repo/github/tmrlvi/kaspa-miner/status.svg)](https://deps.rs/repo/github/elichai/kaspa-miner) [![Discord](https://discordapp.com/api/guilds/599153230659846165/embed.png)](https://discord.gg/kS3SK5F36R) [![Telegram](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/Kaspaenglish) diff --git a/build.rs b/build.rs index 125ddac..04e8d43 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,12 @@ use std::env; +use time::{format_description, OffsetDateTime}; fn main() -> Result<(), Box> { + let format = format_description::parse("[year][month][day][hour][minute][second]")?; + let dt = OffsetDateTime::now_utc().format(&format)?; + //env::set_var("PACKAGE_COMPILE_TIME", dt); + println!("cargo:rustc-env=PACKAGE_COMPILE_TIME={}", dt); + println!("cargo:rerun-if-changed=proto"); println!("cargo:rerun-if-changed=src/keccakf1600_x86-64.s"); tonic_build::configure() diff --git a/proto/messages.proto b/proto/messages.proto index 017a81a..8d62e83 100644 --- a/proto/messages.proto +++ b/proto/messages.proto @@ -44,6 +44,13 @@ message KaspadMessage { PruningPointsMessage pruningPoints = 47; RequestPruningPointProofMessage requestPruningPointProof = 48; PruningPointProofMessage pruningPointProof = 49; + ReadyMessage ready = 50; + BlockWithTrustedDataV4Message blockWithTrustedDataV4 = 51; + TrustedDataMessage trustedData = 52; + RequestIBDChainBlockLocatorMessage requestIBDChainBlockLocator = 53; + IbdChainBlockLocatorMessage ibdChainBlockLocator = 54; + RequestAnticoneMessage requestAnticone = 55; + RequestNextPruningPointAndItsAnticoneBlocksMessage requestNextPruningPointAndItsAnticoneBlocks = 56; GetCurrentNetworkRequestMessage getCurrentNetworkRequest = 1001; GetCurrentNetworkResponseMessage getCurrentNetworkResponse = 1002; @@ -121,6 +128,13 @@ message KaspadMessage { NotifyVirtualDaaScoreChangedRequestMessage notifyVirtualDaaScoreChangedRequest = 1074; NotifyVirtualDaaScoreChangedResponseMessage notifyVirtualDaaScoreChangedResponse = 1075; VirtualDaaScoreChangedNotificationMessage virtualDaaScoreChangedNotification = 1076; + GetBalanceByAddressRequestMessage getBalanceByAddressRequest = 1077; + GetBalanceByAddressResponseMessage getBalanceByAddressResponse = 1078; + GetBalancesByAddressesRequestMessage getBalancesByAddressesRequest = 1079; + GetBalancesByAddressesResponseMessage getBalancesByAddressesResponse = 1080; + NotifyNewBlockTemplateRequestMessage notifyNewBlockTemplateRequest = 1081; + NotifyNewBlockTemplateResponseMessage notifyNewBlockTemplateResponse = 1082; + NewBlockTemplateNotificationMessage newBlockTemplateNotification = 1083; } } diff --git a/proto/p2p.proto b/proto/p2p.proto index b6666ce..51b0351 100644 --- a/proto/p2p.proto +++ b/proto/p2p.proto @@ -78,7 +78,7 @@ message BlockHeader{ } message BlockLevelParents { - repeated Hash parentHashes = 1; + repeated Hash parentHashes = 1; } message Hash{ @@ -190,6 +190,20 @@ message IbdBlockLocatorMessage { repeated Hash blockLocatorHashes = 2; } +message RequestIBDChainBlockLocatorMessage{ + Hash lowHash = 1; + Hash highHash = 2; +} + +message IbdChainBlockLocatorMessage { + repeated Hash blockLocatorHashes = 1; +} + +message RequestAnticoneMessage{ + Hash blockHash = 1; + Hash contextHash = 2; +} + message IbdBlockLocatorHighestHashMessage { Hash highestHash = 1; } @@ -204,6 +218,9 @@ message BlockHeadersMessage { message RequestPruningPointAndItsAnticoneMessage { } +message RequestNextPruningPointAndItsAnticoneBlocksMessage{ +} + message BlockWithTrustedDataMessage { BlockMessage block = 1; uint64 daaScore = 2; @@ -216,6 +233,11 @@ message DaaBlock { GhostdagData ghostdagData = 2; } +message DaaBlockV4 { + BlockHeader header = 1; + GhostdagData ghostdagData = 2; +} + message BlockGhostdagDataHashPair { Hash hash = 1; GhostdagData ghostdagData = 2; @@ -252,3 +274,17 @@ message PruningPointProofMessage { message PruningPointProofHeaderArray { repeated BlockHeader headers = 1; } + +message ReadyMessage { +} + +message BlockWithTrustedDataV4Message { + BlockMessage block = 1; + repeated uint64 daaWindowIndices = 2; + repeated uint64 ghostdagDataIndices = 3; +} + +message TrustedDataMessage { + repeated DaaBlockV4 daaWindow = 1; + repeated BlockGhostdagDataHashPair ghostdagData = 2; +} diff --git a/proto/rpc.proto b/proto/rpc.proto index b4769ae..f9845e2 100644 --- a/proto/rpc.proto +++ b/proto/rpc.proto @@ -52,6 +52,9 @@ message RpcBlockVerboseData{ bool isHeaderOnly = 15; uint64 blueScore = 16; repeated string childrenHashes = 17; + repeated string mergeSetBluesHashes = 18; + repeated string mergeSetRedsHashes = 19; + bool isChainBlock = 20; } message RpcTransaction { @@ -129,6 +132,7 @@ message GetCurrentNetworkResponseMessage{ // See: GetBlockTemplateRequestMessage message SubmitBlockRequestMessage{ RpcBlock block = 2; + bool allowNonDAABlocks = 3; } message SubmitBlockResponseMessage{ @@ -148,6 +152,7 @@ message SubmitBlockResponseMessage{ message GetBlockTemplateRequestMessage{ // Which kaspa address should the coinbase block reward transaction pay into string payAddress = 1; + string extraData = 2; } message GetBlockTemplateResponseMessage{ @@ -498,6 +503,36 @@ message GetUtxosByAddressesResponseMessage { RPCError error = 1000; } +// GetBalanceByAddressRequest returns the total balance in unspent transactions towards a given address +// +// This call is only available when this kaspad was started with `--utxoindex` +message GetBalanceByAddressRequestMessage { + string address = 1; +} + +message GetBalanceByAddressResponseMessage { + uint64 balance = 1; + + RPCError error = 1000; +} + +message GetBalancesByAddressesRequestMessage { + repeated string addresses = 1; +} + +message BalancesByAddressEntry{ + string address = 1; + uint64 balance = 2; + + RPCError error = 1000; +} + +message GetBalancesByAddressesResponseMessage { + repeated BalancesByAddressEntry entries = 1; + + RPCError error = 1000; +} + // GetVirtualSelectedParentBlueScoreRequestMessage requests the blue score of the current selected parent // of the virtual block. message GetVirtualSelectedParentBlueScoreRequestMessage { @@ -620,4 +655,22 @@ message EstimateNetworkHashesPerSecondResponseMessage{ RPCError error = 1000; } +// NotifyNewBlockTemplateRequestMessage registers this connection for +// NewBlockTemplate notifications. +// +// See: NewBlockTemplateNotificationMessage +message NotifyNewBlockTemplateRequestMessage { +} + +message NotifyNewBlockTemplateResponseMessage { + RPCError error = 1000; +} + +// NewBlockTemplateNotificationMessage is sent whenever a new updated block template is +// available for miners. +// +// See NotifyNewBlockTemplateRequestMessage +message NewBlockTemplateNotificationMessage { +} + diff --git a/src/cli.rs b/src/cli.rs index 2af74d6..1fc3529 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -17,7 +17,7 @@ pub struct Opt { #[clap(long = "devfund-percent", help = "The percentage of blocks to send to the devfund (minimum 2%)", default_value = "2", parse(try_from_str = parse_devfund_percent))] pub devfund_percent: u16, - #[clap(short, long, help = "Kaspad port [default: Mainnet = 16111, Testnet = 16211]")] + #[clap(short, long, help = "Kaspad port [default: Mainnet = 16110, Testnet = 16211]")] port: Option, #[clap(long, help = "Use testnet instead of mainnet [default: false]")] diff --git a/src/client/grpc.rs b/src/client/grpc.rs index 9612240..11a4730 100644 --- a/src/client/grpc.rs +++ b/src/client/grpc.rs @@ -4,7 +4,7 @@ use crate::pow::BlockSeed::{FullBlock, PartialBlock}; use crate::proto::kaspad_message::Payload; use crate::proto::rpc_client::RpcClient; use crate::proto::{ - GetBlockTemplateRequestMessage, GetInfoRequestMessage, KaspadMessage, NotifyBlockAddedRequestMessage, + GetBlockTemplateRequestMessage, GetInfoRequestMessage, KaspadMessage, NotifyBlockAddedRequestMessage, NotifyNewBlockTemplateRequestMessage, }; use crate::{miner::MinerManager, Error}; use async_trait::async_trait; @@ -18,7 +18,10 @@ use tokio::task::JoinHandle; use tokio_stream::wrappers::ReceiverStream; use tokio_util::sync::{PollSendError, PollSender}; use tonic::{transport::Channel as TonicChannel, Streaming}; +use semver::Version; +static EXTRA_DATA: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"), "/", env!("PACKAGE_COMPILE_TIME")); +static VERSION_UPDATE: &str = "0.11.15"; type BlockHandle = JoinHandle>>; #[allow(dead_code)] @@ -44,8 +47,7 @@ impl Client for KaspadHandler { } async fn register(&mut self) -> Result<(), Error> { - self.client_send(NotifyBlockAddedRequestMessage {}).await?; - self.client_get_block_template().await?; + // We actually register in connect Ok(()) } @@ -76,9 +78,8 @@ impl KaspadHandler { D::Error: Into, { let mut client = RpcClient::connect(address).await?; - let (send_channel, recv) = mpsc::channel(3); + let (send_channel, recv) = mpsc::channel(2); send_channel.send(GetInfoRequestMessage {}.into()).await?; - send_channel.send(GetBlockTemplateRequestMessage { pay_address: miner_address.clone() }.into()).await?; let stream = client.message_stream(ReceiverStream::new(recv)).await?.into_inner(); let (block_channel, block_handle) = Self::create_block_channel(send_channel.clone()); Ok(Box::new(Self { @@ -126,12 +127,13 @@ impl KaspadHandler { _ => self.miner_address.clone(), }; self.block_template_ctr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |v| Some((v + 1) % 10_000)).unwrap(); - self.client_send(GetBlockTemplateRequestMessage { pay_address }).await + self.client_send(GetBlockTemplateRequestMessage { pay_address, extra_data: EXTRA_DATA.into() }).await } async fn handle_message(&mut self, msg: Payload, miner: &mut MinerManager) -> Result<(), Error> { match msg { Payload::BlockAddedNotification(_) => self.client_get_block_template().await?, + Payload::NewBlockTemplateNotification(_) => self.client_get_block_template().await?, Payload::GetBlockTemplateResponse(template) => match (template.block, template.is_synced, template.error) { (Some(b), true, None) => miner.process_block(Some(FullBlock(b))).await?, (Some(b), false, None) if self.mine_when_not_synced => miner.process_block(Some(FullBlock(b))).await?, @@ -150,9 +152,23 @@ impl KaspadHandler { info!("Get block response: {:?}", msg); } } - Payload::GetInfoResponse(info) => info!("Kaspad version: {}", info.server_version), + Payload::GetInfoResponse(info) => { + info!("Kaspad version: {}", info.server_version); + let kaspad_version = Version::parse(&info.server_version)?; + let update_version = Version::parse(VERSION_UPDATE)?; + match kaspad_version >= update_version { + true => self.client_send(NotifyNewBlockTemplateRequestMessage {}).await?, + false => self.client_send( NotifyBlockAddedRequestMessage{}).await?, + }; + + self.client_get_block_template().await?; + }, + Payload::NotifyNewBlockTemplateResponse(res) => match res.error { + None => info!("Registered for new template notifications"), + Some(e) => error!("Failed registering for new template notifications: {:?}", e), + }, Payload::NotifyBlockAddedResponse(res) => match res.error { - None => info!("Registered for block notifications"), + None => info!("Registered for block notifications (upgrade your Kaspad for better experience)"), Some(e) => error!("Failed registering for block notifications: {:?}", e), }, msg => info!("got unknown msg: {:?}", msg), diff --git a/src/kaspad_messages.rs b/src/kaspad_messages.rs index cf83b7a..77331ee 100644 --- a/src/kaspad_messages.rs +++ b/src/kaspad_messages.rs @@ -1,6 +1,6 @@ use crate::proto::{ kaspad_message::Payload, GetBlockTemplateRequestMessage, GetInfoRequestMessage, KaspadMessage, - NotifyBlockAddedRequestMessage, RpcBlock, SubmitBlockRequestMessage, + NotifyBlockAddedRequestMessage, RpcBlock, SubmitBlockRequestMessage, NotifyNewBlockTemplateRequestMessage }; use crate::{ pow::{self, HeaderHasher}, @@ -19,7 +19,7 @@ impl KaspadMessage { #[inline(always)] pub fn submit_block(block: RpcBlock) -> Self { - KaspadMessage { payload: Some(Payload::SubmitBlockRequest(SubmitBlockRequestMessage { block: Some(block) })) } + KaspadMessage { payload: Some(Payload::SubmitBlockRequest(SubmitBlockRequestMessage { block: Some(block), allow_non_daa_blocks: false })) } } } @@ -40,6 +40,12 @@ impl From for KaspadMessage { } } +impl From for KaspadMessage { + fn from(a: NotifyNewBlockTemplateRequestMessage) -> Self { + KaspadMessage { payload: Some(Payload::NotifyNewBlockTemplateRequest(a)) } + } +} + impl RpcBlock { #[inline(always)] pub fn block_hash(&self) -> Option {