Skip to content
Snippets Groups Projects
Commit d63807b6 authored by Éloïs's avatar Éloïs
Browse files

wip: #76

parent 23233c41
No related branches found
No related tags found
1 merge request!63Resolve "Migrate SQLite to rustbreak"
Showing
with 1319 additions and 1144 deletions
cyclomatic-complexity-threshold = 35
too-many-arguments-threshold = 10
\ No newline at end of file
#[derive(Debug, Copy, Clone)]
pub struct CurrencyParametersV10 {
pub c: f64,
pub dt: i64,
pub ud0: i64,
pub sig_period: u64,
pub sig_stock: i64,
pub sig_window: i64,
pub sig_validity: i64,
pub sig_qty: i64,
pub idty_window: i64,
pub ms_window: i64,
pub x_percent: f64,
pub ms_validity: u64,
pub step_max: u32,
pub median_time_blocks: i64,
pub avg_gen_time: i64,
pub dt_diff_eval: i64,
pub percent_rot: f64,
pub ud_time0: i64,
pub ud_reeval_time0: i64,
pub dt_reeval: i64,
}
pub static G1_PARAMS: &'static CurrencyParametersV10 = &CurrencyParametersV10 {
c: 0.0488,
dt: 86_400,
ud0: 1_000,
sig_period: 432_000,
sig_stock: 100,
sig_window: 5_259_600,
sig_validity: 63_115_200,
sig_qty: 5,
idty_window: 5_259_600,
ms_window: 5_259_600,
x_percent: 0.8,
ms_validity: 31_557_600,
step_max: 5,
median_time_blocks: 24,
avg_gen_time: 300,
dt_diff_eval: 12,
percent_rot: 0.67,
ud_time0: 1_488_970_800,
ud_reeval_time0: 1_490_094_000,
dt_reeval: 15_778_800,
};
pub static G1_CONNECTIVITY_MAX: &'static usize = &125;
pub static MAX_FORKS: &'static usize = &50;
pub static DEFAULT_SIG_RENEW_PERIOD: &'static u64 = &5_259_600;
pub static DEFAULT_MS_PERIOD: &'static u64 = &5_259_600;
pub static DEFAULT_TX_WINDOW: &'static u64 = &604_800;
pub static MAX_FORKS: &'static usize = &100;
use constants::*;
use duniter_documents::blockchain::v10::documents::block::{BlockV10Parameters, CurrencyName};
use *;
#[derive(Debug, Copy, Clone)]
pub struct CurrencyParameters {
pub protocol_version: usize,
pub c: f64,
pub dt: u64,
pub ud0: usize,
pub sig_period: u64,
pub sig_renew_period: u64,
pub sig_stock: usize,
pub sig_window: u64,
pub sig_validity: u64,
pub sig_qty: usize,
pub idty_window: u64,
pub ms_window: u64,
pub tx_window: u64,
pub x_percent: f64,
pub ms_validity: u64,
pub ms_period: u64,
pub step_max: usize,
pub median_time_blocks: usize,
pub avg_gen_time: u64,
pub dt_diff_eval: usize,
pub percent_rot: f64,
pub ud_time0: u64,
pub ud_reeval_time0: u64,
pub dt_reeval: u64,
}
impl From<(CurrencyName, BlockV10Parameters)> for CurrencyParameters {
fn from(source: (CurrencyName, BlockV10Parameters)) -> CurrencyParameters {
let (currency_name, block_params) = source;
let sig_renew_period = match currency_name.0.as_str() {
"default_currency" => *DEFAULT_SIG_RENEW_PERIOD,
"g1" => 5_259_600,
"g1-test" => 5_259_600 / 5,
_ => *DEFAULT_SIG_RENEW_PERIOD,
};
let ms_period = match currency_name.0.as_str() {
"default_currency" => *DEFAULT_MS_PERIOD,
"g1" => 5_259_600,
"g1-test" => 5_259_600 / 5,
_ => *DEFAULT_MS_PERIOD,
};
let tx_window = match currency_name.0.as_str() {
"default_currency" => *DEFAULT_TX_WINDOW,
"g1" => 604_800,
"g1-test" => 604_800,
_ => *DEFAULT_TX_WINDOW,
};
CurrencyParameters {
protocol_version: 10,
c: block_params.c,
dt: block_params.dt,
ud0: block_params.ud0,
sig_period: block_params.sig_period,
sig_renew_period,
sig_stock: block_params.sig_stock,
sig_window: block_params.sig_window,
sig_validity: block_params.sig_validity,
sig_qty: block_params.sig_qty,
idty_window: block_params.idty_window,
ms_window: block_params.ms_window,
tx_window,
x_percent: block_params.x_percent,
ms_validity: block_params.ms_validity,
ms_period,
step_max: block_params.step_max,
median_time_blocks: block_params.median_time_blocks,
avg_gen_time: block_params.avg_gen_time,
dt_diff_eval: block_params.dt_diff_eval,
percent_rot: block_params.percent_rot,
ud_time0: block_params.ud_time0,
ud_reeval_time0: block_params.ud_reeval_time0,
dt_reeval: block_params.dt_reeval,
}
}
}
impl Default for CurrencyParameters {
fn default() -> CurrencyParameters {
CurrencyParameters::from((
CurrencyName(String::from("default_currency")),
BlockV10Parameters::default(),
))
}
}
impl CurrencyParameters {
/// Get max value of connectivity (=1/x_percent)
pub fn max_connectivity(&self) -> f64 {
1.0 / self.x_percent
}
}
/// Get currency parameters
pub fn get_currency_params(
blockchain_db: &BinFileDB<LocalBlockchainV10Datas>,
) -> Result<Option<CurrencyParameters>, DALError> {
Ok(blockchain_db.read(|db| {
if let Some(genesis_block) = db.get(&BlockId(0)) {
if genesis_block.block.parameters.is_some() {
Some(CurrencyParameters::from((
genesis_block.block.currency.clone(),
genesis_block.block.parameters.expect("safe unwrap"),
)))
} else {
panic!("The genesis block are None parameters !");
}
} else {
None
}
})?)
}
extern crate duniter_documents;
extern crate serde;
use self::duniter_documents::blockchain::v10::documents::BlockDocument;
use self::duniter_documents::blockchain::BlockchainProtocol;
use duniter_documents::blockchain::v10::documents::BlockDocument;
use duniter_documents::blockchain::BlockchainProtocol;
use duniter_documents::Blockstamp;
#[derive(Debug, Clone)]
pub enum DALEvent {
StackUpValidBlock(Box<BlockDocument>),
StackUpValidBlock(Box<BlockDocument>, Blockstamp),
RevertBlocks(Vec<Box<BlockDocument>>),
NewValidPendingDoc(BlockchainProtocol),
RefusedPendingDoc(BlockchainProtocol),
......
extern crate duniter_crypto;
extern crate duniter_documents;
extern crate duniter_module;
extern crate serde;
use self::duniter_crypto::keys::*;
use self::duniter_documents::blockchain::v10::documents::{
use self::duniter_module::ModuleReqFullId;
use duniter_crypto::keys::*;
use duniter_documents::blockchain::v10::documents::{
BlockDocument, CertificationDocument, IdentityDocument, MembershipDocument, RevocationDocument,
};
use self::duniter_documents::Hash;
use self::duniter_module::ModuleReqFullId;
use duniter_documents::{Blockstamp, Hash};
use std::collections::HashMap;
#[derive(Debug, Copy, Clone)]
......@@ -50,7 +48,7 @@ pub enum DALResPendings {
#[derive(Debug, Clone)]
pub enum DALResBlockchain {
CurrentBlock(ModuleReqFullId, Box<BlockDocument>),
CurrentBlock(ModuleReqFullId, Box<BlockDocument>, Blockstamp),
BlockByNumber(ModuleReqFullId, Box<BlockDocument>),
Chunk(ModuleReqFullId, Vec<BlockDocument>),
UIDs(HashMap<PubKey, Option<String>>),
......
extern crate crypto;
extern crate duniter_crypto;
extern crate sqlite;
use std::time::Duration;
use self::crypto::digest::Digest;
use self::crypto::sha2::Sha256;
use self::duniter_crypto::keys::*;
use super::DuniterDB;
use super::WriteToDuniterDB;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum DALEndpointApi {
WS2P,
//WS2PS,
//WS2PTOR,
//DASA,
//BMA,
//BMAS,
}
impl From<u32> for DALEndpointApi {
fn from(integer: u32) -> Self {
match integer {
_ => DALEndpointApi::WS2P,
}
}
}
pub fn string_to_api(api: &str) -> Option<DALEndpointApi> {
match api {
"WS2P" => Some(DALEndpointApi::WS2P),
//"WS2PS" => Some(DALEndpointApi::WS2PS),
//"WS2PTOR" => Some(DALEndpointApi::WS2PTOR),
//"DASA" => Some(DALEndpointApi::DASA),
//"BASIC_MERKLED_API" => Some(DALEndpointApi::BMA),
//"BMAS" => Some(DALEndpointApi::BMAS),
&_ => None,
}
}
pub fn api_to_integer(api: &DALEndpointApi) -> i64 {
match *api {
DALEndpointApi::WS2P => 0,
//DALEndpointApi::WS2PS => 1,
//DALEndpointApi::WS2PTOR => 2,
//DALEndpointApi::DASA => 3,
//DALEndpointApi::BMA => 4,
//DALEndpointApi::BMAS => 5,
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DALEndpoint {
pub hash_full_id: String,
pub status: u32,
pub node_id: u32,
pub pubkey: PubKey,
pub api: DALEndpointApi,
pub version: usize,
pub endpoint: String,
pub last_check: u64,
}
impl DALEndpoint {
pub fn new(
status: u32,
node_id: u32,
pubkey: PubKey,
api: DALEndpointApi,
version: usize,
endpoint: String,
last_check: Duration,
) -> DALEndpoint {
let mut sha = Sha256::new();
sha.input_str(&format!(
"{}{}{}{}",
node_id,
pubkey,
api_to_integer(&api),
version
));
DALEndpoint {
hash_full_id: sha.result_str(),
status,
node_id,
pubkey,
api,
version,
endpoint,
last_check: last_check.as_secs(),
}
}
pub fn get_endpoints_for_api(db: &DuniterDB, api: DALEndpointApi) -> Vec<DALEndpoint> {
let mut cursor:sqlite::Cursor = db.0
.prepare("SELECT hash_full_id, status, node_id, pubkey, api, version, endpoint, last_check FROM endpoints WHERE api=? ORDER BY status DESC;")
.expect("get_endpoints_for_api() : Error in SQL request !")
.cursor();
cursor
.bind(&[sqlite::Value::Integer(api_to_integer(&api))])
.expect("get_endpoints_for_api() : Error in cursor binding !");
let mut endpoints = Vec::new();
while let Some(row) = cursor
.next()
.expect("get_endpoints_for_api() : Error in cursor.next()")
{
endpoints.push(DALEndpoint {
hash_full_id: row[0].as_string().unwrap().to_string(),
status: row[1].as_integer().unwrap() as u32,
node_id: row[2].as_integer().unwrap() as u32,
pubkey: PubKey::Ed25519(ed25519::PublicKey::from_base58(row[3].as_string().unwrap()).unwrap()),
api: DALEndpointApi::from(row[4].as_integer().unwrap() as u32),
version: row[5].as_integer().unwrap() as usize,
endpoint: row[6].as_string().unwrap().to_string(),
last_check: row[7].as_integer().unwrap() as u64,
});
}
endpoints
}
}
impl WriteToDuniterDB for DALEndpoint {
fn write(
&self,
db: &DuniterDB,
_written_blockstamp: super::block_v10::BlockStampV10,
_written_timestamp: u64,
) {
// Check if endpoint it's already written
let mut cursor: sqlite::Cursor = db.0
.prepare("SELECT status FROM endpoints WHERE hash_full_id=? ORDER BY status DESC;")
.expect("get_endpoints_for_api() : Error in SQL request !")
.cursor();
cursor
.bind(&[sqlite::Value::String(self.hash_full_id.clone())])
.expect("get_endpoints_for_api() : Error in cursor binding !");
// If endpoint it's already written, update status
if let Some(row) = cursor
.next()
.expect("get_endpoints_for_api() : Error in cursor.next()")
{
if row[0].as_integer().unwrap() as u32 != self.status {
db.0
.execute(format!(
"UPDATE endpoints SET status={} WHERE hash_full_id='{}'",
self.status, self.hash_full_id
))
.unwrap();
}
} else {
db.0
.execute(
format!(
"INSERT INTO endpoints (hash_full_id, status, node_id, pubkey, api, version, endpoint, last_check) VALUES ('{}', {}, {}, '{}', {}, {}, '{}', {});",
self.hash_full_id, self.status, self.node_id, self.pubkey.to_string(),
api_to_integer(&self.api), self.version, self.endpoint, self.last_check
)
)
.unwrap();
}
}
}
This diff is collapsed.
This diff is collapsed.
extern crate serde;
extern crate serde_json;
extern crate sqlite;
use super::super::block::DALBlock;
use super::super::identity::DALIdentity;
use super::super::DuniterDB;
use duniter_crypto::keys::*;
use duniter_documents::blockchain::v10::documents::certification::{
CertificationDocumentBuilder, CompactCertificationDocument,
};
use duniter_documents::blockchain::v10::documents::{
CertificationDocument, IdentityDocument, TextDocumentFormat,
};
use duniter_documents::blockchain::{Document, DocumentBuilder};
use duniter_documents::{BlockHash, BlockId, Blockstamp, Hash};
use std::collections::HashMap;
use duniter_documents::blockchain::v10::documents::certification::CompactCertificationDocument;
use duniter_documents::blockchain::v10::documents::{CertificationDocument, TextDocumentFormat};
use duniter_documents::BlockId;
pub fn parse_certifications_into_compact(
json_certs: &[serde_json::Value],
......@@ -50,94 +40,3 @@ pub fn parse_certifications_into_compact(
}
certifications
}
pub fn parse_certifications_from_json_value(
currency: &str,
db: &DuniterDB,
block_identities: &HashMap<PubKey, IdentityDocument>,
array_certifications: &[serde_json::Value],
) -> Vec<TextDocumentFormat<CertificationDocument>> {
let mut certifications: Vec<TextDocumentFormat<CertificationDocument>> = Vec::new();
for certification in array_certifications.iter() {
let certification_datas: Vec<&str> = certification
.as_str()
.expect("Fail to parse certs : json isn't str !")
.split(':')
.collect();
if certification_datas.len() == 4 {
let target = PubKey::Ed25519(
ed25519::PublicKey::from_base58(certification_datas[1])
.expect("Fail to parse cert target !"),
);
let target_idty_doc: IdentityDocument = match block_identities.get(&target) {
Some(idty_doc) => idty_doc.clone(),
None => {
let dal_idty = DALIdentity::get_identity(currency, db, &target)
.expect("target identity not found in bdd !");
dal_idty.idty_doc
}
};
let cert_blockstamp_id = BlockId(
certification_datas[2]
.parse()
.expect("Fail to parse cert blockstamp !"),
);
let cert_builder =
CertificationDocumentBuilder {
currency,
issuer: &PubKey::Ed25519(
ed25519::PublicKey::from_base58(certification_datas[0])
.expect("Fail to parse cert issuer !"),
),
blockstamp: &Blockstamp {
id: cert_blockstamp_id,
hash: if cert_blockstamp_id == BlockId(0) {
BlockHash(Hash::from_hex(
"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
).expect("Fail to parse cert : invalid genesis hash"))
} else {
DALBlock::get_block_hash(db, &cert_blockstamp_id).expect(&format!(
"Fatal Error : Block {} not found in bdd !",
cert_blockstamp_id
))
},
},
target: &target,
identity_username: target_idty_doc.username(),
identity_blockstamp: &target_idty_doc.blockstamp(),
identity_sig: &target_idty_doc.signatures()[0],
};
let cert_sig = Sig::Ed25519(
ed25519::Signature::from_base64(certification_datas[3])
.expect("Fail to parse cert sig !"),
);
certifications.push(TextDocumentFormat::Complete(
cert_builder.build_with_signature(vec![cert_sig]),
));
}
}
certifications
}
pub fn parse_certifications(
currency: &str,
db: &DuniterDB,
block_identities: &HashMap<PubKey, IdentityDocument>,
json_datas: &str,
) -> Option<Vec<TextDocumentFormat<CertificationDocument>>> {
let raw_certifications: serde_json::Value =
serde_json::from_str(json_datas).expect("Fail to parse certs: str isn't json !");
if raw_certifications.is_array() {
Some(parse_certifications_from_json_value(
currency,
db,
block_identities,
raw_certifications
.as_array()
.expect("Fail to parse certs: json datas must be an array !"),
))
} else {
None
}
}
pub mod blocks;
// Copyright (C) 2018 The Duniter Project Developers.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pub mod certifications;
pub mod excluded;
pub mod identities;
pub mod memberships;
pub mod revoked;
pub mod transactions;
#[cfg(test)]
mod tests {
use super::transactions::*;
use duniter_crypto::keys::*;
use duniter_documents::blockchain::v10::documents::transaction::*;
use duniter_documents::blockchain::DocumentBuilder;
use duniter_documents::Blockstamp;
#[test]
fn parse_json_tx() {
let tx_json = json!({
"version": 10,
"currency": "g1",
"locktime": 0,
"hash": "3424206EF64C69E5F8C3906AAE571E378A498FCDAE0B85E9405A5205D7148EFE",
"blockstamp": "112533-000002150F2E805E604D9B31212D079570AAD8D3A4D8BB75F2C15A94A345B6B1",
"blockstampTime": 0,
"issuers": [
"51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2"
],
"inputs": [
"1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496"
],
"outputs": [
"1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)"
],
"unlocks": [
"0:SIG(0)"
],
"signatures": [
"5olrjFylTCsVq8I5Yr7FpXeviynICyvIwe1yG5N0RJF+VZb+bCFBnLAMpmMCU2qzUvK7z41UXOrMRybXiLa2Dw=="
],
"comment": "Merci pour la calligraphie ;) de Liam"
});
let tx_builder = TransactionDocumentBuilder {
currency: "g1",
blockstamp: &Blockstamp::from_string(
"112533-000002150F2E805E604D9B31212D079570AAD8D3A4D8BB75F2C15A94A345B6B1",
).unwrap(),
locktime: &0,
issuers: &vec![PubKey::Ed25519(
ed25519::PublicKey::from_base58("51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2")
.unwrap(),
)],
inputs: &vec![
TransactionInput::parse_from_str(
"1000:0:D:51EFVNZwpfmTXU7BSLpeh3PZFgfdmm5hq5MzCDopdH2:46496",
).unwrap(),
],
outputs: &vec![
TransactionOutput::parse_from_str(
"1000:0:SIG(2yN8BRSkARcqE8NCxKMBiHfTpx1EvwULFn56Myf6qRmy)",
).unwrap(),
],
unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()],
comment: "Merci pour la calligraphie ;) de Liam",
};
assert_eq!(
parse_transaction("g1", &tx_json).expect("Fail to parse transaction !"),
tx_builder.build_with_signature(vec![Sig::Ed25519(ed25519::Signature::from_base64("5olrjFylTCsVq8I5Yr7FpXeviynICyvIwe1yG5N0RJF+VZb+bCFBnLAMpmMCU2qzUvK7z41UXOrMRybXiLa2Dw==").unwrap())])
);
}
#[test]
fn parse_json_tx2() {
let tx_json = json!({
"version": 10,
"currency": "g1",
"locktime": 0,
"hash": "F98BF7A8BF82E76F5B69E70CEF0A07A08BFDB03561955EC57B254DB1E958529C",
"blockstamp": "58-00005B9167EBA1E32C6EAD42AE7F72D8F14B765D3C9E47D233B553D47C5AEE0C",
"blockstampTime": 1488990541,
"issuers": [
"FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD"
],
"inputs": [
"1000:0:D:FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD:1"
],
"outputs": [
"3:0:SIG(7vU9BMDhN6fBuRa2iK3JRbC6pqQKb4qDMGsFcQuT5cz)",
"997:0:SIG(FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD)"
],
"unlocks": [
"0:SIG(0)"
],
"signatures": [
"VWbvsiybM4L2X5+o+6lIiuKNw5KrD1yGZqmV+lHtA28XoRUFzochSIgfoUqBsTAaYEHY45vSX917LDXudTEzBg=="
],
"comment": "Un petit cafe ;-)"
});
let tx_builder = TransactionDocumentBuilder {
currency: "g1",
blockstamp: &Blockstamp::from_string(
"58-00005B9167EBA1E32C6EAD42AE7F72D8F14B765D3C9E47D233B553D47C5AEE0C",
).unwrap(),
locktime: &0,
issuers: &vec![PubKey::Ed25519(
ed25519::PublicKey::from_base58("FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD")
.unwrap(),
)],
inputs: &vec![
TransactionInput::parse_from_str(
"1000:0:D:FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD:1",
).unwrap(),
],
outputs: &vec![
TransactionOutput::parse_from_str(
"3:0:SIG(7vU9BMDhN6fBuRa2iK3JRbC6pqQKb4qDMGsFcQuT5cz)",
).unwrap(),
TransactionOutput::parse_from_str(
"997:0:SIG(FVUFRrk1K5TQGsY7PRLwqHgdHRoHrwb1hcucp4C2N5tD)",
).unwrap(),
],
unlocks: &vec![TransactionInputUnlocks::parse_from_str("0:SIG(0)").unwrap()],
comment: "Un petit cafe ;-)",
};
assert_eq!(
parse_transaction("g1", &tx_json).expect("Fail to parse transaction !"),
tx_builder.build_with_signature(vec![Sig::Ed25519(ed25519::Signature::from_base64("VWbvsiybM4L2X5+o+6lIiuKNw5KrD1yGZqmV+lHtA28XoRUFzochSIgfoUqBsTAaYEHY45vSX917LDXudTEzBg==").unwrap())])
);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
pub mod block;
pub mod certification;
pub mod dividend;
pub mod identity;
pub mod requests;
pub mod transaction;
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment