Skip to content
Draft
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
10 changes: 4 additions & 6 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ version = "0.1.0"
edition = "2021"

[dependencies]
# bitcoinkernel = { path = "../rust-bitcoinkernel", version = "0.0.15" }
bitcoinkernel = "0.1"
bitcoinkernel = { git = "https://github.com/TheCharlatan/rust-bitcoinkernel", rev = "cf9bae320fcec68a4cff54d3547c529a011a4c96" }
# bitcoinkernel = { path = "../rust-bitcoinkernel" }
# bitcoinkernel = "0.1"
addrman = { package = "bitcoin-address-book", git = "https://github.com/rustaceanrob/bitcoin-address-book", rev = "4417e4c8f5d04245947c758b73fb0dc9e7e0bd15" }
bitcoin = { git = "https://github.com/rust-bitcoin/rust-bitcoin", default-features = false, rev = "16cc257c3695dea0e7301a5fa9cab44b8ed60598" }
p2p = { package = "bitcoin-p2p", git = "https://github.com/2140-dev/bitcoin-p2p.git", rev = "322c4abb2a947f3f2d85991a0cb450249c68c1ea" }
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::try_from(ser_header.as_slice()).unwrap()
}

pub fn get_block_hash(index: BlockTreeEntry) -> bitcoin::BlockHash {
bitcoin::BlockHash::from_byte_array(index.block_hash().to_bytes())
}
54 changes: 43 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, 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,31 @@ pub fn process_message(
}

match state_machine {
PeerStateMachine::AwaitingHeaders => match event {
NetworkMessage::Headers(headers) => {
info!("Received headers message!");
for header in &headers.0 {
let (accepted, state) = node_state.chainman.process_header(&bitcoin_header_to_kernel_header(&header));
if !accepted {
warn!("Rejected header {}: {:?}", header.block_hash(), state.result());
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());
info!("Progressed to best known hash: {} at height: {}", best_hash, node_state.chainman.best_entry().unwrap().height());
(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 +252,10 @@ 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);
writer.send_message(getheaders)?;
let peer = BitcoinPeer {
addr,
writer: Arc::new(writer),
Expand Down