Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/bin/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ static START: Once = Once::new();
static mut GLOBAL_LOG_CALLBACK_HOLDER: Option<Logger> = None;

fn setup_logging() {
let mut builder = env_logger::Builder::from_default_env();
builder.filter(None, log::LevelFilter::Info).init();
let mut builder = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"));
builder.init();

unsafe { GLOBAL_LOG_CALLBACK_HOLDER = Some(Logger::new(KernelLog {}).unwrap()) };
}
Expand Down
5 changes: 5 additions & 0 deletions src/kernel_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ pub fn bitcoin_block_to_kernel_block(block: &bitcoin::Block<Checked>) -> bitcoin
bitcoinkernel::Block::try_from(ser_block.as_slice()).unwrap()
}

pub fn bitcoin_header_to_kernel_header(header: &bitcoin::BlockHeader) -> bitcoinkernel::BlockHeader {
let ser_header = encode::serialize(header);
bitcoinkernel::BlockHeader::new(ser_header.as_slice()).unwrap()
}

pub fn get_block_hash(index: BlockTreeEntry) -> bitcoin::BlockHash {
bitcoin::BlockHash::from_byte_array(index.block_hash().to_bytes())
}
59 changes: 48 additions & 11 deletions src/peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ use std::{
};

use bitcoin::{BlockHash, Network};
use bitcoinkernel::{ChainstateManager, Context};
use log::{debug, info};
use bitcoinkernel::{ChainstateManager, Context, ProcessBlockHeaderResult, ValidationMode, core::BlockHashExt, prelude::BlockValidationStateExt};
use log::{debug, info, warn};
use p2p::{
handshake::ConnectionConfig,
net::{ConnectionExt, ConnectionReader, ConnectionWriter, TimeoutParams},
p2p_message_types::{
message::{AddrV2Payload, InventoryPayload, NetworkMessage},
message_blockdata::{GetBlocksMessage, Inventory},
message_network::UserAgent,
Address, ProtocolVersion, ServiceFlags,
Address, ProtocolVersion, ServiceFlags, message::{AddrV2Payload, InventoryPayload, NetworkMessage}, message_blockdata::{GetBlocksMessage, GetHeadersMessage, Inventory}, message_network::UserAgent
},
};

use crate::kernel_util::bitcoin_block_to_kernel_block;
use crate::kernel_util::{bitcoin_block_to_kernel_block, bitcoin_header_to_kernel_header};

const PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::INVALID_CB_NO_BAN_VERSION;

Expand Down Expand Up @@ -60,6 +57,7 @@ impl NodeState {
///
/// [*]
/// │
/// AwaitingHeaders
/// ▼
/// AwaitingInv
/// ▲ |
Expand All @@ -73,6 +71,7 @@ impl NodeState {
#[derive(Default)]
pub enum PeerStateMachine {
#[default]
AwaitingHeaders,
AwaitingInv,
AwaitingBlock(AwaitingBlock),
}
Expand All @@ -82,6 +81,14 @@ pub struct AwaitingBlock {
pub block_buffer: HashMap<bitcoin::BlockHash /*prev */, bitcoinkernel::Block>,
}

fn create_getheaders_message(known_block_hash: bitcoin::BlockHash) -> NetworkMessage {
NetworkMessage::GetHeaders(GetHeadersMessage {
version: PROTOCOL_VERSION,
locator_hashes: vec![known_block_hash],
stop_hash: bitcoin::BlockHash::GENESIS_PREVIOUS_BLOCK_HASH,
})
}

fn create_getblocks_message(known_block_hash: bitcoin::BlockHash) -> NetworkMessage {
NetworkMessage::GetBlocks(GetBlocksMessage {
version: PROTOCOL_VERSION,
Expand Down Expand Up @@ -118,6 +125,35 @@ pub fn process_message(
}

match state_machine {
PeerStateMachine::AwaitingHeaders => match event {
NetworkMessage::Headers(headers) => {
for header in &headers.0 {
let result = node_state.chainman.process_block_header(&bitcoin_header_to_kernel_header(&header));
match result {
ProcessBlockHeaderResult::Success(state) if state.mode() == ValidationMode::Valid => {
debug!("Processed header: {}", header.time.to_u32());
continue;
}
_ => {
warn!("Rejected header {}", header.block_hash());
break;
}
}
}

if headers.0.len() != 2000 {
let tip_hash = node_state.get_tip_state().block_hash;
return (PeerStateMachine::AwaitingInv, vec![create_getblocks_message(tip_hash)]);
}

let best_hash = BlockHash::from_byte_array(node_state.chainman.best_entry().unwrap().block_hash().to_bytes());
(PeerStateMachine::AwaitingHeaders, vec![create_getheaders_message(best_hash)])
}
message => {
debug!("Ignoring message: {:?}", message);
(PeerStateMachine::AwaitingHeaders, vec![])
}
}
PeerStateMachine::AwaitingInv => match event {
NetworkMessage::Inv(inventory) => {
debug!("Received inventory with {} items", inventory.0.len());
Expand Down Expand Up @@ -220,10 +256,11 @@ impl BitcoinPeer {

let addr = Address::new(&socket_addr, ServiceFlags::WITNESS);
info!("Connected to {:?}", addr);
let state_machine = PeerStateMachine::AwaitingInv;
let our_best = node_state.get_tip_state().block_hash;
let getblocks = create_getblocks_message(our_best);
writer.send_message(getblocks)?;
let state_machine = PeerStateMachine::AwaitingHeaders;
let best_hash = BlockHash::from_byte_array(node_state.chainman.best_entry().unwrap().block_hash().to_bytes());
let getheaders = create_getheaders_message(best_hash);
debug!("sending headers message...");
writer.send_message(getheaders)?;
let peer = BitcoinPeer {
addr,
writer: Arc::new(writer),
Expand Down