diff --git a/Cargo.lock b/Cargo.lock index a1edfd9..1d8cc9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,10 +50,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" dependencies = [ - "bitcoin-internals 0.3.0", - "bitcoin_hashes 0.14.0", + "bitcoin-internals", + "bitcoin_hashes", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "bech32" version = "0.11.0" @@ -65,7 +71,8 @@ name = "bip324" version = "0.3.1" dependencies = [ "bitcoin", - "hex-conservative 0.2.0", + "bitcoincore-rpc", + "hex-conservative", "rand", ] @@ -76,7 +83,7 @@ dependencies = [ "bip324", "bitcoin", "bytes", - "hex-conservative 0.2.0", + "hex-conservative", "tokio", ] @@ -88,26 +95,24 @@ checksum = "7170e7750a20974246f17ece04311b4205a6155f1db564c5b224af817663c3ea" dependencies = [ "base58ck", "bech32", - "bitcoin-internals 0.3.0", + "bitcoin-internals", "bitcoin-io", "bitcoin-units", - "bitcoin_hashes 0.14.0", - "hex-conservative 0.2.0", + "bitcoin_hashes", + "hex-conservative", "hex_lit", "secp256k1", + "serde", ] -[[package]] -name = "bitcoin-internals" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" - [[package]] name = "bitcoin-internals" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +dependencies = [ + "serde", +] [[package]] name = "bitcoin-io" @@ -121,27 +126,43 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb54da0b28892f3c52203a7191534033e051b6f4b52bc15480681b57b7e036f5" dependencies = [ - "bitcoin-internals 0.3.0", + "bitcoin-internals", + "serde", ] [[package]] name = "bitcoin_hashes" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" dependencies = [ - "bitcoin-internals 0.2.0", - "hex-conservative 0.1.1", + "bitcoin-io", + "hex-conservative", + "serde", ] [[package]] -name = "bitcoin_hashes" -version = "0.14.0" +name = "bitcoincore-rpc" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +checksum = "aedd23ae0fd321affb4bbbc36126c6f49a32818dc6b979395d24da8c9d4e80ee" dependencies = [ - "bitcoin-io", - "hex-conservative 0.2.0", + "bitcoincore-rpc-json", + "jsonrpc", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "bitcoincore-rpc-json" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8909583c5fab98508e80ef73e5592a651c954993dc6b7739963257d19f0e71a" +dependencies = [ + "bitcoin", + "serde", + "serde_json", ] [[package]] @@ -191,12 +212,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "hex-conservative" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" - [[package]] name = "hex-conservative" version = "0.2.0" @@ -212,6 +227,24 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jsonrpc" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3662a38d341d77efecb73caf01420cfa5aa63c0253fd7bc05289ef9f6616e1bf" +dependencies = [ + "base64", + "minreq", + "serde", + "serde_json", +] + [[package]] name = "libc" version = "0.2.153" @@ -228,6 +261,18 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -238,6 +283,17 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minreq" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763d142cdff44aaadd9268bebddb156ef6c65a0e13486bb81673cf2d8739f9b0" +dependencies = [ + "log", + "serde", + "serde_json", +] + [[package]] name = "mio" version = "0.8.11" @@ -363,6 +419,12 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + [[package]] name = "scopeguard" version = "1.2.0" @@ -375,8 +437,10 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" dependencies = [ - "bitcoin_hashes 0.13.0", + "bitcoin_hashes", + "rand", "secp256k1-sys", + "serde", ] [[package]] @@ -388,6 +452,38 @@ dependencies = [ "cc", ] +[[package]] +name = "serde" +version = "1.0.205" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.205" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" diff --git a/protocol/Cargo.toml b/protocol/Cargo.toml index d418a53..7f84d4f 100644 --- a/protocol/Cargo.toml +++ b/protocol/Cargo.toml @@ -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" diff --git a/protocol/tests/regtest.sh b/protocol/tests/regtest.sh new file mode 100755 index 0000000..106222c --- /dev/null +++ b/protocol/tests/regtest.sh @@ -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 \ No newline at end of file diff --git a/protocol/tests/round_trips.rs b/protocol/tests/round_trips.rs index 89172b9..7d4af2f 100644 --- a/protocol/tests/round_trips.rs +++ b/protocol/tests/round_trips.rs @@ -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() { @@ -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)); +}