Fixed parsing of DomainData, many other fixes.

This commit is contained in:
Revertron
2021-04-11 17:50:55 +02:00
parent 514c49307a
commit 92209689d6
9 changed files with 112 additions and 41 deletions
+76 -24
View File
@@ -8,7 +8,7 @@ use chrono::Utc;
use log::{debug, error, info, trace, warn};
use sqlite::{Connection, State, Statement};
use crate::{Block, Bytes, Keystore, Transaction, check_domain, get_domain_zone, is_yggdrasil_record};
use crate::{Block, Bytes, Keystore, Transaction, check_domain, get_domain_zone, is_yggdrasil_record, from_hex};
use crate::commons::constants::*;
use crate::blockchain::types::{BlockQuality, MineResult, Options};
use crate::blockchain::types::BlockQuality::*;
@@ -27,6 +27,7 @@ const SQL_ADD_BLOCK: &str = "INSERT INTO blocks (id, timestamp, version, difficu
prev_block_hash, hash, pub_key, signature) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
const SQL_REPLACE_BLOCK: &str = "UPDATE blocks SET timestamp = ?, version = ?, difficulty = ?, random = ?, nonce = ?, 'transaction' = ?,\
prev_block_hash = ?, hash = ?, pub_key = ?, signature = ? WHERE id = ?;";
const SQL_DELETE_FAULTY_BLOCKS: &str = "DELETE FROM blocks WHERE id >= ?;";
const SQL_GET_LAST_BLOCK: &str = "SELECT * FROM blocks ORDER BY id DESC LIMIT 1;";
const SQL_ADD_DOMAIN: &str = "INSERT INTO domains (id, timestamp, identity, confirmation, data, pub_key) VALUES (?, ?, ?, ?, ?, ?)";
const SQL_ADD_ZONE: &str = "INSERT INTO zones (id, timestamp, identity, confirmation, data, pub_key) VALUES (?, ?, ?, ?, ?, ?)";
@@ -73,7 +74,21 @@ impl Chain {
}
// Trying to get last block from DB to check its version
let block: Option<Block> = match self.db.prepare(SQL_GET_LAST_BLOCK) {
// If some block loaded we check its version and determine if we need some migration
if let Some(block) = self.load_last_block() {
// Cache some info
self.last_block = Some(block.clone());
if block.transaction.is_some() {
self.last_full_block = Some(block);
} else {
self.last_full_block = self.get_last_full_block(None);
}
}
self.check_chain();
}
fn load_last_block(&mut self) -> Option<Block> {
match self.db.prepare(SQL_GET_LAST_BLOCK) {
Ok(mut statement) => {
let mut result = None;
while statement.next().unwrap() == State::Row {
@@ -96,16 +111,6 @@ impl Chain {
self.db.execute(SQL_CREATE_TABLES).expect("Error creating DB tables");
None
}
};
// If some block loaded we check its version and determine if we need some migration
if let Some(block) = block {
// Cache some info
self.last_block = Some(block.clone());
if block.transaction.is_some() {
self.last_full_block = Some(block);
} else {
self.last_full_block = self.get_last_full_block(None);
}
}
}
@@ -128,6 +133,30 @@ impl Chain {
let _ = fs::remove_file(&file).is_err();
}
fn check_chain(&mut self) {
let height = self.height();
info!("Local blockchain height is {}", height);
for id in (1..=height).rev() {
info!("Checking block {}", id);
match self.get_block(id) {
None => {}
Some(block) => {
let faulty_block_hash = "0000133B790B61460D757E1F1F2D04480C8340D28CA73AE5AF27DBBF60548D00";
let bytes = Bytes::from_bytes(&from_hex(faulty_block_hash).unwrap());
if block.hash == bytes {
if block.transaction.is_some() {
let _ = self.delete_transaction(block.index);
}
let _ = self.delete_faulty_blocks(id);
}
}
}
}
self.last_block = self.load_last_block();
info!("Last block after chain check: {:?}", &self.last_block);
}
fn get_options(&self) -> Options {
let mut options = Options::empty();
if let Ok(mut statement) = self.db.prepare(SQL_GET_OPTIONS) {
@@ -144,6 +173,13 @@ impl Chain {
options
}
fn delete_faulty_blocks(&mut self, from: u64) -> sqlite::Result<State> {
warn!("Removing block with error {}", from);
let mut statement = self.db.prepare(SQL_DELETE_FAULTY_BLOCKS)?;
statement.bind(1, from as i64)?;
statement.next()
}
pub fn add_block(&mut self, block: Block) {
debug!("Adding block:\n{:?}", &block);
let index = block.index;
@@ -164,13 +200,7 @@ impl Chain {
debug!("Replacing block {} with:\n{:?}", index, &block);
let old_block = self.get_block(index).unwrap();
if old_block.transaction.is_some() {
let mut statement = self.db.prepare(SQL_DELETE_DOMAIN)?;
statement.bind(1, index as i64)?;
statement.next()?;
let mut statement = self.db.prepare(SQL_DELETE_ZONE)?;
statement.bind(1, index as i64)?;
statement.next()?;
let _ = self.delete_transaction(index);
}
let index = block.index;
@@ -188,6 +218,17 @@ impl Chain {
Ok(())
}
fn delete_transaction(&mut self, index: u64) -> sqlite::Result<()> {
let mut statement = self.db.prepare(SQL_DELETE_DOMAIN)?;
statement.bind(1, index as i64)?;
statement.next()?;
let mut statement = self.db.prepare(SQL_DELETE_ZONE)?;
statement.bind(1, index as i64)?;
statement.next()?;
Ok(())
}
/// Adds block to blocks table
fn add_block_to_table(&mut self, block: Block) -> sqlite::Result<State> {
let mut statement = self.db.prepare(SQL_ADD_BLOCK)?;
@@ -447,10 +488,10 @@ impl Chain {
}
let identity = Bytes::from_bytes(&statement.read::<Vec<u8>>(2).unwrap());
let confirmation = Bytes::from_bytes(&statement.read::<Vec<u8>>(3).unwrap());
let method = statement.read::<String>(4).unwrap();
let data = statement.read::<String>(5).unwrap();
let pub_key = Bytes::from_bytes(&statement.read::<Vec<u8>>(6).unwrap());
let transaction = Transaction { identity, confirmation, class: method, data, pub_key };
let class = String::from("domain");
let data = statement.read::<String>(4).unwrap();
let pub_key = Bytes::from_bytes(&statement.read::<Vec<u8>>(5).unwrap());
let transaction = Transaction { identity, confirmation, class, data, pub_key };
debug!("Found transaction for domain {}: {:?}", domain, &transaction);
if transaction.check_identity(domain) {
return Some(transaction);
@@ -556,6 +597,14 @@ impl Chain {
warn!("Block {:?} has wrong signature! Ignoring!", &block);
return Bad;
}
let faulty_block_hash = "0000133B790B61460D757E1F1F2D04480C8340D28CA73AE5AF27DBBF60548D00";
let bytes = Bytes::from_bytes(&from_hex(faulty_block_hash).unwrap());
if block.hash == bytes {
warn!("Block {:?} is faulty! Ignoring!", &block);
return Bad;
}
if let Some(transaction) = &block.transaction {
// TODO check for zone transaction
if !self.is_id_available(&transaction.identity, &block.pub_key, false) || !self.is_id_available(&transaction.identity, &block.pub_key, true) {
@@ -662,7 +711,10 @@ impl Chain {
}
u32::max_value()
}
Err(_) => { u32::max_value() }
Err(_) => {
warn!("Error parsing DomainData from {:?}", transaction);
u32::max_value()
}
}
}
"zone" => { ZONE_DIFFICULTY }
+1 -1
View File
@@ -36,7 +36,7 @@ pub fn hash_identity(identity: &str, key: Option<&Bytes>) -> Bytes {
None => { Bytes::from_bytes(&identity) }
Some(key) => {
let mut buf = Vec::new();
buf.append(&mut identity.clone());
buf.append(&mut base.clone());
buf.append(&mut key.to_vec());
Bytes::from_bytes(&hash_sha256(&buf))
}
+1 -1
View File
@@ -89,7 +89,7 @@ impl Serialize for Transaction {
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct DomainData {
pub domain: Bytes,
pub zone: String,