Skip to content

Commit

Permalink
Merge pull request #97 from xelis-project/dev
Browse files Browse the repository at this point in the history
v1.15.0
  • Loading branch information
Slixe authored Sep 30, 2024
2 parents 7056f59 + 3998d6c commit d438b2f
Show file tree
Hide file tree
Showing 26 changed files with 541 additions and 127 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@ This file contains all the changelogs to ensure that changes can be tracked and

To see the full history and exact changes, please refer to the commits history directly.

## v1.15.0

Bug fixes for daemon & wallet, improvements & new features.

Common:
- Improve error messges
- non-zero optional serializer fns
- allow nullable responses in RPC client

Daemon:
- fix visual bugs for peerlist
- no connection to tempbanned peers
- `temp_ban_address` cli command
- `print_balance` cli command
- do not include txs present in orphaned tips
- `get_estimated_fee_rates` experimental rpc method

Wallet:
- add `export_transactions` cli command
- more logs

## v1.14.0

Moving to 1.14.0 due to breaking changes in peerlist storage.
Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion xelis_common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "xelis_common"
version = "1.14.0"
version = "1.15.0"
edition = "2021"
authors = ["Slixe <slixeprivate@gmail.com>"]
build = "build.rs"
Expand Down
14 changes: 14 additions & 0 deletions xelis_common/src/api/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,20 @@ pub struct GetMempoolCacheResult {
balances: HashMap<Hash, CiphertextCache>
}

// This struct is used to store the fee rate estimation for the following priority levels:
// 1. Low
// 2. Medium
// 3. High
// Each priority is in fee per KB. It cannot be below `FEE_PER_KB` which is required by the network.
#[derive(Serialize, Deserialize)]
pub struct FeeRatesEstimated {
pub low: u64,
pub medium: u64,
pub high: u64,
// The minimum fee rate possible on the network
pub default: u64
}

#[derive(Serialize, Deserialize)]
pub struct GetDifficultyResult {
pub difficulty: Difficulty,
Expand Down
8 changes: 6 additions & 2 deletions xelis_common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::crypto::Hash;
pub const VERSION: &str = env!("BUILD_VERSION");
pub const XELIS_ASSET: Hash = Hash::zero();

// Lowest fee per KB possible on the network
// 0.00010000 XEL per KB
pub const FEE_PER_KB: u64 = 10000;
// 0.00100000 XEL per account creation
Expand All @@ -26,12 +27,15 @@ pub const PREFIX_ADDRESS: &str = "xel";
// testnet prefix address
pub const TESTNET_PREFIX_ADDRESS: &str = "xet";

// 1 KB = 1024 bytes
pub const BYTES_PER_KB: usize = 1024;

// Max transaction size in bytes
pub const MAX_TRANSACTION_SIZE: usize = 1024 * 1024; // 1 MB
pub const MAX_TRANSACTION_SIZE: usize = BYTES_PER_KB * BYTES_PER_KB; // 1 MB

// Max block size in bytes
// 1024 * 1024 + (256 * 1024) bytes = 1.25 MB maximum size per block with txs
pub const MAX_BLOCK_SIZE: usize = (1024 * 1024) + (256 * 1024);
pub const MAX_BLOCK_SIZE: usize = (BYTES_PER_KB * BYTES_PER_KB) + (256 * BYTES_PER_KB);

// BlockDAG rules
pub const TIPS_LIMIT: usize = 3; // maximum 3 TIPS per block
12 changes: 6 additions & 6 deletions xelis_common/src/json_rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ pub enum JsonRPCError {
message: String,
data: Option<String>,
},
#[error("Server did not respond to the request")]
NoResponse,
#[error("No response in the given time")]
TimedOut,
#[error("Server did not respond to the request '{}': {}", _0, _1)]
NoResponse(String, String),
#[error("No response in the given time for '{}'", _0)]
TimedOut(String),
#[error("Server returned a response without result")]
MissingResult,
#[error("Error while (de)serializing JSON data: {}", _0)]
Expand All @@ -74,6 +74,6 @@ pub enum JsonRPCError {
SocketError(#[from] TungsteniteError),
#[error(transparent)]
Any(#[from] anyhow::Error),
#[error("Error while sending message: {}", _0)]
SendError(String)
#[error("Error while sending message '{}': {}", _0, _1)]
SendError(String, String)
}
33 changes: 26 additions & 7 deletions xelis_common/src/json_rpc/websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ impl<E: Serialize + Hash + Eq + Send + Sync + Clone + std::fmt::Debug + 'static>
continue;
}
}

// Check if this ID corresponds to a event subscribed
{
let mut handlers = self.handler_by_id.lock().await;
Expand All @@ -442,7 +442,9 @@ impl<E: Serialize + Hash + Eq + Send + Sync + Clone + std::fmt::Debug + 'static>
Message::Close(_) => {
break;
},
_ => {}
m => {
debug!("Received unhandled message: {:?}", m);
}
}
}
}
Expand Down Expand Up @@ -528,12 +530,14 @@ impl<E: Serialize + Hash + Eq + Send + Sync + Clone + std::fmt::Debug + 'static>
// Send a request to the sender channel that will be sent to the server
async fn send_message_internal<P: Serialize>(&self, id: Option<usize>, method: &str, params: &P) -> JsonRPCResult<()> {
let sender = self.sender.lock().await;
sender.send(InternalMessage::Send(serde_json::to_string(&json!({
let value = json!({
"jsonrpc": JSON_RPC_VERSION,
"method": method,
"id": id,
"params": params
}))?)).await.map_err(|e| JsonRPCError::SendError(e.to_string()))?;
});
sender.send(InternalMessage::Send(serde_json::to_string(&value)?)).await
.map_err(|e| JsonRPCError::SendError(value.to_string(), e.to_string()))?;

Ok(())
}
Expand All @@ -547,11 +551,26 @@ impl<E: Serialize + Hash + Eq + Send + Sync + Clone + std::fmt::Debug + 'static>
requests.insert(id, sender);
}

// Send the request to the server
// If the request fails, we remove it from the pending requests
match self.send_internal(method, id, params, receiver).await {
Ok(res) => Ok(res),
Err(e) => {
let mut requests = self.requests.lock().await;
debug!("Removing request with id {} from the pending requests due to its fail", id);
requests.remove(&id);
Err(e)
}
}
}

// Send a request to the server and wait for the response
async fn send_internal<P: Serialize, R: DeserializeOwned>(&self, method: &str, id: usize, params: &P, receiver: oneshot::Receiver<JsonRPCResponse>) -> JsonRPCResult<R> {
self.send_message_internal(Some(id), method, params).await?;

let response = timeout(self.timeout_after, receiver).await
.or(Err(JsonRPCError::TimedOut))?
.or(Err(JsonRPCError::NoResponse))?;
.map_err(|_| JsonRPCError::TimedOut(json!(params).to_string()))?
.map_err(|e| JsonRPCError::NoResponse(json!(params).to_string(), e.to_string()))?;

if let Some(error) = response.error {
return Err(JsonRPCError::ServerError {
Expand All @@ -561,7 +580,7 @@ impl<E: Serialize + Hash + Eq + Send + Sync + Clone + std::fmt::Debug + 'static>
});
}

let result = response.result.ok_or(JsonRPCError::NoResponse)?;
let result = response.result.unwrap_or(Value::Null);

Ok(serde_json::from_value(result)?)
}
Expand Down
10 changes: 6 additions & 4 deletions xelis_common/src/rpc_server/websocket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ pub enum WebSocketError {
SessionClosed(#[from] actix_ws::Closed),
#[error("this session was already closed")]
SessionAlreadyClosed,
#[error("error while sending message, channel is closed")]
ChannelClosed,
#[error("error while sending message '{}', channel is closed", _0)]
ChannelClosed(String),
#[error("error while closing, channel is already closed")]
ChannelAlreadyClosed,
#[error(transparent)]
Elapsed(#[from] Elapsed),
}
Expand All @@ -93,7 +95,7 @@ where
// Send a text message to the session
pub async fn send_text<S: Into<String>>(self: &Arc<Self>, value: S) -> Result<(), WebSocketError> {
self.channel.send(InnerMessage::Text(value.into()))
.map_err(|_| WebSocketError::ChannelClosed)?;
.map_err(|e| WebSocketError::ChannelClosed(e.to_string()))?;

Ok(())
}
Expand Down Expand Up @@ -127,7 +129,7 @@ where
// Close the session
pub async fn close(&self, reason: Option<CloseReason>) -> Result<(), WebSocketError> {
self.channel.send(InnerMessage::Close(reason))
.map_err(|_| WebSocketError::ChannelClosed)?;
.map_err(|_| WebSocketError::ChannelAlreadyClosed)?;

Ok(())
}
Expand Down
18 changes: 18 additions & 0 deletions xelis_common/src/serializer/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,24 @@ impl<'a> Reader<'a> {
Ok(Some(byte))
}

pub fn read_optional_non_zero_u16(&mut self) -> Result<Option<u16>, ReaderError> {
let value = self.read_u16()?;
if value == 0 {
return Ok(None)
}

Ok(Some(value))
}

pub fn read_optional_non_zero_u64(&mut self) -> Result<Option<u64>, ReaderError> {
let value = self.read_u64()?;
if value == 0 {
return Ok(None)
}

Ok(Some(value))
}

pub fn total_size(&self) -> usize {
self.bytes.len()
}
Expand Down
17 changes: 9 additions & 8 deletions xelis_common/src/serializer/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ impl Writer {
}

pub fn write_optional_non_zero_u8(&mut self, opt: Option<u8>) {
match opt {
Some(v) if v != 0 => {
self.bytes.push(v);
},
_ => {
self.bytes.push(0);
}
};
self.bytes.push(opt.unwrap_or(0));
}

pub fn write_optional_non_zero_u16(&mut self, opt: Option<u16>) {
self.write_u16(opt.unwrap_or(0));
}

pub fn write_optional_non_zero_u64(&mut self, opt: Option<u64>) {
self.write_u64(&opt.unwrap_or(0));
}

pub fn total_write(&self) -> usize {
Expand Down
8 changes: 5 additions & 3 deletions xelis_common/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::{
COIN_DECIMALS,
FEE_PER_ACCOUNT_CREATION,
FEE_PER_KB,
FEE_PER_TRANSFER
FEE_PER_TRANSFER,
BYTES_PER_KB
},
difficulty::Difficulty,
varuint::VarUint
Expand Down Expand Up @@ -50,9 +51,10 @@ pub fn from_coin(value: impl Into<String>, coin_decimals: u8) -> Option<u64> {
// Sending to a newly created address will increase the fee
// Each transfers output will also increase the fee
pub fn calculate_tx_fee(tx_size: usize, output_count: usize, new_addresses: usize) -> u64 {
let mut size_in_kb = tx_size as u64 / 1024;
let mut size_in_kb = tx_size as u64 / BYTES_PER_KB as u64;

if tx_size % 1024 != 0 { // we consume a full kb for fee
// we consume a full kb for fee
if tx_size % BYTES_PER_KB != 0 {
size_in_kb += 1;
}

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.14.0"
version = "1.15.0"
edition = "2021"
authors = ["Slixe <slixeprivate@gmail.com>"]

Expand Down
11 changes: 8 additions & 3 deletions xelis_daemon/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ 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;
// time in seconds between each time we try to connect to a outgoing peer
// At least 5 minutes of countdown to retry to connect to the same peer
// This will be multiplied by the number of fails
pub const P2P_PEERLIST_RETRY_AFTER: u64 = 60 * 15;
// Peer wait on error accept new p2p connections in seconds
pub const P2P_PEER_WAIT_ON_ERROR: u64 = 15;
// Delay in second to connect to priority nodes
Expand All @@ -147,12 +151,13 @@ pub const PEER_FAIL_TIME_RESET: u64 = 30 * 60;
pub const PEER_FAIL_LIMIT: u8 = 50;
// number of fail during handshake before temp ban
pub const PEER_FAIL_TO_CONNECT_LIMIT: u8 = 3;
// 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
// It is only used for incoming connections
// Set to 1 minute
pub const PEER_TEMP_BAN_TIME_ON_CONNECT: u64 = 60;
// number of seconds to temp ban the peer in case of fail count limit (`PEER_FAIL_LIMIT`) reached
// Set to 15 minutes
pub const PEER_TEMP_BAN_TIME: u64 = 15 * 60;
// millis until we timeout
pub const PEER_TIMEOUT_REQUEST_OBJECT: u64 = 15_000;
// millis until we timeout during a bootstrap request
Expand Down
Loading

0 comments on commit d438b2f

Please sign in to comment.