summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock105
-rw-r--r--Cargo.toml2
-rw-r--r--src/blocks.rs103
-rw-r--r--src/client.rs3
-rw-r--r--src/lib.rs2
-rw-r--r--src/network.rs18
-rw-r--r--src/transaction.rs3
7 files changed, 177 insertions, 59 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bebdc38..729212d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,13 +3,35 @@
version = 4
[[package]]
+name = "bincode"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
+dependencies = [
+ "bincode_derive",
+ "serde",
+ "unty",
+]
+
+[[package]]
+name = "bincode_derive"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
+dependencies = [
+ "virtue",
+]
+
+[[package]]
name = "bitcoin"
version = "0.1.0"
dependencies = [
+ "bincode",
"futures",
"rand",
"serde",
"serde_json",
+ "sha2",
"tokio",
"tokio-serde",
"tokio-util",
@@ -22,6 +44,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
name = "bytes"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -34,6 +65,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
name = "educe"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -155,6 +215,16 @@ dependencies = [
]
[[package]]
+name = "generic-array"
+version = "0.14.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
name = "getrandom"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -386,6 +456,17 @@ dependencies = [
]
[[package]]
+name = "sha2"
+version = "0.10.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
name = "signal-hook-registry"
version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -484,12 +565,36 @@ dependencies = [
]
[[package]]
+name = "typenum"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
+
+[[package]]
name = "unicode-ident"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]]
+name = "unty"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "virtue"
+version = "0.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
+
+[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 7343510..6367695 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,3 +11,5 @@ tokio-serde = { version = "0.9.0", features = ["json"] }
tokio-util = { version = "0.7.16", features = ["codec"] }
futures = "0.3.31"
rand = "0.9.2"
+sha2 = "0.10.9"
+bincode = "2.0.1"
diff --git a/src/blocks.rs b/src/blocks.rs
index 1fa8486..17e6d4f 100644
--- a/src/blocks.rs
+++ b/src/blocks.rs
@@ -1,5 +1,7 @@
+use bincode::Encode;
+use sha2::{Digest, Sha256, digest::DynDigest};
use std::{
- hash::{DefaultHasher, Hash, Hasher},
+ hash::{Hash, Hasher},
ops::Deref,
};
@@ -7,68 +9,69 @@ use serde::{Deserialize, Serialize};
use crate::{ZERO_PREFIX_AMOUNT, transaction::Transaction};
-#[derive(Deserialize, Serialize, Clone, Copy, PartialEq)]
+pub trait CryptoDigest {
+ fn digest(&self, state: &mut impl DynDigest);
+}
+
+#[derive(Deserialize, Serialize, Clone, PartialEq, Encode)]
pub struct Block {
- pub prev_hash: u64,
+ pub prev_hash: Vec<u8>,
pub trans: Transaction,
- pub pow: Option<u64>,
+ pub pow: Vec<u8>,
}
impl Block {
- fn new(prev_hash: Option<u64>, trans: Transaction) -> Self {
+ fn new(prev_hash: Option<&[u8]>, trans: Transaction) -> Self {
Self {
- prev_hash: prev_hash.unwrap_or(0), // special blocks
+ prev_hash: prev_hash
+ .unwrap_or(&[])
+ .to_vec(), // special blocks
trans,
- pow: None,
+ pow: Vec::default(),
}
}
- fn calc_pow(&self) -> u64 {
+ fn pref_zeros(hashed: &[u8]) -> Result<usize, usize> {
+ hashed
+ .iter()
+ .try_fold(0, |nonce, x| {
+ if nonce >= ZERO_PREFIX_AMOUNT {
+ Ok(nonce)
+ } else if *x == 0 {
+ Ok(nonce + 1)
+ } else {
+ Err(nonce)
+ }
+ })
+ }
+
+ fn calc_pow(&self) -> Vec<u8> {
for i in 0.. {
// reset every loop
- let mut hasher = DefaultHasher::new();
- (&self.prev_hash, &self.trans, i).hash(&mut hasher);
- let hashed = hasher.finish();
- if hashed
- .to_string()
- .starts_with(
- &"0".repeat(ZERO_PREFIX_AMOUNT)
- .to_string(),
- )
- {
- return hashed;
+ let mut hasher = Sha256::new();
+ Digest::update(&mut hasher, bincode::encode_to_vec((&self.prev_hash, &self.trans, i), bincode::config::standard()).unwrap());
+ let hashed = hasher.finalize();
+ if Self::pref_zeros(&hashed).is_ok() {
+ return hashed.to_vec();
}
}
unreachable!()
}
pub fn verify_pow(&mut self) -> bool {
- let mut hasher = DefaultHasher::new();
- self.hash(&mut hasher);
- hasher
- .finish()
- .to_string()
- .to_string()
- .starts_with(
- &"0".repeat(ZERO_PREFIX_AMOUNT)
- .to_string(),
- )
+ let mut hasher = Sha256::new();
+ Digest::update(&mut hasher, bincode::encode_to_vec(&*self, bincode::config::standard()).unwrap());
+ Self::pref_zeros(&hasher.finalize()).is_ok()
}
pub fn calc_set_pow(&mut self) {
- self.pow = Some(self.calc_pow());
+ self.pow = self.calc_pow();
}
}
-impl Hash for Block {
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.prev_hash
- .hash(state);
- self.trans
- .hash(state);
- self.pow
- .expect("Cannot hash whole block with no PoW")
- .hash(state);
+impl CryptoDigest for Block {
+ fn digest(&self, state: &mut impl DynDigest) {
+ state.update(&bincode::encode_to_vec((&self.prev_hash, &self.trans, &self.pow), bincode::config::standard()).unwrap());
}
}
@@ -85,16 +88,17 @@ impl BlockChain {
}
pub fn new_block(&self, trans: Transaction) -> Block {
- let mut hasher = DefaultHasher::new();
- Block::new(
- self.blocks
- .last()
- .map(|b| {
- b.hash(&mut hasher);
- hasher.finish()
- }),
- trans,
- )
+ let mut hasher = Sha256::new();
+ let prev = self
+ .blocks
+ .last();
+ let prev_hash = if let Some(b) = prev {
+ b.digest(&mut hasher);
+ Some(&*hasher.finalize())
+ } else {
+ None
+ };
+ Block::new(prev_hash, trans)
}
pub fn store(&mut self, block: Block) {
@@ -106,6 +110,7 @@ impl BlockChain {
impl Deref for BlockChain {
type Target = Vec<Block>;
+
fn deref(&self) -> &Self::Target {
&self.blocks
}
diff --git a/src/client.rs b/src/client.rs
index 457a70d..eb417fd 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -1,7 +1,8 @@
+use bincode::Encode;
use rand::Rng;
use serde::{Deserialize, Serialize};
-#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq)]
+#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Encode)]
pub struct Client {
id: u32,
}
diff --git a/src/lib.rs b/src/lib.rs
index 0545aa5..9cdbdcd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,4 +6,4 @@ pub mod client;
pub mod network;
-const ZERO_PREFIX_AMOUNT: usize = 5; // TODO: make this dynamic
+const ZERO_PREFIX_AMOUNT: usize = 2; // TODO: make this dynamic
diff --git a/src/network.rs b/src/network.rs
index 753f743..c18ae07 100644
--- a/src/network.rs
+++ b/src/network.rs
@@ -75,7 +75,7 @@ impl Network {
let peer = Arc::new(Mutex::new(Peer::new(
self.this
.clone(),
- TcpStream::connect("192.168.143.90:6767")
+ TcpStream::connect("192.168.1.16:6767")
.await
.unwrap(),
)));
@@ -222,8 +222,11 @@ impl Peer {
async fn handle(parent: Weak<Mutex<Network>>, req: Request) {
match req {
- Request::Block(mut block) => match block.pow {
- Some(_pow) => {
+ Request::Block(mut block) => {
+ if !block
+ .pow
+ .is_empty()
+ {
if !block.verify_pow() {
eprintln!("Rejecting remote block, POW verification failed"); // TODO: log remote IP
return;
@@ -237,8 +240,8 @@ impl Peer {
.lock()
.await
.store(block)
- }
- None => {
+ } else {
+ print!("as");
block.calc_set_pow();
let parent = parent
.upgrade()
@@ -250,7 +253,7 @@ impl Peer {
.broadcast(Request::Block(block))
.await;
}
- },
+ }
Request::Ibd(bc) => match bc {
Some(bc) => {
let parent = parent
@@ -267,10 +270,11 @@ impl Peer {
|| (self_bc
.blocks
.iter()
+ // TODO: Optimize via try_fold
.fold(true, |i, b| {
if i {
b.pow
- .is_none()
+ .is_empty()
} else {
false
}
diff --git a/src/transaction.rs b/src/transaction.rs
index dcaff49..760f080 100644
--- a/src/transaction.rs
+++ b/src/transaction.rs
@@ -1,8 +1,9 @@
+use bincode::Encode;
use serde::{Deserialize, Serialize};
use crate::client::Client;
-#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq)]
+#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Encode)]
pub struct Transaction {
from: Client,
to: Client,