1
1
use crate :: {
2
2
node_type:: { Child , Children , InternalNode , LeafNode , Node , NodeKey , NodeType } ,
3
3
proof:: { definition:: UpdateMerkleProof , SparseMerkleLeafNode , SparseMerkleNode } ,
4
- storage:: { Node :: Leaf , TreeReader , TreeReaderExt , TreeUpdateBatch } ,
4
+ storage:: { Node :: Leaf , TreeReader , TreeUpdateBatch } ,
5
5
tree_cache:: { FreezeError , NodeAlreadyExists , TreeCache } ,
6
6
types:: {
7
7
nibble:: {
@@ -14,7 +14,7 @@ use crate::{
14
14
Bytes32Ext , KeyHash , MissingRootError , OwnedValue , RootHash , SimpleHasher , ValueHash ,
15
15
} ;
16
16
use alloc:: { collections:: BTreeMap , vec, vec:: Vec } ;
17
- use anyhow:: { bail , format_err} ;
17
+ use anyhow:: format_err;
18
18
use core:: { cmp:: Ordering , convert:: TryInto , marker:: PhantomData } ;
19
19
20
20
#[ cfg( not( feature = "std" ) ) ]
@@ -56,8 +56,17 @@ pub enum LookupError<E> {
56
56
ValueNotFound { version : u64 , key_hash : KeyHash } ,
57
57
#[ error( "Non-root null node exists with node key {key:?}" ) ]
58
58
NonRootNullNodeExists { key : NodeKey } ,
59
+ #[ error( "Internal node has no children" ) ]
60
+ InternalNodeHasNoChildren ,
59
61
#[ error( "Jellyfish Merkle tree has cyclic graph inside." ) ]
60
62
CyclicGraphDetected ,
63
+ #[ error( "Found exact key when searching for bounding path for nonexistence proof" ) ]
64
+ FoundKeyInBoundingPath ,
65
+ #[ error( "Invalid exclusion proof" ) ]
66
+ ExclusionProofIsNotValid ,
67
+ // Some actions might fail because the tree is empty.
68
+ #[ error( "{msg}" ) ]
69
+ TreeIsEmpty { msg : & ' static str } ,
61
70
}
62
71
63
72
/// Errors that can occur when a value set is [applied] to a [`JellyfishMerkleTree<'a, R, H>`].
@@ -1143,7 +1152,7 @@ where
1143
1152
extreme : Extreme ,
1144
1153
to : NibblePath ,
1145
1154
parents : Vec < InternalNode > ,
1146
- ) -> Result < Option < KeyHash > , anyhow :: Error > {
1155
+ ) -> Result < Option < KeyHash > , LookupError < R :: Error > > {
1147
1156
fn neighbor_nibble (
1148
1157
node : & InternalNode ,
1149
1158
child_index : Nibble ,
@@ -1188,27 +1197,35 @@ where
1188
1197
& self ,
1189
1198
version : Version ,
1190
1199
search_key : KeyHash ,
1191
- ) -> Result < SearchResult , anyhow :: Error > {
1200
+ ) -> Result < SearchResult , LookupError < R :: Error > > {
1192
1201
let search_path = NibblePath :: new ( search_key. 0 . to_vec ( ) ) ;
1193
1202
let mut search_nibbles = search_path. nibbles ( ) ;
1194
1203
let mut next_node_key = NodeKey :: new_empty_path ( version) ;
1195
1204
let mut internal_nodes = vec ! [ ] ;
1196
1205
1197
1206
for nibble_depth in 0 ..=ROOT_NIBBLE_HEIGHT {
1198
- let next_node = self . reader . get_node ( & next_node_key) . map_err ( |err| {
1199
- if nibble_depth == 0 {
1200
- anyhow:: anyhow!( MissingRootError { version } )
1201
- } else {
1202
- err
1203
- }
1204
- } ) ?;
1207
+ let next_node = self
1208
+ . reader
1209
+ . get_node_option ( & next_node_key)
1210
+ . map_err ( LookupError :: Read ) ?
1211
+ . ok_or_else ( || {
1212
+ if nibble_depth == 0 {
1213
+ // If this is the first loop iteration, we are missing our root.
1214
+ LookupError :: RootMissing ( MissingRootError { version } )
1215
+ } else {
1216
+ // Otherwise, we are missing some other node.
1217
+ LookupError :: NodeMissing {
1218
+ nibble_depth,
1219
+ key : next_node_key. clone ( ) ,
1220
+ }
1221
+ }
1222
+ } ) ?;
1205
1223
1206
1224
match next_node {
1207
1225
Node :: Internal ( node) => {
1208
1226
internal_nodes. push ( node. clone ( ) ) ;
1209
- let queried_child_index = search_nibbles
1210
- . next ( )
1211
- . ok_or_else ( || format_err ! ( "ran out of nibbles" ) ) ?;
1227
+ let queried_child_index =
1228
+ search_nibbles. next ( ) . ok_or ( LookupError :: RanOutOfNibbles ) ?;
1212
1229
1213
1230
let child_node_key =
1214
1231
node. get_only_child_without_siblings ( & next_node_key, queried_child_index) ;
@@ -1238,27 +1255,25 @@ where
1238
1255
}
1239
1256
Node :: Null => {
1240
1257
if nibble_depth == 0 {
1241
- bail ! (
1242
- "Cannot manufacture nonexistence proof by exclusion for the empty tree"
1243
- ) ;
1258
+ return Err ( LookupError :: TreeIsEmpty {
1259
+ msg : "Cannot manufacture nonexistence proof by exclusion for the \
1260
+ empty tree",
1261
+ } ) ;
1244
1262
} else {
1245
- bail ! (
1246
- "Non-root null node exists with node key {:?}" ,
1247
- next_node_key
1248
- ) ;
1263
+ return Err ( LookupError :: NonRootNullNodeExists { key : next_node_key } ) ;
1249
1264
}
1250
1265
}
1251
1266
}
1252
1267
}
1253
1268
1254
- bail ! ( "Jellyfish Merkle tree has cyclic graph inside." ) ;
1269
+ return Err ( LookupError :: CyclicGraphDetected ) ;
1255
1270
}
1256
1271
1257
1272
fn get_bounding_path (
1258
1273
& self ,
1259
1274
search_key : KeyHash ,
1260
1275
version : Version ,
1261
- ) -> Result < ( Option < KeyHash > , Option < KeyHash > ) , anyhow :: Error > {
1276
+ ) -> Result < ( Option < KeyHash > , Option < KeyHash > ) , LookupError < R :: Error > > {
1262
1277
let search_result = self . search_for_closest_node ( version, search_key) ?;
1263
1278
1264
1279
match search_result {
@@ -1293,7 +1308,7 @@ where
1293
1308
Ok ( ( rightmost_left_keyhash, Some ( leaf_hash) ) )
1294
1309
}
1295
1310
Ordering :: Equal => {
1296
- bail ! ( "found exact key when searching for bounding path for nonexistence proof" )
1311
+ return Err ( LookupError :: FoundKeyInBoundingPath ) ;
1297
1312
}
1298
1313
}
1299
1314
}
@@ -1319,12 +1334,21 @@ where
1319
1334
}
1320
1335
}
1321
1336
1322
- /// Returns the value (if applicable) and the corresponding merkle proof.
1337
+ /// Returns the [value] (if applicable) and the corresponding [merkle proof].
1338
+ ///
1339
+ /// - Returns a tuple `Ok(Ok((value, proof)))` if a value associated with the given key exists.
1340
+ /// - Returns an [`ExclusionProof<H>`] as `Ok(Err(exclusion_proof))` if no value associated
1341
+ /// with the given key exists.
1342
+ /// - Returns `Err(e)` if an unexpected error was encountered while retrieving the value.
1343
+ ///
1344
+ /// [value]: OwnedValue
1345
+ /// [merkle proof]: SparseMerkleProof
1323
1346
pub fn get_with_exclusion_proof (
1324
1347
& self ,
1325
1348
key_hash : KeyHash ,
1326
1349
version : Version ,
1327
- ) -> Result < Result < ( OwnedValue , SparseMerkleProof < H > ) , ExclusionProof < H > > , anyhow:: Error > {
1350
+ ) -> Result < Result < ( OwnedValue , SparseMerkleProof < H > ) , ExclusionProof < H > > , LookupError < R :: Error > >
1351
+ {
1328
1352
// Optimistically attempt get_with_proof, if that succeeds, we're done.
1329
1353
if let ( Some ( value) , proof) = self . get_with_proof ( key_hash, version) ? {
1330
1354
return Ok ( Ok ( ( value, proof) ) ) ;
@@ -1359,7 +1383,7 @@ where
1359
1383
leftmost_right_proof : right_proof,
1360
1384
} ) )
1361
1385
}
1362
- _ => bail ! ( "Invalid exclusion proof" ) ,
1386
+ _ => return Err ( LookupError :: ExclusionProofIsNotValid ) ,
1363
1387
}
1364
1388
}
1365
1389
@@ -1369,7 +1393,7 @@ where
1369
1393
mut node_key : NodeKey ,
1370
1394
nibble_depth : usize ,
1371
1395
extreme : Extreme ,
1372
- ) -> Result < KeyHash , anyhow :: Error > {
1396
+ ) -> Result < KeyHash , LookupError < R :: Error > > {
1373
1397
// Depending on the extreme specified, get either the least nibble or the most nibble
1374
1398
let min_or_max = |internal_node : & InternalNode | {
1375
1399
match extreme {
@@ -1382,13 +1406,22 @@ where
1382
1406
// We limit the number of loops here deliberately to avoid potential cyclic graph bugs
1383
1407
// in the tree structure.
1384
1408
for nibble_depth in nibble_depth..=ROOT_NIBBLE_HEIGHT {
1385
- let node = self . reader . get_node ( & node_key) . map_err ( |err| {
1386
- if nibble_depth == 0 {
1387
- anyhow:: anyhow!( MissingRootError { version } )
1388
- } else {
1389
- err
1390
- }
1391
- } ) ?;
1409
+ let node = self
1410
+ . reader
1411
+ . get_node_option ( & node_key)
1412
+ . map_err ( LookupError :: Read ) ?
1413
+ . ok_or_else ( || {
1414
+ if nibble_depth == 0 {
1415
+ // If this is the first loop iteration, we are missing our root.
1416
+ LookupError :: RootMissing ( MissingRootError { version } )
1417
+ } else {
1418
+ // Otherwise, we are missing some other node.
1419
+ LookupError :: NodeMissing {
1420
+ nibble_depth,
1421
+ key : node_key. clone ( ) ,
1422
+ }
1423
+ }
1424
+ } ) ?;
1392
1425
match node {
1393
1426
Node :: Internal ( internal_node) => {
1394
1427
// Find the leftmost nibble in the children
@@ -1399,18 +1432,23 @@ where
1399
1432
// Proceed downwards
1400
1433
node_key = match child_node_key {
1401
1434
Some ( node_key) => node_key,
1402
- None => {
1403
- bail ! ( "Internal node has no children" ) ;
1404
- }
1435
+ None => return Err ( LookupError :: InternalNodeHasNoChildren ) ,
1405
1436
} ;
1406
1437
}
1407
- Node :: Leaf ( leaf_node) => {
1408
- return Ok ( leaf_node. key_hash ( ) ) ;
1438
+ Node :: Leaf ( leaf_node) => return Ok ( leaf_node. key_hash ( ) ) ,
1439
+ Node :: Null => {
1440
+ if nibble_depth == 0 {
1441
+ return Err ( LookupError :: TreeIsEmpty {
1442
+ msg : "Null node cannot have children" ,
1443
+ } ) ;
1444
+ } else {
1445
+ return Err ( LookupError :: NonRootNullNodeExists { key : node_key } ) ;
1446
+ }
1409
1447
}
1410
- Node :: Null => bail ! ( "Null node cannot have children" ) ,
1411
1448
}
1412
1449
}
1413
- bail ! ( "Jellyfish Merkle tree has cyclic graph inside." ) ;
1450
+
1451
+ return Err ( LookupError :: CyclicGraphDetected ) ;
1414
1452
}
1415
1453
1416
1454
fn get_without_proof (
0 commit comments