Skip to content

Commit 1fc0800

Browse files
committed
Merge upstream PR mimblewimble#3810 into my fork
2 parents 8e79856 + b792640 commit 1fc0800

File tree

11 files changed

+338
-19
lines changed

11 files changed

+338
-19
lines changed

core/src/global.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ pub fn get_chain_type() -> ChainTypes {
197197
CHAIN_TYPE.with(|chain_type| match chain_type.get() {
198198
None => {
199199
if !GLOBAL_CHAIN_TYPE.is_init() {
200-
panic!("GLOBAL_CHAIN_TYPE and CHAIN_TYPE unset. Consider set_local_chain_type() in tests.");
200+
std::panic!("GLOBAL_CHAIN_TYPE and CHAIN_TYPE unset. Consider set_local_chain_type() in tests.");
201201
}
202202
let chain_type = GLOBAL_CHAIN_TYPE.borrow();
203203
set_local_chain_type(chain_type);

core/src/ser.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,11 @@ impl ProtocolVersion {
361361
PROTOCOL_VERSION
362362
}
363363

364+
/// Default implementation that returns the current protocol version
365+
pub fn default() -> ProtocolVersion {
366+
PROTOCOL_VERSION
367+
}
368+
364369
/// We need to specify a protocol version for our local database.
365370
/// Regardless of specific version used when sending/receiving data between peers
366371
/// we need to take care with serialization/deserialization of data locally in the db.

doc/macros.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Macros for Array Newtypes
2+
3+
The `grin_util` crate provides several macros for working with array newtypes - wrapper types around fixed-size arrays. These macros help implement common traits and functionality for these types.
4+
5+
## Available Macros
6+
7+
### `impl_array_newtype`
8+
9+
Implements standard array traits and behavior for newtype wrappers around fixed-size arrays. This includes:
10+
11+
- Methods like `as_ptr()`, `as_mut_ptr()`, `len()`, etc.
12+
- Indexing via `Index` traits
13+
- Comparison traits (`PartialEq`, `Eq`, `PartialOrd`, `Ord`)
14+
- Common traits like `Clone`, `Copy`, and `Hash`
15+
16+
### `impl_array_newtype_encodable`
17+
18+
Implements serialization and deserialization support via Serde for newtype wrappers.
19+
20+
### `impl_array_newtype_show`
21+
22+
Implements the `Debug` trait for pretty-printing the array newtype.
23+
24+
### `impl_index_newtype`
25+
26+
Implements various indexing operations for the newtype. This is automatically called by `impl_array_newtype`.
27+
28+
## Usage Examples
29+
30+
```rust
31+
// Define a newtype for a 32-byte array
32+
pub struct ChainCode([u8; 32]);
33+
34+
// Implement standard array traits
35+
impl_array_newtype!(ChainCode, u8, 32);
36+
37+
// Implement Debug formatting
38+
impl_array_newtype_show!(ChainCode);
39+
40+
// Implement Serde serialization/deserialization
41+
impl_array_newtype_encodable!(ChainCode, u8, 32);
42+
```
43+
44+
## Notes on Feature Flags
45+
46+
With recent Rust versions, conditional compilation within macros is handled differently. The `serde` and other features are now defined at the crate level rather than inside the macros themselves, which prevents warnings about unexpected `cfg` conditions.

doc/pool/transaction_pool.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
## Transaction Pool
2+
3+
Grin's transaction pool is designed to hold all transactions that are not yet included in a block.
4+
5+
The transaction pool is split into a stempool and a txpool. The stempool contains "stem" transactions, which are less actively propagated to the rest of the network, as well as txs received via Dandelion "stem" phase. The txpool contains transactions that may be directly propagated to the network, as well as txs received via Dandelion "fluff" phase.
6+
7+
### Reconciliation
8+
9+
The `Pool::reconcile` function validates transactions in the stempool or txpool against a given block header and removes invalid or duplicated transactions (present in txpool). The optimized implementation filters entries in-place, reducing validations from O(n² + n*m) to O(n + m), where n is the number of transactions in the pool being reconciled and m is the number of transactions in txpool.
10+
11+
Reconciliation logs include:
12+
- Number of entries before/after reconciliation
13+
- Count of invalid or duplicated transactions removed
14+
15+
Example:
16+
```
17+
INFO: Starting transaction pool reconciliation with 200 entries
18+
WARN: Skipping duplicate transaction: <hash>
19+
WARN: Invalid transaction <hash>: Validation failed
20+
INFO: Reconciliation complete: retained 180 entries, removed 10 invalid, 10 duplicates
21+
```

grin/p2p/src/msg.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// ...existing code...
2+
use log::{info, warn};
3+
// ...existing code...
4+
5+
impl Message {
6+
pub fn read<R: Read>(
7+
reader: &mut R,
8+
msg_type: Option<MessageTypeEnum>,
9+
) -> Result<Message, Error> {
10+
// ...existing code...
11+
let header = MessageHeader::read(reader)?;
12+
let msg_len = header.msg_len as usize;
13+
14+
match msg_type {
15+
Some(msg_type) => {
16+
let max_len = max_msg_size(msg_type);
17+
let current_max_len = max_len * 4; // Current 4x limit
18+
if msg_len > current_max_len {
19+
return Err(Error::MsgTooLarge(msg_len, current_max_len));
20+
}
21+
info!(
22+
"Received {:?} message: size={} bytes, 1x limit={} bytes, 4x limit={} bytes",
23+
msg_type, msg_len, max_len, current_max_len
24+
);
25+
if msg_len > max_len {
26+
warn!(
27+
"Message size ({} bytes) exceeds 1x limit ({} bytes) for type {:?}",
28+
msg_len, max_len, msg_type
29+
);
30+
}
31+
}
32+
None => {
33+
info!("Received unknown message type: size={} bytes", msg_len);
34+
}
35+
}
36+
37+
let mut payload = vec![0u8; msg_len];
38+
reader.read_exact(&mut payload)?;
39+
Ok(Message { header, payload })
40+
}
41+
// ...existing code...
42+
}
43+
// ...existing code...

p2p/src/msg.rs

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use crate::types::{
3434
};
3535
use crate::util::secp::pedersen::RangeProof;
3636
use bytes::Bytes;
37+
use log::{info, warn};
3738
use num::FromPrimitive;
3839
use std::fs::File;
3940
use std::io::{Read, Write};
@@ -97,7 +98,7 @@ fn default_max_msg_size() -> u64 {
9798
}
9899

99100
// Max msg size for each msg type.
100-
fn max_msg_size(msg_type: Type) -> u64 {
101+
pub fn max_msg_size(msg_type: Type) -> u64 {
101102
match msg_type {
102103
Type::Error => 0,
103104
Type::Hand => 128,
@@ -172,7 +173,7 @@ impl Msg {
172173
///
173174
/// Note: We return a MsgHeaderWrapper here as we may encounter an unknown msg type.
174175
///
175-
pub fn read_header<R: Read>(
176+
pub fn read_header<R: std::io::Read>(
176177
stream: &mut R,
177178
version: ProtocolVersion,
178179
) -> Result<MsgHeaderWrapper, Error> {
@@ -186,7 +187,7 @@ pub fn read_header<R: Read>(
186187
/// Read a single item from the provided stream, always blocking until we
187188
/// have a result (or timeout).
188189
/// Returns the item and the total bytes read.
189-
pub fn read_item<T: Readable, R: Read>(
190+
pub fn read_item<T: Readable, R: std::io::Read>(
190191
stream: &mut R,
191192
version: ProtocolVersion,
192193
) -> Result<(T, u64), Error> {
@@ -197,7 +198,7 @@ pub fn read_item<T: Readable, R: Read>(
197198

198199
/// Read a message body from the provided stream, always blocking
199200
/// until we have a result (or timeout).
200-
pub fn read_body<T: Readable, R: Read>(
201+
pub fn read_body<T: Readable, R: std::io::Read>(
201202
h: &MsgHeader,
202203
stream: &mut R,
203204
version: ProtocolVersion,
@@ -208,14 +209,14 @@ pub fn read_body<T: Readable, R: Read>(
208209
}
209210

210211
/// Read (an unknown) message from the provided stream and discard it.
211-
pub fn read_discard<R: Read>(msg_len: u64, stream: &mut R) -> Result<(), Error> {
212+
pub fn read_discard<R: std::io::Read>(msg_len: u64, stream: &mut R) -> Result<(), Error> {
212213
let mut buffer = vec![0u8; msg_len as usize];
213214
stream.read_exact(&mut buffer)?;
214215
Ok(())
215216
}
216217

217218
/// Reads a full message from the underlying stream.
218-
pub fn read_message<T: Readable, R: Read>(
219+
pub fn read_message<T: Readable, R: std::io::Read>(
219220
stream: &mut R,
220221
version: ProtocolVersion,
221222
msg_type: Type,
@@ -322,6 +323,24 @@ impl Writeable for MsgHeader {
322323
}
323324
}
324325

326+
impl MsgHeader {
327+
/// Read a message header from the provided reader
328+
pub fn read<R: std::io::Read>(reader: &mut R) -> Result<MsgHeader, Error> {
329+
let mut head = vec![0u8; MsgHeader::LEN];
330+
reader.read_exact(&mut head)?;
331+
let header: MsgHeaderWrapper = ser::deserialize(
332+
&mut &head[..],
333+
ProtocolVersion::local(),
334+
DeserializationMode::default(),
335+
)?;
336+
337+
match header {
338+
MsgHeaderWrapper::Known(header) => Ok(header),
339+
MsgHeaderWrapper::Unknown(_, _) => Err(Error::BadMessage),
340+
}
341+
}
342+
}
343+
325344
impl Readable for MsgHeaderWrapper {
326345
fn read<R: Reader>(reader: &mut R) -> Result<MsgHeaderWrapper, ser::Error> {
327346
let m = magic();
@@ -986,3 +1005,41 @@ impl fmt::Debug for Consumed {
9861005
}
9871006
}
9881007
}
1008+
1009+
impl Message {
1010+
pub fn read<R: std::io::Read>(
1011+
reader: &mut R,
1012+
msg_type: Option<Type>,
1013+
) -> Result<Vec<u8>, Error> {
1014+
use log::{info, warn};
1015+
let header = MsgHeader::read(reader)?;
1016+
let msg_len = header.msg_len;
1017+
1018+
match msg_type {
1019+
Some(msg_type) => {
1020+
let max_len = max_msg_size(msg_type);
1021+
let current_max_len = max_len * 4; // Current 4x limit
1022+
if msg_len > current_max_len {
1023+
return Err(Error::MsgTooLarge(msg_len as usize, current_max_len));
1024+
}
1025+
info!(
1026+
"Received {:?} message: size={} bytes, 1x limit={} bytes, 4x limit={} bytes",
1027+
msg_type, msg_len, max_len, current_max_len
1028+
);
1029+
if msg_len > max_len {
1030+
warn!(
1031+
"Message size ({} bytes) exceeds 1x limit ({} bytes) for type {:?}",
1032+
msg_len, max_len, msg_type
1033+
);
1034+
}
1035+
}
1036+
None => {
1037+
info!("Received unknown message type: size={} bytes", msg_len);
1038+
}
1039+
}
1040+
1041+
let mut payload = vec![0u8; msg_len as usize];
1042+
reader.read_exact(&mut payload)?;
1043+
std::result::Result::Ok(payload)
1044+
}
1045+
}

p2p/src/types.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub enum Error {
9090
PeerNotBanned,
9191
PeerException,
9292
Internal,
93+
MsgTooLarge(usize, u64), // Message size, maximum allowed size
9394
}
9495

9596
impl From<ser::Error> for Error {
@@ -113,6 +114,38 @@ impl From<io::Error> for Error {
113114
}
114115
}
115116

117+
impl fmt::Display for Error {
118+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119+
match self {
120+
Error::Serialization(ref e) => write!(f, "Serialization error: {}", e),
121+
Error::Connection(ref e) => write!(f, "Connection error: {}", e),
122+
Error::BadMessage => write!(f, "Bad message"),
123+
Error::UnexpectedMessage => write!(f, "Unexpected message"),
124+
Error::MsgLen => write!(f, "Wrong message length"),
125+
Error::Banned => write!(f, "Peer banned"),
126+
Error::ConnectionClose => write!(f, "Connection closed"),
127+
Error::Timeout => write!(f, "Connection timed out"),
128+
Error::Store(ref e) => write!(f, "Store error: {}", e),
129+
Error::Chain(ref e) => write!(f, "Chain error: {}", e),
130+
Error::PeerWithSelf => write!(f, "Connect to self"),
131+
Error::NoDandelionRelay => write!(f, "No Dandelion relay"),
132+
Error::GenesisMismatch { us, peer } => {
133+
write!(f, "Genesis mismatch: our={}, peer={}", us, peer)
134+
}
135+
Error::Send(ref s) => write!(f, "Send error: {}", s),
136+
Error::PeerNotFound => write!(f, "Peer not found"),
137+
Error::PeerNotBanned => write!(f, "Peer not banned"),
138+
Error::PeerException => write!(f, "Peer exception"),
139+
Error::Internal => write!(f, "Internal error"),
140+
Error::MsgTooLarge(size, max) => write!(
141+
f,
142+
"Message too large: {} bytes, maximum: {} bytes",
143+
size, max
144+
),
145+
}
146+
}
147+
}
148+
116149
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
117150
pub struct PeerAddr(pub SocketAddr);
118151

servers/src/grin/server.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,8 @@ impl Server {
577577
// this call is blocking and makes sure all peers stop, however
578578
// we can't be sure that we stopped a listener blocked on accept, so we don't join the p2p thread
579579
self.p2p.stop();
580-
let _ = self.lock_file.unlock();
580+
// let _ = self.lock_file.unlock();
581+
let _ = fs2::FileExt::unlock(&*self.lock_file);
581582
warn!("Shutdown complete");
582583
}
583584

src/main.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use std::error::Error;
2+
3+
fn main() -> Result<(), Box<dyn Error>> {
4+
env_logger::init();
5+
6+
// ...existing code...
7+
8+
Ok(())
9+
}

0 commit comments

Comments
 (0)