diff --git a/lib/modules-lib/bc-db-reader/src/current_metadata.rs b/lib/modules-lib/bc-db-reader/src/current_metadata.rs index 2210838b892a8cdd27d3bad3398cb686e7d14408..4e9ecb888ccb780172fdd0d23750b32fd91dfec7 100644 --- a/lib/modules-lib/bc-db-reader/src/current_metadata.rs +++ b/lib/modules-lib/bc-db-reader/src/current_metadata.rs @@ -15,6 +15,9 @@ //! Current meta datas +pub mod current_ud; + +use self::current_ud::{CurrentUdDb, CurrentUdDbInternal}; use crate::blocks::fork_tree::ForkTree; use crate::constants::*; use crate::*; @@ -38,6 +41,8 @@ pub enum CurrentMetaDataKey { ForkTree, /// Greatest wot id NextWotId, + /// Current Universal Dividend + CurrentUd, } impl CurrentMetaDataKey { @@ -50,6 +55,7 @@ impl CurrentMetaDataKey { Self::CurrentBlockchainTime => 3, Self::ForkTree => 4, Self::NextWotId => 5, + Self::CurrentUd => 6, } } } @@ -155,3 +161,16 @@ pub fn get_greatest_wot_id_<DB: BcDbInReadTx>(db: &DB) -> Result<WotId, DbError> Ok(WotId(0)) } } + +/// Get current UD +pub fn get_current_ud<DB: BcDbInReadTx>(db: &DB) -> Result<Option<CurrentUdDb>, DbError> { + if let Some(v) = db + .db() + .get_int_store(CURRENT_METADATA) + .get(db.r(), CurrentMetaDataKey::CurrentUd.to_u32())? + { + Ok(from_db_value::<CurrentUdDbInternal>(v)?.into()) + } else { + Ok(None) + } +} diff --git a/lib/modules-lib/bc-db-reader/src/current_metadata/current_ud.rs b/lib/modules-lib/bc-db-reader/src/current_metadata/current_ud.rs new file mode 100644 index 0000000000000000000000000000000000000000..6fda114c448f9ceb8355f5c01ef9429668092d99 --- /dev/null +++ b/lib/modules-lib/bc-db-reader/src/current_metadata/current_ud.rs @@ -0,0 +1,63 @@ +// Copyright (C) 2017-2019 The AXIOM TEAM Association. +// +// 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/>. + +//! Define entity CurrentUdDb + +use dubp_block_doc::BlockDocument; +use dubp_common_doc::BlockNumber; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +pub struct CurrentUdDb { + pub amount: usize, + pub base: usize, + pub block_number: BlockNumber, + pub members_count: usize, + pub monetary_mass: usize, + pub common_time: u64, +} + +#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)] +pub struct CurrentUdDbInternal { + current: Option<CurrentUdDb>, + previous: Option<CurrentUdDb>, +} + +impl Into<Option<CurrentUdDb>> for CurrentUdDbInternal { + fn into(self) -> Option<CurrentUdDb> { + self.current + } +} + +impl CurrentUdDbInternal { + pub fn update(&mut self, block_doc: &BlockDocument) { + let BlockDocument::V10(ref block_doc_v10) = block_doc; + if let Some(dividend) = block_doc_v10.dividend { + self.previous = self.current; + self.current = Some(CurrentUdDb { + amount: dividend, + base: block_doc_v10.unit_base, + block_number: block_doc_v10.number, + members_count: block_doc_v10.members_count, + monetary_mass: block_doc_v10.monetary_mass, + common_time: block_doc_v10.median_time, + }) + } + } + pub fn revert(&mut self) { + self.current = self.previous; + self.previous = None; + } +} diff --git a/lib/modules-lib/bc-db-reader/src/traits.rs b/lib/modules-lib/bc-db-reader/src/traits.rs index 26b7ca71e1b3d7fac3960b2c61afa98d4d6a1bd8..06e4ecc773b44eca8017f01af5ae7126516c340e 100644 --- a/lib/modules-lib/bc-db-reader/src/traits.rs +++ b/lib/modules-lib/bc-db-reader/src/traits.rs @@ -17,6 +17,7 @@ // ! Define read only trait use crate::blocks::BlockDb; +use crate::current_metadata::current_ud::CurrentUdDb; use crate::indexes::identities::{IdentityDb, IdentityStateDb}; use crate::{BcDbWithReaderStruct, DbReadable, DbReader}; use dubp_common_doc::{BlockNumber, Blockstamp}; @@ -87,6 +88,7 @@ pub trait BcDbInReadTx: BcDbWithReader { fn get_idty_state_by_pubkey(&self, pubkey: &PubKey) -> Result<Option<IdentityStateDb>, DbError>; fn get_identity_by_pubkey(&self, pubkey: &PubKey) -> Result<Option<IdentityDb>, DbError>; + fn get_current_ud(&self) -> Result<Option<CurrentUdDb>, DbError>; } impl<T> BcDbInReadTx for T @@ -135,4 +137,8 @@ where fn get_identity_by_pubkey(&self, pubkey: &PubKey) -> Result<Option<IdentityDb>, DbError> { crate::indexes::identities::get_identity_by_pubkey(self, pubkey) } + #[inline] + fn get_current_ud(&self) -> Result<Option<CurrentUdDb>, DbError> { + crate::current_metadata::get_current_ud(self) + } } diff --git a/lib/modules/blockchain/bc-db-writer/src/current_metadata.rs b/lib/modules/blockchain/bc-db-writer/src/current_metadata.rs index 36e1c675347839590b868f966cda0018d825e56d..a50d780b962ddbc60aa294ab37c09099288c005f 100644 --- a/lib/modules/blockchain/bc-db-writer/src/current_metadata.rs +++ b/lib/modules/blockchain/bc-db-writer/src/current_metadata.rs @@ -20,7 +20,9 @@ use dubp_block_doc::block::BlockDocumentTrait; use dubp_block_doc::BlockDocument; use dubp_common_doc::traits::Document; use durs_bc_db_reader::constants::CURRENT_METADATA; +use durs_bc_db_reader::current_metadata::current_ud::CurrentUdDbInternal; use durs_bc_db_reader::current_metadata::CurrentMetaDataKey; +use durs_bc_db_reader::from_db_value; use durs_bc_db_reader::DbValue; /// Update CURRENT_METADATA @@ -43,6 +45,64 @@ pub fn update_current_metadata( CurrentMetaDataKey::CurrentBlockchainTime.to_u32(), &DbValue::U64(new_current_block.common_time()), )?; + // Update current UD + let BlockDocument::V10(ref block_v10) = new_current_block; + if block_v10.dividend.is_some() { + let mut current_ud_internal = db + .get_int_store(CURRENT_METADATA) + .get(w.as_ref(), CurrentMetaDataKey::CurrentUd.to_u32())? + .map(from_db_value::<CurrentUdDbInternal>) + .transpose()? + .unwrap_or_default(); + current_ud_internal.update(new_current_block); + let current_ud_internal_bytes = durs_dbs_tools::to_bytes(¤t_ud_internal)?; + db.get_int_store(CURRENT_METADATA).put( + w.as_mut(), + CurrentMetaDataKey::CurrentUd.to_u32(), + &DbValue::Blob(¤t_ud_internal_bytes), + )?; + } + + Ok(()) +} + +/// Revert CURRENT_METADATA +pub fn revert_current_metadata( + db: &Db, + w: &mut DbWriter, + new_current_block: &BlockDocument, +) -> Result<(), DbError> { + let new_current_blockstamp_bytes: Vec<u8> = new_current_block.blockstamp().into(); + + // Update current blockstamp + db.get_int_store(CURRENT_METADATA).put( + w.as_mut(), + CurrentMetaDataKey::CurrentBlockstamp.to_u32(), + &DbValue::Blob(&new_current_blockstamp_bytes), + )?; + // Update current common time (also named "blockchain time") + db.get_int_store(CURRENT_METADATA).put( + w.as_mut(), + CurrentMetaDataKey::CurrentBlockchainTime.to_u32(), + &DbValue::U64(new_current_block.common_time()), + )?; + // Revert current UD + let BlockDocument::V10(ref block_v10) = new_current_block; + if block_v10.dividend.is_some() { + let mut current_ud_internal = db + .get_int_store(CURRENT_METADATA) + .get(w.as_ref(), CurrentMetaDataKey::CurrentUd.to_u32())? + .map(from_db_value::<CurrentUdDbInternal>) + .transpose()? + .unwrap_or_default(); + current_ud_internal.revert(); + let current_ud_internal_bytes = durs_dbs_tools::to_bytes(¤t_ud_internal)?; + db.get_int_store(CURRENT_METADATA).put( + w.as_mut(), + CurrentMetaDataKey::CurrentUd.to_u32(), + &DbValue::Blob(¤t_ud_internal_bytes), + )?; + } Ok(()) } diff --git a/lib/modules/blockchain/bc-db-writer/src/writers/requests.rs b/lib/modules/blockchain/bc-db-writer/src/writers/requests.rs index 537c14088c5c9c500a3ae738dc48d3854eede67c..031954da43f1d3b5de393a60a0deefdba1f54095 100644 --- a/lib/modules/blockchain/bc-db-writer/src/writers/requests.rs +++ b/lib/modules/blockchain/bc-db-writer/src/writers/requests.rs @@ -79,6 +79,7 @@ impl BlocksDBsWriteQuery { } BlocksDBsWriteQuery::RevertBlock(block_db) => { trace!("BlocksDBsWriteQuery::WriteBlock..."); + crate::current_metadata::revert_current_metadata(db, w, &block_db.block)?; crate::blocks::remove_block(db, w, block_db.block.number())?; trace!("BlocksDBsWriteQuery::WriteBlock...finish"); }