Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Saruniks committed Mar 26, 2023
1 parent 2d173a9 commit 6dc17e1
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 117 deletions.
72 changes: 72 additions & 0 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
sha2 = "0.10.6"
tokio = { version = "1", features = ["net", "io-util", "macros", "rt-multi-thread"] }
207 changes: 90 additions & 117 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,156 +1,129 @@
use std::net::SocketAddr;
use sha2::{Digest, Sha256};
use std::net::{IpAddr, SocketAddr};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;

static VERSION_MESSAGE: &[u8] = &[
// header
249, 190, 180, 217, // magic
118, 101, 114, 115, 105, 111, 110, 0, 0, 0, 0, 0, // "version" command
86, 0, 0, 0, // payload len
94, 38, 138, 233, // checksum
// payload
113, 17, 1, 0, // protocol version
0, 0, 0, 0, 0, 0, 0, 0, // services
0, 0, 0, 0, 0, 0, 0, 0, // time
// 36, 99, 31, 100, 0, 0, 0, 0, // time
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 134, 195, 185, 52, 32, 141, // recipient address info
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, // sender address info
0, 0, 0, 0, 0, 0, 0, 0, // Node ID,
// 131, 67, 161, 229, 100, 242, 249, 181, // Node ID,
0, // "" sub-version string, 0 bytes long
0, // relay
0, 0, 0, 0, // last block sending node
];

static VERACK_MESSAGE: &[u8] = &[
// header
249, 190, 180, 217, // magic
18, 101, 114, 97, 99, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // payload len
18, 101, 114, 97, 99, 107, 0, 0, 0, 0, 0, 0, // "verack" command
0, 0, 0, 0, // payload len
93, 246, 224, 226, // checksum
];

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let address: SocketAddr = "134.195.185.52:8333".parse().unwrap();
let address: SocketAddr = "134.195.185.52:8333".parse()?;

let mut stream = TcpStream::connect(address).await?;

let _ = stream.write_all(VERSION_MESSAGE).await;
stream.write_all(build_version_message(address).as_slice()).await?;
println!("Version message sent");
println!("Waiting for response...");
read_version_message(&mut stream).await?;
println!("Version message received");

let _ = stream.write_all(VERACK_MESSAGE).await;
stream.write_all(VERACK_MESSAGE).await?;
println!("Verack message sent");
println!("Waiting for response...");
read_verack_message(&mut stream).await?;
println!("Verack message received");

Ok(())
}

async fn read_version_message(stream: &mut TcpStream) -> Result<(), Box<dyn std::error::Error>> {
let mut magic = vec![0; 4];
stream.read_exact(&mut magic).await?;

println!("{:?}", magic);
fn build_version_message(address: SocketAddr) -> Vec<u8> {
let mut payload: Vec<u8> = vec![
113, 17, 1, 0, // protocol version
0, 0, 0, 0, 0, 0, 0, 0, // services
0, 0, 0, 0, 0, 0, 0, 0, // time
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, // start of recipient address bytes
];

let mut addr = socket_addr_to_vec(address);
payload.append(&mut addr);
payload.append(&mut vec![
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, // sender address info
0, 0, 0, 0, 0, 0, 0, 0, // Node ID,
0, // "" sub-version string, 0 bytes long
0, // relay
0, 0, 0, 0, // last block sending node
]);

let mut header: Vec<u8> = vec![
// header
249, 190, 180, 217, // magic
118, 101, 114, 115, 105, 111, 110, 0, 0, 0, 0, 0, // "version" command
];

// Add payload len
header.extend_from_slice(&mut (payload.len() as u32).to_le_bytes());

// Add checksum
let mut checksum = get_first_4_bytes_of_double_sha256(&payload);
header.extend_from_slice(&mut checksum);
header.extend(&payload);
header
}

let mut cmd = vec![0; 12];
stream.read_exact(&mut cmd).await?;
fn socket_addr_to_vec(socket_addr: SocketAddr) -> Vec<u8> {
let ip = match socket_addr.ip() {
IpAddr::V4(ip) => ip.octets().to_vec(),
IpAddr::V6(ip) => ip.octets().to_vec(),
};

println!("{:?}", cmd);
let port = socket_addr.port();
let mut port_bytes = [0u8; 2];
port_bytes.copy_from_slice(&(port as u16).to_be_bytes());

let mut len = vec![0; 4];
stream.read_exact(&mut len).await?;
[ip, port_bytes.to_vec()].concat()
}

println!("{:?}", len);
async fn read_version_message(stream: &mut TcpStream) -> Result<(), Box<dyn std::error::Error>> {
let mut header = vec![0; 24];
stream.read_exact(&mut header).await?;

let mut checksum = vec![0; 4];
stream.read_exact(&mut checksum).await?;
if "version" != std::str::from_utf8(&header[4..11])? {
return Err("Unexpected command".into());
}

println!("{:?}", checksum);
let len = u32::from_le_bytes([header[16], header[17], header[18], header[19]]);

let mut payload = vec![0; 102];
let mut payload = vec![0; len as usize];
stream.read_exact(&mut payload).await?;

println!("{:?}", payload);
let checksum = get_first_4_bytes_of_double_sha256(&payload);

println!("Finished reading version");
Ok(())
if checksum == &header[20..24] {
Ok(())
} else {
Err("Invalid version message checksum".into())
}
}

async fn read_verack_message(stream: &mut TcpStream) -> Result<(), Box<dyn std::error::Error>> {
let mut verack = vec![0; 24];
stream.read_exact(&mut verack).await.unwrap();
stream.read_exact(&mut verack).await?;

if "verack" != std::str::from_utf8(&verack[4..10])? {
return Err("Unexpected command".into());
}

println!("{:?}", verack);
if [93, 246, 224, 226] != &verack[20..24] {
return Err("Invalid verack message checksum".into());
}

println!("Finished reading verack");
Ok(())
}

// fn build_version_message_vec(address: SocketAddr) -> Vec<u8> {
// vec![
// // header
// 249, 190, 180, 217, // magic
// 118, 101, 114, 115, 105, 111, 110, 0, 0, 0, 0, 0, // "version" command
// 86, 0, 0, 0, // payload len
// 94, 38, 138, 233, // checksum

// // payload
// 113, 17, 1, 0, // protocol version
// 0, 0, 0, 0, 0, 0, 0, 0, // services
// 0, 0, 0, 0, 0, 0, 0, 0, // time
// // 36, 99, 31, 100, 0, 0, 0, 0, // time
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 134, 195, 185, 52, 32, 141, // recipient address info
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, // sender address info
// 0, 0, 0, 0, 0, 0, 0, 0, // Node ID,
// // 131, 67, 161, 229, 100, 242, 249, 181, // Node ID,
// 0, // "" sub-version string, 0 bytes long
// 0, // relay
// 0, 0, 0, 0, // last block sending node
// ]
// }

// fn build_verack_message_vec() -> Vec<u8> {
// vec![
// // header
// 249, 190, 180, 217, // magic
// 18, 101, 114, 97, 99, 107, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, // payload len
// 93, 246, 224, 226, // checksum
// ]
// }

// fn build_version_message(address: SocketAddr) -> message::NetworkMessage {
// // Building version message, see https://en.bitcoin.it/wiki/Protocol_documentation#version
// let my_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);

// // "bitfield of features to be enabled for this connection"
// let services = constants::ServiceFlags::NONE;

// // "standard UNIX timestamp in seconds"
// // let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time error").as_secs();
// let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time error").as_secs();

// // "The network address of the node receiving this message"
// let addr_recv = address::Address::new(&address, constants::ServiceFlags::NONE);

// // "The network address of the node emitting this message"
// let addr_from = address::Address::new(&my_address, constants::ServiceFlags::NONE);

// // "Node random nonce, randomly generated every time a version packet is sent. This nonce is used to detect connections to self."
// // let nonce: u64 = secp256k1::rand::thread_rng().gen();
// let nonce: u64 = secp256k1::rand::thread_rng().gen();

// // "User Agent (0x00 if string is 0 bytes long)"
// let user_agent = String::from("rust-example");

// // "The last block received by the emitting node"
// let start_height: i32 = 0;

// // Construct the message
// message::NetworkMessage::Version(message_network::VersionMessage::new(
// services,
// timestamp as i64,
// addr_recv,
// addr_from,
// nonce,
// user_agent,
// start_height,
// ))
// }
fn get_first_4_bytes_of_double_sha256(data: &[u8]) -> [u8; 4] {
let mut hasher = Sha256::new();
hasher.update(data);
let hash = hasher.finalize();

let mut hasher2 = Sha256::new();
hasher2.update(hash);
let hash2 = hasher2.finalize();

[hash2[0], hash2[1], hash2[2], hash2[3]]
}

0 comments on commit 6dc17e1

Please sign in to comment.