mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
Return Result from methods of ChainAdapter (#2722)
Most of the methods return nothing or bool which is used to decide if a sender of a message should be banned or not. However underlying chain implementation may fail so we need a way to reflect this fact in API. Also it allows to reduce number of unwraps and makes the code more robust.
This commit is contained in:
parent
cdc17c6cd9
commit
94732b0d58
13 changed files with 303 additions and 156 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -853,6 +853,7 @@ dependencies = [
|
||||||
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"grin_chain 1.0.3",
|
||||||
"grin_core 1.0.3",
|
"grin_core 1.0.3",
|
||||||
"grin_pool 1.0.3",
|
"grin_pool 1.0.3",
|
||||||
"grin_store 1.0.3",
|
"grin_store 1.0.3",
|
||||||
|
|
|
@ -24,6 +24,7 @@ chrono = { version = "0.4.4", features = ["serde"] }
|
||||||
|
|
||||||
grin_core = { path = "../core", version = "1.0.3" }
|
grin_core = { path = "../core", version = "1.0.3" }
|
||||||
grin_store = { path = "../store", version = "1.0.3" }
|
grin_store = { path = "../store", version = "1.0.3" }
|
||||||
|
grin_chain = { path = "../chain", version = "1.0.3" }
|
||||||
grin_util = { path = "../util", version = "1.0.3" }
|
grin_util = { path = "../util", version = "1.0.3" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -29,6 +29,7 @@ use lmdb_zero as lmdb;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate grin_core as core;
|
extern crate grin_core as core;
|
||||||
|
use grin_chain as chain;
|
||||||
use grin_util as util;
|
use grin_util as util;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -17,6 +17,7 @@ use std::fs::File;
|
||||||
use std::net::{Shutdown, TcpStream};
|
use std::net::{Shutdown, TcpStream};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::chain;
|
||||||
use crate::conn;
|
use crate::conn;
|
||||||
use crate::core::core::hash::{Hash, Hashed};
|
use crate::core::core::hash::{Hash, Hashed};
|
||||||
use crate::core::pow::Difficulty;
|
use crate::core::pow::Difficulty;
|
||||||
|
@ -513,11 +514,11 @@ impl TrackingAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChainAdapter for TrackingAdapter {
|
impl ChainAdapter for TrackingAdapter {
|
||||||
fn total_difficulty(&self) -> Difficulty {
|
fn total_difficulty(&self) -> Result<Difficulty, chain::Error> {
|
||||||
self.adapter.total_difficulty()
|
self.adapter.total_difficulty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn total_height(&self) -> u64 {
|
fn total_height(&self) -> Result<u64, chain::Error> {
|
||||||
self.adapter.total_height()
|
self.adapter.total_height()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,12 +526,16 @@ impl ChainAdapter for TrackingAdapter {
|
||||||
self.adapter.get_transaction(kernel_hash)
|
self.adapter.get_transaction(kernel_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) {
|
fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) -> Result<bool, chain::Error> {
|
||||||
self.push_recv(kernel_hash);
|
self.push_recv(kernel_hash);
|
||||||
self.adapter.tx_kernel_received(kernel_hash, addr)
|
self.adapter.tx_kernel_received(kernel_hash, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transaction_received(&self, tx: core::Transaction, stem: bool) {
|
fn transaction_received(
|
||||||
|
&self,
|
||||||
|
tx: core::Transaction,
|
||||||
|
stem: bool,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
// Do not track the tx hash for stem txs.
|
// Do not track the tx hash for stem txs.
|
||||||
// Otherwise we fail to handle the subsequent fluff or embargo expiration
|
// Otherwise we fail to handle the subsequent fluff or embargo expiration
|
||||||
// correctly.
|
// correctly.
|
||||||
|
@ -541,27 +546,40 @@ impl ChainAdapter for TrackingAdapter {
|
||||||
self.adapter.transaction_received(tx, stem)
|
self.adapter.transaction_received(tx, stem)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_received(&self, b: core::Block, addr: PeerAddr, _was_requested: bool) -> bool {
|
fn block_received(
|
||||||
|
&self,
|
||||||
|
b: core::Block,
|
||||||
|
addr: PeerAddr,
|
||||||
|
_was_requested: bool,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
let bh = b.hash();
|
let bh = b.hash();
|
||||||
self.push_recv(bh);
|
self.push_recv(bh);
|
||||||
self.adapter.block_received(b, addr, self.has_req(bh))
|
self.adapter.block_received(b, addr, self.has_req(bh))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compact_block_received(&self, cb: core::CompactBlock, addr: PeerAddr) -> bool {
|
fn compact_block_received(
|
||||||
|
&self,
|
||||||
|
cb: core::CompactBlock,
|
||||||
|
addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
self.push_recv(cb.hash());
|
self.push_recv(cb.hash());
|
||||||
self.adapter.compact_block_received(cb, addr)
|
self.adapter.compact_block_received(cb, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_received(&self, bh: core::BlockHeader, addr: PeerAddr) -> bool {
|
fn header_received(&self, bh: core::BlockHeader, addr: PeerAddr) -> Result<bool, chain::Error> {
|
||||||
self.push_recv(bh.hash());
|
self.push_recv(bh.hash());
|
||||||
self.adapter.header_received(bh, addr)
|
self.adapter.header_received(bh, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn headers_received(&self, bh: &[core::BlockHeader], addr: PeerAddr) -> bool {
|
fn headers_received(
|
||||||
|
&self,
|
||||||
|
bh: &[core::BlockHeader],
|
||||||
|
addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
self.adapter.headers_received(bh, addr)
|
self.adapter.headers_received(bh, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn locate_headers(&self, locator: &[Hash]) -> Vec<core::BlockHeader> {
|
fn locate_headers(&self, locator: &[Hash]) -> Result<Vec<core::BlockHeader>, chain::Error> {
|
||||||
self.adapter.locate_headers(locator)
|
self.adapter.locate_headers(locator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,7 +595,12 @@ impl ChainAdapter for TrackingAdapter {
|
||||||
self.adapter.txhashset_receive_ready()
|
self.adapter.txhashset_receive_ready()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: PeerAddr) -> bool {
|
fn txhashset_write(
|
||||||
|
&self,
|
||||||
|
h: Hash,
|
||||||
|
txhashset_data: File,
|
||||||
|
peer_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
self.adapter.txhashset_write(h, txhashset_data, peer_addr)
|
self.adapter.txhashset_write(h, txhashset_data, peer_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
116
p2p/src/peers.rs
116
p2p/src/peers.rs
|
@ -19,6 +19,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
|
use crate::chain;
|
||||||
use crate::core::core;
|
use crate::core::core;
|
||||||
use crate::core::core::hash::{Hash, Hashed};
|
use crate::core::core::hash::{Hash, Hashed};
|
||||||
use crate::core::global;
|
use crate::core::global;
|
||||||
|
@ -171,13 +172,13 @@ impl Peers {
|
||||||
|
|
||||||
// Return vec of connected peers that currently advertise more work
|
// Return vec of connected peers that currently advertise more work
|
||||||
// (total_difficulty) than we do.
|
// (total_difficulty) than we do.
|
||||||
pub fn more_work_peers(&self) -> Vec<Arc<Peer>> {
|
pub fn more_work_peers(&self) -> Result<Vec<Arc<Peer>>, chain::Error> {
|
||||||
let peers = self.connected_peers();
|
let peers = self.connected_peers();
|
||||||
if peers.len() == 0 {
|
if peers.len() == 0 {
|
||||||
return vec![];
|
return Ok(vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let total_difficulty = self.total_difficulty();
|
let total_difficulty = self.total_difficulty()?;
|
||||||
|
|
||||||
let mut max_peers = peers
|
let mut max_peers = peers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -185,28 +186,34 @@ impl Peers {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
thread_rng().shuffle(&mut max_peers);
|
thread_rng().shuffle(&mut max_peers);
|
||||||
max_peers
|
Ok(max_peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return number of connected peers that currently advertise more/same work
|
// Return number of connected peers that currently advertise more/same work
|
||||||
// (total_difficulty) than/as we do.
|
// (total_difficulty) than/as we do.
|
||||||
pub fn more_or_same_work_peers(&self) -> usize {
|
pub fn more_or_same_work_peers(&self) -> Result<usize, chain::Error> {
|
||||||
let peers = self.connected_peers();
|
let peers = self.connected_peers();
|
||||||
if peers.len() == 0 {
|
if peers.len() == 0 {
|
||||||
return 0;
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let total_difficulty = self.total_difficulty();
|
let total_difficulty = self.total_difficulty()?;
|
||||||
|
|
||||||
peers
|
Ok(peers
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|x| x.info.total_difficulty() >= total_difficulty)
|
.filter(|x| x.info.total_difficulty() >= total_difficulty)
|
||||||
.count()
|
.count())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns single random peer with more work than us.
|
/// Returns single random peer with more work than us.
|
||||||
pub fn more_work_peer(&self) -> Option<Arc<Peer>> {
|
pub fn more_work_peer(&self) -> Option<Arc<Peer>> {
|
||||||
self.more_work_peers().pop()
|
match self.more_work_peers() {
|
||||||
|
Ok(mut peers) => peers.pop(),
|
||||||
|
Err(e) => {
|
||||||
|
error!("failed to get more work peers: {:?}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return vec of connected peers that currently have the most worked
|
/// Return vec of connected peers that currently have the most worked
|
||||||
|
@ -452,10 +459,15 @@ impl Peers {
|
||||||
rm.push(peer.info.addr.clone());
|
rm.push(peer.info.addr.clone());
|
||||||
} else {
|
} else {
|
||||||
let (stuck, diff) = peer.is_stuck();
|
let (stuck, diff) = peer.is_stuck();
|
||||||
if stuck && diff < self.adapter.total_difficulty() {
|
match self.adapter.total_difficulty() {
|
||||||
debug!("clean_peers {:?}, stuck peer", peer.info.addr);
|
Ok(total_difficulty) => {
|
||||||
let _ = self.update_state(peer.info.addr, State::Defunct);
|
if stuck && diff < total_difficulty {
|
||||||
rm.push(peer.info.addr.clone());
|
debug!("clean_peers {:?}, stuck peer", peer.info.addr);
|
||||||
|
let _ = self.update_state(peer.info.addr, State::Defunct);
|
||||||
|
rm.push(peer.info.addr.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => error!("failed to get total difficulty: {:?}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -529,11 +541,11 @@ impl Peers {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChainAdapter for Peers {
|
impl ChainAdapter for Peers {
|
||||||
fn total_difficulty(&self) -> Difficulty {
|
fn total_difficulty(&self) -> Result<Difficulty, chain::Error> {
|
||||||
self.adapter.total_difficulty()
|
self.adapter.total_difficulty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn total_height(&self) -> u64 {
|
fn total_height(&self) -> Result<u64, chain::Error> {
|
||||||
self.adapter.total_height()
|
self.adapter.total_height()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,17 +553,26 @@ impl ChainAdapter for Peers {
|
||||||
self.adapter.get_transaction(kernel_hash)
|
self.adapter.get_transaction(kernel_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) {
|
fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) -> Result<bool, chain::Error> {
|
||||||
self.adapter.tx_kernel_received(kernel_hash, addr)
|
self.adapter.tx_kernel_received(kernel_hash, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transaction_received(&self, tx: core::Transaction, stem: bool) {
|
fn transaction_received(
|
||||||
|
&self,
|
||||||
|
tx: core::Transaction,
|
||||||
|
stem: bool,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
self.adapter.transaction_received(tx, stem)
|
self.adapter.transaction_received(tx, stem)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_received(&self, b: core::Block, peer_addr: PeerAddr, was_requested: bool) -> bool {
|
fn block_received(
|
||||||
|
&self,
|
||||||
|
b: core::Block,
|
||||||
|
peer_addr: PeerAddr,
|
||||||
|
was_requested: bool,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
let hash = b.hash();
|
let hash = b.hash();
|
||||||
if !self.adapter.block_received(b, peer_addr, was_requested) {
|
if !self.adapter.block_received(b, peer_addr, was_requested)? {
|
||||||
// if the peer sent us a block that's intrinsically bad
|
// if the peer sent us a block that's intrinsically bad
|
||||||
// they are either mistaken or malevolent, both of which require a ban
|
// they are either mistaken or malevolent, both of which require a ban
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -559,15 +580,19 @@ impl ChainAdapter for Peers {
|
||||||
hash, peer_addr
|
hash, peer_addr
|
||||||
);
|
);
|
||||||
self.ban_peer(peer_addr, ReasonForBan::BadBlock);
|
self.ban_peer(peer_addr, ReasonForBan::BadBlock);
|
||||||
false
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compact_block_received(&self, cb: core::CompactBlock, peer_addr: PeerAddr) -> bool {
|
fn compact_block_received(
|
||||||
|
&self,
|
||||||
|
cb: core::CompactBlock,
|
||||||
|
peer_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
let hash = cb.hash();
|
let hash = cb.hash();
|
||||||
if !self.adapter.compact_block_received(cb, peer_addr) {
|
if !self.adapter.compact_block_received(cb, peer_addr)? {
|
||||||
// if the peer sent us a block that's intrinsically bad
|
// if the peer sent us a block that's intrinsically bad
|
||||||
// they are either mistaken or malevolent, both of which require a ban
|
// they are either mistaken or malevolent, both of which require a ban
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -575,35 +600,43 @@ impl ChainAdapter for Peers {
|
||||||
hash, peer_addr
|
hash, peer_addr
|
||||||
);
|
);
|
||||||
self.ban_peer(peer_addr, ReasonForBan::BadCompactBlock);
|
self.ban_peer(peer_addr, ReasonForBan::BadCompactBlock);
|
||||||
false
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_received(&self, bh: core::BlockHeader, peer_addr: PeerAddr) -> bool {
|
fn header_received(
|
||||||
if !self.adapter.header_received(bh, peer_addr) {
|
&self,
|
||||||
|
bh: core::BlockHeader,
|
||||||
|
peer_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
|
if !self.adapter.header_received(bh, peer_addr)? {
|
||||||
// if the peer sent us a block header that's intrinsically bad
|
// if the peer sent us a block header that's intrinsically bad
|
||||||
// they are either mistaken or malevolent, both of which require a ban
|
// they are either mistaken or malevolent, both of which require a ban
|
||||||
self.ban_peer(peer_addr, ReasonForBan::BadBlockHeader);
|
self.ban_peer(peer_addr, ReasonForBan::BadBlockHeader);
|
||||||
false
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn headers_received(&self, headers: &[core::BlockHeader], peer_addr: PeerAddr) -> bool {
|
fn headers_received(
|
||||||
if !self.adapter.headers_received(headers, peer_addr) {
|
&self,
|
||||||
|
headers: &[core::BlockHeader],
|
||||||
|
peer_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
|
if !self.adapter.headers_received(headers, peer_addr)? {
|
||||||
// if the peer sent us a block header that's intrinsically bad
|
// if the peer sent us a block header that's intrinsically bad
|
||||||
// they are either mistaken or malevolent, both of which require a ban
|
// they are either mistaken or malevolent, both of which require a ban
|
||||||
self.ban_peer(peer_addr, ReasonForBan::BadBlockHeader);
|
self.ban_peer(peer_addr, ReasonForBan::BadBlockHeader);
|
||||||
false
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn locate_headers(&self, hs: &[Hash]) -> Vec<core::BlockHeader> {
|
fn locate_headers(&self, hs: &[Hash]) -> Result<Vec<core::BlockHeader>, chain::Error> {
|
||||||
self.adapter.locate_headers(hs)
|
self.adapter.locate_headers(hs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,16 +652,21 @@ impl ChainAdapter for Peers {
|
||||||
self.adapter.txhashset_receive_ready()
|
self.adapter.txhashset_receive_ready()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: PeerAddr) -> bool {
|
fn txhashset_write(
|
||||||
if !self.adapter.txhashset_write(h, txhashset_data, peer_addr) {
|
&self,
|
||||||
|
h: Hash,
|
||||||
|
txhashset_data: File,
|
||||||
|
peer_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
|
if !self.adapter.txhashset_write(h, txhashset_data, peer_addr)? {
|
||||||
debug!(
|
debug!(
|
||||||
"Received a bad txhashset data from {}, the peer will be banned",
|
"Received a bad txhashset data from {}, the peer will be banned",
|
||||||
&peer_addr
|
&peer_addr
|
||||||
);
|
);
|
||||||
self.ban_peer(peer_addr, ReasonForBan::BadTxHashSet);
|
self.ban_peer(peer_addr, ReasonForBan::BadTxHashSet);
|
||||||
false
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,8 +68,8 @@ impl MessageHandler for Protocol {
|
||||||
Ok(Some(Response::new(
|
Ok(Some(Response::new(
|
||||||
Type::Pong,
|
Type::Pong,
|
||||||
Pong {
|
Pong {
|
||||||
total_difficulty: adapter.total_difficulty(),
|
total_difficulty: adapter.total_difficulty()?,
|
||||||
height: adapter.total_height(),
|
height: adapter.total_height()?,
|
||||||
},
|
},
|
||||||
writer,
|
writer,
|
||||||
)?))
|
)?))
|
||||||
|
@ -93,7 +93,7 @@ impl MessageHandler for Protocol {
|
||||||
"handle_payload: received tx kernel: {}, msg_len: {}",
|
"handle_payload: received tx kernel: {}, msg_len: {}",
|
||||||
h, msg.header.msg_len
|
h, msg.header.msg_len
|
||||||
);
|
);
|
||||||
adapter.tx_kernel_received(h, self.addr);
|
adapter.tx_kernel_received(h, self.addr)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ impl MessageHandler for Protocol {
|
||||||
msg.header.msg_len
|
msg.header.msg_len
|
||||||
);
|
);
|
||||||
let tx: core::Transaction = msg.body()?;
|
let tx: core::Transaction = msg.body()?;
|
||||||
adapter.transaction_received(tx, false);
|
adapter.transaction_received(tx, false)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ impl MessageHandler for Protocol {
|
||||||
msg.header.msg_len
|
msg.header.msg_len
|
||||||
);
|
);
|
||||||
let tx: core::Transaction = msg.body()?;
|
let tx: core::Transaction = msg.body()?;
|
||||||
adapter.transaction_received(tx, true);
|
adapter.transaction_received(tx, true)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ impl MessageHandler for Protocol {
|
||||||
|
|
||||||
// we can't know at this level whether we requested the block or not,
|
// we can't know at this level whether we requested the block or not,
|
||||||
// the boolean should be properly set in higher level adapter
|
// the boolean should be properly set in higher level adapter
|
||||||
adapter.block_received(b, self.addr, false);
|
adapter.block_received(b, self.addr, false)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,14 +176,14 @@ impl MessageHandler for Protocol {
|
||||||
);
|
);
|
||||||
let b: core::CompactBlock = msg.body()?;
|
let b: core::CompactBlock = msg.body()?;
|
||||||
|
|
||||||
adapter.compact_block_received(b, self.addr);
|
adapter.compact_block_received(b, self.addr)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::GetHeaders => {
|
Type::GetHeaders => {
|
||||||
// load headers from the locator
|
// load headers from the locator
|
||||||
let loc: Locator = msg.body()?;
|
let loc: Locator = msg.body()?;
|
||||||
let headers = adapter.locate_headers(&loc.hashes);
|
let headers = adapter.locate_headers(&loc.hashes)?;
|
||||||
|
|
||||||
// serialize and send all the headers over
|
// serialize and send all the headers over
|
||||||
Ok(Some(Response::new(
|
Ok(Some(Response::new(
|
||||||
|
@ -197,7 +197,7 @@ impl MessageHandler for Protocol {
|
||||||
// we can go request it from some of our peers
|
// we can go request it from some of our peers
|
||||||
Type::Header => {
|
Type::Header => {
|
||||||
let header: core::BlockHeader = msg.body()?;
|
let header: core::BlockHeader = msg.body()?;
|
||||||
adapter.header_received(header, self.addr);
|
adapter.header_received(header, self.addr)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ impl MessageHandler for Protocol {
|
||||||
headers.push(header);
|
headers.push(header);
|
||||||
total_bytes_read += bytes_read;
|
total_bytes_read += bytes_read;
|
||||||
}
|
}
|
||||||
adapter.headers_received(&headers, self.addr);
|
adapter.headers_received(&headers, self.addr)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now check we read the correct total number of bytes off the stream.
|
// Now check we read the correct total number of bytes off the stream.
|
||||||
|
@ -335,7 +335,7 @@ impl MessageHandler for Protocol {
|
||||||
let tmp_zip = File::open(tmp)?;
|
let tmp_zip = File::open(tmp)?;
|
||||||
let res = self
|
let res = self
|
||||||
.adapter
|
.adapter
|
||||||
.txhashset_write(sm_arch.hash, tmp_zip, self.addr);
|
.txhashset_write(sm_arch.hash, tmp_zip, self.addr)?;
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"handle_payload: txhashset archive for {} at {}, DONE. Data Ok: {}",
|
"handle_payload: txhashset archive for {} at {}, DONE. Data Ok: {}",
|
||||||
|
|
|
@ -12,19 +12,13 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::fs::File;
|
use crate::chain;
|
||||||
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::time::Duration;
|
|
||||||
use std::{io, thread};
|
|
||||||
|
|
||||||
use crate::lmdb;
|
|
||||||
|
|
||||||
use crate::core::core;
|
use crate::core::core;
|
||||||
use crate::core::core::hash::Hash;
|
use crate::core::core::hash::Hash;
|
||||||
use crate::core::global;
|
use crate::core::global;
|
||||||
use crate::core::pow::Difficulty;
|
use crate::core::pow::Difficulty;
|
||||||
use crate::handshake::Handshake;
|
use crate::handshake::Handshake;
|
||||||
|
use crate::lmdb;
|
||||||
use crate::peer::Peer;
|
use crate::peer::Peer;
|
||||||
use crate::peers::Peers;
|
use crate::peers::Peers;
|
||||||
use crate::store::PeerStore;
|
use crate::store::PeerStore;
|
||||||
|
@ -33,6 +27,11 @@ use crate::types::{
|
||||||
};
|
};
|
||||||
use crate::util::{Mutex, StopState};
|
use crate::util::{Mutex, StopState};
|
||||||
use chrono::prelude::{DateTime, Utc};
|
use chrono::prelude::{DateTime, Utc};
|
||||||
|
use std::fs::File;
|
||||||
|
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::{io, thread};
|
||||||
|
|
||||||
/// P2P server implementation, handling bootstrapping to find and connect to
|
/// P2P server implementation, handling bootstrapping to find and connect to
|
||||||
/// peers, receiving connections from other peers and keep track of all of them.
|
/// peers, receiving connections from other peers and keep track of all of them.
|
||||||
|
@ -139,7 +138,7 @@ impl Server {
|
||||||
match TcpStream::connect_timeout(&addr.0, Duration::from_secs(10)) {
|
match TcpStream::connect_timeout(&addr.0, Duration::from_secs(10)) {
|
||||||
Ok(mut stream) => {
|
Ok(mut stream) => {
|
||||||
let addr = SocketAddr::new(self.config.host, self.config.port);
|
let addr = SocketAddr::new(self.config.host, self.config.port);
|
||||||
let total_diff = self.peers.total_difficulty();
|
let total_diff = self.peers.total_difficulty()?;
|
||||||
|
|
||||||
let mut peer = Peer::connect(
|
let mut peer = Peer::connect(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
|
@ -168,7 +167,7 @@ impl Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_new_peer(&self, mut stream: TcpStream) -> Result<(), Error> {
|
fn handle_new_peer(&self, mut stream: TcpStream) -> Result<(), Error> {
|
||||||
let total_diff = self.peers.total_difficulty();
|
let total_diff = self.peers.total_difficulty()?;
|
||||||
|
|
||||||
// accept the peer and add it to the server map
|
// accept the peer and add it to the server map
|
||||||
let mut peer = Peer::accept(
|
let mut peer = Peer::accept(
|
||||||
|
@ -231,31 +230,48 @@ impl Server {
|
||||||
pub struct DummyAdapter {}
|
pub struct DummyAdapter {}
|
||||||
|
|
||||||
impl ChainAdapter for DummyAdapter {
|
impl ChainAdapter for DummyAdapter {
|
||||||
fn total_difficulty(&self) -> Difficulty {
|
fn total_difficulty(&self) -> Result<Difficulty, chain::Error> {
|
||||||
Difficulty::min()
|
Ok(Difficulty::min())
|
||||||
}
|
}
|
||||||
fn total_height(&self) -> u64 {
|
fn total_height(&self) -> Result<u64, chain::Error> {
|
||||||
0
|
Ok(0)
|
||||||
}
|
}
|
||||||
fn get_transaction(&self, _h: Hash) -> Option<core::Transaction> {
|
fn get_transaction(&self, _h: Hash) -> Option<core::Transaction> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn tx_kernel_received(&self, _h: Hash, _addr: PeerAddr) {}
|
|
||||||
fn transaction_received(&self, _: core::Transaction, _stem: bool) {}
|
fn tx_kernel_received(&self, _h: Hash, _addr: PeerAddr) -> Result<bool, chain::Error> {
|
||||||
fn compact_block_received(&self, _cb: core::CompactBlock, _addr: PeerAddr) -> bool {
|
Ok(true)
|
||||||
true
|
|
||||||
}
|
}
|
||||||
fn header_received(&self, _bh: core::BlockHeader, _addr: PeerAddr) -> bool {
|
fn transaction_received(
|
||||||
true
|
&self,
|
||||||
|
_: core::Transaction,
|
||||||
|
_stem: bool,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn block_received(&self, _: core::Block, _: PeerAddr, _: bool) -> bool {
|
fn compact_block_received(
|
||||||
true
|
&self,
|
||||||
|
_cb: core::CompactBlock,
|
||||||
|
_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn headers_received(&self, _: &[core::BlockHeader], _: PeerAddr) -> bool {
|
fn header_received(
|
||||||
true
|
&self,
|
||||||
|
_bh: core::BlockHeader,
|
||||||
|
_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn locate_headers(&self, _: &[Hash]) -> Vec<core::BlockHeader> {
|
fn block_received(&self, _: core::Block, _: PeerAddr, _: bool) -> Result<bool, chain::Error> {
|
||||||
vec![]
|
Ok(true)
|
||||||
|
}
|
||||||
|
fn headers_received(&self, _: &[core::BlockHeader], _: PeerAddr) -> Result<bool, chain::Error> {
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
fn locate_headers(&self, _: &[Hash]) -> Result<Vec<core::BlockHeader>, chain::Error> {
|
||||||
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
fn get_block(&self, _: Hash) -> Option<core::Block> {
|
fn get_block(&self, _: Hash) -> Option<core::Block> {
|
||||||
None
|
None
|
||||||
|
@ -268,8 +284,13 @@ impl ChainAdapter for DummyAdapter {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn txhashset_write(&self, _h: Hash, _txhashset_data: File, _peer_addr: PeerAddr) -> bool {
|
fn txhashset_write(
|
||||||
false
|
&self,
|
||||||
|
_h: Hash,
|
||||||
|
_txhashset_data: File,
|
||||||
|
_peer_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn txhashset_download_update(
|
fn txhashset_download_update(
|
||||||
|
|
|
@ -168,7 +168,8 @@ impl PeerStore {
|
||||||
/// Used for /v1/peers/all api endpoint
|
/// Used for /v1/peers/all api endpoint
|
||||||
pub fn all_peers(&self) -> Result<Vec<PeerData>, Error> {
|
pub fn all_peers(&self) -> Result<Vec<PeerData>, Error> {
|
||||||
let key = to_key(PEER_PREFIX, &mut "".to_string().into_bytes());
|
let key = to_key(PEER_PREFIX, &mut "".to_string().into_bytes());
|
||||||
Ok(self.db
|
Ok(self
|
||||||
|
.db
|
||||||
.iter::<PeerData>(&key)?
|
.iter::<PeerData>(&key)?
|
||||||
.map(|(_, v)| v)
|
.map(|(_, v)| v)
|
||||||
.collect::<Vec<_>>())
|
.collect::<Vec<_>>())
|
||||||
|
|
|
@ -23,6 +23,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
|
|
||||||
|
use crate::chain;
|
||||||
use crate::core::core;
|
use crate::core::core;
|
||||||
use crate::core::core::hash::Hash;
|
use crate::core::core::hash::Hash;
|
||||||
use crate::core::global;
|
use crate::core::global;
|
||||||
|
@ -63,6 +64,7 @@ pub enum Error {
|
||||||
ConnectionClose,
|
ConnectionClose,
|
||||||
Timeout,
|
Timeout,
|
||||||
Store(grin_store::Error),
|
Store(grin_store::Error),
|
||||||
|
Chain(chain::Error),
|
||||||
PeerWithSelf,
|
PeerWithSelf,
|
||||||
NoDandelionRelay,
|
NoDandelionRelay,
|
||||||
ProtocolMismatch {
|
ProtocolMismatch {
|
||||||
|
@ -88,6 +90,11 @@ impl From<grin_store::Error> for Error {
|
||||||
Error::Store(e)
|
Error::Store(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<chain::Error> for Error {
|
||||||
|
fn from(e: chain::Error) -> Error {
|
||||||
|
Error::Chain(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl From<io::Error> for Error {
|
impl From<io::Error> for Error {
|
||||||
fn from(e: io::Error) -> Error {
|
fn from(e: io::Error) -> Error {
|
||||||
Error::Connection(e)
|
Error::Connection(e)
|
||||||
|
@ -465,37 +472,51 @@ pub struct TxHashSetRead {
|
||||||
/// other things.
|
/// other things.
|
||||||
pub trait ChainAdapter: Sync + Send {
|
pub trait ChainAdapter: Sync + Send {
|
||||||
/// Current total difficulty on our chain
|
/// Current total difficulty on our chain
|
||||||
fn total_difficulty(&self) -> Difficulty;
|
fn total_difficulty(&self) -> Result<Difficulty, chain::Error>;
|
||||||
|
|
||||||
/// Current total height
|
/// Current total height
|
||||||
fn total_height(&self) -> u64;
|
fn total_height(&self) -> Result<u64, chain::Error>;
|
||||||
|
|
||||||
/// A valid transaction has been received from one of our peers
|
/// A valid transaction has been received from one of our peers
|
||||||
fn transaction_received(&self, tx: core::Transaction, stem: bool);
|
fn transaction_received(&self, tx: core::Transaction, stem: bool)
|
||||||
|
-> Result<bool, chain::Error>;
|
||||||
|
|
||||||
fn get_transaction(&self, kernel_hash: Hash) -> Option<core::Transaction>;
|
fn get_transaction(&self, kernel_hash: Hash) -> Option<core::Transaction>;
|
||||||
|
|
||||||
fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr);
|
fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) -> Result<bool, chain::Error>;
|
||||||
|
|
||||||
/// A block has been received from one of our peers. Returns true if the
|
/// A block has been received from one of our peers. Returns true if the
|
||||||
/// block could be handled properly and is not deemed defective by the
|
/// block could be handled properly and is not deemed defective by the
|
||||||
/// chain. Returning false means the block will never be valid and
|
/// chain. Returning false means the block will never be valid and
|
||||||
/// may result in the peer being banned.
|
/// may result in the peer being banned.
|
||||||
fn block_received(&self, b: core::Block, addr: PeerAddr, was_requested: bool) -> bool;
|
fn block_received(
|
||||||
|
&self,
|
||||||
|
b: core::Block,
|
||||||
|
addr: PeerAddr,
|
||||||
|
was_requested: bool,
|
||||||
|
) -> Result<bool, chain::Error>;
|
||||||
|
|
||||||
fn compact_block_received(&self, cb: core::CompactBlock, addr: PeerAddr) -> bool;
|
fn compact_block_received(
|
||||||
|
&self,
|
||||||
|
cb: core::CompactBlock,
|
||||||
|
addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error>;
|
||||||
|
|
||||||
fn header_received(&self, bh: core::BlockHeader, addr: PeerAddr) -> bool;
|
fn header_received(&self, bh: core::BlockHeader, addr: PeerAddr) -> Result<bool, chain::Error>;
|
||||||
|
|
||||||
/// A set of block header has been received, typically in response to a
|
/// A set of block header has been received, typically in response to a
|
||||||
/// block
|
/// block
|
||||||
/// header request.
|
/// header request.
|
||||||
fn headers_received(&self, bh: &[core::BlockHeader], addr: PeerAddr) -> bool;
|
fn headers_received(
|
||||||
|
&self,
|
||||||
|
bh: &[core::BlockHeader],
|
||||||
|
addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error>;
|
||||||
|
|
||||||
/// Finds a list of block headers based on the provided locator. Tries to
|
/// Finds a list of block headers based on the provided locator. Tries to
|
||||||
/// identify the common chain and gets the headers that follow it
|
/// identify the common chain and gets the headers that follow it
|
||||||
/// immediately.
|
/// immediately.
|
||||||
fn locate_headers(&self, locator: &[Hash]) -> Vec<core::BlockHeader>;
|
fn locate_headers(&self, locator: &[Hash]) -> Result<Vec<core::BlockHeader>, chain::Error>;
|
||||||
|
|
||||||
/// Gets a full block by its hash.
|
/// Gets a full block by its hash.
|
||||||
fn get_block(&self, h: Hash) -> Option<core::Block>;
|
fn get_block(&self, h: Hash) -> Option<core::Block>;
|
||||||
|
@ -523,7 +544,12 @@ pub trait ChainAdapter: Sync + Send {
|
||||||
/// If we're willing to accept that new state, the data stream will be
|
/// If we're willing to accept that new state, the data stream will be
|
||||||
/// read as a zip file, unzipped and the resulting state files should be
|
/// read as a zip file, unzipped and the resulting state files should be
|
||||||
/// rewound to the provided indexes.
|
/// rewound to the provided indexes.
|
||||||
fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: PeerAddr) -> bool;
|
fn txhashset_write(
|
||||||
|
&self,
|
||||||
|
h: Hash,
|
||||||
|
txhashset_data: File,
|
||||||
|
peer_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods required by the protocol that don't need to be
|
/// Additional methods required by the protocol that don't need to be
|
||||||
|
|
|
@ -50,22 +50,22 @@ pub struct NetToChainAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl p2p::ChainAdapter for NetToChainAdapter {
|
impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
fn total_difficulty(&self) -> Difficulty {
|
fn total_difficulty(&self) -> Result<Difficulty, chain::Error> {
|
||||||
self.chain().head().unwrap().total_difficulty
|
Ok(self.chain().head()?.total_difficulty)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn total_height(&self) -> u64 {
|
fn total_height(&self) -> Result<u64, chain::Error> {
|
||||||
self.chain().head().unwrap().height
|
Ok(self.chain().head()?.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_transaction(&self, kernel_hash: Hash) -> Option<core::Transaction> {
|
fn get_transaction(&self, kernel_hash: Hash) -> Option<core::Transaction> {
|
||||||
self.tx_pool.read().retrieve_tx_by_kernel_hash(kernel_hash)
|
self.tx_pool.read().retrieve_tx_by_kernel_hash(kernel_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) {
|
fn tx_kernel_received(&self, kernel_hash: Hash, addr: PeerAddr) -> Result<bool, chain::Error> {
|
||||||
// nothing much we can do with a new transaction while syncing
|
// nothing much we can do with a new transaction while syncing
|
||||||
if self.sync_state.is_syncing() {
|
if self.sync_state.is_syncing() {
|
||||||
return;
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tx = self.tx_pool.read().retrieve_tx_by_kernel_hash(kernel_hash);
|
let tx = self.tx_pool.read().retrieve_tx_by_kernel_hash(kernel_hash);
|
||||||
|
@ -73,12 +73,17 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
if tx.is_none() {
|
if tx.is_none() {
|
||||||
self.request_transaction(kernel_hash, addr);
|
self.request_transaction(kernel_hash, addr);
|
||||||
}
|
}
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transaction_received(&self, tx: core::Transaction, stem: bool) {
|
fn transaction_received(
|
||||||
|
&self,
|
||||||
|
tx: core::Transaction,
|
||||||
|
stem: bool,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
// nothing much we can do with a new transaction while syncing
|
// nothing much we can do with a new transaction while syncing
|
||||||
if self.sync_state.is_syncing() {
|
if self.sync_state.is_syncing() {
|
||||||
return;
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let source = pool::TxSource {
|
let source = pool::TxSource {
|
||||||
|
@ -87,7 +92,7 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
};
|
};
|
||||||
|
|
||||||
let tx_hash = tx.hash();
|
let tx_hash = tx.hash();
|
||||||
let header = self.chain().head_header().unwrap();
|
let header = self.chain().head_header()?;
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Received tx {}, [in/out/kern: {}/{}/{}] going to process.",
|
"Received tx {}, [in/out/kern: {}/{}/{}] going to process.",
|
||||||
|
@ -97,17 +102,22 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
tx.kernels().len(),
|
tx.kernels().len(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = {
|
let mut tx_pool = self.tx_pool.write();
|
||||||
let mut tx_pool = self.tx_pool.write();
|
match tx_pool.add_to_pool(source, tx, stem, &header) {
|
||||||
tx_pool.add_to_pool(source, tx, stem, &header)
|
Ok(_) => Ok(true),
|
||||||
};
|
Err(e) => {
|
||||||
|
debug!("Transaction {} rejected: {:?}", tx_hash, e);
|
||||||
if let Err(e) = res {
|
Ok(false)
|
||||||
debug!("Transaction {} rejected: {:?}", tx_hash, e);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_received(&self, b: core::Block, addr: PeerAddr, was_requested: bool) -> bool {
|
fn block_received(
|
||||||
|
&self,
|
||||||
|
b: core::Block,
|
||||||
|
addr: PeerAddr,
|
||||||
|
was_requested: bool,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
debug!(
|
debug!(
|
||||||
"Received block {} at {} from {} [in/out/kern: {}/{}/{}] going to process.",
|
"Received block {} at {} from {} [in/out/kern: {}/{}/{}] going to process.",
|
||||||
b.hash(),
|
b.hash(),
|
||||||
|
@ -120,7 +130,11 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
self.process_block(b, addr, was_requested)
|
self.process_block(b, addr, was_requested)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compact_block_received(&self, cb: core::CompactBlock, addr: PeerAddr) -> bool {
|
fn compact_block_received(
|
||||||
|
&self,
|
||||||
|
cb: core::CompactBlock,
|
||||||
|
addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
let bhash = cb.hash();
|
let bhash = cb.hash();
|
||||||
debug!(
|
debug!(
|
||||||
"Received compact_block {} at {} from {} [out/kern/kern_ids: {}/{}/{}] going to process.",
|
"Received compact_block {} at {} from {} [out/kern/kern_ids: {}/{}/{}] going to process.",
|
||||||
|
@ -139,7 +153,7 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
Ok(block) => self.process_block(block, addr, false),
|
Ok(block) => self.process_block(block, addr, false),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
debug!("Invalid hydrated block {}: {:?}", cb_hash, e);
|
debug!("Invalid hydrated block {}: {:?}", cb_hash, e);
|
||||||
return false;
|
return Ok(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -149,7 +163,7 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
.process_block_header(&cb.header, self.chain_opts(false))
|
.process_block_header(&cb.header, self.chain_opts(false))
|
||||||
{
|
{
|
||||||
debug!("Invalid compact block header {}: {:?}", cb_hash, e.kind());
|
debug!("Invalid compact block header {}: {:?}", cb_hash, e.kind());
|
||||||
return !e.is_bad_data();
|
return Ok(!e.is_bad_data());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (txs, missing_short_ids) = {
|
let (txs, missing_short_ids) = {
|
||||||
|
@ -173,7 +187,7 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
Ok(block) => block,
|
Ok(block) => block,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
debug!("Invalid hydrated block {}: {:?}", cb.hash(), e);
|
debug!("Invalid hydrated block {}: {:?}", cb.hash(), e);
|
||||||
return false;
|
return Ok(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -188,20 +202,20 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
if self.sync_state.status() == SyncStatus::NoSync {
|
if self.sync_state.status() == SyncStatus::NoSync {
|
||||||
debug!("adapter: block invalid after hydration, requesting full block");
|
debug!("adapter: block invalid after hydration, requesting full block");
|
||||||
self.request_block(&cb.header, addr);
|
self.request_block(&cb.header, addr);
|
||||||
true
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
debug!("block invalid after hydration, ignoring it, cause still syncing");
|
debug!("block invalid after hydration, ignoring it, cause still syncing");
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!("failed to retrieve previous block header (still syncing?)");
|
debug!("failed to retrieve previous block header (still syncing?)");
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_received(&self, bh: core::BlockHeader, addr: PeerAddr) -> bool {
|
fn header_received(&self, bh: core::BlockHeader, addr: PeerAddr) -> Result<bool, chain::Error> {
|
||||||
let bhash = bh.hash();
|
let bhash = bh.hash();
|
||||||
debug!(
|
debug!(
|
||||||
"Received block header {} at {} from {}, going to process.",
|
"Received block header {} at {} from {}, going to process.",
|
||||||
|
@ -214,14 +228,14 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
.chain()
|
.chain()
|
||||||
.process_block_header(&bh, self.chain_opts(false));
|
.process_block_header(&bh, self.chain_opts(false));
|
||||||
|
|
||||||
if let &Err(ref e) = &res {
|
if let Err(e) = res {
|
||||||
debug!("Block header {} refused by chain: {:?}", bhash, e.kind());
|
debug!("Block header {} refused by chain: {:?}", bhash, e.kind());
|
||||||
if e.is_bad_data() {
|
if e.is_bad_data() {
|
||||||
return false;
|
return Ok(false);
|
||||||
} else {
|
} else {
|
||||||
// we got an error when trying to process the block header
|
// we got an error when trying to process the block header
|
||||||
// but nothing serious enough to need to ban the peer upstream
|
// but nothing serious enough to need to ban the peer upstream
|
||||||
return true;
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,37 +244,43 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
self.request_compact_block(&bh, addr);
|
self.request_compact_block(&bh, addr);
|
||||||
|
|
||||||
// done receiving the header
|
// done receiving the header
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn headers_received(&self, bhs: &[core::BlockHeader], addr: PeerAddr) -> bool {
|
fn headers_received(
|
||||||
|
&self,
|
||||||
|
bhs: &[core::BlockHeader],
|
||||||
|
addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
info!("Received {} block headers from {}", bhs.len(), addr,);
|
info!("Received {} block headers from {}", bhs.len(), addr,);
|
||||||
|
|
||||||
if bhs.len() == 0 {
|
if bhs.len() == 0 {
|
||||||
return false;
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to add headers to our header chain
|
// try to add headers to our header chain
|
||||||
let res = self.chain().sync_block_headers(bhs, self.chain_opts(true));
|
match self.chain().sync_block_headers(bhs, self.chain_opts(true)) {
|
||||||
if let &Err(ref e) = &res {
|
Ok(_) => Ok(true),
|
||||||
debug!("Block headers refused by chain: {:?}", e);
|
Err(e) => {
|
||||||
|
debug!("Block headers refused by chain: {:?}", e);
|
||||||
if e.is_bad_data() {
|
if e.is_bad_data() {
|
||||||
return false;
|
return Ok(false);
|
||||||
|
} else {
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn locate_headers(&self, locator: &[Hash]) -> Vec<core::BlockHeader> {
|
fn locate_headers(&self, locator: &[Hash]) -> Result<Vec<core::BlockHeader>, chain::Error> {
|
||||||
debug!("locator: {:?}", locator);
|
debug!("locator: {:?}", locator);
|
||||||
|
|
||||||
let header = match self.find_common_header(locator) {
|
let header = match self.find_common_header(locator) {
|
||||||
Some(header) => header,
|
Some(header) => header,
|
||||||
None => return vec![],
|
None => return Ok(vec![]),
|
||||||
};
|
};
|
||||||
|
|
||||||
let max_height = self.chain().header_head().unwrap().height;
|
let max_height = self.chain().header_head()?.height;
|
||||||
|
|
||||||
let txhashset = self.chain().txhashset();
|
let txhashset = self.chain().txhashset();
|
||||||
let txhashset = txhashset.read();
|
let txhashset = txhashset.read();
|
||||||
|
@ -283,7 +303,7 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
|
|
||||||
debug!("returning headers: {}", headers.len());
|
debug!("returning headers: {}", headers.len());
|
||||||
|
|
||||||
headers
|
Ok(headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a full block by its hash.
|
/// Gets a full block by its hash.
|
||||||
|
@ -348,11 +368,16 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
/// If we're willing to accept that new state, the data stream will be
|
/// If we're willing to accept that new state, the data stream will be
|
||||||
/// read as a zip file, unzipped and the resulting state files should be
|
/// read as a zip file, unzipped and the resulting state files should be
|
||||||
/// rewound to the provided indexes.
|
/// rewound to the provided indexes.
|
||||||
fn txhashset_write(&self, h: Hash, txhashset_data: File, _peer_addr: PeerAddr) -> bool {
|
fn txhashset_write(
|
||||||
|
&self,
|
||||||
|
h: Hash,
|
||||||
|
txhashset_data: File,
|
||||||
|
_peer_addr: PeerAddr,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
// check status again after download, in case 2 txhashsets made it somehow
|
// check status again after download, in case 2 txhashsets made it somehow
|
||||||
if let SyncStatus::TxHashsetDownload { .. } = self.sync_state.status() {
|
if let SyncStatus::TxHashsetDownload { .. } = self.sync_state.status() {
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = self
|
if let Err(e) = self
|
||||||
|
@ -361,12 +386,13 @@ impl p2p::ChainAdapter for NetToChainAdapter {
|
||||||
{
|
{
|
||||||
self.chain().clean_txhashset_sandbox();
|
self.chain().clean_txhashset_sandbox();
|
||||||
error!("Failed to save txhashset archive: {}", e);
|
error!("Failed to save txhashset archive: {}", e);
|
||||||
|
|
||||||
let is_good_data = !e.is_bad_data();
|
let is_good_data = !e.is_bad_data();
|
||||||
self.sync_state.set_sync_error(types::Error::Chain(e));
|
self.sync_state.set_sync_error(types::Error::Chain(e));
|
||||||
is_good_data
|
Ok(is_good_data)
|
||||||
} else {
|
} else {
|
||||||
info!("Received valid txhashset data for {}.", h);
|
info!("Received valid txhashset data for {}.", h);
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,15 +454,20 @@ impl NetToChainAdapter {
|
||||||
|
|
||||||
// pushing the new block through the chain pipeline
|
// pushing the new block through the chain pipeline
|
||||||
// remembering to reset the head if we have a bad block
|
// remembering to reset the head if we have a bad block
|
||||||
fn process_block(&self, b: core::Block, addr: PeerAddr, was_requested: bool) -> bool {
|
fn process_block(
|
||||||
|
&self,
|
||||||
|
b: core::Block,
|
||||||
|
addr: PeerAddr,
|
||||||
|
was_requested: bool,
|
||||||
|
) -> Result<bool, chain::Error> {
|
||||||
// We cannot process blocks earlier than the horizon so check for this here.
|
// We cannot process blocks earlier than the horizon so check for this here.
|
||||||
{
|
{
|
||||||
let head = self.chain().head().unwrap();
|
let head = self.chain().head()?;
|
||||||
let horizon = head
|
let horizon = head
|
||||||
.height
|
.height
|
||||||
.saturating_sub(global::cut_through_horizon() as u64);
|
.saturating_sub(global::cut_through_horizon() as u64);
|
||||||
if b.header.height < horizon {
|
if b.header.height < horizon {
|
||||||
return true;
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,11 +481,11 @@ impl NetToChainAdapter {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
self.validate_chain(bhash);
|
self.validate_chain(bhash);
|
||||||
self.check_compact();
|
self.check_compact();
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
Err(ref e) if e.is_bad_data() => {
|
Err(ref e) if e.is_bad_data() => {
|
||||||
self.validate_chain(bhash);
|
self.validate_chain(bhash);
|
||||||
false
|
Ok(false)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
match e.kind() {
|
match e.kind() {
|
||||||
|
@ -468,7 +499,7 @@ impl NetToChainAdapter {
|
||||||
self.request_block_by_hash(previous.hash(), addr)
|
self.request_block_by_hash(previous.hash(), addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -476,7 +507,7 @@ impl NetToChainAdapter {
|
||||||
bhash,
|
bhash,
|
||||||
e.kind()
|
e.kind()
|
||||||
);
|
);
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,8 +129,12 @@ pub fn connect_and_monitor(
|
||||||
if Utc::now() - prev_ping > Duration::seconds(10) {
|
if Utc::now() - prev_ping > Duration::seconds(10) {
|
||||||
let total_diff = peers.total_difficulty();
|
let total_diff = peers.total_difficulty();
|
||||||
let total_height = peers.total_height();
|
let total_height = peers.total_height();
|
||||||
peers.check_all(total_diff, total_height);
|
if total_diff.is_ok() && total_height.is_ok() {
|
||||||
prev_ping = Utc::now();
|
peers.check_all(total_diff.unwrap(), total_height.unwrap());
|
||||||
|
prev_ping = Utc::now();
|
||||||
|
} else {
|
||||||
|
error!("failed to get peers difficulty and/or height");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
thread::sleep(time::Duration::from_secs(1));
|
thread::sleep(time::Duration::from_secs(1));
|
||||||
|
|
|
@ -100,7 +100,7 @@ impl BodySync {
|
||||||
|
|
||||||
hashes.reverse();
|
hashes.reverse();
|
||||||
|
|
||||||
let peers = self.peers.more_work_peers();
|
let peers = self.peers.more_work_peers()?;
|
||||||
|
|
||||||
// if we have 5 peers to sync from then ask for 50 blocks total (peer_count *
|
// if we have 5 peers to sync from then ask for 50 blocks total (peer_count *
|
||||||
// 10) max will be 80 if all 8 peers are advertising more work
|
// 10) max will be 80 if all 8 peers are advertising more work
|
||||||
|
|
|
@ -77,7 +77,7 @@ impl SyncRunner {
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
const MIN_PEERS: usize = 3;
|
const MIN_PEERS: usize = 3;
|
||||||
loop {
|
loop {
|
||||||
let wp = self.peers.more_or_same_work_peers();
|
let wp = self.peers.more_or_same_work_peers()?;
|
||||||
// exit loop when:
|
// exit loop when:
|
||||||
// * we have more than MIN_PEERS more_or_same_work peers
|
// * we have more than MIN_PEERS more_or_same_work peers
|
||||||
// * we are synced already, e.g. grin was quickly restarted
|
// * we are synced already, e.g. grin was quickly restarted
|
||||||
|
|
Loading…
Reference in a new issue