Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 1 addition & 24 deletions core/src/blockchain/block_info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018 Kodebox, Inc.
// Copyright 2018-2020 Kodebox, Inc.
// This file is part of CodeChain.
//
// This program is free software: you can redistribute it and/or modify
Expand All @@ -14,7 +14,6 @@
// 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/>.

use super::route::TreeRoute;
use crate::views::{BlockView, HeaderView};
use ctypes::BlockHash;
use primitives::Bytes;
Expand All @@ -28,13 +27,6 @@ pub enum BestBlockChanged {
},
/// Nothing changed.
None,
/// It's part of the fork which should become canon chain,
/// because its total score is higher than current
/// canon chain score.
BranchBecomingCanonChain {
best_block: Bytes,
tree_route: TreeRoute,
},
}

impl BestBlockChanged {
Expand All @@ -47,10 +39,6 @@ impl BestBlockChanged {
BestBlockChanged::CanonChainAppended {
best_block,
} => best_block,
BestBlockChanged::BranchBecomingCanonChain {
best_block,
..
} => best_block,
BestBlockChanged::None => return None,
};

Expand All @@ -67,13 +55,6 @@ pub enum BestHeaderChanged {
},
/// Nothing changed.
None,
/// It's part of the fork which should become canon chain,
/// because its total score is higher than current
/// canon chain score.
BranchBecomingCanonChain {
best_header: Vec<u8>,
tree_route: TreeRoute,
},
}

impl BestHeaderChanged {
Expand All @@ -86,10 +67,6 @@ impl BestHeaderChanged {
BestHeaderChanged::CanonChainAppended {
best_header,
} => best_header,
BestHeaderChanged::BranchBecomingCanonChain {
best_header,
..
} => best_header,
BestHeaderChanged::None => return None,
};

Expand Down
15 changes: 10 additions & 5 deletions core/src/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2019 Kodebox, Inc.
// Copyright 2018-2020 Kodebox, Inc.
// This file is part of CodeChain.
//
// This program is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -256,10 +256,15 @@ impl BlockChain {
0 => BestBlockChanged::CanonChainAppended {
best_block: new_best_block,
},
_ => BestBlockChanged::BranchBecomingCanonChain {
tree_route: route,
best_block: new_best_block,
},
_ => {
cerror!(
BLOCKCHAIN,
"Older/Forked block header #{}({}) is inserted as a new block",
new_header.number(),
new_header.hash()
);
BestBlockChanged::None
}
}
} else {
BestBlockChanged::None
Expand Down
120 changes: 16 additions & 104 deletions core/src/blockchain/body_db.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2019 Kodebox, Inc.
// Copyright 2018-2020 Kodebox, Inc.
// This file is part of CodeChain.
//
// This program is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -36,10 +36,10 @@ pub struct BodyDB {
// block cache
body_cache: Mutex<LruCache<BlockHash, Bytes>>,
address_by_hash_cache: RwLock<HashMap<TxHash, TransactionAddress>>,
pending_addresses_by_hash: RwLock<HashMap<TxHash, Option<TransactionAddress>>>,
pending_addresses_by_hash: RwLock<HashMap<TxHash, TransactionAddress>>,

addresses_by_tracker_cache: Mutex<HashMap<Tracker, TransactionAddresses>>,
pending_addresses_by_tracker: Mutex<HashMap<Tracker, Option<TransactionAddresses>>>,
pending_addresses_by_tracker: Mutex<HashMap<Tracker, TransactionAddresses>>,

db: Arc<dyn KeyValueDB>,
}
Expand Down Expand Up @@ -90,13 +90,13 @@ impl BodyDB {
pub fn update_best_block(&self, batch: &mut DBTransaction, best_block_changed: &BestBlockChanged) {
let mut pending_addresses_by_hash = self.pending_addresses_by_hash.write();
let mut pending_addresses_by_tracker = self.pending_addresses_by_tracker.lock();
batch.extend_with_option_cache(
batch.extend_with_cache(
db::COL_EXTRA,
&mut *pending_addresses_by_hash,
self.new_transaction_address_entries(best_block_changed),
CacheUpdatePolicy::Overwrite,
);
batch.extend_with_option_cache(
batch.extend_with_cache(
db::COL_EXTRA,
&mut *pending_addresses_by_tracker,
self.new_transaction_addresses_entries(best_block_changed),
Expand All @@ -113,38 +113,19 @@ impl BodyDB {
let mut pending_addresses_by_tracker = self.pending_addresses_by_tracker.lock();

let new_txs_by_hash = mem::replace(&mut *pending_addresses_by_hash, HashMap::new());
let (retracted_txs, enacted_txs) =
new_txs_by_hash.into_iter().partition::<HashMap<_, _>, _>(|&(_, ref value)| value.is_none());

address_by_hash_cache
.extend(enacted_txs.into_iter().map(|(k, v)| (k, v.expect("Transactions were partitioned; qed"))));

for hash in retracted_txs.keys() {
address_by_hash_cache.remove(hash);
}
address_by_hash_cache.extend(new_txs_by_hash.into_iter());

let new_txs_by_tracker = mem::replace(&mut *pending_addresses_by_tracker, HashMap::new());
let (removed_transactions, added_transactions) =
new_txs_by_tracker.into_iter().partition::<HashMap<_, _>, _>(|&(_, ref value)| value.is_none());

addresses_by_tracker_cache
.extend(added_transactions.into_iter().map(|(k, v)| (k, v.expect("Transactions were partitioned; qed"))));

for hash in removed_transactions.keys() {
addresses_by_tracker_cache.remove(hash);
}
addresses_by_tracker_cache.extend(new_txs_by_tracker.into_iter());
}

/// This function returns modified transaction addresses.
fn new_transaction_address_entries(
&self,
best_block_changed: &BestBlockChanged,
) -> HashMap<TxHash, Option<TransactionAddress>> {
let block_hash = if let Some(best_block_hash) = best_block_changed.new_best_hash() {
best_block_hash
} else {
return HashMap::new()
};
) -> HashMap<TxHash, TransactionAddress> {
let block = match best_block_changed.best_block() {
Some(block) => block,
None => return HashMap::new(),
Expand All @@ -155,35 +136,14 @@ impl BodyDB {
BestBlockChanged::CanonChainAppended {
..
} => tx_hash_and_address_entries(best_block_changed.new_best_hash().unwrap(), tx_hashes).collect(),
BestBlockChanged::BranchBecomingCanonChain {
tree_route,
..
} => {
let enacted = tree_route.enacted.iter().flat_map(|hash| {
let body = self.block_body(hash).expect("Enacted block must be in database.");
let enacted_tx_hashes = body.transaction_hashes();
tx_hash_and_address_entries(*hash, enacted_tx_hashes)
});

let current_addresses = { tx_hash_and_address_entries(block_hash, tx_hashes) };

let retracted = tree_route.retracted.iter().flat_map(|hash| {
let body = self.block_body(&hash).expect("Retracted block must be in database.");
let retracted_tx_hashes = body.transaction_hashes().into_iter();
retracted_tx_hashes.map(|hash| (hash, None))
});

// The order here is important! Don't remove transactions if it was part of enacted blocks as well.
retracted.chain(enacted).chain(current_addresses).collect()
}
BestBlockChanged::None => HashMap::new(),
}
}

fn new_transaction_addresses_entries(
&self,
best_block_changed: &BestBlockChanged,
) -> HashMap<Tracker, Option<TransactionAddresses>> {
) -> HashMap<Tracker, TransactionAddresses> {
let block_hash = if let Some(best_block_hash) = best_block_changed.new_best_hash() {
best_block_hash
} else {
Expand All @@ -194,77 +154,32 @@ impl BodyDB {
None => return HashMap::new(),
};

let (removed, added): (
Box<dyn Iterator<Item = TrackerAndAddress>>,
Box<dyn Iterator<Item = TrackerAndAddress>>,
) = match best_block_changed {
let added: Box<dyn Iterator<Item = TrackerAndAddress>> = match best_block_changed {
BestBlockChanged::CanonChainAppended {
..
} => (
Box::new(::std::iter::empty()),
Box::new(tracker_and_addresses_entries(block_hash, block.transactions())),
),
BestBlockChanged::BranchBecomingCanonChain {
ref tree_route,
..
} => {
let enacted = tree_route
.enacted
.iter()
.flat_map(|hash| {
let body = self.block_body(hash).expect("Enacted block must be in database.");
tracker_and_addresses_entries(*hash, body.transactions())
})
.chain(tracker_and_addresses_entries(block_hash, block.transactions()));

let retracted = tree_route.retracted.iter().flat_map(|hash| {
let body = self.block_body(hash).expect("Retracted block must be in database.");
tracker_and_addresses_entries(*hash, body.transactions())
});

(Box::new(retracted), Box::new(enacted))
}
} => Box::new(tracker_and_addresses_entries(block_hash, block.transactions())),
BestBlockChanged::None => return Default::default(),
};

let mut added_addresses: HashMap<Tracker, TransactionAddresses> = Default::default();
let mut removed_addresses: HashMap<Tracker, TransactionAddresses> = Default::default();
let mut trackers: HashSet<Tracker> = Default::default();
for (tracker, address) in added {
trackers.insert(tracker);
*added_addresses.entry(tracker).or_insert_with(Default::default) += address;
}
for (tracker, address) in removed {
trackers.insert(tracker);
*removed_addresses.entry(tracker).or_insert_with(Default::default) += address;
}
let mut inserted_address: HashMap<Tracker, TransactionAddresses> = Default::default();
for tracker in trackers.into_iter() {
let address: TransactionAddresses = self.db.read(db::COL_EXTRA, &tracker).unwrap_or_default();
inserted_address.insert(tracker, address);
}

for (tracker, removed_address) in removed_addresses.into_iter() {
*inserted_address
.get_mut(&tracker)
.expect("inserted addresses are sum of added_addresses and removed_addresses") -= removed_address;
}
for (tracker, added_address) in added_addresses.into_iter() {
*inserted_address
.get_mut(&tracker)
.expect("inserted addresses are sum of added_addresses and removed_addresses") += added_address;
}

inserted_address
.into_iter()
.map(|(hash, address)| {
if address.is_empty() {
(hash, None)
} else {
(hash, Some(address))
}
})
.collect()
}

/// Create a block body from a block.
Expand Down Expand Up @@ -332,15 +247,12 @@ impl BodyProvider for BodyDB {
fn tx_hash_and_address_entries(
block_hash: BlockHash,
tx_hashes: impl IntoIterator<Item = TxHash>,
) -> impl Iterator<Item = (TxHash, Option<TransactionAddress>)> {
) -> impl Iterator<Item = (TxHash, TransactionAddress)> {
tx_hashes.into_iter().enumerate().map(move |(index, tx_hash)| {
(
tx_hash,
Some(TransactionAddress {
block_hash,
index,
}),
)
(tx_hash, TransactionAddress {
block_hash,
index,
})
})
}

Expand Down
6 changes: 1 addition & 5 deletions core/src/blockchain/extras.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2019 Kodebox, Inc.
// Copyright 2018-2020 Kodebox, Inc.
// This file is part of CodeChain.
//
// This program is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -128,10 +128,6 @@ impl TransactionAddresses {
addresses: vec![address],
}
}

pub fn is_empty(&self) -> bool {
self.addresses.is_empty()
}
}

impl IntoIterator for TransactionAddresses {
Expand Down
29 changes: 10 additions & 19 deletions core/src/blockchain/headerchain.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2019 Kodebox, Inc.
// Copyright 2018-2020 Kodebox, Inc.
// This file is part of CodeChain.
//
// This program is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -243,20 +243,6 @@ impl HeaderChain {
let best_header_view = HeaderView::new(best_header);
hashes.insert(best_header_view.number(), best_header_view.hash());
}
BestHeaderChanged::BranchBecomingCanonChain {
tree_route,
best_header,
} => {
let ancestor_number = self.block_number(&tree_route.ancestor).expect("Ancestor always exist in DB");
let start_number = ancestor_number + 1;

for (index, hash) in tree_route.enacted.iter().enumerate() {
hashes.insert(start_number + index as BlockNumber, *hash);
}

let best_header_view = HeaderView::new(best_header);
hashes.insert(best_header_view.number(), best_header_view.hash());
}
}

hashes
Expand Down Expand Up @@ -321,10 +307,15 @@ impl HeaderChain {
0 => BestHeaderChanged::CanonChainAppended {
best_header: new_best_header,
},
_ => BestHeaderChanged::BranchBecomingCanonChain {
tree_route: route,
best_header: new_best_header,
},
_ => {
cerror!(
HEADERCHAIN,
"Older/Forked block header #{}({}) is inserted as a new block",
new_header.number(),
new_header.hash()
);
BestHeaderChanged::None
}
}
} else {
BestHeaderChanged::None
Expand Down
Loading