Skip to content

Commit

Permalink
add more info to Block struct
Browse files Browse the repository at this point in the history
  • Loading branch information
stojanov-igor committed Jun 27, 2024
1 parent b71368d commit 6a79d2a
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 16 deletions.
28 changes: 26 additions & 2 deletions jam/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::transaction::Transaction;
use crate::utils::sha256;
use chrono::prelude::*;
use serde::{Serialize, Deserialize};
use serde_json::Value;

#[derive(Serialize, Deserialize, Debug)]
pub struct Block {
Expand All @@ -11,26 +12,49 @@ pub struct Block {
pub transactions: Vec<Transaction>,
pub nonce: u64,
pub block_hash: String,
pub state_root: String,
pub block_producer: String,
pub metadata: Value,
}

impl Block {
pub fn new(index: u32, previous_hash: String, transactions: Vec<Transaction>) -> Self {
pub fn new(index: u32, previous_hash: String, transactions: Vec<Transaction>, block_producer: String, metadata: Value) -> Self {
let timestamp = Utc::now().timestamp();
let state_root = Self::calculate_state_root(&transactions);
let mut block = Block {
index,
previous_hash,
timestamp,
transactions,
nonce: 0,
block_hash: String::new(),
state_root,
block_producer,
metadata,
};
block.block_hash = block.calculate_hash();
block
}

fn calculate_state_root(transactions: &Vec<Transaction>) -> String {
// Placeholder implementation, should calculate the state root based on the transactions
let state_data: String = transactions.iter().map(|tx| tx.tx_hash.clone()).collect();
sha256(&state_data)
}

pub fn calculate_hash(&self) -> String {
let transactions_data: String = self.transactions.iter().map(|tx| tx.tx_hash.clone()).collect();
sha256(&format!("{}{}{}{}{}", self.index, self.previous_hash, self.timestamp, transactions_data, self.nonce))
let data = format!(
"{}{}{}{}{}{}{}",
self.index,
self.previous_hash,
self.timestamp,
transactions_data,
self.nonce,
self.state_root,
self.block_producer
);
sha256(&data)
}

pub fn mine_block(&mut self, difficulty: usize) {
Expand Down
20 changes: 18 additions & 2 deletions jam/src/blockchain.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::block::Block;
use crate::transaction::Transaction;
use serde_json::json;
use chrono::Utc;

pub struct Blockchain {
pub chain: Vec<Block>,
Expand All @@ -20,7 +22,11 @@ impl Blockchain {

fn create_genesis_block(&mut self) {
let genesis_transaction = Transaction::new("system".to_string(), "genesis".to_string(), 0.0, 0);
let genesis_block = Block::new(0, "0".to_string(), vec![genesis_transaction]);
let metadata = json!({
"description": "Genesis block",
"timestamp": Utc::now().to_rfc3339(),
});
let genesis_block = Block::new(0, "0".to_string(), vec![genesis_transaction], "genesis_producer".to_string(), metadata);
self.chain.push(genesis_block);
}

Expand All @@ -34,7 +40,17 @@ impl Blockchain {

pub fn mine_pending_transactions(&mut self, miner_address: String) {
let latest_block = self.get_latest_block();
let mut new_block = Block::new(latest_block.index + 1, latest_block.block_hash.clone(), self.pending_transactions.clone());
let metadata = json!({
"miner": miner_address.clone(),
"timestamp": Utc::now().to_rfc3339(),
});
let mut new_block = Block::new(
latest_block.index + 1,
latest_block.block_hash.clone(),
self.pending_transactions.clone(),
miner_address.clone(),
metadata
);
new_block.mine_block(self.difficulty);
self.chain.push(new_block);
self.pending_transactions = vec![Transaction::new("system".to_string(), miner_address, 1.0, 0)];
Expand Down
26 changes: 22 additions & 4 deletions jam/tests/block.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,46 @@
#[cfg(test)]
mod tests {
use jam::block::Block;
use super::*;
use jam::transaction::Transaction;
use jam::block::Block;
use serde_json::json;
use chrono::Utc;

#[test]
fn test_new_block() {
let transactions = vec![Transaction::new("Alice".to_string(), "Bob".to_string(), 10.0, 1)];
let block = Block::new(1, "0".to_string(), transactions.clone());
let metadata = json!({
"miner": "Miner1",
"timestamp": Utc::now().to_rfc3339(),
});
let block = Block::new(1, "0".to_string(), transactions.clone(), "Miner1".to_string(), metadata.clone());
assert_eq!(block.index, 1);
assert_eq!(block.previous_hash, "0".to_string());
// assert_eq!(block.transactions, transactions);
assert_eq!(block.block_producer, "Miner1");
assert_eq!(block.metadata, metadata);
}

#[test]
fn test_calculate_hash() {
let transactions = vec![Transaction::new("Alice".to_string(), "Bob".to_string(), 10.0, 1)];
let block = Block::new(1, "0".to_string(), transactions.clone());
let metadata = json!({
"miner": "Miner1",
"timestamp": Utc::now().to_rfc3339(),
});
let block = Block::new(1, "0".to_string(), transactions.clone(), "Miner1".to_string(), metadata);
let expected_hash = block.calculate_hash();
assert_eq!(block.block_hash, expected_hash);
}

#[test]
fn test_mine_block() {
let transactions = vec![Transaction::new("Alice".to_string(), "Bob".to_string(), 10.0, 1)];
let mut block = Block::new(1, "0".to_string(), transactions.clone());
let metadata = json!({
"miner": "Miner1",
"timestamp": Utc::now().to_rfc3339(),
});
let mut block = Block::new(1, "0".to_string(), transactions.clone(), "Miner1".to_string(), metadata);
block.mine_block(2);
assert!(block.block_hash.starts_with("00"));
}
Expand Down
23 changes: 15 additions & 8 deletions jam/tests/blockchain.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
#[cfg(test)]
mod tests {
use jam::blockchain::Blockchain;
use super::*;
use jam::transaction::Transaction;
use jam::blockchain::Blockchain;
// use serde_json::json;

#[test]
fn test_create_genesis_block() {
let mut blockchain = Blockchain::new(2);
let blockchain = Blockchain::new(2);
assert_eq!(blockchain.chain.len(), 1);
assert_eq!(blockchain.chain[0].index, 0);
assert_eq!(blockchain.chain[0].transactions.len(), 1);
assert_eq!(blockchain.chain[0].transactions[0].sender, "system");
assert_eq!(blockchain.chain[0].transactions[0].receiver, "genesis");
assert_eq!(blockchain.chain[0].transactions[0].amount, 0.0);
let genesis_block = &blockchain.chain[0];
assert_eq!(genesis_block.index, 0);
assert_eq!(genesis_block.transactions.len(), 1);
assert_eq!(genesis_block.transactions[0].sender, "system");
assert_eq!(genesis_block.transactions[0].receiver, "genesis");
assert_eq!(genesis_block.transactions[0].amount, 0.0);
assert_eq!(genesis_block.block_producer, "genesis_producer");
assert_eq!(genesis_block.metadata["description"], "Genesis block");
}

#[test]
Expand All @@ -20,7 +25,6 @@ mod tests {
let transaction = Transaction::new("Alice".to_string(), "Bob".to_string(), 10.0, 1);
blockchain.add_transaction(transaction.clone());
assert_eq!(blockchain.pending_transactions.len(), 1);
// TODO fix
// assert_eq!(blockchain.pending_transactions[0], transaction);
}

Expand All @@ -32,6 +36,9 @@ mod tests {
assert_eq!(blockchain.chain.len(), 2);
assert_eq!(blockchain.pending_transactions.len(), 1);
assert_eq!(blockchain.pending_transactions[0].receiver, "Miner1");
let new_block = &blockchain.chain[1];
assert_eq!(new_block.block_producer, "Miner1");
assert!(new_block.metadata["timestamp"].is_string());
}

#[test]
Expand Down

0 comments on commit 6a79d2a

Please sign in to comment.