Skip to content
Snippets Groups Projects

WIP: Resolve "Add block checking (checking all rules of the unit protocol)"

Files
3
@@ -23,40 +23,222 @@ use dubp_documents::*;
@@ -23,40 +23,222 @@ use dubp_documents::*;
use dup_crypto::keys::PubKey;
use dup_crypto::keys::PubKey;
use durs_blockchain_dal::*;
use durs_blockchain_dal::*;
use durs_wot::*;
use durs_wot::*;
 
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::HashMap;
#[derive(Debug, Copy, Clone)]
#[derive(Fail, Debug, Copy, Clone)]
 
pub enum InvalidRuleError {
 
#[fail(display = "BR_G99: different currency")]
 
DifferentCurrency,
 
#[fail(display = "BR_G03: wrong previous issuer")]
 
WrongPreviousIssuer,
 
#[fail(display = "BR_G100: issuer is not a member")]
 
NotMemberIssuer,
 
#[fail(display = "BR_G04: wrong issuers count")]
 
WrongIssuersCount,
 
#[fail(display = "BR_G05: genesis: issuers frame must be 1")]
 
WrongIssuersFrame,
 
}
 
 
#[derive(Fail, Debug, Copy, Clone)]
pub enum InvalidBlockError {
pub enum InvalidBlockError {
 
#[fail(display = "Error: not found previous block")]
NoPreviousBlock,
NoPreviousBlock,
 
#[fail(display = "Error: version decrease in new block")]
VersionDecrease,
VersionDecrease,
 
#[fail(display = "Error at {}", _0)]
 
InvalidRule(InvalidRuleError),
 
}
 
 
#[inline]
 
fn invalid_rule_error(error: InvalidRuleError) -> BlockError {
 
BlockError::InvalidBlock(InvalidBlockError::InvalidRule(error))
 
}
 
 
pub fn verify_genesis_block_validity(block: &BlockDocument) -> Result<(), BlockError> {
 
// BR_G03 - previous issuer
 
if block.previous_issuer != None {
 
return Err(invalid_rule_error(InvalidRuleError::WrongPreviousIssuer));
 
}
 
 
// BR_G04 - issuers count
 
if block.issuers_count != 0 {
 
return Err(invalid_rule_error(InvalidRuleError::WrongIssuersCount));
 
}
 
 
// BR_G05 - issuers count
 
if block.issuers_frame != 1 {
 
return Err(invalid_rule_error(InvalidRuleError::WrongIssuersFrame));
 
}
 
 
Ok(())
}
}
pub fn verify_block_validity<W: WebOfTrust>(
pub fn verify_block_validity<W: WebOfTrust>(
block: &BlockDocument,
block: &BlockDocument,
blockchain_db: &BinDB<LocalBlockchainV10Datas>,
blockchain_db: &BinDB<LocalBlockchainV10Datas>,
 
identities_db: &BinDB<IdentitiesV10Datas>,
_certs_db: &BinDB<CertsExpirV10Datas>,
_certs_db: &BinDB<CertsExpirV10Datas>,
_wot_index: &HashMap<PubKey, NodeId>,
_wot_index: &HashMap<PubKey, NodeId>,
_wot_db: &BinDB<W>,
_wot_db: &BinDB<W>,
) -> Result<(), BlockError> {
) -> Result<(), BlockError> {
// Rules that do not concern genesis block
// Get previous block
if block.number.0 > 0 {
let previous_block_opt = readers::block::get_block_in_local_blockchain(
// Get previous block
blockchain_db,
let previous_block_opt = readers::block::get_block_in_local_blockchain(
BlockNumber(block.number.0 - 1),
blockchain_db,
)?;
BlockNumber(block.number.0 - 1),
)?;
// Previous block must exist
if previous_block_opt.is_none() {
// Previous block must exist
return Err(BlockError::InvalidBlock(InvalidBlockError::NoPreviousBlock));
if previous_block_opt.is_none() {
}
return Err(BlockError::InvalidBlock(InvalidBlockError::NoPreviousBlock));
let previous_block = previous_block_opt.expect("safe unwrap");
}
let previous_block = previous_block_opt.expect("safe unwrap");
// Block version must not decrease
if previous_block.version > block.version {
// Block version must not decrease
return Err(BlockError::InvalidBlock(InvalidBlockError::VersionDecrease));
if previous_block.version > block.version {
}
return Err(BlockError::InvalidBlock(InvalidBlockError::VersionDecrease));
}
// BR_G99 - same currency
 
if previous_block.currency != block.currency {
 
return Err(invalid_rule_error(InvalidRuleError::DifferentCurrency));
 
}
 
 
// BR_G03 - previous issuer
 
if Some(previous_block.issuers[0]) != block.previous_issuer {
 
return Err(invalid_rule_error(InvalidRuleError::WrongPreviousIssuer));
 
}
 
 
// BR_G100 - issuer is member
 
match readers::identity::get_identity(identities_db, &block.issuers[0])?
 
.expect("safe unwrap")
 
.state
 
{
 
entities::identity::DALIdentityState::Member(_) => {}
 
_ => return Err(invalid_rule_error(InvalidRuleError::NotMemberIssuer)),
 
}
 
 
// BR_G04 - issuers count
 
let issuers_frame = readers::block::get_current_frame(
 
&entities::block::DALBlock {
 
block: block.clone(),
 
expire_certs: None,
 
},
 
blockchain_db,
 
)?;
 
if issuers_frame.len() != block.issuers_count {
 
return Err(invalid_rule_error(InvalidRuleError::WrongIssuersCount));
 
}
 
 
//BR_G05 - issuers frame
 
if block.issuers_frame
 
!= previous_block.issuers_frame
 
+ match previous_block.issuers_frame_var.cmp(&0) {
 
Ordering::Less => -1,
 
Ordering::Greater => 1,
 
Ordering::Equal => 0,
 
}
 
{
 
return Err(invalid_rule_error(InvalidRuleError::WrongIssuersFrame));
}
}
Ok(())
Ok(())
}
}
 
 
#[cfg(test)]
 
mod tests {
 
use super::*;
 
use dubp_documents_tests_tools::mocks::*;
 
use dup_crypto_tests_tools::mocks::*;
 
use durs_blockchain_dal::entities::block::DALBlock;
 
use durs_blockchain_dal::entities::identity::*;
 
 
#[test]
 
fn test_verify_blocks() {
 
let blocks_dbs = BlocksV10DBs::open(None);
 
let wot_dbs = WotsV10DBs::open(None);
 
let wot_index: HashMap<PubKey, NodeId> = HashMap::new();
 
 
let idty_a = identity::gen_mock_idty(pubkey('A'), BlockNumber(0));
 
let pubkey_a = idty_a.issuers()[0];
 
 
let idty_b = identity::gen_mock_idty(pubkey('B'), BlockNumber(0));
 
let pubkey_b = idty_b.issuers()[0];
 
 
let mut blocks = gen_empty_timed_blocks(2, 300);
 
 
// Valid block 0
 
blocks[0].issuers_frame = 1;
 
blocks[0].issuers.push(pubkey_a);
 
blocks[0].identities.push(idty_a.clone());
 
blocks[0].identities.push(idty_b.clone());
 
 
verify_genesis_block_validity(&blocks[0]).expect("Fail to valid genesis block");
 
 
blocks_dbs
 
.blockchain_db
 
.write(|db| {
 
db.insert(
 
blocks[0].number,
 
DALBlock {
 
block: blocks[0].clone(),
 
expire_certs: None,
 
},
 
);
 
})
 
.expect("Fail write to blockchain db");
 
 
wot_dbs
 
.identities_db
 
.write(|db| {
 
db.insert(
 
pubkey_a,
 
DALIdentity {
 
hash: String::new(),
 
state: DALIdentityState::Member(vec![]),
 
joined_on: blocks[0].blockstamp(),
 
expired_on: None,
 
revoked_on: None,
 
idty_doc: idty_a,
 
wot_id: NodeId(0),
 
ms_created_block_id: blocks[0].number,
 
ms_chainable_on: vec![0],
 
cert_chainable_on: vec![0],
 
},
 
);
 
db.insert(
 
pubkey_b,
 
DALIdentity {
 
hash: String::new(),
 
state: DALIdentityState::Member(vec![]),
 
joined_on: blocks[0].blockstamp(),
 
expired_on: None,
 
revoked_on: None,
 
idty_doc: idty_b,
 
wot_id: NodeId(1),
 
ms_created_block_id: blocks[0].number,
 
ms_chainable_on: vec![0],
 
cert_chainable_on: vec![0],
 
},
 
);
 
})
 
.expect("Fail write to idty db");
 
 
// Valid block 1
 
blocks[1].issuers_count = 1;
 
blocks[1].issuers_frame = 1;
 
blocks[1].issuers_frame_var = 5;
 
blocks[1].issuers.push(pubkey_b);
 
blocks[1].previous_issuer = Some(pubkey_a);
 
 
verify_block_validity(
 
&blocks[1],
 
&blocks_dbs.blockchain_db,
 
&wot_dbs.identities_db,
 
&wot_dbs.certs_db,
 
&wot_index,
 
&wot_dbs.wot_db,
 
)
 
.expect("Fail to valid block");
 
}
 
}
Loading