|
|
|
@ -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 {
|
|
|
|
|