Skip to content

Commit

Permalink
test(protocol): add handshake with Bitcoin Core
Browse files Browse the repository at this point in the history
  • Loading branch information
rustaceanrob committed Aug 9, 2024
1 parent ab9f9d2 commit 9518479
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 30 deletions.
156 changes: 126 additions & 30 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ bitcoin = { version = "0.32.0", default-features = false }

[dev-dependencies]
hex = { package = "hex-conservative", version = "0.2.0" }
bitcoincore-rpc = "0.19.0"

[lib]
name = "bip324"
Expand Down
3 changes: 3 additions & 0 deletions protocol/tests/regtest.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bitcoind --chain=regtest --txindex --blockfilterindex --peerblockfilters --rpcport=18443 --rpcuser=test --rpcpassword=b324 --rest=1 --server=1 --listen=1 --v2transport=1 &
sleep 1
cargo test regtest_handshake -- --nocapture
102 changes: 102 additions & 0 deletions protocol/tests/round_trips.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

const RPC_USER: &str = "test";
const RPC_PASSWORD: &str = "b324";
const HOST: &str = "http://localhost:18443";
const PORT: u16 = 18444;

#[test]
#[cfg(feature = "std")]
fn hello_world_happy_path() {
Expand Down Expand Up @@ -53,3 +58,100 @@ fn hello_world_happy_path() {
.unwrap();
assert_eq!(message, messages.message.unwrap());
}

#[test]
#[cfg(feature = "std")]
#[ignore = "CI"]
fn regtest_handshake() {
use std::{
io::{Read, Write},
net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream},
time::{Duration, SystemTime, UNIX_EPOCH},
};

use bip324::{
serde::{deserialize, serialize, NetworkMessage},
Handshake, ReceivedMessage,
};
use bitcoincore_rpc::{
bitcoin::p2p::{message_network::VersionMessage, Address, ServiceFlags},
RpcApi,
};

let rpc = bitcoincore_rpc::Client::new(
HOST,
bitcoincore_rpc::Auth::UserPass(RPC_USER.into(), RPC_PASSWORD.into()),
)
.unwrap();
let mut stream = TcpStream::connect(format!("127.0.0.1:{PORT}")).unwrap();
let mut public_key = [0u8; 64];
let mut handshake = Handshake::new(
bip324::Network::Regtest,
bip324::Role::Initiator,
None,
&mut public_key,
)
.unwrap();
dbg!("Writing public key to the remote node");
stream.write_all(&public_key).unwrap();
stream.flush().unwrap();
let mut remote_public_key = [0u8; 64];
dbg!("Reading the remote node public key");
stream.read_exact(&mut remote_public_key).unwrap();
let mut local_garbage_terminator_message = [0u8; 36];
dbg!("Sending our garbage terminator");
handshake
.complete_materials(remote_public_key, &mut local_garbage_terminator_message)
.unwrap();
stream.write_all(&local_garbage_terminator_message).unwrap();
stream.flush().unwrap();
let mut max_response = [0; 4096];
dbg!("Reading the response buffer");
let size = stream.read(&mut max_response).unwrap();
let response = &mut max_response[..size];
dbg!("Authenticating the handshake");
handshake
.authenticate_garbage_and_version(response)
.unwrap();
dbg!("Finalizing the handshake");
let packet_handler = handshake.finalize().unwrap();
let (mut decrypter, mut encrypter) = packet_handler.into_split();
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("time went backwards")
.as_secs();
let ip = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), PORT);
let from_and_recv = Address::new(&ip, ServiceFlags::NONE);
let msg = VersionMessage {
version: 70015,
services: ServiceFlags::NONE,
timestamp: now as i64,
receiver: from_and_recv.clone(),
sender: from_and_recv,
nonce: 1,
user_agent: "BIP324 Client".to_string(),
start_height: 0,
relay: false,
};
let message = serialize(NetworkMessage::Version(msg)).unwrap();
let packet = encrypter
.prepare_packet_with_alloc(&message, None, false)
.unwrap();
dbg!("Serializing and writing version message");
stream.write_all(&packet).unwrap();
dbg!("Reading the response length buffer");
let mut response_len = [0; 3];
stream.read_exact(&mut response_len).unwrap();
let message_len = decrypter.decypt_len(response_len);
let mut response_message = vec![0; message_len];
stream.read_exact(&mut response_message).unwrap();
let msg = decrypter
.decrypt_contents_with_alloc(&response_message, None)
.unwrap();
let message = ReceivedMessage::new(&msg.clone()).unwrap();
let message = deserialize(&message.message.unwrap()).unwrap();
dbg!("{}", message.cmd());
assert_eq!(message.cmd(), "version");
rpc.stop().unwrap();
std::thread::sleep(Duration::from_secs(1));
}

0 comments on commit 9518479

Please sign in to comment.