diff --git a/palette/support/src/storage/child.rs b/palette/support/src/storage/child.rs index d43c2e896f3d8..bc6150c52f96b 100644 --- a/palette/support/src/storage/child.rs +++ b/palette/support/src/storage/child.rs @@ -26,8 +26,12 @@ use codec::{Codec, Encode, Decode}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(storage_key: &[u8], key: &[u8]) -> Option { - runtime_io::storage::child_get(storage_key, key).map(|v| { - Decode::decode(&mut &v[..]).expect("storage is not null, therefore must be a valid type") + runtime_io::storage::child_get(storage_key, key).and_then(|v| { + Decode::decode(&mut &v[..]).map(Some).unwrap_or_else(|_| { + // TODO #3700: error should be handleable. + runtime_print!("ERROR: Corrupted state in child trie at {:?}/{:?}", storage_key, key); + None + }) }) } diff --git a/palette/support/src/storage/generator/linked_map.rs b/palette/support/src/storage/generator/linked_map.rs index 9e2722d5fc496..cf403496990b9 100644 --- a/palette/support/src/storage/generator/linked_map.rs +++ b/palette/support/src/storage/generator/linked_map.rs @@ -164,9 +164,18 @@ where let (val, linkage): (V, Linkage) = { let next_full_key = F::storage_linked_map_final_key(self.prefix, &next); - read_with_linkage::(next_full_key.as_ref()) - .expect("previous/next only contains existing entries; - we enumerate using next; entry exists; qed") + match read_with_linkage::(next_full_key.as_ref()) { + Some(value) => value, + None => { + // TODO #3700: error should be handleable. + runtime_print!( + "ERROR: Corrupted state: linked map head_key={:?}: \ + next value doesn't exist at {:?}", + F::head_key(), next_full_key.as_ref(), + ); + return None + } + } }; self.next = linkage.next; @@ -193,22 +202,34 @@ where if let Some(prev_key) = prev_key { // Retrieve previous element and update `next` - let mut res = read_with_linkage::(prev_key.as_ref()) - .expect("Linkage is updated in case entry is removed; - it always points to existing keys; qed"); - res.1.next = linkage.next; - unhashed::put(prev_key.as_ref(), &res); + if let Some(mut res) = read_with_linkage::(prev_key.as_ref()) { + res.1.next = linkage.next; + unhashed::put(prev_key.as_ref(), &res); + } else { + // TODO #3700: error should be handleable. + runtime_print!( + "ERROR: Corrupted state: linked map head_key={:?}: \ + previous value doesn't exist at {:?}", + F::head_key(), prev_key, + ); + } } else { // we were first so let's update the head write_head::<&K, K, F>(linkage.next.as_ref()); } if let Some(next_key) = next_key { // Update previous of next element - let mut res = read_with_linkage::(next_key.as_ref()) - .expect("Linkage is updated in case entry is removed; - it always points to existing keys; qed"); - res.1.previous = linkage.previous; - unhashed::put(next_key.as_ref(), &res); + if let Some(mut res) = read_with_linkage::(next_key.as_ref()) { + res.1.previous = linkage.previous; + unhashed::put(next_key.as_ref(), &res); + } else { + // TODO #3700: error should be handleable. + runtime_print!( + "ERROR: Corrupted state: linked map head_key={:?}: \ + next value doesn't exist at {:?}", + F::head_key(), next_key, + ); + } } } @@ -235,16 +256,25 @@ where // update previous head predecessor { let head_key = F::storage_linked_map_final_key(prefix, &head); - let (data, linkage) = read_with_linkage::(head_key.as_ref()) - .expect("head is set when first element is inserted - and unset when last element is removed; - if head is Some then it points to existing key; qed"); - let new_linkage = EncodeLikeLinkage::<_, _, K> { - previous: Some(Ref::from(&key)), - next: linkage.next.as_ref(), - phantom: Default::default(), - }; - unhashed::put(head_key.as_ref(), &(data, new_linkage)); + if let Some((data, linkage)) = read_with_linkage::(head_key.as_ref()) { + let new_linkage = EncodeLikeLinkage::<_, _, K> { + previous: Some(Ref::from(&key)), + next: linkage.next.as_ref(), + phantom: Default::default(), + }; + unhashed::put(head_key.as_ref(), &(data, new_linkage)); + } else { + // TODO #3700: error should be handleable. + runtime_print!( + "ERROR: Corrupted state: linked map head_key={:?}: \ + head value doesn't exist at {:?}", + F::head_key(), head_key.as_ref(), + ); + // Thus we consider we are first - update the head and produce empty linkage + + write_head::<_, _, F>(Some(key)); + return Linkage::default(); + } } // update to current head write_head::<_, _, F>(Some(key)); diff --git a/palette/support/src/storage/unhashed.rs b/palette/support/src/storage/unhashed.rs index 803a512b2a2c4..a128f6bf18d0e 100644 --- a/palette/support/src/storage/unhashed.rs +++ b/palette/support/src/storage/unhashed.rs @@ -21,8 +21,12 @@ use codec::{Encode, Decode}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(key: &[u8]) -> Option { - runtime_io::storage::get(key).map(|val| { - Decode::decode(&mut &val[..]).expect("storage is not null, therefore must be a valid type") + runtime_io::storage::get(key).and_then(|val| { + Decode::decode(&mut &val[..]).map(Some).unwrap_or_else(|_| { + // TODO #3700: error should be handleable. + runtime_print!("ERROR: Corrupted state at {:?}", key); + None + }) }) }