From 61b70e7e3df93d409ab7845d150c1b75776724f9 Mon Sep 17 00:00:00 2001 From: rvcas Date: Thu, 4 Aug 2022 11:59:40 -0400 Subject: [PATCH] feat: encode plutus data --- Cargo.lock | 117 +++++++++++++++++++++++++++++++++++++++- crates/uplc/Cargo.toml | 1 + crates/uplc/src/ast.rs | 13 ++--- crates/uplc/src/flat.rs | 23 +++++--- 4 files changed, 134 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef523a26..0e9415ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + +[[package]] +name = "bech32" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5738be7561b0eeb501ef1d5c5db3f24e01ceb55fededd9b00039aada34966ad" + [[package]] name = "bit-set" version = "0.5.2" @@ -112,6 +124,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "cryptoxide" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129eabb7b0b78644a3a7e7cf220714aba47463bb281f69fa7a71ca5d12564cca" + [[package]] name = "fastrand" version = "1.7.0" @@ -146,6 +164,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "hashbrown" version = "0.11.2" @@ -192,6 +216,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + [[package]] name = "lazy_static" version = "1.4.0" @@ -213,13 +243,34 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "minicbor" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e575910763b21a0db7df5e142907fe944bff84d1dfc78e2ba92e7f3bdfd36b" +dependencies = [ + "half", + "minicbor-derive 0.11.0", +] + [[package]] name = "minicbor" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a20020e8e2d1881d8736f64011bb5ff99f1db9947ce3089706945c8915695cb" dependencies = [ - "minicbor-derive", + "minicbor-derive 0.12.0", +] + +[[package]] +name = "minicbor-derive" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a86c5f04def8fb7735ae918bb589af82f985526f4c62e0249544b668b2f456" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -248,6 +299,44 @@ version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d8d0b2f198229de29dca79676f2738ff952edf3fde542eb8bf94d8c21b435" +[[package]] +name = "pallas-codec" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dce0ea17341c1a0e43e2bb4a637740198dcb09826879ce3ac5ae1c6f4398a5d" +dependencies = [ + "minicbor 0.17.1", +] + +[[package]] +name = "pallas-crypto" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051226367cd851895c73e3115d378b58495ade1ee60c3a154c0d0c30554565fa" +dependencies = [ + "cryptoxide", + "hex", + "pallas-codec", + "rand_core", + "thiserror", +] + +[[package]] +name = "pallas-primitives" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a0fcc7d5a7120bc2b2e203ec5e7f8088107c500c0eb665569d0e77a910d3c0" +dependencies = [ + "base58", + "bech32", + "hex", + "log", + "pallas-codec", + "pallas-crypto", + "serde", + "serde_json", +] + [[package]] name = "peg" version = "0.8.0" @@ -442,6 +531,29 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "serde" +version = "1.0.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2" + +[[package]] +name = "serde_json" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "strsim" version = "0.10.0" @@ -532,7 +644,8 @@ version = "0.0.6" dependencies = [ "flat-rs", "hex", - "minicbor", + "minicbor 0.18.0", + "pallas-primitives", "peg", "pretty", "proptest", diff --git a/crates/uplc/Cargo.toml b/crates/uplc/Cargo.toml index 8c917ca3..d2fb4e51 100644 --- a/crates/uplc/Cargo.toml +++ b/crates/uplc/Cargo.toml @@ -16,6 +16,7 @@ exclude = ["test_data/*"] flat-rs = { path = "../flat", version = "0.0.6" } hex = "0.4.3" minicbor = { version = "0.18.0", features = ["std"] } +pallas-primitives = "0.12.0" peg = "0.8.0" pretty = "0.11.3" thiserror = "1.0.31" diff --git a/crates/uplc/src/ast.rs b/crates/uplc/src/ast.rs index 5ccfcbca..e02570eb 100644 --- a/crates/uplc/src/ast.rs +++ b/crates/uplc/src/ast.rs @@ -1,5 +1,7 @@ use std::fmt::Display; +use pallas_primitives::alonzo::PlutusData; + use crate::{ builtins::DefaultFunction, debruijn::{self, Converter}, @@ -109,7 +111,7 @@ pub enum Constant { // tag: 7 // Apply(Box, Type), // tag: 8 - Data(Data), + Data(PlutusData), } #[derive(Debug, Clone, PartialEq)] @@ -139,15 +141,6 @@ impl Display for Type { } } -#[derive(Debug, Clone, PartialEq)] -pub enum Data { - Constr(isize, Vec), - Map(Vec<(Data, Data)>), - List(Vec), - I(isize), - B(Vec), -} - /// A Name containing it's parsed textual representation /// and a unique id from string interning. The Name's text is /// interned during parsing. diff --git a/crates/uplc/src/flat.rs b/crates/uplc/src/flat.rs index 04f191aa..d7a44a85 100644 --- a/crates/uplc/src/flat.rs +++ b/crates/uplc/src/flat.rs @@ -5,6 +5,7 @@ use flat_rs::{ en::{self, Encode, Encoder}, Flat, }; +use pallas_primitives::Fragment; use crate::{ ast::{ @@ -78,6 +79,7 @@ where fn decode(d: &mut Decoder) -> Result { let version = (usize::decode(d)?, usize::decode(d)?, usize::decode(d)?); let term = Term::decode(d)?; + Ok(Program { version, term }) } } @@ -163,15 +165,15 @@ where } } +/// Integers are typically smaller so we save space +/// by encoding them in 7 bits and this allows it to be byte alignment agnostic. +/// Strings and bytestrings span multiple bytes so using bytestring is +/// the most effective encoding. +/// i.e. A 17 or greater length byte array loses efficiency being encoded as +/// a unsigned integer instead of a byte array impl Encode for Constant { fn encode(&self, e: &mut Encoder) -> Result<(), en::Error> { match self { - // Integers are typically smaller so we save space - // by encoding them in 7 bits and this allows it to be byte alignment agnostic. - // Strings and bytestrings span multiple bytes so using bytestring is - // the most effective encoding. - // i.e. A 17 or greater length byte array loses efficiency being encoded as - // a unsigned integer instead of a byte array Constant::Integer(i) => { encode_constant(&[0], e)?; i.encode(e)?; @@ -210,9 +212,14 @@ impl Encode for Constant { encode_constant_value(a, e)?; encode_constant_value(b, e)?; } - Constant::Data(_) => { + Constant::Data(data) => { encode_constant(&[8], e)?; - todo!() + + let cbor = data + .encode_fragment() + .map_err(|err| en::Error::Message(err.to_string()))?; + + cbor.encode(e)?; } }