Refactored block and transaction structure. Introduced a 'confirmation' entity to avoid block interceptions (at least make them pointless).

This commit is contained in:
Revertron
2021-02-13 23:37:44 +01:00
parent 279b3e87c3
commit 1331f44b0e
9 changed files with 97 additions and 85 deletions
+5 -8
View File
@@ -17,8 +17,7 @@ use crate::Transaction;
pub struct Block {
pub index: u64,
pub timestamp: i64,
pub chain_name: String,
pub version_flags: u32,
pub version: u32,
pub difficulty: usize,
pub random: u32,
pub nonce: u64,
@@ -31,12 +30,11 @@ pub struct Block {
}
impl Block {
pub fn new(index: u64, timestamp: i64, chain_name: &str, version_flags: u32, prev_block_hash: Bytes, transaction: Option<Transaction>) -> Self {
pub fn new(index: u64, timestamp: i64, version: u32, prev_block_hash: Bytes, transaction: Option<Transaction>) -> Self {
Block {
index,
timestamp,
chain_name: chain_name.to_owned(),
version_flags,
version,
// TODO make difficulty parameter
difficulty: 20,
random: 0,
@@ -47,12 +45,11 @@ impl Block {
}
}
pub fn from_all_params(index: u64, timestamp: i64, chain_name: &str, version_flags: u32, difficulty: usize, random: u32, nonce: u64, prev_block_hash: Bytes, hash: Bytes, transaction: Option<Transaction>) -> Self {
pub fn from_all_params(index: u64, timestamp: i64, version: u32, difficulty: usize, random: u32, nonce: u64, prev_block_hash: Bytes, hash: Bytes, transaction: Option<Transaction>) -> Self {
Block {
index,
timestamp,
chain_name: chain_name.to_owned(),
version_flags,
version,
difficulty,
random,
nonce,
+33 -36
View File
@@ -6,17 +6,17 @@ use crate::{Block, Bytes, Keystore, Transaction};
const DB_NAME: &str = "blockchain.db";
pub struct Blockchain {
pub chain_name: String,
pub version_flags: u32,
origin: String,
pub version: u32,
pub blocks: Vec<Block>,
last_block: Option<Block>,
db: Connection,
}
impl Blockchain {
pub fn new(chain_name: &str, version_flags: u32) -> Self {
pub fn new(origin: String, version: u32) -> Self {
let db = sqlite::open(DB_NAME).expect("Unable to open blockchain DB");
let mut blockchain = Blockchain{ chain_name: chain_name.to_owned(), version_flags, blocks: Vec::new(), last_block: None, db};
let mut blockchain = Blockchain{ origin, version, blocks: Vec::new(), last_block: None, db};
blockchain.init_db();
blockchain
}
@@ -30,12 +30,11 @@ impl Blockchain {
None => { println!("Something wrong with block in DB!"); }
Some(block) => {
println!("Loaded last block: {:?}", &block);
self.chain_name = block.chain_name.clone();
self.version_flags = block.version_flags;
self.version = block.version;
self.last_block = Some(block);
}
}
println!("Loaded from DB: chain_name = {}, version_flags = {}", self.chain_name, self.version_flags);
println!("Blockchain version from DB = {}", self.version);
}
}
Err(_) => {
@@ -44,8 +43,7 @@ impl Blockchain {
CREATE TABLE blocks (
'id' BIGINT,
'timestamp' BIGINT,
'chain_name' TEXT,
'version_flags' TEXT,
'version' TEXT,
'difficulty' INTEGER,
'random' INTEGER,
'nonce' INTEGER,
@@ -54,7 +52,7 @@ impl Blockchain {
'hash' BINARY
);
CREATE INDEX block_index ON blocks (id);
CREATE TABLE transactions (id INTEGER PRIMARY KEY AUTOINCREMENT, identity BINARY, method TEXT, data TEXT, pub_key BINARY, signature BINARY);
CREATE TABLE transactions (id INTEGER PRIMARY KEY AUTOINCREMENT, identity BINARY, confirmation BINARY, method TEXT, data TEXT, pub_key BINARY, signature BINARY);
CREATE INDEX ids ON transactions (identity);"
).expect("Error creating blocks table");
}
@@ -71,24 +69,23 @@ impl Blockchain {
{
// Adding block to DB
let mut statement = self.db.prepare("INSERT INTO blocks (\
id, timestamp, chain_name, version_flags, difficulty,\
random, nonce, 'transaction', prev_block_hash, hash)\
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);").unwrap();
id, timestamp, version, difficulty, random,\
nonce, 'transaction', prev_block_hash, hash)\
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);").unwrap();
statement.bind(1, block.index as i64);
statement.bind(2, block.timestamp as i64);
statement.bind(3, block.chain_name.as_ref() as &str);
statement.bind(4, block.version_flags as i64);
statement.bind(5, block.difficulty as i64);
statement.bind(6, block.random as i64);
statement.bind(7, block.nonce as i64);
statement.bind(3, block.version as i64);
statement.bind(4, block.difficulty as i64);
statement.bind(5, block.random as i64);
statement.bind(6, block.nonce as i64);
match &transaction {
None => { statement.bind(8, ""); }
None => { statement.bind(7, ""); }
Some(transaction) => {
statement.bind(8, transaction.to_string().as_ref() as &str);
statement.bind(7, transaction.to_string().as_ref() as &str);
}
}
statement.bind(9, block.prev_block_hash.as_bytes());
statement.bind(10, block.hash.as_bytes());
statement.bind(8, block.prev_block_hash.as_bytes());
statement.bind(9, block.hash.as_bytes());
statement.next().expect("Error adding block to DB");
}
@@ -104,12 +101,13 @@ impl Blockchain {
}
fn add_transaction(&mut self, t: &Transaction) {
let mut statement = self.db.prepare("INSERT INTO transactions (identity, method, data, pub_key, signature) VALUES (?, ?, ?, ?, ?)").unwrap();
let mut statement = self.db.prepare("INSERT INTO transactions (identity, confirmation, method, data, pub_key, signature) VALUES (?, ?, ?, ?, ?, ?)").unwrap();
statement.bind(1, t.identity.as_bytes());
statement.bind(2, t.method.as_ref() as &str);
statement.bind(3, t.data.as_ref() as &str);
statement.bind(4, t.pub_key.as_bytes());
statement.bind(5, t.signature.as_bytes());
statement.bind(2, t.confirmation.as_bytes());
statement.bind(3, t.method.as_ref() as &str);
statement.bind(4, t.data.as_ref() as &str);
statement.bind(5, t.pub_key.as_bytes());
statement.bind(6, t.signature.as_bytes());
statement.next().expect("Error adding transaction to DB");
}
@@ -212,15 +210,14 @@ impl Blockchain {
fn get_block_from_statement(statement: &mut Statement) -> Option<Block> {
let index = statement.read::<i64>(0).unwrap() as u64;
let timestamp = statement.read::<i64>(1).unwrap();
let chain_name = statement.read::<String>(2).unwrap();
let version_flags = statement.read::<i64>(3).unwrap() as u32;
let difficulty = statement.read::<i64>(4).unwrap() as usize;
let random = statement.read::<i64>(5).unwrap() as u32;
let nonce = statement.read::<i64>(6).unwrap() as u64;
let transaction = Transaction::from_json(&statement.read::<String>(7).unwrap());
let prev_block_hash = Bytes::from_bytes(statement.read::<Vec<u8>>(8).unwrap().as_slice());
let hash = Bytes::from_bytes(statement.read::<Vec<u8>>(9).unwrap().as_slice());
Some(Block::from_all_params(index, timestamp, &chain_name, version_flags, difficulty, random, nonce, prev_block_hash, hash, transaction))
let version = statement.read::<i64>(2).unwrap() as u32;
let difficulty = statement.read::<i64>(3).unwrap() as usize;
let random = statement.read::<i64>(4).unwrap() as u32;
let nonce = statement.read::<i64>(5).unwrap() as u64;
let transaction = Transaction::from_json(&statement.read::<String>(6).unwrap());
let prev_block_hash = Bytes::from_bytes(statement.read::<Vec<u8>>(7).unwrap().as_slice());
let hash = Bytes::from_bytes(statement.read::<Vec<u8>>(8).unwrap().as_slice());
Some(Block::from_all_params(index, timestamp, version, difficulty, random, nonce, prev_block_hash, hash, transaction))
}
pub fn check_block_hash(block: &Block) -> bool {
+19 -7
View File
@@ -12,6 +12,7 @@ use crypto::digest::Digest;
#[derive(Clone, Deserialize, PartialEq)]
pub struct Transaction {
pub identity: Bytes,
pub confirmation: Bytes,
pub method: String,
pub data: String,
pub pub_key: Bytes,
@@ -20,12 +21,13 @@ pub struct Transaction {
impl Transaction {
pub fn from_str(identity: String, method: String, data: String, pub_key: Bytes) -> Self {
let bytes = Self::hash_identity(&identity);
return Self::new(bytes, method, data, pub_key);
let hash = Self::hash_identity(&identity);
let confirmation = Self::hash_with_key(&identity, &pub_key);
return Self::new(hash, confirmation, method, data, pub_key);
}
pub fn new(identity: Bytes, method: String, data: String, pub_key: Bytes) -> Self {
Transaction { identity, method, data, pub_key, signature: Bytes::zero64() }
pub fn new(identity: Bytes, confirmation: Bytes, method: String, data: String, pub_key: Bytes) -> Self {
Transaction { identity, confirmation, method, data, pub_key, signature: Bytes::zero64() }
}
pub fn from_json(json: &str) -> Option<Self> {
@@ -56,12 +58,22 @@ impl Transaction {
digest.result(&mut buf);
Bytes::from_bytes(&buf)
}
pub fn hash_with_key(identity: &str, key: &Bytes) -> Bytes {
let mut buf: [u8; 32] = [0; 32];
let mut digest = Sha256::new();
digest.input_str(identity);
digest.input(key.as_bytes());
digest.result(&mut buf);
Bytes::from_bytes(&buf)
}
}
impl fmt::Debug for Transaction {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Transaction")
.field("identity", &self.identity)
.field("confirmation", &self.confirmation)
.field("method", &self.method)
.field("data", &self.data)
.field("pub", &&self.pub_key)
@@ -71,10 +83,10 @@ impl fmt::Debug for Transaction {
}
impl Serialize for Transaction {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error> where
S: Serializer {
let mut structure = serializer.serialize_struct("Transaction", 3).unwrap();
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error> where S: Serializer {
let mut structure = serializer.serialize_struct("Transaction", 6).unwrap();
structure.serialize_field("identity", &self.identity);
structure.serialize_field("confirmation", &self.confirmation);
structure.serialize_field("method", &self.method);
structure.serialize_field("data", &self.data);
structure.serialize_field("pub_key", &self.pub_key);