feat(primitives): Implement length-preserving uints (#92)

This commit is contained in:
Santiago Carmuega 2022-04-25 23:04:07 -03:00 committed by GitHub
parent 4ce608ea6f
commit 016b76d747
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 93 additions and 5 deletions

View file

@ -375,3 +375,87 @@ where
Ok(())
}
}
/// A uint structure that preserves original int length
#[derive(Debug, PartialEq, Copy, Clone, PartialOrd)]
pub enum AnyUInt {
MajorByte(u8),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
}
impl<'b> minicbor::decode::Decode<'b> for AnyUInt {
fn decode(d: &mut minicbor::Decoder<'b>) -> Result<Self, minicbor::decode::Error> {
match d.datatype()? {
minicbor::data::Type::U8 => match d.u8()? {
x @ 0..=0x17 => Ok(AnyUInt::MajorByte(x)),
x @ 0x18..=0xff => Ok(AnyUInt::U8(x)),
},
minicbor::data::Type::U16 => Ok(AnyUInt::U16(d.u16()?)),
minicbor::data::Type::U32 => Ok(AnyUInt::U32(d.u32()?)),
minicbor::data::Type::U64 => Ok(AnyUInt::U64(d.u64()?)),
_ => Err(minicbor::decode::Error::message(
"invalid data type for AnyUInt",
)),
}
}
}
impl minicbor::encode::Encode for AnyUInt {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
AnyUInt::MajorByte(x) => {
let b = &x.to_be_bytes()[..];
e.encode(minicbor::data::Cbor::from(b))?;
Ok(())
}
AnyUInt::U8(x) => {
let x = x.to_be_bytes();
let b = &[[24u8], x].concat()[..];
e.encode(minicbor::data::Cbor::from(b))?;
Ok(())
}
AnyUInt::U16(x) => {
let x = &x.to_be_bytes()[..];
let b = &[&[25u8], x].concat()[..];
e.encode(minicbor::data::Cbor::from(b))?;
Ok(())
}
AnyUInt::U32(x) => {
let x = &x.to_be_bytes()[..];
let b = &[&[26u8], x].concat()[..];
e.encode(minicbor::data::Cbor::from(b))?;
Ok(())
}
AnyUInt::U64(x) => {
let x = &x.to_be_bytes()[..];
let b = &[&[27u8], x].concat()[..];
e.encode(minicbor::data::Cbor::from(b))?;
Ok(())
}
}
}
}
impl From<AnyUInt> for u64 {
fn from(x: AnyUInt) -> Self {
match x {
AnyUInt::MajorByte(x) => x as u64,
AnyUInt::U8(x) => x as u64,
AnyUInt::U16(x) => x as u64,
AnyUInt::U32(x) => x as u64,
AnyUInt::U64(x) => x as u64,
}
}
}
impl From<&AnyUInt> for u64 {
fn from(x: &AnyUInt) -> Self {
u64::from(*x)
}
}

View file

@ -6,7 +6,7 @@ use pallas_codec::minicbor::{bytes::ByteVec, data::Int, data::Tag, Decode, Encod
use pallas_crypto::hash::Hash;
use std::ops::Deref;
use pallas_codec::utils::{KeyValuePairs, MaybeIndefArray};
use pallas_codec::utils::{AnyUInt, KeyValuePairs, MaybeIndefArray};
// required for derive attrs to work
use pallas_codec::minicbor;
@ -114,12 +114,12 @@ pub type Multiasset<A> = KeyValuePairs<PolicyId, KeyValuePairs<AssetName, A>>;
pub type Mint = Multiasset<i64>;
pub type Coin = u64;
pub type Coin = AnyUInt;
#[derive(Debug, PartialEq, Clone)]
pub enum Value {
Coin(Coin),
Multiasset(Coin, Multiasset<u64>),
Multiasset(Coin, Multiasset<Coin>),
}
impl<'b> minicbor::decode::Decode<'b> for Value {
@ -129,7 +129,7 @@ impl<'b> minicbor::decode::Decode<'b> for Value {
minicbor::data::Type::U64 => Ok(Value::Coin(d.decode()?)),
minicbor::data::Type::Array => {
d.array()?;
let coin = d.u64()?;
let coin = d.decode()?;
let multiasset = d.decode()?;
Ok(Value::Multiasset(coin, multiasset))
}
@ -170,7 +170,7 @@ pub struct TransactionOutput {
pub amount: Value,
#[n(2)]
pub datum_hash: Option<ByteVec>,
pub datum_hash: Option<Hash<32>>,
}
pub type PoolKeyhash = Hash<28>;
@ -699,6 +699,7 @@ pub enum TransactionBodyComponent {
RequiredSigners(MaybeIndefArray<AddrKeyhash>),
NetworkId(NetworkId),
}
impl<'b> minicbor::decode::Decode<'b> for TransactionBodyComponent {
fn decode(d: &mut minicbor::Decoder<'b>) -> Result<Self, minicbor::decode::Error> {
let key: u32 = d.decode()?;
@ -1442,6 +1443,8 @@ mod tests {
include_str!("test_data/test19.block"),
// peculiar block with very BigInt in plutus code
include_str!("test_data/test20.block"),
// peculiar block with bad tx hash
include_str!("test_data/test21.block"),
];
for (idx, block_str) in test_blocks.iter().enumerate() {

File diff suppressed because one or more lines are too long