referrerpolicy=no-referrer-when-downgrade

sc_client_db/
children.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Functionality for reading and storing children hashes from db.
20
21use crate::DbHash;
22use codec::{Decode, Encode};
23use sp_blockchain;
24use sp_database::{Database, Transaction};
25use std::hash::Hash;
26
27/// Returns the hashes of the children blocks of the block with `parent_hash`.
28pub fn read_children<
29	K: Eq + Hash + Clone + Encode + Decode,
30	V: Eq + Hash + Clone + Encode + Decode,
31>(
32	db: &dyn Database<DbHash>,
33	column: u32,
34	prefix: &[u8],
35	parent_hash: K,
36) -> sp_blockchain::Result<Vec<V>> {
37	let mut buf = prefix.to_vec();
38	parent_hash.using_encoded(|s| buf.extend(s));
39
40	let raw_val_opt = db.get(column, &buf[..]);
41
42	let raw_val = match raw_val_opt {
43		Some(val) => val,
44		None => return Ok(Vec::new()),
45	};
46
47	let children: Vec<V> = match Decode::decode(&mut &raw_val[..]) {
48		Ok(children) => children,
49		Err(_) => return Err(sp_blockchain::Error::Backend("Error decoding children".into())),
50	};
51
52	Ok(children)
53}
54
55/// Insert the key-value pair (`parent_hash`, `children_hashes`) in the transaction.
56/// Any existing value is overwritten upon write.
57pub fn write_children<
58	K: Eq + Hash + Clone + Encode + Decode,
59	V: Eq + Hash + Clone + Encode + Decode,
60>(
61	tx: &mut Transaction<DbHash>,
62	column: u32,
63	prefix: &[u8],
64	parent_hash: K,
65	children_hashes: V,
66) {
67	let mut key = prefix.to_vec();
68	parent_hash.using_encoded(|s| key.extend(s));
69	tx.set_from_vec(column, &key[..], children_hashes.encode());
70}
71
72/// Prepare transaction to remove the children of `parent_hash`.
73pub fn remove_children<K: Eq + Hash + Clone + Encode + Decode>(
74	tx: &mut Transaction<DbHash>,
75	column: u32,
76	prefix: &[u8],
77	parent_hash: K,
78) {
79	let mut key = prefix.to_vec();
80	parent_hash.using_encoded(|s| key.extend(s));
81	tx.remove(column, &key);
82}
83
84#[cfg(test)]
85mod tests {
86	use super::*;
87	use std::sync::Arc;
88
89	#[test]
90	fn children_write_read_remove() {
91		const PREFIX: &[u8] = b"children";
92		let db = Arc::new(sp_database::MemDb::default());
93
94		let mut tx = Transaction::new();
95
96		let mut children1 = Vec::new();
97		children1.push(1_3);
98		children1.push(1_5);
99		write_children(&mut tx, 0, PREFIX, 1_1, children1);
100
101		let mut children2 = Vec::new();
102		children2.push(1_4);
103		children2.push(1_6);
104		write_children(&mut tx, 0, PREFIX, 1_2, children2);
105
106		db.commit(tx.clone()).unwrap();
107
108		let r1: Vec<u32> = read_children(&*db, 0, PREFIX, 1_1).expect("(1) Getting r1 failed");
109		let r2: Vec<u32> = read_children(&*db, 0, PREFIX, 1_2).expect("(1) Getting r2 failed");
110
111		assert_eq!(r1, vec![1_3, 1_5]);
112		assert_eq!(r2, vec![1_4, 1_6]);
113
114		remove_children(&mut tx, 0, PREFIX, 1_2);
115		db.commit(tx).unwrap();
116
117		let r1: Vec<u32> = read_children(&*db, 0, PREFIX, 1_1).expect("(2) Getting r1 failed");
118		let r2: Vec<u32> = read_children(&*db, 0, PREFIX, 1_2).expect("(2) Getting r2 failed");
119
120		assert_eq!(r1, vec![1_3, 1_5]);
121		assert_eq!(r2.len(), 0);
122	}
123}