fix: use PlutusBytes to encode BigUInt/BigNInt (#216)
This commit is contained in:
parent
d2a784edb3
commit
8480c4502f
4 changed files with 96 additions and 94 deletions
|
|
@ -786,88 +786,6 @@ impl fmt::Display for Bytes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defined to encode PlutusData bytestring as it is done in the canonical plutus implementation
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
#[serde(into = "String")]
|
|
||||||
#[serde(try_from = "String")]
|
|
||||||
pub struct PlutusBytes(Vec<u8>);
|
|
||||||
|
|
||||||
impl From<Vec<u8>> for PlutusBytes {
|
|
||||||
fn from(xs: Vec<u8>) -> Self {
|
|
||||||
PlutusBytes(xs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<PlutusBytes> for Vec<u8> {
|
|
||||||
fn from(b: PlutusBytes) -> Self {
|
|
||||||
b.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for PlutusBytes {
|
|
||||||
type Target = Vec<u8>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<String> for PlutusBytes {
|
|
||||||
type Error = hex::FromHexError;
|
|
||||||
|
|
||||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
|
||||||
let v = hex::decode(value)?;
|
|
||||||
Ok(PlutusBytes(v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<PlutusBytes> for String {
|
|
||||||
fn from(b: PlutusBytes) -> Self {
|
|
||||||
hex::encode(b.deref())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for PlutusBytes {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
let bytes: Vec<u8> = self.clone().into();
|
|
||||||
|
|
||||||
f.write_str(&hex::encode(bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C> Encode<C> for PlutusBytes {
|
|
||||||
fn encode<W: minicbor::encode::Write>(
|
|
||||||
&self,
|
|
||||||
e: &mut minicbor::Encoder<W>,
|
|
||||||
_: &mut C,
|
|
||||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
|
||||||
// we match the haskell implementation by encoding bytestrings longer than 64 bytes as indefinite lists of bytes
|
|
||||||
const CHUNK_SIZE: usize = 64;
|
|
||||||
let bs: &Vec<u8> = self.deref();
|
|
||||||
if bs.len() <= 64 {
|
|
||||||
e.bytes(bs)?;
|
|
||||||
} else {
|
|
||||||
e.begin_bytes()?;
|
|
||||||
for b in bs.chunks(CHUNK_SIZE) {
|
|
||||||
e.bytes(b)?;
|
|
||||||
}
|
|
||||||
e.end()?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'b, C> minicbor::decode::Decode<'b, C> for PlutusBytes {
|
|
||||||
fn decode(d: &mut minicbor::Decoder<'b>, _: &mut C) -> Result<Self, minicbor::decode::Error> {
|
|
||||||
let mut res = Vec::new();
|
|
||||||
for chunk in d.bytes_iter()? {
|
|
||||||
let bs = chunk?;
|
|
||||||
res.extend_from_slice(bs);
|
|
||||||
}
|
|
||||||
Ok(PlutusBytes::from(res))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Serialize, Deserialize, Clone, Copy, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord,
|
Serialize, Deserialize, Clone, Copy, Encode, Decode, Debug, PartialEq, Eq, PartialOrd, Ord,
|
||||||
)]
|
)]
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,12 @@
|
||||||
//! Handcrafted, idiomatic rust artifacts based on based on the [Alonzo CDDL](https://github.com/input-output-hk/cardano-ledger/blob/master/eras/alonzo/test-suite/cddl-files/alonzo.cddl) file in IOHK repo.
|
//! Handcrafted, idiomatic rust artifacts based on based on the [Alonzo CDDL](https://github.com/input-output-hk/cardano-ledger/blob/master/eras/alonzo/test-suite/cddl-files/alonzo.cddl) file in IOHK repo.
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{fmt, ops::Deref};
|
||||||
|
|
||||||
use pallas_codec::minicbor::{data::Tag, Decode, Encode};
|
use pallas_codec::minicbor::{data::Tag, Decode, Encode};
|
||||||
use pallas_crypto::hash::Hash;
|
use pallas_crypto::hash::Hash;
|
||||||
|
|
||||||
use pallas_codec::utils::{
|
use pallas_codec::utils::{Bytes, Int, KeepRaw, KeyValuePairs, MaybeIndefArray, Nullable};
|
||||||
Bytes, Int, KeepRaw, KeyValuePairs, MaybeIndefArray, Nullable, PlutusBytes,
|
|
||||||
};
|
|
||||||
|
|
||||||
// required for derive attrs to work
|
// required for derive attrs to work
|
||||||
use pallas_codec::minicbor;
|
use pallas_codec::minicbor;
|
||||||
|
|
@ -845,6 +844,88 @@ impl AsRef<[u8]> for PlutusScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defined to encode PlutusData bytestring as it is done in the canonical plutus implementation
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[serde(into = "String")]
|
||||||
|
#[serde(try_from = "String")]
|
||||||
|
pub struct BoundedBytes(Vec<u8>);
|
||||||
|
|
||||||
|
impl From<Vec<u8>> for BoundedBytes {
|
||||||
|
fn from(xs: Vec<u8>) -> Self {
|
||||||
|
BoundedBytes(xs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BoundedBytes> for Vec<u8> {
|
||||||
|
fn from(b: BoundedBytes) -> Self {
|
||||||
|
b.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for BoundedBytes {
|
||||||
|
type Target = Vec<u8>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for BoundedBytes {
|
||||||
|
type Error = hex::FromHexError;
|
||||||
|
|
||||||
|
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||||
|
let v = hex::decode(value)?;
|
||||||
|
Ok(BoundedBytes(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BoundedBytes> for String {
|
||||||
|
fn from(b: BoundedBytes) -> Self {
|
||||||
|
hex::encode(b.deref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for BoundedBytes {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let bytes: Vec<u8> = self.clone().into();
|
||||||
|
|
||||||
|
f.write_str(&hex::encode(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C> Encode<C> for BoundedBytes {
|
||||||
|
fn encode<W: minicbor::encode::Write>(
|
||||||
|
&self,
|
||||||
|
e: &mut minicbor::Encoder<W>,
|
||||||
|
_: &mut C,
|
||||||
|
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||||
|
// we match the haskell implementation by encoding bytestrings longer than 64 bytes as indefinite lists of bytes
|
||||||
|
const CHUNK_SIZE: usize = 64;
|
||||||
|
let bs: &Vec<u8> = self.deref();
|
||||||
|
if bs.len() <= 64 {
|
||||||
|
e.bytes(bs)?;
|
||||||
|
} else {
|
||||||
|
e.begin_bytes()?;
|
||||||
|
for b in bs.chunks(CHUNK_SIZE) {
|
||||||
|
e.bytes(b)?;
|
||||||
|
}
|
||||||
|
e.end()?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'b, C> minicbor::decode::Decode<'b, C> for BoundedBytes {
|
||||||
|
fn decode(d: &mut minicbor::Decoder<'b>, _: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
for chunk in d.bytes_iter()? {
|
||||||
|
let bs = chunk?;
|
||||||
|
res.extend_from_slice(bs);
|
||||||
|
}
|
||||||
|
Ok(BoundedBytes::from(res))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
big_int = int / big_uint / big_nint ; New
|
big_int = int / big_uint / big_nint ; New
|
||||||
big_uint = #6.2(bounded_bytes) ; New
|
big_uint = #6.2(bounded_bytes) ; New
|
||||||
|
|
@ -854,8 +935,8 @@ big_nint = #6.3(bounded_bytes) ; New
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub enum BigInt {
|
pub enum BigInt {
|
||||||
Int(Int),
|
Int(Int),
|
||||||
BigUInt(Bytes),
|
BigUInt(BoundedBytes),
|
||||||
BigNInt(Bytes),
|
BigNInt(BoundedBytes),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, C> minicbor::decode::Decode<'b, C> for BigInt {
|
impl<'b, C> minicbor::decode::Decode<'b, C> for BigInt {
|
||||||
|
|
@ -919,7 +1000,7 @@ pub enum PlutusData {
|
||||||
Constr(Constr<PlutusData>),
|
Constr(Constr<PlutusData>),
|
||||||
Map(KeyValuePairs<PlutusData, PlutusData>),
|
Map(KeyValuePairs<PlutusData, PlutusData>),
|
||||||
BigInt(BigInt),
|
BigInt(BigInt),
|
||||||
BoundedBytes(PlutusBytes),
|
BoundedBytes(BoundedBytes),
|
||||||
Array(Vec<PlutusData>),
|
Array(Vec<PlutusData>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -962,7 +1043,7 @@ impl<'b, C> minicbor::decode::Decode<'b, C> for PlutusData {
|
||||||
full.extend(slice?);
|
full.extend(slice?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self::BoundedBytes(PlutusBytes::from(full)))
|
Ok(Self::BoundedBytes(BoundedBytes::from(full)))
|
||||||
}
|
}
|
||||||
minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
|
minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
|
||||||
Ok(Self::Array(d.decode_with(ctx)?))
|
Ok(Self::Array(d.decode_with(ctx)?))
|
||||||
|
|
|
||||||
|
|
@ -684,6 +684,8 @@ mod tests {
|
||||||
include_str!("../../../test_data/babbage6.block"),
|
include_str!("../../../test_data/babbage6.block"),
|
||||||
// block with generic int in cbor
|
// block with generic int in cbor
|
||||||
include_str!("../../../test_data/babbage7.block"),
|
include_str!("../../../test_data/babbage7.block"),
|
||||||
|
// block with indef bytes for plutus data bignum
|
||||||
|
include_str!("../../../test_data/babbage8.block"),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (idx, block_str) in test_blocks.iter().enumerate() {
|
for (idx, block_str) in test_blocks.iter().enumerate() {
|
||||||
|
|
|
||||||
1
test_data/babbage8.block
Normal file
1
test_data/babbage8.block
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue