Update to parity-scale-codec (#3232)

* WIP: update codec

* WIP

* compiling

* WIP

* rename parity-scale-codec to codec

* WIP

* fix

* remove old comments

* use published crates

* fix expected error msg

* bump version

* fmt and fix

* remove old comment

* fix wrong decoding impl

* implement encode like for structures

* undo removal of old pending changes

* trailingzeroinput

* Apply suggestions from code review

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>
Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* update codec

* fmt

* version is 1.0.0

* show more error

* fmt
This commit is contained in:
thiolliere
2019-08-06 19:36:23 +02:00
committed by Bastian Köcher
parent a0d442333f
commit 4ed67e03a4
211 changed files with 867 additions and 682 deletions
@@ -22,7 +22,7 @@ use serde::Serialize;
use rstd::prelude::*;
use crate::ConsensusEngineId;
use crate::codec::{Decode, Encode, Input};
use crate::codec::{Decode, Encode, Input, Error};
/// Generic header digest.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
@@ -221,27 +221,29 @@ impl<Hash: Encode> Encode for DigestItem<Hash> {
}
}
impl<Hash: Encode> codec::EncodeLike for DigestItem<Hash> {}
impl<Hash: Decode> Decode for DigestItem<Hash> {
#[allow(deprecated)]
fn decode<I: Input>(input: &mut I) -> Option<Self> {
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
let item_type: DigestItemType = Decode::decode(input)?;
match item_type {
DigestItemType::ChangesTrieRoot => Some(DigestItem::ChangesTrieRoot(
DigestItemType::ChangesTrieRoot => Ok(DigestItem::ChangesTrieRoot(
Decode::decode(input)?,
)),
DigestItemType::PreRuntime => {
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
Some(DigestItem::PreRuntime(vals.0, vals.1))
Ok(DigestItem::PreRuntime(vals.0, vals.1))
},
DigestItemType::Consensus => {
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
Some(DigestItem::Consensus(vals.0, vals.1))
Ok(DigestItem::Consensus(vals.0, vals.1))
}
DigestItemType::Seal => {
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
Some(DigestItem::Seal(vals.0, vals.1))
Ok(DigestItem::Seal(vals.0, vals.1))
},
DigestItemType::Other => Some(DigestItem::Other(
DigestItemType::Other => Ok(DigestItem::Other(
Decode::decode(input)?,
)),
}
@@ -305,7 +307,7 @@ impl<'a, Hash> DigestItemRef<'a, Hash> {
/// Try to match this digest item to the given opaque item identifier; if it matches, then
/// try to cast to the given datatype; if that works, return it.
pub fn try_to<T: Decode>(&self, id: OpaqueDigestItemId) -> Option<T> {
self.try_as_raw(id).and_then(|mut x| Decode::decode(&mut x))
self.try_as_raw(id).and_then(|mut x| Decode::decode(&mut x).ok())
}
}
@@ -340,6 +342,8 @@ impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> {
}
}
impl<'a, Hash: Encode> codec::EncodeLike for DigestItemRef<'a, Hash> {}
#[cfg(test)]
mod tests {
use super::*;
@@ -19,7 +19,7 @@
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
use crate::codec::{Decode, Encode, Input, Output};
use crate::codec::{Decode, Encode, Input, Output, Error};
/// Era period
pub type Period = u64;
@@ -111,20 +111,22 @@ impl Encode for Era {
}
}
impl codec::EncodeLike for Era {}
impl Decode for Era {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
let first = input.read_byte()?;
if first == 0 {
Some(Era::Immortal)
Ok(Era::Immortal)
} else {
let encoded = first as u64 + ((input.read_byte()? as u64) << 8);
let period = 2 << (encoded % (1 << 4));
let quantize_factor = (period >> 12).max(1);
let phase = (encoded >> 4) * quantize_factor;
if period >= 4 && phase < period {
Some(Era::Mortal(period, phase))
Ok(Era::Mortal(period, phase))
} else {
None
Err("Invalid period and phase".into())
}
}
}
@@ -20,7 +20,7 @@
use serde::Serialize;
#[cfg(feature = "std")]
use log::debug;
use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef};
use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef, Error};
use crate::traits::{
self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Hash as HashT, MaybeSerializeDebug,
MaybeSerializeDebugButNotDeserialize
@@ -60,8 +60,8 @@ impl<Number, Hash> Decode for Header<Number, Hash> where
Hash: HashT,
Hash::Output: Decode,
{
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Header {
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
Ok(Header {
parent_hash: Decode::decode(input)?,
number: <<Number as HasCompact>::Type>::decode(input)?.into(),
state_root: Decode::decode(input)?,
@@ -85,6 +85,12 @@ impl<Number, Hash> Encode for Header<Number, Hash> where
}
}
impl<Number, Hash> codec::EncodeLike for Header<Number, Hash> where
Number: HasCompact + Copy + Into<u128>,
Hash: HashT,
Hash::Output: Encode,
{}
impl<Number, Hash> traits::Header for Header<Number, Hash> where
Number: Member + MaybeSerializeDebug + ::rstd::hash::Hash + MaybeDisplay + SimpleArithmetic + Codec + Copy + Into<u128>,
Hash: HashT,
@@ -21,7 +21,7 @@ use std::fmt;
use rstd::prelude::*;
use runtime_io::blake2_256;
use crate::codec::{Decode, Encode, Input};
use crate::codec::{Decode, Encode, Input, Error};
use crate::traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic};
use super::CheckedExtrinsic;
@@ -131,7 +131,7 @@ where
Call: Decode,
Extra: SignedExtension,
{
fn decode<I: Input>(input: &mut I) -> Option<Self> {
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
// This is a little more complicated than usual since the binary format must be compatible
// with substrate's generic `Vec<u8>` type. Basically this just means accepting that there
// will be a prefix of vector length (we don't need
@@ -143,10 +143,10 @@ where
let is_signed = version & 0b1000_0000 != 0;
let version = version & 0b0111_1111;
if version != TRANSACTION_VERSION {
return None
return Err("Invalid transaction version".into());
}
Some(UncheckedExtrinsic {
Ok(UncheckedExtrinsic {
signature: if is_signed { Some(Decode::decode(input)?) } else { None },
function: Decode::decode(input)?,
})
@@ -245,7 +245,7 @@ mod tests {
fn unsigned_codec_should_work() {
let ux = Ex::new_unsigned(vec![0u8; 0]);
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux));
assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
}
#[test]
@@ -257,7 +257,7 @@ mod tests {
TestExtra
);
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux));
assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
}
#[test]
@@ -270,7 +270,7 @@ mod tests {
TestExtra
);
let encoded = ux.encode();
assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux));
assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
}
#[test]
+4
View File
@@ -694,6 +694,8 @@ impl codec::Encode for ApplyOutcome {
}
}
impl codec::EncodeLike for ApplyOutcome {}
#[derive(Eq, PartialEq, Clone, Copy, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
#[repr(u8)]
@@ -717,6 +719,8 @@ impl codec::Encode for ApplyError {
}
}
impl codec::EncodeLike for ApplyError {}
/// Result from attempt to apply an extrinsic.
pub type ApplyResult = Result<ApplyOutcome, ApplyError>;
+7 -3
View File
@@ -70,7 +70,9 @@ impl OpaqueKeys for UintAuthorityId {
)
}
}
fn get<T: Decode>(&self, _: KeyTypeId) -> Option<T> { self.0.using_encoded(|mut x| T::decode(&mut x)) }
fn get<T: Decode>(&self, _: KeyTypeId) -> Option<T> {
self.0.using_encoded(|mut x| T::decode(&mut x)).ok()
}
}
/// Digest item
@@ -136,7 +138,8 @@ impl traits::Header for Header {
impl<'a> Deserialize<'a> for Header {
fn deserialize<D: Deserializer<'a>>(de: D) -> Result<Self, D::Error> {
let r = <Vec<u8>>::deserialize(de)?;
Decode::decode(&mut &r[..]).ok_or(DeError::custom("Invalid value passed into decode"))
Decode::decode(&mut &r[..])
.map_err(|e| DeError::custom(format!("Invalid value passed into decode: {}", e.what())))
}
}
@@ -204,7 +207,8 @@ impl<Xt: 'static + Codec + Sized + Send + Sync + Serialize + Clone + Eq + Debug
impl<'a, Xt> Deserialize<'a> for Block<Xt> where Block<Xt>: Decode {
fn deserialize<D: Deserializer<'a>>(de: D) -> Result<Self, D::Error> {
let r = <Vec<u8>>::deserialize(de)?;
Decode::decode(&mut &r[..]).ok_or(DeError::custom("Invalid value passed into decode"))
Decode::decode(&mut &r[..])
.map_err(|e| DeError::custom(format!("Invalid value passed into decode: {}", e.what())))
}
}
+34 -9
View File
@@ -1029,21 +1029,30 @@ pub trait OpaqueKeys: Clone {
/// Get the raw bytes of key with key-type ID `i`.
fn get_raw(&self, i: super::KeyTypeId) -> &[u8];
/// Get the decoded key with index `i`.
fn get<T: Decode>(&self, i: super::KeyTypeId) -> Option<T> { T::decode(&mut self.get_raw(i)) }
fn get<T: Decode>(&self, i: super::KeyTypeId) -> Option<T> {
T::decode(&mut self.get_raw(i)).ok()
}
/// Verify a proof of ownership for the keys.
fn ownership_proof_is_valid(&self, _proof: &[u8]) -> bool { true }
}
/// Input that adds infinite number of zero after wrapped input.
struct TrailingZeroInput<'a>(&'a [u8]);
impl<'a> codec::Input for TrailingZeroInput<'a> {
fn read(&mut self, into: &mut [u8]) -> usize {
let len = into.len().min(self.0.len());
into[..len].copy_from_slice(&self.0[..len]);
for i in &mut into[len..] {
fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
Ok(None)
}
fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
let len_from_inner = into.len().min(self.0.len());
into[..len_from_inner].copy_from_slice(&self.0[..len_from_inner]);
for i in &mut into[len_from_inner..] {
*i = 0;
}
self.0 = &self.0[len..];
into.len()
self.0 = &self.0[len_from_inner..];
Ok(())
}
}
@@ -1091,7 +1100,7 @@ impl<T: Encode + Decode + Default, Id: Encode + Decode + TypeId> AccountIdConver
x.using_encoded(|d| {
if &d[0..4] != Id::TYPE_ID { return None }
let mut cursor = &d[4..];
let result = Decode::decode(&mut cursor)?;
let result = Decode::decode(&mut cursor).ok()?;
if cursor.iter().all(|x| *x == 0) {
Some(result)
} else {
@@ -1104,7 +1113,7 @@ impl<T: Encode + Decode + Default, Id: Encode + Decode + TypeId> AccountIdConver
#[cfg(test)]
mod tests {
use super::AccountIdConversion;
use crate::codec::{Encode, Decode};
use crate::codec::{Encode, Decode, Input};
#[derive(Encode, Decode, Default, PartialEq, Debug)]
struct U32Value(u32);
@@ -1153,6 +1162,22 @@ mod tests {
let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64);
assert!(r.is_none());
}
#[test]
fn trailing_zero_should_work() {
let mut t = super::TrailingZeroInput(&[1, 2, 3]);
assert_eq!(t.remaining_len(), Ok(None));
let mut buffer = [0u8; 2];
assert_eq!(t.read(&mut buffer), Ok(()));
assert_eq!(t.remaining_len(), Ok(None));
assert_eq!(buffer, [1, 2]);
assert_eq!(t.read(&mut buffer), Ok(()));
assert_eq!(t.remaining_len(), Ok(None));
assert_eq!(buffer, [3, 0]);
assert_eq!(t.read(&mut buffer), Ok(()));
assert_eq!(t.remaining_len(), Ok(None));
assert_eq!(buffer, [0, 0]);
}
}
/// Calls a given macro a number of times with a set of fixed params and an incrementing numeral.
@@ -17,7 +17,7 @@
//! Transaction validity interface.
use rstd::prelude::*;
use crate::codec::{Encode, Decode};
use crate::codec::{Encode, Decode, Error};
use crate::traits::DispatchError;
/// Priority for a transaction. Additive. Higher is better.
@@ -113,9 +113,9 @@ impl ValidTransaction {
}
impl Decode for TransactionValidity {
fn decode<I: crate::codec::Input>(value: &mut I) -> Option<Self> {
fn decode<I: crate::codec::Input>(value: &mut I) -> Result<Self, Error> {
match value.read_byte()? {
0 => Some(TransactionValidity::Invalid(i8::decode(value)?)),
0 => Ok(TransactionValidity::Invalid(i8::decode(value)?)),
1 => {
let priority = TransactionPriority::decode(value)?;
let requires = Vec::decode(value)?;
@@ -123,12 +123,12 @@ impl Decode for TransactionValidity {
let longevity = TransactionLongevity::decode(value)?;
let propagate = bool::decode(value).unwrap_or(true);
Some(TransactionValidity::Valid(ValidTransaction {
Ok(TransactionValidity::Valid(ValidTransaction {
priority, requires, provides, longevity, propagate,
}))
},
2 => Some(TransactionValidity::Unknown(i8::decode(value)?)),
_ => None,
2 => Ok(TransactionValidity::Unknown(i8::decode(value)?)),
_ => Err("Invalid transaction validity variant".into()),
}
}
}
@@ -143,7 +143,7 @@ mod tests {
1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0
];
assert_eq!(TransactionValidity::decode(&mut &*old_encoding), Some(TransactionValidity::Valid(ValidTransaction {
assert_eq!(TransactionValidity::decode(&mut &*old_encoding), Ok(TransactionValidity::Valid(ValidTransaction {
priority: 5,
requires: vec![vec![1, 2, 3, 4]],
provides: vec![vec![4, 5, 6]],
@@ -169,6 +169,6 @@ mod tests {
);
// decode back
assert_eq!(TransactionValidity::decode(&mut &*encoded), Some(v));
assert_eq!(TransactionValidity::decode(&mut &*encoded), Ok(v));
}
}