fix storage decode error (#3997)

This commit is contained in:
thiolliere
2019-11-22 16:29:26 +01:00
committed by Bastian Köcher
parent 145efab68f
commit f000392cc0
3 changed files with 65 additions and 27 deletions
@@ -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<T: Decode + Sized>(storage_key: &[u8], key: &[u8]) -> Option<T> {
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
})
})
}
@@ -164,9 +164,18 @@ where
let (val, linkage): (V, Linkage<K>) = {
let next_full_key = F::storage_linked_map_final_key(self.prefix, &next);
read_with_linkage::<K, V>(next_full_key.as_ref())
.expect("previous/next only contains existing entries;
we enumerate using next; entry exists; qed")
match read_with_linkage::<K, V>(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::<K, V>(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::<K, V>(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::<K, V>(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::<K, V>(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::<K, V>(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::<K, V>(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));
@@ -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<T: Decode + Sized>(key: &[u8]) -> Option<T> {
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
})
})
}