From c3188c4146f7627e11f2f3a7d2797e38723556a9 Mon Sep 17 00:00:00 2001 From: Michael Zaikin Date: Tue, 3 Jan 2023 00:01:15 +0200 Subject: [PATCH] Fix existing and add new instructions --- tezos-contract/src/contract.rs | 2 +- tezos-michelson/src/internal/normalizer.rs | 4 +- tezos-michelson/src/internal/packer.rs | 2 +- .../src/michelson/data/instructions.rs | 25 +++++++-- .../src/michelson/data/instructions/macros.rs | 32 +++++++----- tezos-michelson/src/michelson/metadata.rs | 51 +++++++++++++++++++ tezos-michelson/src/michelson/types.rs | 15 +++--- 7 files changed, 101 insertions(+), 30 deletions(-) diff --git a/tezos-contract/src/contract.rs b/tezos-contract/src/contract.rs index 6d35ed1..0f8948b 100644 --- a/tezos-contract/src/contract.rs +++ b/tezos-contract/src/contract.rs @@ -363,7 +363,7 @@ impl CompatibleWith for DataSequence { let element_type = &value.r#type; self.values() .iter() - .all(|item| item.is_compatible_with(&element_type.clone().into())) + .all(|item| item.is_compatible_with(&element_type)) } Type::Pair(_) => { let pair: Data = Pair::new(self.clone().into_values()).into(); diff --git a/tezos-michelson/src/internal/normalizer.rs b/tezos-michelson/src/internal/normalizer.rs index 5371585..187f551 100644 --- a/tezos-michelson/src/internal/normalizer.rs +++ b/tezos-michelson/src/internal/normalizer.rs @@ -123,7 +123,7 @@ impl Normalizer for MichelsonNormalizer { types::List::new(Self::normalize(*value.r#type), Some(value.metadata)).into() } Type::Set(value) => { - types::Set::new(Self::normalize(value.r#type), Some(value.metadata)).into() + types::Set::new(Self::normalize(*value.r#type), Some(value.metadata)).into() } Type::Contract(value) => { types::Contract::new(Self::normalize(*value.r#type), Some(value.metadata)).into() @@ -269,7 +269,7 @@ impl Normalizer for MichelsonNormalizer { } Instruction::Loop(value) => instructions::Loop::new(Self::normalize(value.body)).into(), Instruction::Dip(value) => { - instructions::Dip::new(Self::normalize(value.instruction), value.n).into() + instructions::Dip::new(value.n, Self::normalize(value.instruction)).into() } Instruction::EmptyBigMap(value) => instructions::EmptyBigMap::new( Self::normalize(value.key_type), diff --git a/tezos-michelson/src/internal/packer.rs b/tezos-michelson/src/internal/packer.rs index 818ba18..7d2ffa0 100644 --- a/tezos-michelson/src/internal/packer.rs +++ b/tezos-michelson/src/internal/packer.rs @@ -1150,8 +1150,8 @@ mod test { ( &hex!("050200000009051f0200000002034f"), vec![data::instructions::dip( - vec![data::instructions::unit()].into(), None, + vec![data::instructions::unit()].into(), )] .into(), Some(types::lambda(types::unit(), types::unit())), diff --git a/tezos-michelson/src/michelson/data/instructions.rs b/tezos-michelson/src/michelson/data/instructions.rs index a60e7ff..71eb4d8 100644 --- a/tezos-michelson/src/michelson/data/instructions.rs +++ b/tezos-michelson/src/michelson/data/instructions.rs @@ -8,7 +8,7 @@ make_instructions!( (Swap, SWAP, swap, 76), (GetAndUpdate, GET_AND_UPDATE, get_and_update, 140), (Apply, APPLY, apply, 115), - (FailWith, FAIL_WITH, fail_with, 39), + (FailWith, FAILWITH, failwith, 39), ( Rename, RENAME, @@ -28,7 +28,8 @@ make_instructions!( CAST, cast, 87, - metadata_type: crate::michelson::metadata::VariableMetadata + metadata_type: crate::michelson::metadata::VariableMetadata, + (r#type: crate::michelson::types::Type) ), ( Cdr, @@ -118,7 +119,14 @@ make_instructions!( ), (Slice, SLICE, slice, 111), (Pack, PACK, pack, 12), - (Unpack, UNPACK, unpack, 13), + ( + Unpack, + UNPACK, + unpack, + 13, + metadata_type: crate::michelson::metadata::TypeVariableMetadata, + (r#type: crate::michelson::types::Type) + ), ( Add, ADD, @@ -298,6 +306,13 @@ make_instructions!( 75, metadata_type: crate::michelson::metadata::VariableMetadata ), + ( + SubMutez, + SUB_MUTEZ, + sub_mutez, + 147, + metadata_type: crate::michelson::metadata::VariableMetadata + ), ( Mul, MUL, @@ -436,7 +451,7 @@ make_instructions!( SELF, self_, 73, - metadata_type: crate::michelson::metadata::VariableMetadata + metadata_type: crate::michelson::metadata::FieldMetadata ), ( SelfAddress, @@ -450,7 +465,7 @@ make_instructions!( CONTRACT, contract, 85, - metadata_type: crate::michelson::metadata::VariableMetadata, + metadata_type: crate::michelson::metadata::FieldMetadata, (r#type: crate::michelson::types::Type) ), (TransferTokens, TRANSFER_TOKENS, transfer_tokens, 77), diff --git a/tezos-michelson/src/michelson/data/instructions/macros.rs b/tezos-michelson/src/michelson/data/instructions/macros.rs index 6905883..bb4e2a3 100644 --- a/tezos-michelson/src/michelson/data/instructions/macros.rs +++ b/tezos-michelson/src/michelson/data/instructions/macros.rs @@ -117,10 +117,10 @@ macro_rules! make_instruction { #[derive(Debug, Clone, PartialEq)] pub struct $name { $( - pub $field_name: $field_type, + pub $opt_field_name: Option<$opt_field_type>, )* $( - pub $opt_field_name: Option<$opt_field_type>, + pub $field_name: $field_type, )* $( pub $boxed_field_name: Box<$boxed_field_type>, @@ -141,10 +141,10 @@ macro_rules! make_instruction { } )? - pub fn new($($field_name: $field_type,)* $($opt_field_name: Option<$opt_field_type>,)* $($boxed_field_name: $boxed_field_type,)* $(metadata: $metadata_type)?) -> Self { + pub fn new($($opt_field_name: Option<$opt_field_type>,)* $($field_name: $field_type,)* $($boxed_field_name: $boxed_field_type,)* $(metadata: $metadata_type)?) -> Self { Self { - $($field_name,)* $($opt_field_name,)* + $($field_name,)* $($boxed_field_name: Box::new($boxed_field_name),)* $( metadata: metadata as $metadata_type @@ -206,14 +206,14 @@ macro_rules! make_instruction { #[allow(unused)] fn from(value: $name) -> Self { let mut args: Vec = vec![]; - $( - args.push(value.$field_name.into()); - )* $( if let Some(value) = value.$opt_field_name { args.push(value.into()); } )* + $( + args.push(value.$field_name.into()); + )* $( args.push((*value.$boxed_field_name).into()); )* @@ -232,14 +232,14 @@ macro_rules! make_instruction { #[allow(unused)] fn from(value: &$name) -> Self { let mut args: Vec = vec![]; - $( - args.push((&value.$field_name).into()); - )* $( if let Some(value) = &value.$opt_field_name { args.push(value.into()); } )* + $( + args.push((&value.$field_name).into()); + )* $( args.push((&*value.$boxed_field_name).into()); )* @@ -268,10 +268,14 @@ macro_rules! make_instruction { let mut args = value.into_args().unwrap_or(vec![]); Ok(Self { $( - $field_name: if !args.is_empty() { args.remove(0).try_into()? } else { Err(Error::InvalidPrimitiveApplication)? }, + $opt_field_name: match args.get(0) { + Some(Micheline::Literal(_)) => Some(args.remove(0).try_into()?), + Some(_) => None, + None => None + }, )* $( - $opt_field_name: if !args.is_empty() { Some(args.remove(0).try_into()?) } else { None }, + $field_name: if !args.is_empty() { args.remove(0).try_into()? } else { Err(Error::InvalidPrimitiveApplication)? }, )* $( $boxed_field_name: if !args.is_empty() { Box::new(args.remove(0).try_into()?) } else { Err(Error::InvalidPrimitiveApplication)? }, @@ -283,10 +287,10 @@ macro_rules! make_instruction { } } - pub fn $mod_name($($field_name: $field_type,)* $($opt_field_name: Option<$opt_field_type>,)* $($boxed_field_name: $boxed_field_type,)*) -> Output where Output: From<$name> { + pub fn $mod_name($($opt_field_name: Option<$opt_field_type>,)* $($field_name: $field_type,)* $($boxed_field_name: $boxed_field_type,)*) -> Output where Output: From<$name> { $name::new( - $($field_name, )* $($opt_field_name, )* + $($field_name, )* $($boxed_field_name,)* $(<$metadata_type>::default(), )? ).into() diff --git a/tezos-michelson/src/michelson/metadata.rs b/tezos-michelson/src/michelson/metadata.rs index 3665941..3b457b9 100644 --- a/tezos-michelson/src/michelson/metadata.rs +++ b/tezos-michelson/src/michelson/metadata.rs @@ -1,6 +1,57 @@ use super::annotations::{Annotation, Kind}; use crate::{micheline::primitive_application::PrimitiveApplication, Error, Result}; +#[derive(Debug, Clone, PartialEq)] +pub struct FieldMetadata { + field_name: Option, +} + +impl FieldMetadata { + pub fn field_name(&self) -> &Option { + &self.field_name + } + + pub fn annotations(&self) -> Vec<&Annotation> { + vec![self.field_name()] + .into_iter() + .flat_map(|annot| annot) + .collect::>() + } + + pub fn new(field_name: Option) -> Result { + if let Some(field_name) = &field_name { + if !Self::is_valid_field_name(&field_name) { + return Err(Error::InvalidAnnotation); + } + } + Ok(Self { field_name }) + } + + pub fn with_field_name(mut self, name: String) -> Self { + self.field_name = Some(Annotation::new_with_kind(Kind::Field, name)); + + self + } + + fn is_valid_field_name(annotation: &Annotation) -> bool { + annotation.kind() == Kind::Field + } +} + +impl Default for FieldMetadata { + fn default() -> Self { + Self { field_name: None } + } +} + +impl TryFrom<&PrimitiveApplication> for FieldMetadata { + type Error = Error; + + fn try_from(value: &PrimitiveApplication) -> Result { + Self::new(value.first_annot(Kind::Field)?) + } +} + #[derive(Debug, Clone, PartialEq)] pub struct TypeFieldMetadata { type_name: Option, diff --git a/tezos-michelson/src/michelson/types.rs b/tezos-michelson/src/michelson/types.rs index 70788b7..0e1b7bd 100644 --- a/tezos-michelson/src/michelson/types.rs +++ b/tezos-michelson/src/michelson/types.rs @@ -38,12 +38,7 @@ make_types!( ), (Option, option, 99, boxed: (r#type: Type)), (List, list, 95, boxed: (r#type: Type)), - ( - Set, - set, - 102, - (r#type: crate::michelson::types::comparables::Type) - ), + (Set, set, 102, boxed: (r#type: Type)), (Operation, operation, 109), (Contract, contract, 90, boxed: (r#type: Type)), (Ticket, ticket, 135, boxed: (r#type: Type)), @@ -56,7 +51,13 @@ make_types!( boxed: (parameter_type: Type), boxed: (return_type: Type) ), - (Map, map, 96, boxed: (key_type: Type), boxed: (value_type: Type)), + ( + Map, + map, + 96, + boxed: (key_type: Type), + boxed: (value_type: Type) + ), ( BigMap, big_map,