1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Tetsy Vapory.

// Tetsy Vapory is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Tetsy Vapory 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 General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Tetsy Vapory.  If not, see <http://www.gnu.org/licenses/>.

//! Façade crate for `patricia_trie` for Vapory specific impls

pub extern crate tetsy_trie_db as trie; // `pub` because we need to import this crate for the tests in `patricia_trie` and there were issues: https://gist.github.com/dvdplm/869251ee557a1b4bd53adc7c971979aa
extern crate elastic_array;
extern crate tetsy_bytes;
extern crate vapory_types;
extern crate tetsy_hash_db;
extern crate tetsy_keccak_hasher;
extern crate tetsy_rlp;

mod rlp_node_codec;

pub use rlp_node_codec::RlpNodeCodec;

use vapory_types::H256;
use tetsy_keccak_hasher::KeccakHasher;
use tetsy_rlp::DecoderError;

/// Convenience type alias to instantiate a Keccak-flavoured `RlpNodeCodec`
pub type RlpCodec = RlpNodeCodec<KeccakHasher>;

#[derive(Clone, Default)]
/// Defines the working of a particular flavour of trie:
/// how keys are hashed, how values are encoded, does it use extension nodes or not.
pub struct Layout;

impl tetsy_trie_db::TrieLayout for Layout {
	const USE_EXTENSION: bool = true;
	type Hash = tetsy_keccak_hasher::KeccakHasher;
	type Codec = RlpNodeCodec<KeccakHasher>;
}

/// Convenience type alias to instantiate a Keccak/Rlp-flavoured `TrieDB`
///
/// Use it as a `Trie` trait object. You can use `db()` to get the backing database object.
/// Use `get` and `contains` to query values associated with keys in the trie.
///
/// # Example
/// ```
/// extern crate tetsy_trie_db as trie;
/// extern crate patricia_trie_vapory as vaptrie;
/// extern crate tetsy_hash_db;
/// extern crate tetsy_keccak_hasher;
/// extern crate tetsy_memory_db;
/// extern crate vapory_types;
/// extern crate elastic_array;
/// extern crate journaldb;
///
/// use trie::*;
/// use tetsy_hash_db::*;
/// use tetsy_keccak_hasher::KeccakHasher;
/// use tetsy_memory_db::*;
/// use vapory_types::H256;
/// use vaptrie::{TrieDB, TrieDBMut};
/// use elastic_array::ElasticArray128;
///
/// type DBValue = ElasticArray128<u8>;
///
/// fn main() {
///   let mut memdb = journaldb::new_tetsy_memory_db();
///   let mut root = H256::zero();
///   TrieDBMut::new(&mut memdb, &mut root).insert(b"foo", b"bar").unwrap();
///   let t = TrieDB::new(&memdb, &root).unwrap();
///   assert!(t.contains(b"foo").unwrap());
///   assert_eq!(t.get(b"foo").unwrap().unwrap(), b"bar".to_vec());
/// }
/// ```
pub type TrieDB<'db> = trie::TrieDB<'db, Layout>;

/// Convenience type alias to instantiate a Keccak/Rlp-flavoured `SecTrieDB`
pub type SecTrieDB<'db> = trie::SecTrieDB<'db, Layout>;

/// Convenience type alias to instantiate a Keccak/Rlp-flavoured `FatDB`
pub type FatDB<'db> = trie::FatDB<'db, Layout>;

/// Convenience type alias to instantiate a Keccak/Rlp-flavoured `TrieDBMut`
///
/// Use it as a `TrieMut` trait object. You can use `db()` to get the backing database object.
/// Note that changes are not committed to the database until `commit` is called.
/// Querying the root or dropping the trie will commit automatically.

/// # Example
/// ```
/// extern crate tetsy_trie_db as trie;
/// extern crate patricia_trie_vapory as vaptrie;
/// extern crate tetsy_hash_db;
/// extern crate tetsy_keccak_hash;
/// extern crate tetsy_keccak_hasher;
/// extern crate tetsy_memory_db;
/// extern crate vapory_types;
/// extern crate elastic_array;
/// extern crate journaldb;
///
/// use tetsy_keccak_hash::KECCAK_NULL_RLP;
/// use vaptrie::{TrieDBMut, trie::TrieMut};
/// use tetsy_keccak_hasher::KeccakHasher;
/// use tetsy_memory_db::*;
/// use vapory_types::H256;
/// use elastic_array::ElasticArray128;
/// use trie::Trie;
///
/// type DBValue = ElasticArray128<u8>;
///
/// fn main() {
///   let mut memdb = journaldb::new_tetsy_memory_db();
///   let mut root = H256::zero();
///   let mut t = TrieDBMut::new(&mut memdb, &mut root);
///   assert!(t.is_empty());
///   assert_eq!(*t.root(), KECCAK_NULL_RLP);
///   t.insert(b"foo", b"bar").unwrap();
///   assert!(t.contains(b"foo").unwrap());
///   assert_eq!(t.get(b"foo").unwrap().unwrap(), b"bar".to_vec());
///   t.remove(b"foo").unwrap();
///   assert!(!t.contains(b"foo").unwrap());
/// }
/// ```
pub type TrieDBMut<'db> = trie::TrieDBMut<'db, Layout>;

/// Convenience type alias to instantiate a Keccak/Rlp-flavoured `SecTrieDBMut`
pub type SecTrieDBMut<'db> = trie::SecTrieDBMut<'db, Layout>;

/// Convenience type alias to instantiate a Keccak/Rlp-flavoured `FatDBMut`
pub type FatDBMut<'db> = trie::FatDBMut<'db, Layout>;

/// Convenience type alias to instantiate a Keccak/Rlp-flavoured `TrieFactory`
pub type TrieFactory = trie::TrieFactory<Layout>;

/// Convenience type alias for Keccak/Rlp flavoured trie errors
pub type TrieError = trie::TrieError<H256, DecoderError>;
/// Convenience type alias for Keccak/Rlp flavoured trie results
pub type Result<T> = trie::Result<T, H256, DecoderError>;

#[cfg(test)]
mod tests {
	use vapory_types::H256;
	use trie::Trie;

	use crate::{TrieDB, TrieDBMut, trie::TrieMut};

	#[test]
	fn test_inline_encoding_branch() {
		let mut memdb = journaldb::new_tetsy_memory_db();
		let mut root = H256::zero();
		{
			let mut triedbmut = TrieDBMut::new(&mut memdb, &mut root);
			triedbmut.insert(b"foo", b"bar").unwrap();
			triedbmut.insert(b"fog", b"b").unwrap();
			triedbmut.insert(b"fot", &vec![0u8;33][..]).unwrap();
		}
		let t = TrieDB::new(&memdb, &root).unwrap();
		assert!(t.contains(b"foo").unwrap());
		assert!(t.contains(b"fog").unwrap());
		assert_eq!(t.get(b"foo").unwrap().unwrap(), b"bar".to_vec());
		assert_eq!(t.get(b"fog").unwrap().unwrap(), b"b".to_vec());
		assert_eq!(t.get(b"fot").unwrap().unwrap(), vec![0u8;33]);
	}

	#[test]
	fn test_inline_encoding_extension() {
		let mut memdb = journaldb::new_tetsy_memory_db();
		let mut root = H256::zero();
		{
			let mut triedbmut = TrieDBMut::new(&mut memdb, &mut root);
			triedbmut.insert(b"foo", b"b").unwrap();
			triedbmut.insert(b"fog", b"a").unwrap();
		}
		let t = TrieDB::new(&memdb, &root).unwrap();
		assert!(t.contains(b"foo").unwrap());
		assert!(t.contains(b"fog").unwrap());
		assert_eq!(t.get(b"foo").unwrap().unwrap(), b"b".to_vec());
		assert_eq!(t.get(b"fog").unwrap().unwrap(), b"a".to_vec());
	}

}