github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/tests/test_merkle_trie/tests.py (about) 1 # Copyright 2017 Intel Corporation 2 # 3 # Licensed under the Apache License, Version 2.0 (the 'License'); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an 'AS IS' BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 # ------------------------------------------------------------------------------ 15 16 import hashlib 17 import os 18 import unittest 19 import random 20 import shutil 21 import tempfile 22 from string import ascii_lowercase 23 24 from sawtooth_validator.state.merkle import MerkleDatabase 25 from sawtooth_validator.database.native_lmdb import NativeLmdbDatabase 26 27 28 class TestSawtoothMerkleTrie(unittest.TestCase): 29 def setUp(self): 30 self.dir = tempfile.mkdtemp() 31 self.file = os.path.join(self.dir, 'merkle.lmdb') 32 33 self.lmdb = NativeLmdbDatabase( 34 self.file, 35 indexes=MerkleDatabase.create_index_configuration(), 36 _size=120 * 1024 * 1024) 37 38 self.trie = MerkleDatabase(self.lmdb) 39 40 def tearDown(self): 41 self.trie.close() 42 shutil.rmtree(self.dir) 43 44 def test_merkle_trie_root_advance(self): 45 value = {'name': 'foo', 'value': 1} 46 47 orig_root = self.get_merkle_root() 48 new_root = self.set('foo', value) 49 50 self.assert_root(orig_root) 51 self.assert_no_key('foo') 52 53 self.set_merkle_root(new_root) 54 55 self.assert_root(new_root) 56 self.assert_value_at_address('foo', value) 57 58 def test_merkle_trie_delete(self): 59 value = {'name': 'bar', 'value': 1} 60 61 new_root = self.set('bar', value) 62 self.set_merkle_root(new_root) 63 64 self.assert_root(new_root) 65 self.assert_value_at_address('bar', value) 66 67 # deleting an invalid key should raise an error 68 with self.assertRaises(KeyError): 69 self.delete('barf') 70 71 del_root = self.delete('bar') 72 73 # del_root hasn't been set yet, so address should still have value 74 self.assert_root(new_root) 75 self.assert_value_at_address('bar', value) 76 77 self.set_merkle_root(del_root) 78 79 self.assert_root(del_root) 80 self.assert_no_key('bar') 81 82 def test_merkle_trie_update(self): 83 init_root = self.get_merkle_root() 84 85 values = {} 86 key_hashes = { 87 key: _hash(key) 88 for key in (_random_string(10) for _ in range(1000)) 89 } 90 91 for key, hashed in key_hashes.items(): 92 value = {key: _random_string(512)} 93 new_root = self.set(hashed, value, ishash=True) 94 values[hashed] = value 95 self.set_merkle_root(new_root) 96 97 self.assert_not_root(init_root) 98 99 for address, value in values.items(): 100 self.assert_value_at_address( 101 address, value, ishash=True) 102 103 set_items = { 104 hashed: { 105 key: 5.0 106 } 107 for key, hashed in random.sample(key_hashes.items(), 50) 108 } 109 values.update(set_items) 110 delete_items = { 111 hashed 112 for hashed in random.sample(list(key_hashes.values()), 50) 113 } 114 115 # make sure there are no sets and deletes of the same key 116 delete_items = delete_items - set_items.keys() 117 for addr in delete_items: 118 del values[addr] 119 120 virtual_root = self.update(set_items, delete_items, virtual=True) 121 122 # virtual root shouldn't match actual contents of tree 123 with self.assertRaises(KeyError): 124 self.set_merkle_root(virtual_root) 125 126 actual_root = self.update(set_items, delete_items, virtual=False) 127 128 # the virtual root should be the same as the actual root 129 self.assertEqual(virtual_root, actual_root) 130 131 # neither should be the root yet 132 self.assert_not_root( 133 virtual_root, 134 actual_root) 135 136 self.set_merkle_root(actual_root) 137 self.assert_root(actual_root) 138 139 for address, value in values.items(): 140 self.assert_value_at_address( 141 address, value, ishash=True) 142 143 for address in delete_items: 144 with self.assertRaises(KeyError): 145 self.get(address, ishash=True) 146 147 def test_merkle_trie_leaf_iteration(self): 148 new_root = self.update({ 149 "010101": {"my_data": 1}, 150 "010202": {"my_data": 2}, 151 "010303": {"my_data": 3} 152 }, [], virtual=False) 153 154 # iterate over the empty trie 155 iterator = iter(self.trie) 156 with self.assertRaises(StopIteration): 157 next(iterator) 158 159 self.set_merkle_root(new_root) 160 161 # Test complete trie iteration 162 self.assertEqual( 163 [("010101", {"my_data": 1}), 164 ("010202", {"my_data": 2}), 165 ("010303", {"my_data": 3})], 166 [entry for entry in iter(self.trie)]) 167 168 # Test prefixed iteration 169 self.assertEqual([("010202", {"my_data": 2})], 170 [entry for entry in self.trie.leaves('0102')]) 171 172 # assertions 173 def assert_value_at_address(self, address, value, ishash=False): 174 self.assertEqual( 175 self.get(address, ishash), 176 value, 177 'Wrong value') 178 179 def assert_no_key(self, key): 180 with self.assertRaises(KeyError): 181 self.get(key) 182 183 def assert_root(self, expected): 184 self.assertEqual( 185 expected, 186 self.get_merkle_root(), 187 'Wrong root') 188 189 def assert_not_root(self, *not_roots): 190 root = self.get_merkle_root() 191 for not_root in not_roots: 192 self.assertNotEqual( 193 root, 194 not_root, 195 'Wrong root') 196 197 # trie accessors 198 199 # For convenience, assume keys are not hashed 200 # unless otherwise indicated. 201 202 def set(self, key, val, ishash=False): 203 key_ = key if ishash else _hash(key) 204 return self.trie.set(key_, val) 205 206 def get(self, key, ishash=False): 207 key_ = key if ishash else _hash(key) 208 return self.trie.get(key_) 209 210 def delete(self, key, ishash=False): 211 key_ = key if ishash else _hash(key) 212 return self.trie.delete(key_) 213 214 def set_merkle_root(self, root): 215 self.trie.set_merkle_root(root) 216 217 def get_merkle_root(self): 218 return self.trie.get_merkle_root() 219 220 def update(self, set_items, delete_items=None, virtual=True): 221 return self.trie.update(set_items, delete_items, virtual=virtual) 222 223 224 def _hash(key): 225 return hashlib.sha512(key.encode()).hexdigest()[:64] 226 227 228 def _random_string(length): 229 return ''.join(random.choice(ascii_lowercase) for _ in range(length))