Skip to content

Commit

Permalink
Merge pull request #35 from xelis-project/dev
Browse files Browse the repository at this point in the history
Version 1.9.3 Mainnet
  • Loading branch information
Slixe committed Apr 24, 2024
2 parents bae2f65 + 0afc301 commit 1bfbb02
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 74 deletions.
13 changes: 13 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -6425,6 +6425,19 @@ It can be broadcasted or not to the network.
| tx_as_hex | Boolean | Optional | Serialize TX to hexadecimal. By default set to false |
| transfers OR burn | TransactionType | Required | Transaction Type parameter |

Fee builder has two variants:
- One to provide a multiplier applied on estimated fees.
```json
{"multiplier":1.0}
```

- One to provide a fixed amount of fee to pay
```json
{"value":100}
```

When it's not provided, Fee Builder is set by default to multiplier 1 to pay what is estimated.

##### Request
```json
{
Expand Down
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions xelis_common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "xelis_common"
version = "1.9.2"
version = "1.9.3"
edition = "2021"
authors = ["Slixe <slixeprivate@gmail.com>"]
build = "build.rs"
Expand All @@ -20,7 +20,7 @@ zeroize = "1.7.0"
lazy_static = "1.4.0"
sha3 = "0.10.8"
chacha20poly1305 = "0.10.1"
xelis-hash = { git = "https://github.com/xelis-project/xelis-hash", branch = "master" }
xelis-hash = { git = "https://github.com/xelis-project/xelis-hash", branch = "master", default-features = false }

thiserror = "1.0.58"
anyhow = "1.0.81"
Expand Down Expand Up @@ -50,6 +50,7 @@ primitive-types = { version = "0.12.2", features = ["serde"] }
tokio = { version = "1.36", features = ["full"] }

[features]
nightly = ["xelis-hash/nightly"]
json_rpc = ["dep:reqwest"]
prompt = ["dep:tokio"]
clap = ["dep:clap"]
Expand Down
40 changes: 20 additions & 20 deletions xelis_common/src/block/miner.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use std::borrow::Cow;

use log::warn;

use crate::{
crypto::{
elgamal::RISTRETTO_COMPRESSED_SIZE,
pow_hash_with_scratch_pad,
Hash,
Hashable,
PublicKey,
XelisHashError,
pow_hash_with_scratch_pad,
Input,
ScratchPad
PublicKey,
ScratchPad,
XelisHashError
},
serializer::{Reader, ReaderError, Serializer, Writer},
time::TimestampMillis,
Expand Down Expand Up @@ -62,8 +65,8 @@ impl<'a> BlockMiner<'a> {
self.cache = Some(input);
}

let bytes = self.cache.as_mut().unwrap();
pow_hash_with_scratch_pad(bytes.as_mut_slice()?, scratch_pad)
let mut bytes = self.cache.as_mut().unwrap().as_mut_slice()?.clone();
pow_hash_with_scratch_pad(&mut bytes, scratch_pad)
}

pub fn get_extra_nonce(&mut self) -> &mut [u8; EXTRA_NONCE_SIZE] {
Expand Down Expand Up @@ -107,28 +110,25 @@ impl<'a> BlockMiner<'a> {

impl<'a> Serializer for BlockMiner<'a> {
fn write(&self, writer: &mut Writer) {
if let Some(cache) = self.cache.as_ref() {
writer.write_bytes(cache.as_slice().unwrap());
writer.write_hash(&self.header_work_hash); // 32
writer.write_u64(&self.timestamp); // 32 + 8 = 40
writer.write_u64(&self.nonce); // 40 + 8 = 48
writer.write_bytes(&self.extra_nonce); // 48 + 32 = 80

// 80 + 32 = 112
if let Some(miner) = &self.miner {
miner.write(writer);
} else {
writer.write_hash(&self.header_work_hash); // 32
writer.write_u64(&self.timestamp); // 32 + 8 = 40
writer.write_u64(&self.nonce); // 40 + 8 = 48
writer.write_bytes(&self.extra_nonce); // 48 + 32 = 80

// 80 + 32 = 112
if let Some(miner) = &self.miner {
miner.write(writer);
} else {
// We set a 32 bytes empty public key as we don't have any miner
writer.write_bytes(&[0u8; 32]);
}
// We set a 32 bytes empty public key as we don't have any miner
writer.write_bytes(&[0u8; RISTRETTO_COMPRESSED_SIZE]);
}

debug_assert!(writer.total_write() == BLOCK_WORK_SIZE, "invalid block work size, expected {}, got {}", BLOCK_WORK_SIZE, writer.total_write());
}

fn read(reader: &mut Reader) -> Result<BlockMiner<'a>, ReaderError> {
if reader.total_size() != BLOCK_WORK_SIZE {
warn!("invalid block work size, expected {}, got {}", BLOCK_WORK_SIZE, reader.total_size());
return Err(ReaderError::InvalidSize)
}

Expand Down
2 changes: 1 addition & 1 deletion xelis_common/src/prompt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ impl Prompt {

base.level_for("sled", log::LevelFilter::Warn)
.level_for("actix_server", log::LevelFilter::Warn)
.level_for("actix_web", log::LevelFilter::Warn)
.level_for("actix_web", log::LevelFilter::Off)
.level_for("actix_http", log::LevelFilter::Warn)
.level_for("mio", log::LevelFilter::Warn)
.level_for("tokio_tungstenite", log::LevelFilter::Warn)
Expand Down
2 changes: 1 addition & 1 deletion xelis_daemon/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "xelis_daemon"
version = "1.9.2"
version = "1.9.3"
edition = "2021"
authors = ["Slixe <slixeprivate@gmail.com>"]

Expand Down
19 changes: 13 additions & 6 deletions xelis_daemon/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ pub const BLOCK_TIME_MILLIS: u64 = 15 * MILLIS_PER_SECOND; // 15s block time
// Current: BLOCK TIME in millis * 20 = 20 KH/s minimum
// This is to prevent spamming the network with low difficulty blocks
// This is active only on mainnet mode
pub const MINIMUM_DIFFICULTY: Difficulty = Difficulty::from_u64(BLOCK_TIME_MILLIS * 20);
pub const MAINNET_MINIMUM_DIFFICULTY: Difficulty = Difficulty::from_u64(BLOCK_TIME_MILLIS * 20);
// Testnet & Devnet minimum difficulty
pub const OTHER_MINIMUM_DIFFICULTY: Difficulty = Difficulty::from_u64(BLOCK_TIME_MILLIS);
// This is also used as testnet and devnet minimum difficulty
pub const GENESIS_BLOCK_DIFFICULTY: Difficulty = Difficulty::from_u64(1);
// 1024 * 1024 + (256 * 1024) bytes = 1.25 MB maximum size per block with txs
Expand Down Expand Up @@ -114,6 +116,8 @@ pub const P2P_PING_PEER_LIST_LIMIT: usize = 16;
pub const P2P_DEFAULT_MAX_PEERS: usize = 32;
// time in seconds between each time we try to connect to a new peer
pub const P2P_EXTEND_PEERLIST_DELAY: u64 = 60;
// Peer wait on error accept new p2p connections in seconds
pub const P2P_PEER_WAIT_ON_ERROR: u64 = 15;

// Peer rules
// number of seconds to reset the counter
Expand All @@ -122,10 +126,13 @@ pub const PEER_FAIL_TIME_RESET: u64 = 30 * 60;
// number of fail to disconnect the peer
pub const PEER_FAIL_LIMIT: u8 = 50;
// number of fail during handshake before temp ban
pub const PEER_FAIL_TO_CONNECT_LIMIT: u8 = 3;
pub const PEER_FAIL_TO_CONNECT_LIMIT: u8 = 10;
// number of seconds to temp ban the peer in case of fail reached
// Set to 15 minutes
pub const PEER_TEMP_BAN_TIME: u64 = 15 * 60;
// number of seconds to temp ban the peer in case of fail reached during handshake
// Set to 1 minute
pub const PEER_TEMP_BAN_TIME_ON_CONNECT: u64 = 60;
// millis until we timeout
pub const PEER_TIMEOUT_REQUEST_OBJECT: u64 = 15000;
// millis until we timeout during a bootstrap request
Expand All @@ -143,7 +150,7 @@ pub const PEER_BLOCK_CACHE_SIZE: usize = 1024;
// Genesis block to have the same starting point for every nodes
// Genesis block in hexadecimal format
const MAINNET_GENESIS_BLOCK: &str = "0000000000000000000000018efc057580000000000000000000000000000000000000000000000000000000000000000000000000000000000000006423b4908e5bd32241e3443fccfb7bab86a899a8cca12b3fedf255634d156d66";
const TESTNET_GENESIS_BLOCK: &str = "0000000000000000000000018dc0f93552000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac6738cec61a2033103f21b2ed2ddcf8f561eebc7ba4ecab337c484fef8bff6";
const TESTNET_GENESIS_BLOCK: &str = "0000000000000000000000018f116b47cf000000000000000000000000000000000000000000000000000000000000000000000000000000000000006423b4908e5bd32241e3443fccfb7bab86a899a8cca12b3fedf255634d156d66";

// Genesis block getter
// This is necessary to prevent having the same Genesis Block for differents network
Expand All @@ -164,7 +171,7 @@ lazy_static! {
// Genesis block hash for both networks
// It must be the same as the hash of the genesis block
const MAINNET_GENESIS_BLOCK_HASH: Hash = Hash::new([175, 118, 37, 203, 175, 200, 25, 148, 9, 202, 29, 120, 93, 128, 36, 209, 146, 193, 217, 36, 61, 51, 24, 194, 114, 113, 121, 208, 237, 163, 27, 55]);
const TESTNET_GENESIS_BLOCK_HASH: Hash = Hash::new([183, 21, 203, 2, 41, 209, 63, 95, 84, 10, 228, 138, 223, 3, 188, 49, 176, 148, 176, 64, 176, 117, 106, 36, 84, 99, 27, 45, 221, 137, 156, 58]);
const TESTNET_GENESIS_BLOCK_HASH: Hash = Hash::new([171, 50, 219, 186, 28, 164, 189, 225, 197, 167, 187, 143, 213, 59, 217, 238, 51, 242, 133, 181, 188, 235, 151, 50, 110, 33, 185, 188, 100, 146, 23, 132]);

// Genesis block hash based on network selected
pub fn get_genesis_block_hash(network: &Network) -> &'static Hash {
Expand Down Expand Up @@ -209,7 +216,7 @@ pub const fn get_seed_nodes(network: &Network) -> &[&str] {
// Testnet has a lower difficulty to allow faster block generation
pub const fn get_minimum_difficulty(network: &Network) -> Difficulty {
match network {
Network::Mainnet => MINIMUM_DIFFICULTY,
_ => GENESIS_BLOCK_DIFFICULTY,
Network::Mainnet => MAINNET_MINIMUM_DIFFICULTY,
_ => OTHER_MINIMUM_DIFFICULTY,
}
}
6 changes: 3 additions & 3 deletions xelis_daemon/src/core/difficulty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,17 @@ pub fn calculate_difficulty(parent_timestamp: TimestampMillis, timestamp: Timest

#[cfg(test)]
mod tests {
use crate::config::MINIMUM_DIFFICULTY;
use crate::config::MAINNET_MINIMUM_DIFFICULTY;
use super::*;

#[test]
fn test_kalman_filter() {
let z = MINIMUM_DIFFICULTY / VarUint::from_u64(1000);
let z = MAINNET_MINIMUM_DIFFICULTY / VarUint::from_u64(1000);
let (x_est_new, p_new) = kalman_filter(z, VarUint::one(), P);
assert_eq!(x_est_new, VarUint::one());
assert_eq!(p_new, VarUint::from_u64(4501837440));

let (x_est_new, p_new) = kalman_filter(MINIMUM_DIFFICULTY / VarUint::from_u64(2000), x_est_new, p_new);
let (x_est_new, p_new) = kalman_filter(MAINNET_MINIMUM_DIFFICULTY / VarUint::from_u64(2000), x_est_new, p_new);
assert_eq!(x_est_new, VarUint::one());
assert_eq!(p_new, VarUint::from_u64(4699383461));
}
Expand Down
45 changes: 43 additions & 2 deletions xelis_daemon/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub mod config;
use config::{DEV_PUBLIC_KEY, STABLE_LIMIT};
use fern::colors::Color;
use humantime::format_duration;
use log::{info, error, warn};
use log::{debug, error, info, warn};
use p2p::P2pServer;
use rpc::{
getwork_server::SharedGetWorkServer,
Expand Down Expand Up @@ -176,6 +176,8 @@ async fn run_prompt<S: Storage>(prompt: ShareablePrompt, blockchain: Arc<Blockch
command_manager.add_command(Command::with_required_arguments("kick_peer", "Kick a peer using its ip:port", vec![Arg::new("address", ArgType::String)], CommandHandler::Async(async_handler!(kick_peer::<S>))))?;
command_manager.add_command(Command::new("clear_caches", "Clear storage caches", CommandHandler::Async(async_handler!(clear_caches::<S>))))?;
command_manager.add_command(Command::new("clear_rpc_connections", "Clear all WS connections from RPC", CommandHandler::Async(async_handler!(clear_rpc_connections::<S>))))?;
command_manager.add_command(Command::new("clear_p2p_connections", "Clear all P2P connections", CommandHandler::Async(async_handler!(clear_p2p_connections::<S>))))?;
command_manager.add_command(Command::new("clear_p2p_peerlist", "Clear P2P peerlist", CommandHandler::Async(async_handler!(clear_p2p_peerlist::<S>))))?;
command_manager.add_command(Command::with_optional_arguments("difficulty_dataset", "Create a dataset for difficulty from chain", vec![Arg::new("output", ArgType::String)], CommandHandler::Async(async_handler!(difficulty_dataset::<S>))))?;
command_manager.add_command(Command::with_optional_arguments("mine_block", "Mine a block on testnet", vec![Arg::new("count", ArgType::Number)], CommandHandler::Async(async_handler!(mine_block::<S>))))?;
command_manager.add_command(Command::new("p2p_outgoing_connections", "Accept/refuse to connect to outgoing nodes", CommandHandler::Async(async_handler!(p2p_outgoing_connections::<S>))))?;
Expand All @@ -200,28 +202,34 @@ async fn run_prompt<S: Storage>(prompt: ShareablePrompt, blockchain: Arc<Blockch
};

let closure = |_: &_, _: _| async {
debug!("Retrieving P2P peers and median topoheight");
let (peers, median) = match &p2p {
Some(p2p) => (p2p.get_peer_count().await, p2p.get_median_topoheight_of_peers().await),
None => (0, blockchain.get_topo_height())
};

debug!("Retrieving RPC connections count");
let rpc_count = match &rpc {
Some(rpc) => rpc.get_websocket().count_connections().await,
None => 0
};

debug!("Retrieving miners count");
let miners = match &getwork {
Some(getwork) => getwork.count_miners().await,
None => 0
};

debug!("Retrieving mempool size");
let mempool = {
let mempool = blockchain.get_mempool().read().await;
mempool.size()
};

debug!("Retrieving network hashrate");
let network_hashrate = (blockchain.get_difficulty().await / BLOCK_TIME).into();

debug!("Building prompt message");
Ok(
build_prompt_message(
blockchain.get_topo_height(),
Expand All @@ -236,7 +244,7 @@ async fn run_prompt<S: Storage>(prompt: ShareablePrompt, blockchain: Arc<Blockch
)
};

prompt.start(Duration::from_millis(100), Box::new(async_handler!(closure)), Some(&command_manager)).await
prompt.start(Duration::from_secs(1), Box::new(async_handler!(closure)), Some(&command_manager)).await
}

fn build_prompt_message(topoheight: u64, median_topoheight: u64, network_hashrate: f64, peers_count: usize, rpc_count: usize, miners_count: usize, mempool: usize, network: Network) -> String {
Expand Down Expand Up @@ -633,6 +641,39 @@ async fn clear_rpc_connections<S: Storage>(manager: &CommandManager, _: Argument
Ok(())
}

async fn clear_p2p_connections<S: Storage>(manager: &CommandManager, _: ArgumentManager) -> Result<(), CommandError> {
let context = manager.get_context().lock()?;
let blockchain: &Arc<Blockchain<S>> = context.get()?;
match blockchain.get_p2p().read().await.as_ref() {
Some(p2p) => {
p2p.clear_connections().await;
manager.message("All P2P connections cleared");
},
None => {
manager.error("P2P is not enabled");
}
};

Ok(())
}

async fn clear_p2p_peerlist<S: Storage>(manager: &CommandManager, _: ArgumentManager) -> Result<(), CommandError> {
let context = manager.get_context().lock()?;
let blockchain: &Arc<Blockchain<S>> = context.get()?;
match blockchain.get_p2p().read().await.as_ref() {
Some(p2p) => {
let mut peerlist = p2p.get_peer_list().write().await;
peerlist.clear_peerlist();
manager.message("P2P peerlist cleared");
},
None => {
manager.error("P2P is not enabled");
}
};

Ok(())
}

async fn clear_caches<S: Storage>(manager: &CommandManager, _: ArgumentManager) -> Result<(), CommandError> {
let context = manager.get_context().lock()?;
let blockchain: &Arc<Blockchain<S>> = context.get()?;
Expand Down

0 comments on commit 1bfbb02

Please sign in to comment.