From c9e5d823f4d0c56ce2cc67f81f6f1227875fd91c Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Mon, 11 Dec 2023 17:22:02 +0300 Subject: [PATCH 1/6] MIR: Add MUL instruction for BLS types --- contrib/mir/src/ast.rs | 1 + contrib/mir/src/ast/overloads.rs | 11 +++ contrib/mir/src/gas.rs | 12 +++ contrib/mir/src/interpreter.rs | 132 +++++++++++++++++++++++++++++++ contrib/mir/src/typechecker.rs | 106 +++++++++++++++++++++++++ 5 files changed, 262 insertions(+) diff --git a/contrib/mir/src/ast.rs b/contrib/mir/src/ast.rs index bbece0653953..8d0dcf649820 100644 --- a/contrib/mir/src/ast.rs +++ b/contrib/mir/src/ast.rs @@ -398,6 +398,7 @@ impl<'a> TypedValue<'a> { #[derive(Debug, Eq, PartialEq, Clone)] pub enum Instruction<'a> { Add(overloads::Add), + Mul(overloads::Mul), Dip(Option, Vec), Drop(Option), Dup(Option), diff --git a/contrib/mir/src/ast/overloads.rs b/contrib/mir/src/ast/overloads.rs index 34dcee615b64..96d1ae72ee6a 100644 --- a/contrib/mir/src/ast/overloads.rs +++ b/contrib/mir/src/ast/overloads.rs @@ -53,6 +53,17 @@ pub enum Mem { Map, } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Mul { + Bls12381G1Bls12381Fr, + Bls12381G2Bls12381Fr, + Bls12381FrBls12381Fr, + NatBls12381Fr, + IntBls12381Fr, + Bls12381FrNat, + Bls12381FrInt, +} + #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Get { Map, diff --git a/contrib/mir/src/gas.rs b/contrib/mir/src/gas.rs index d281e1947ff1..d0c54a55114d 100644 --- a/contrib/mir/src/gas.rs +++ b/contrib/mir/src/gas.rs @@ -238,6 +238,9 @@ pub mod interpret_cost { pub const ADD_BLS_FR: u32 = 30; pub const ADD_BLS_G1: u32 = 900; pub const ADD_BLS_G2: u32 = 2470; + pub const MUL_BLS_G1: u32 = 103000; + pub const MUL_BLS_G2: u32 = 220000; + pub const MUL_BLS_FR: u32 = 45; pub const UNIT: u32 = 10; pub const AND_BOOL: u32 = 10; pub const OR_BOOL: u32 = 10; @@ -685,6 +688,15 @@ pub mod interpret_cost { pub fn pairing_check(size: usize) -> Result { (450_000 + 342_500 * Checked::from(size)).as_gas_cost() } + + pub fn mul_bls_fr_big_int(int: &impl BigIntByteSize) -> Result { + // 265. + 1.0625 * size + // NB: cost_N_IMul_bls12_381_fr_z and + // cost_N_IMul_bls12_381_z_fr ar distinct in the protocol, but they're the + // same exact operation, so we opted to use one function. + let size = Checked::from(int.byte_size()); + (265 + ((size >> 4) + size)).as_gas_cost() + } } #[cfg(test)] diff --git a/contrib/mir/src/interpreter.rs b/contrib/mir/src/interpreter.rs index 579967fc379f..99815fe17e9f 100644 --- a/contrib/mir/src/interpreter.rs +++ b/contrib/mir/src/interpreter.rs @@ -199,6 +199,54 @@ fn interpret_one<'a>( stack.push(V::Bls12381G2(o1 + o2)); } }, + I::Mul(overload) => match overload { + overloads::Mul::Bls12381G1Bls12381Fr => { + ctx.gas.consume(interpret_cost::MUL_BLS_G1)?; + let x1 = pop!(V::Bls12381G1); + let x2 = pop!(V::Bls12381Fr); + stack.push(V::Bls12381G1(x1 * x2)); + } + overloads::Mul::Bls12381G2Bls12381Fr => { + ctx.gas.consume(interpret_cost::MUL_BLS_G2)?; + let x1 = pop!(V::Bls12381G2); + let x2 = pop!(V::Bls12381Fr); + stack.push(V::Bls12381G2(x1 * x2)); + } + overloads::Mul::Bls12381FrBls12381Fr => { + ctx.gas.consume(interpret_cost::MUL_BLS_FR)?; + let x1 = pop!(V::Bls12381Fr); + let x2 = pop!(V::Bls12381Fr); + stack.push(V::Bls12381Fr(x1 * x2)); + } + overloads::Mul::NatBls12381Fr => { + let nat = pop!(V::Nat); + ctx.gas.consume(interpret_cost::mul_bls_fr_big_int(&nat)?)?; + let x1 = bls::Fr::from_big_int(&nat.into()); + let x2 = pop!(V::Bls12381Fr); + stack.push(V::Bls12381Fr(x1 * x2)); + } + overloads::Mul::IntBls12381Fr => { + let int = pop!(V::Int); + ctx.gas.consume(interpret_cost::mul_bls_fr_big_int(&int)?)?; + let x1 = bls::Fr::from_big_int(&int); + let x2 = pop!(V::Bls12381Fr); + stack.push(V::Bls12381Fr(x1 * x2)); + } + overloads::Mul::Bls12381FrNat => { + let x1 = pop!(V::Bls12381Fr); + let nat = pop!(V::Nat); + ctx.gas.consume(interpret_cost::mul_bls_fr_big_int(&nat)?)?; + let x2 = bls::Fr::from_big_int(&nat.into()); + stack.push(V::Bls12381Fr(x1 * x2)); + } + overloads::Mul::Bls12381FrInt => { + let x1 = pop!(V::Bls12381Fr); + let int = pop!(V::Int); + ctx.gas.consume(interpret_cost::mul_bls_fr_big_int(&int)?)?; + let x2 = bls::Fr::from_big_int(&int); + stack.push(V::Bls12381Fr(x1 * x2)); + } + }, I::And(overload) => match overload { overloads::And::Bool => { let o1 = pop!(V::Bool); @@ -3785,4 +3833,88 @@ mod interpreter_tests { assert_eq!(stack, stk![V::Bool(true)]); assert!(Ctx::default().gas.milligas() > ctx.gas.milligas()); } + + mod mul { + use super::*; + + #[track_caller] + fn test_mul( + overload: overloads::Mul, + input1: TypedValue, + input2: TypedValue, + output: TypedValue, + ) { + let mut stack = stk![input2, input1]; + let ctx = &mut Ctx::default(); + assert_eq!(interpret_one(&Mul(overload), ctx, &mut stack), Ok(())); + assert_eq!(stack, stk![output]); + // assert some gas is consumed, exact values are subject to change + assert!(Ctx::default().gas.milligas() > ctx.gas.milligas()); + } + + use crate::bls::*; + use TypedValue as V; + + macro_rules! test { + ($overload:ident, $i1:expr, $i2:expr, $out:expr $(,)*) => { + #[test] + #[allow(non_snake_case)] + fn $overload() { + test_mul(overloads::Mul::$overload, $i1, $i2, $out); + } + }; + } + + // NB: actual bls arithmetic is tested in the bls module, here we only + // need to check the interpreter works. + + test!( + Bls12381G1Bls12381Fr, + V::Bls12381G1(G1::one()), + V::Bls12381Fr(Fr::one()), + V::Bls12381G1(G1::one()), + ); + + test!( + Bls12381G2Bls12381Fr, + V::Bls12381G2(G2::one()), + V::Bls12381Fr(Fr::one()), + V::Bls12381G2(G2::one()), + ); + + test!( + Bls12381FrBls12381Fr, + V::Bls12381Fr(Fr::one()), + V::Bls12381Fr(Fr::one()), + V::Bls12381Fr(Fr::one()), + ); + + test!( + NatBls12381Fr, + V::Nat(1u8.into()), + V::Bls12381Fr(Fr::one()), + V::Bls12381Fr(Fr::one()), + ); + + test!( + IntBls12381Fr, + V::Int(1.into()), + V::Bls12381Fr(Fr::one()), + V::Bls12381Fr(Fr::one()), + ); + + test!( + Bls12381FrNat, + V::Bls12381Fr(Fr::one()), + V::Nat(1u8.into()), + V::Bls12381Fr(Fr::one()), + ); + + test!( + Bls12381FrInt, + V::Bls12381Fr(Fr::one()), + V::Int(1.into()), + V::Bls12381Fr(Fr::one()), + ); + } } diff --git a/contrib/mir/src/typechecker.rs b/contrib/mir/src/typechecker.rs index d283788f7dde..06399d106db6 100644 --- a/contrib/mir/src/typechecker.rs +++ b/contrib/mir/src/typechecker.rs @@ -650,6 +650,42 @@ pub(crate) fn typecheck_instruction<'a>( (App(ADD, [], _), [_] | []) => no_overload!(ADD, len 2), (App(ADD, expect_args!(0), _), _) => unexpected_micheline!(), + (App(MUL, [], _), [.., T::Bls12381Fr, T::Bls12381G1]) => { + stack.drop_top(2); + stack.push(T::Bls12381G1); + I::Mul(overloads::Mul::Bls12381G1Bls12381Fr) + } + (App(MUL, [], _), [.., T::Bls12381Fr, T::Bls12381G2]) => { + stack.drop_top(2); + stack.push(T::Bls12381G2); + I::Mul(overloads::Mul::Bls12381G2Bls12381Fr) + } + (App(MUL, [], _), [.., T::Bls12381Fr, T::Bls12381Fr]) => { + pop!(); + I::Mul(overloads::Mul::Bls12381FrBls12381Fr) + } + (App(MUL, [], _), [.., T::Bls12381Fr, T::Nat]) => { + pop!(); + I::Mul(overloads::Mul::NatBls12381Fr) + } + (App(MUL, [], _), [.., T::Bls12381Fr, T::Int]) => { + pop!(); + I::Mul(overloads::Mul::IntBls12381Fr) + } + (App(MUL, [], _), [.., T::Nat, T::Bls12381Fr]) => { + stack.drop_top(2); + stack.push(T::Bls12381Fr); + I::Mul(overloads::Mul::Bls12381FrNat) + } + (App(MUL, [], _), [.., T::Int, T::Bls12381Fr]) => { + stack.drop_top(2); + stack.push(T::Bls12381Fr); + I::Mul(overloads::Mul::Bls12381FrInt) + } + (App(MUL, [], _), [.., _, _]) => no_overload!(MUL), + (App(MUL, [], _), [_] | []) => no_overload!(MUL, len 2), + (App(MUL, expect_args!(0), _), _) => unexpected_micheline!(), + (App(AND, [], _), [.., T::Nat, T::Nat]) => { pop!(); I::And(overloads::And::NatNat) @@ -5033,6 +5069,76 @@ mod typecheck_tests { too_short_test(&app!(PAIRING_CHECK), Prim::PAIRING_CHECK, 1) } + mod mul { + use super::*; + use Type as T; + + #[track_caller] + fn test_mul( + mut stack: FailingTypeStack, + expected_stack: FailingTypeStack, + overload: overloads::Mul, + ) { + assert_eq!( + typecheck_instruction(&parse("MUL").unwrap(), &mut Ctx::default(), &mut stack), + Ok(Mul(overload)) + ); + assert_eq!(stack, expected_stack); + } + macro_rules! test { + ($overload:ident, $i1:expr, $i2:expr, $out:expr $(,)*) => { + #[test] + #[allow(non_snake_case)] + fn $overload() { + test_mul(tc_stk![$i2, $i1], tc_stk![$out], overloads::Mul::$overload); + } + }; + } + test!( + Bls12381G1Bls12381Fr, + T::Bls12381G1, + T::Bls12381Fr, + T::Bls12381G1, + ); + test!( + Bls12381G2Bls12381Fr, + T::Bls12381G2, + T::Bls12381Fr, + T::Bls12381G2, + ); + test!( + Bls12381FrBls12381Fr, + T::Bls12381Fr, + T::Bls12381Fr, + T::Bls12381Fr, + ); + test!(NatBls12381Fr, T::Nat, T::Bls12381Fr, T::Bls12381Fr); + test!(IntBls12381Fr, T::Int, T::Bls12381Fr, T::Bls12381Fr); + test!(Bls12381FrNat, T::Bls12381Fr, T::Nat, T::Bls12381Fr); + test!(Bls12381FrInt, T::Bls12381Fr, T::Int, T::Bls12381Fr); + + #[test] + fn wrong_type() { + assert_eq!( + parse("MUL").unwrap().typecheck_instruction( + &mut Ctx::default(), + None, + &[app!(unit), app!(unit)] + ), + Err(TcError::NoMatchingOverload { + instr: Prim::MUL, + stack: stk![Type::Unit, Type::Unit], + reason: None + }) + ); + } + + #[test] + fn too_short() { + too_short_test(&app!(MUL), Prim::MUL, 2) + } + } + #[test] fn transfer_tokens() { let stk = &mut tc_stk![Type::new_contract(Type::Nat), Type::Mutez, Type::Int]; -- GitLab From b785a38d926a1a524f1ec154d4e2b5bd4ccf4851 Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Mon, 11 Dec 2023 17:51:09 +0300 Subject: [PATCH 2/6] MIR: Add NEG instruction for BLS types --- contrib/mir/src/ast.rs | 1 + contrib/mir/src/ast/overloads.rs | 7 ++++ contrib/mir/src/gas.rs | 3 ++ contrib/mir/src/interpreter.rs | 65 ++++++++++++++++++++++++++++++++ contrib/mir/src/typechecker.rs | 63 +++++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+) diff --git a/contrib/mir/src/ast.rs b/contrib/mir/src/ast.rs index 8d0dcf649820..5deb16e21bd5 100644 --- a/contrib/mir/src/ast.rs +++ b/contrib/mir/src/ast.rs @@ -399,6 +399,7 @@ impl<'a> TypedValue<'a> { pub enum Instruction<'a> { Add(overloads::Add), Mul(overloads::Mul), + Neg(overloads::Neg), Dip(Option, Vec), Drop(Option), Dup(Option), diff --git a/contrib/mir/src/ast/overloads.rs b/contrib/mir/src/ast/overloads.rs index 96d1ae72ee6a..f32390dfb33e 100644 --- a/contrib/mir/src/ast/overloads.rs +++ b/contrib/mir/src/ast/overloads.rs @@ -64,6 +64,13 @@ pub enum Mul { Bls12381FrInt, } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Neg { + Bls12381G1, + Bls12381G2, + Bls12381Fr, +} + #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Get { Map, diff --git a/contrib/mir/src/gas.rs b/contrib/mir/src/gas.rs index d0c54a55114d..95dffcabbe7b 100644 --- a/contrib/mir/src/gas.rs +++ b/contrib/mir/src/gas.rs @@ -241,6 +241,9 @@ pub mod interpret_cost { pub const MUL_BLS_G1: u32 = 103000; pub const MUL_BLS_G2: u32 = 220000; pub const MUL_BLS_FR: u32 = 45; + pub const NEG_FR: u32 = 30; + pub const NEG_G1: u32 = 50; + pub const NEG_G2: u32 = 70; pub const UNIT: u32 = 10; pub const AND_BOOL: u32 = 10; pub const OR_BOOL: u32 = 10; diff --git a/contrib/mir/src/interpreter.rs b/contrib/mir/src/interpreter.rs index 99815fe17e9f..5c392bc60131 100644 --- a/contrib/mir/src/interpreter.rs +++ b/contrib/mir/src/interpreter.rs @@ -247,6 +247,23 @@ fn interpret_one<'a>( stack.push(V::Bls12381Fr(x1 * x2)); } }, + I::Neg(overload) => match overload { + overloads::Neg::Bls12381G1 => { + ctx.gas.consume(interpret_cost::NEG_G1)?; + let v = irrefutable_match!(&mut stack[0]; V::Bls12381G1); + *v = -(v as &bls::G1); + } + overloads::Neg::Bls12381G2 => { + ctx.gas.consume(interpret_cost::NEG_G2)?; + let v = irrefutable_match!(&mut stack[0]; V::Bls12381G2); + *v = -(v as &bls::G2); + } + overloads::Neg::Bls12381Fr => { + ctx.gas.consume(interpret_cost::NEG_FR)?; + let v = irrefutable_match!(&mut stack[0]; V::Bls12381Fr); + *v = -(v as &bls::Fr); + } + }, I::And(overload) => match overload { overloads::And::Bool => { let o1 = pop!(V::Bool); @@ -3917,4 +3934,52 @@ mod interpreter_tests { V::Bls12381Fr(Fr::one()), ); } + + mod neg { + use super::*; + + #[track_caller] + fn test_neg(overload: overloads::Neg, input: TypedValue, output: TypedValue) { + let mut stack = stk![input]; + let ctx = &mut Ctx::default(); + assert_eq!(interpret_one(&Neg(overload), ctx, &mut stack), Ok(())); + assert_eq!(stack, stk![output]); + // assert some gas is consumed, exact values are subject to change + assert!(Ctx::default().gas.milligas() > ctx.gas.milligas()); + } + + use crate::bls::*; + use TypedValue as V; + + macro_rules! test { + ($overload:ident, $inp:expr, $out:expr $(,)*) => { + #[test] + #[allow(non_snake_case)] + fn $overload() { + test_neg(overloads::Neg::$overload, $inp, $out); + } + }; + } + + // NB: actual bls arithmetic is tested in the bls module, here we only + // need to check the interpreter works. + + test!( + Bls12381G1, + V::Bls12381G1(G1::one()), + V::Bls12381G1(G1::neg_one()), + ); + + test!( + Bls12381G2, + V::Bls12381G2(G2::one()), + V::Bls12381G2(G2::neg_one()), + ); + + test!( + Bls12381Fr, + V::Bls12381Fr(Fr::one()), + V::Bls12381Fr(-Fr::one()), + ); + } } diff --git a/contrib/mir/src/typechecker.rs b/contrib/mir/src/typechecker.rs index 06399d106db6..3d1bbc521e3a 100644 --- a/contrib/mir/src/typechecker.rs +++ b/contrib/mir/src/typechecker.rs @@ -686,6 +686,14 @@ pub(crate) fn typecheck_instruction<'a>( (App(MUL, [], _), [_] | []) => no_overload!(MUL, len 2), (App(MUL, expect_args!(0), _), _) => unexpected_micheline!(), + // NB: stack type doesn't change in these NEG overloads + (App(NEG, [], _), [.., T::Bls12381G1]) => I::Neg(overloads::Neg::Bls12381G1), + (App(NEG, [], _), [.., T::Bls12381G2]) => I::Neg(overloads::Neg::Bls12381G2), + (App(NEG, [], _), [.., T::Bls12381Fr]) => I::Neg(overloads::Neg::Bls12381Fr), + (App(NEG, [], _), [.., _]) => no_overload!(NEG), + (App(NEG, [], _), []) => no_overload!(NEG, len 1), + (App(NEG, expect_args!(0), _), _) => unexpected_micheline!(), + (App(AND, [], _), [.., T::Nat, T::Nat]) => { pop!(); I::And(overloads::And::NatNat) @@ -5139,6 +5147,61 @@ mod typecheck_tests { } } + mod neg { + use super::*; + use Type as T; + + #[track_caller] + fn test_neg( + mut stack: FailingTypeStack, + expected_stack: FailingTypeStack, + overload: overloads::Neg, + ) { + assert_eq!( + typecheck_instruction(&parse("NEG").unwrap(), &mut Ctx::default(), &mut stack), + Ok(Neg(overload)) + ); + assert_eq!(stack, expected_stack) + } + macro_rules! test { + ($overload:ident) => { + #[test] + #[allow(non_snake_case)] + fn $overload() { + test_neg( + tc_stk![T::$overload], + tc_stk![T::$overload], + overloads::Neg::$overload, + ); + } + }; + } + test!(Bls12381G1); + test!(Bls12381G2); + test!(Bls12381Fr); + + #[test] + fn wrong_type() { + assert_eq!( + parse("NEG").unwrap().typecheck_instruction( + &mut Ctx::default(), + None, + &[app!(unit)] + ), + Err(TcError::NoMatchingOverload { + instr: Prim::NEG, + stack: stk![Type::Unit], + reason: None + }) + ); + } + + #[test] + fn too_short() { + too_short_test(&app!(NEG), Prim::NEG, 1) + } + } + #[test] fn transfer_tokens() { let stk = &mut tc_stk![Type::new_contract(Type::Nat), Type::Mutez, Type::Int]; -- GitLab From 1fbef99a1e7f4ffe56c615767d4206d98f6bff9a Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Wed, 20 Dec 2023 11:59:16 +0300 Subject: [PATCH 3/6] MIR: box BLS G1 and G2 values in TypedValue These two are a bit too large to lug about on-stack. --- contrib/mir/src/ast.rs | 13 +++++++-- contrib/mir/src/interpreter.rs | 53 ++++++++++++++++++---------------- contrib/mir/src/typechecker.rs | 8 ++--- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/contrib/mir/src/ast.rs b/contrib/mir/src/ast.rs index 5deb16e21bd5..c5bb9cfd3e0a 100644 --- a/contrib/mir/src/ast.rs +++ b/contrib/mir/src/ast.rs @@ -270,8 +270,9 @@ pub enum TypedValue<'a> { Ticket(Box>), Timestamp(BigInt), Bls12381Fr(bls::Fr), - Bls12381G1(bls::G1), - Bls12381G2(bls::G2), + // G1 and G2 are a bit too large to lug them about on-stack + Bls12381G1(Box), + Bls12381G2(Box), } impl<'a> IntoMicheline<'a> for TypedValue<'a> { @@ -393,6 +394,14 @@ impl<'a> TypedValue<'a> { pub fn new_ticket(t: Ticket<'a>) -> Self { Self::Ticket(Box::new(t)) } + + pub fn new_bls12381_g1(x: bls::G1) -> Self { + Self::Bls12381G1(Box::new(x)) + } + + pub fn new_bls12381_g2(x: bls::G2) -> Self { + Self::Bls12381G2(Box::new(x)) + } } #[derive(Debug, Eq, PartialEq, Clone)] diff --git a/contrib/mir/src/interpreter.rs b/contrib/mir/src/interpreter.rs index 5c392bc60131..20d9ceaa7723 100644 --- a/contrib/mir/src/interpreter.rs +++ b/contrib/mir/src/interpreter.rs @@ -190,13 +190,13 @@ fn interpret_one<'a>( let o1 = pop!(V::Bls12381G1); let o2 = pop!(V::Bls12381G1); ctx.gas.consume(interpret_cost::ADD_BLS_G1)?; - stack.push(V::Bls12381G1(o1 + o2)); + stack.push(V::new_bls12381_g1(o1.as_ref() + o2.as_ref())); } overloads::Add::Bls12381G2 => { let o1 = pop!(V::Bls12381G2); let o2 = pop!(V::Bls12381G2); ctx.gas.consume(interpret_cost::ADD_BLS_G2)?; - stack.push(V::Bls12381G2(o1 + o2)); + stack.push(V::new_bls12381_g2(o1.as_ref() + o2.as_ref())); } }, I::Mul(overload) => match overload { @@ -204,13 +204,13 @@ fn interpret_one<'a>( ctx.gas.consume(interpret_cost::MUL_BLS_G1)?; let x1 = pop!(V::Bls12381G1); let x2 = pop!(V::Bls12381Fr); - stack.push(V::Bls12381G1(x1 * x2)); + stack.push(V::new_bls12381_g1(x1.as_ref() * x2)); } overloads::Mul::Bls12381G2Bls12381Fr => { ctx.gas.consume(interpret_cost::MUL_BLS_G2)?; let x1 = pop!(V::Bls12381G2); let x2 = pop!(V::Bls12381Fr); - stack.push(V::Bls12381G2(x1 * x2)); + stack.push(V::new_bls12381_g2(x1.as_ref() * x2)); } overloads::Mul::Bls12381FrBls12381Fr => { ctx.gas.consume(interpret_cost::MUL_BLS_FR)?; @@ -250,12 +250,12 @@ fn interpret_one<'a>( I::Neg(overload) => match overload { overloads::Neg::Bls12381G1 => { ctx.gas.consume(interpret_cost::NEG_G1)?; - let v = irrefutable_match!(&mut stack[0]; V::Bls12381G1); + let v = irrefutable_match!(&mut stack[0]; V::Bls12381G1).as_mut(); *v = -(v as &bls::G1); } overloads::Neg::Bls12381G2 => { ctx.gas.consume(interpret_cost::NEG_G2)?; - let v = irrefutable_match!(&mut stack[0]; V::Bls12381G2); + let v = irrefutable_match!(&mut stack[0]; V::Bls12381G2).as_mut(); *v = -(v as &bls::G2); } overloads::Neg::Bls12381Fr => { @@ -1064,8 +1064,8 @@ fn interpret_one<'a>( let it = list.iter().map(|elt| { let (g1, g2) = irrefutable_match!(elt; V::Pair).as_ref(); ( - irrefutable_match!(g1; V::Bls12381G1), - irrefutable_match!(g2; V::Bls12381G2), + irrefutable_match!(g1; V::Bls12381G1).as_ref(), + irrefutable_match!(g2; V::Bls12381G2).as_ref(), ) }); let res = bls::pairing::pairing_check(it); @@ -1118,10 +1118,10 @@ mod interpreter_tests { #[test] fn test_add_bls12_381_g1() { let mut stack = stk![ - V::Bls12381G1(bls::G1::one()), - V::Bls12381G1(bls::G1::zero()) + V::new_bls12381_g1(bls::G1::one()), + V::new_bls12381_g1(bls::G1::zero()) ]; - let expected_stack = stk![V::Bls12381G1(bls::G1::one())]; + let expected_stack = stk![V::new_bls12381_g1(bls::G1::one())]; let mut ctx = Ctx::default(); assert!(interpret_one(&Add(overloads::Add::Bls12381G1), &mut ctx, &mut stack).is_ok()); assert_eq!(stack, expected_stack); @@ -1130,10 +1130,10 @@ mod interpreter_tests { #[test] fn test_add_bls12_381_g2() { let mut stack = stk![ - V::Bls12381G2(bls::G2::one()), - V::Bls12381G2(bls::G2::zero()) + V::new_bls12381_g2(bls::G2::one()), + V::new_bls12381_g2(bls::G2::zero()) ]; - let expected_stack = stk![V::Bls12381G2(bls::G2::one())]; + let expected_stack = stk![V::new_bls12381_g2(bls::G2::one())]; let mut ctx = Ctx::default(); assert!(interpret_one(&Add(overloads::Add::Bls12381G2), &mut ctx, &mut stack).is_ok()); assert_eq!(stack, expected_stack); @@ -3839,10 +3839,13 @@ mod interpreter_tests { #[test] fn pairing_check() { let mut stack = stk![V::List(MichelsonList::from(vec![ - V::new_pair(V::Bls12381G1(bls::G1::one()), V::Bls12381G2(bls::G2::one())), V::new_pair( - V::Bls12381G1(bls::G1::one()), - V::Bls12381G2(bls::G2::neg_one()) + V::new_bls12381_g1(bls::G1::one()), + V::new_bls12381_g2(bls::G2::one()) + ), + V::new_pair( + V::new_bls12381_g1(bls::G1::one()), + V::new_bls12381_g2(bls::G2::neg_one()) ) ]))]; let ctx = &mut Ctx::default(); @@ -3887,16 +3890,16 @@ mod interpreter_tests { test!( Bls12381G1Bls12381Fr, - V::Bls12381G1(G1::one()), + V::new_bls12381_g1(G1::one()), V::Bls12381Fr(Fr::one()), - V::Bls12381G1(G1::one()), + V::new_bls12381_g1(G1::one()), ); test!( Bls12381G2Bls12381Fr, - V::Bls12381G2(G2::one()), + V::new_bls12381_g2(G2::one()), V::Bls12381Fr(Fr::one()), - V::Bls12381G2(G2::one()), + V::new_bls12381_g2(G2::one()), ); test!( @@ -3966,14 +3969,14 @@ mod interpreter_tests { test!( Bls12381G1, - V::Bls12381G1(G1::one()), - V::Bls12381G1(G1::neg_one()), + V::new_bls12381_g1(G1::one()), + V::new_bls12381_g1(G1::neg_one()), ); test!( Bls12381G2, - V::Bls12381G2(G2::one()), - V::Bls12381G2(G2::neg_one()), + V::new_bls12381_g2(G2::one()), + V::new_bls12381_g2(G2::neg_one()), ); test!( diff --git a/contrib/mir/src/typechecker.rs b/contrib/mir/src/typechecker.rs index 3d1bbc521e3a..e8f4f688c23a 100644 --- a/contrib/mir/src/typechecker.rs +++ b/contrib/mir/src/typechecker.rs @@ -1818,14 +1818,14 @@ pub(crate) fn typecheck_value<'a>( } (T::Bls12381G1, V::Bytes(bs)) => { ctx.gas.consume(gas::tc_cost::BLS_G1)?; - TV::Bls12381G1( + TV::new_bls12381_g1( bls::G1::from_bytes(bs) .ok_or_else(|| TcError::InvalidValueForType(format!("{v:?}"), t.clone()))?, ) } (T::Bls12381G2, V::Bytes(bs)) => { ctx.gas.consume(gas::tc_cost::BLS_G2)?; - TV::Bls12381G2( + TV::new_bls12381_g2( bls::G2::from_bytes(bs) .ok_or_else(|| TcError::InvalidValueForType(format!("{v:?}"), t.clone()))?, ) @@ -2710,7 +2710,7 @@ mod typecheck_tests { &mut Ctx::default(), &mut stack ), - Ok(Push(TypedValue::Bls12381G1( + Ok(Push(TypedValue::new_bls12381_g1( bls::G1::from_bytes(&hex::decode(hex_val).unwrap()).unwrap() ))) ); @@ -2760,7 +2760,7 @@ mod typecheck_tests { &mut Ctx::default(), &mut stack ), - Ok(Push(TypedValue::Bls12381G2( + Ok(Push(TypedValue::new_bls12381_g2( bls::G2::from_bytes(&hex::decode(hex_val).unwrap()).unwrap() ))) ); -- GitLab From 4383ed437f3e7c0c93375eb196573cd053ee5ee6 Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Wed, 20 Dec 2023 12:00:18 +0300 Subject: [PATCH 4/6] MIR: fix some clippy warnings --- contrib/mir/src/interpreter.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contrib/mir/src/interpreter.rs b/contrib/mir/src/interpreter.rs index 20d9ceaa7723..bb211052b89f 100644 --- a/contrib/mir/src/interpreter.rs +++ b/contrib/mir/src/interpreter.rs @@ -2479,7 +2479,7 @@ mod interpreter_tests { let mut ctx = Ctx::default(); let mut stack = stk![TypedValue::String("abc".into())]; assert_eq!( - interpret(&vec![Size(overloads::Size::String)], &mut ctx, &mut stack), + interpret(&[Size(overloads::Size::String)], &mut ctx, &mut stack), Ok(()) ); assert_eq!(stack, stk![TypedValue::nat(3)]); @@ -2494,7 +2494,7 @@ mod interpreter_tests { let mut ctx = Ctx::default(); let mut stack = stk![TypedValue::Bytes(b"abc".to_vec())]; assert_eq!( - interpret(&vec![Size(overloads::Size::Bytes)], &mut ctx, &mut stack), + interpret(&[Size(overloads::Size::Bytes)], &mut ctx, &mut stack), Ok(()) ); assert_eq!(stack, stk![TypedValue::nat(3)]); @@ -2506,7 +2506,7 @@ mod interpreter_tests { let list = (1..=3).map(TypedValue::nat).collect(); let mut stack = stk![TypedValue::List(list)]; assert_eq!( - interpret(&vec![Size(overloads::Size::List)], &mut ctx, &mut stack), + interpret(&[Size(overloads::Size::List)], &mut ctx, &mut stack), Ok(()) ); assert_eq!(stack, stk![TypedValue::nat(3)]); @@ -2522,7 +2522,7 @@ mod interpreter_tests { let set = (1..=3).map(TypedValue::nat).collect(); let mut stack = stk![TypedValue::Set(set)]; assert_eq!( - interpret(&vec![Size(overloads::Size::Set)], &mut ctx, &mut stack), + interpret(&[Size(overloads::Size::Set)], &mut ctx, &mut stack), Ok(()) ); assert_eq!(stack, stk![TypedValue::nat(3)]); @@ -2537,7 +2537,7 @@ mod interpreter_tests { ]); let mut stack = stk![TypedValue::Map(map)]; assert_eq!( - interpret(&vec![Size(overloads::Size::Map)], &mut ctx, &mut stack), + interpret(&[Size(overloads::Size::Map)], &mut ctx, &mut stack), Ok(()) ); assert_eq!(stack, stk![TypedValue::nat(2)]); @@ -3444,7 +3444,7 @@ mod interpreter_tests { ctx.balance = 70; let mut stack = stk![]; let start_milligas = ctx.gas.milligas(); - assert_eq!(interpret(&vec![Balance], &mut ctx, &mut stack), Ok(())); + assert_eq!(interpret(&[Balance], &mut ctx, &mut stack), Ok(())); assert_eq!(stack, stk![V::Mutez(70),]); assert_eq!( start_milligas - ctx.gas.milligas(), -- GitLab From 338514a1ff83ec8d0db9c860d0beaef277f9639a Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Wed, 20 Dec 2023 21:12:15 +0300 Subject: [PATCH 5/6] MIR: move unsupported instructions match to the end --- contrib/mir/src/typechecker.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contrib/mir/src/typechecker.rs b/contrib/mir/src/typechecker.rs index e8f4f688c23a..431d4e77258f 100644 --- a/contrib/mir/src/typechecker.rs +++ b/contrib/mir/src/typechecker.rs @@ -609,9 +609,6 @@ pub(crate) fn typecheck_instruction<'a>( micheline_types!() | micheline_literals!() | micheline_fields!() | micheline_values!(), _, ) => unexpected_micheline!(), - (App(prim @ micheline_unsupported_instructions!(), ..), _) => { - Err(TcError::TodoInstr(*prim))? - } (App(ADD, [], _), [.., T::Nat, T::Nat]) => { pop!(); @@ -1550,6 +1547,10 @@ pub(crate) fn typecheck_instruction<'a>( (App(PAIRING_CHECK, [], _), []) => no_overload!(PAIRING_CHECK, len 1), (App(PAIRING_CHECK, expect_args!(0), _), _) => unexpected_micheline!(), + (App(prim @ micheline_unsupported_instructions!(), ..), _) => { + Err(TcError::TodoInstr(*prim))? + } + (Seq(nested), _) => I::Seq(typecheck(nested, ctx, self_entrypoints, opt_stack)?), }) } -- GitLab From ac34f697764eee127caf6b090fa61fffd9020bfe Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Wed, 20 Dec 2023 21:13:07 +0300 Subject: [PATCH 6/6] MIR: update unsupported instructions and types --- contrib/mir/src/ast/micheline.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/contrib/mir/src/ast/micheline.rs b/contrib/mir/src/ast/micheline.rs index cb199d1f17c3..56f4cbf717c5 100644 --- a/contrib/mir/src/ast/micheline.rs +++ b/contrib/mir/src/ast/micheline.rs @@ -127,9 +127,6 @@ pub trait IntoMicheline<'a> { macro_rules! micheline_unsupported_types { () => { Prim::big_map - | Prim::bls12_381_fr - | Prim::bls12_381_g1 - | Prim::bls12_381_g2 | Prim::chest | Prim::chest_key | Prim::tx_rollup_l2_address @@ -215,8 +212,6 @@ macro_rules! micheline_unsupported_instructions { | Prim::BYTES | Prim::SUB | Prim::SUB_MUTEZ - | Prim::MUL - | Prim::NEG | Prim::EDIV | Prim::GE | Prim::LT -- GitLab