From f582e273a2b803b1ec2e76c242b07defa7dbc779 Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Thu, 7 Dec 2023 21:05:16 +0300 Subject: [PATCH] MIR: extend existing arithmetic for bls types --- contrib/mir/src/ast.rs | 2 +- contrib/mir/src/ast/overloads.rs | 9 ++++ contrib/mir/src/gas.rs | 4 ++ contrib/mir/src/interpreter.rs | 85 +++++++++++++++++++++++++++++--- contrib/mir/src/typechecker.rs | 74 +++++++++++++++++++++++++-- 5 files changed, 163 insertions(+), 11 deletions(-) diff --git a/contrib/mir/src/ast.rs b/contrib/mir/src/ast.rs index 8c3f2f023e73..ecfd9d778d92 100644 --- a/contrib/mir/src/ast.rs +++ b/contrib/mir/src/ast.rs @@ -406,7 +406,7 @@ pub enum Instruction<'a> { Le, If(Vec, Vec), IfNone(Vec, Vec), - Int, + Int(overloads::Int), Loop(Vec), Push(TypedValue<'a>), Swap, diff --git a/contrib/mir/src/ast/overloads.rs b/contrib/mir/src/ast/overloads.rs index 274cd883a9d1..34dcee615b64 100644 --- a/contrib/mir/src/ast/overloads.rs +++ b/contrib/mir/src/ast/overloads.rs @@ -12,6 +12,9 @@ pub enum Add { IntNat, NatInt, MutezMutez, + Bls12381G1, + Bls12381G2, + Bls12381Fr, } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -90,3 +93,9 @@ pub enum Concat { ListOfStrings, ListOfBytes, } + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Int { + Nat, + Bls12381Fr, +} diff --git a/contrib/mir/src/gas.rs b/contrib/mir/src/gas.rs index f0241e2b2cf7..e78927a08bd4 100644 --- a/contrib/mir/src/gas.rs +++ b/contrib/mir/src/gas.rs @@ -232,8 +232,12 @@ pub mod interpret_cost { pub const ITER: u32 = 20; pub const SWAP: u32 = 10; pub const INT_NAT: u32 = 10; + pub const INT_BLS_FR: u32 = 115; pub const PUSH: u32 = 10; pub const ADD_TEZ: u32 = 20; + pub const ADD_BLS_FR: u32 = 30; + pub const ADD_BLS_G1: u32 = 900; + pub const ADD_BLS_G2: u32 = 2470; 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 eb5123211fd1..72eb248e77ad 100644 --- a/contrib/mir/src/interpreter.rs +++ b/contrib/mir/src/interpreter.rs @@ -179,6 +179,24 @@ fn interpret_one<'a>( let sum = o1.checked_add(o2).ok_or(InterpretError::MutezOverflow)?; stack.push(V::Mutez(sum)); } + overloads::Add::Bls12381Fr => { + let o1 = pop!(V::Bls12381Fr); + let o2 = pop!(V::Bls12381Fr); + ctx.gas.consume(interpret_cost::ADD_BLS_FR)?; + stack.push(V::Bls12381Fr(o1 + o2)); + } + overloads::Add::Bls12381G1 => { + let o1 = pop!(V::Bls12381G1); + let o2 = pop!(V::Bls12381G1); + ctx.gas.consume(interpret_cost::ADD_BLS_G1)?; + stack.push(V::Bls12381G1(o1 + o2)); + } + 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)); + } }, I::And(overload) => match overload { overloads::And::Bool => { @@ -378,11 +396,18 @@ fn interpret_one<'a>( } } } - I::Int => { - let i = pop!(V::Nat); - ctx.gas.consume(interpret_cost::INT_NAT)?; - stack.push(V::Int(i.into())); - } + I::Int(overload) => match overload { + overloads::Int::Nat => { + let i = pop!(V::Nat); + ctx.gas.consume(interpret_cost::INT_NAT)?; + stack.push(V::Int(i.into())); + } + overloads::Int::Bls12381Fr => { + let i = pop!(V::Bls12381Fr); + ctx.gas.consume(interpret_cost::INT_BLS_FR)?; + stack.push(V::Int(i.to_big_int())) + } + }, I::Loop(nested) => { ctx.gas.consume(interpret_cost::LOOP_ENTER)?; loop { @@ -978,6 +1003,7 @@ mod interpreter_tests { use super::*; use super::{Lambda, Or}; use crate::ast::michelson_address as addr; + use crate::bls; use crate::gas::Gas; use Instruction::*; use Option::None; @@ -997,6 +1023,42 @@ mod interpreter_tests { assert_eq!(stack, expected_stack); } + #[test] + fn test_add_bls12_381_fr() { + let mut stack = stk![ + V::Bls12381Fr(bls::Fr::one()), + V::Bls12381Fr(bls::Fr::zero()) + ]; + let expected_stack = stk![V::Bls12381Fr(bls::Fr::one())]; + let mut ctx = Ctx::default(); + assert!(interpret_one(&Add(overloads::Add::Bls12381Fr), &mut ctx, &mut stack).is_ok()); + assert_eq!(stack, expected_stack); + } + + #[test] + fn test_add_bls12_381_g1() { + let mut stack = stk![ + V::Bls12381G1(bls::G1::one()), + V::Bls12381G1(bls::G1::zero()) + ]; + let expected_stack = stk![V::Bls12381G1(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); + } + + #[test] + fn test_add_bls12_381_g2() { + let mut stack = stk![ + V::Bls12381G2(bls::G2::one()), + V::Bls12381G2(bls::G2::zero()) + ]; + let expected_stack = stk![V::Bls12381G2(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); + } + #[test] fn test_add_mutez() { let mut stack = stk![V::Mutez(2i64.pow(62)), V::Mutez(20)]; @@ -1411,11 +1473,20 @@ mod interpreter_tests { } #[test] - fn test_int() { + fn test_int_nat() { let mut stack = stk![V::nat(20), V::nat(10)]; let expected_stack = stk![V::nat(20), V::int(10)]; let mut ctx = Ctx::default(); - assert!(interpret_one(&Int, &mut ctx, &mut stack).is_ok()); + assert!(interpret_one(&Int(overloads::Int::Nat), &mut ctx, &mut stack).is_ok()); + assert_eq!(stack, expected_stack); + } + + #[test] + fn test_int_bls12_381_fr() { + let mut stack = stk![V::Bls12381Fr(bls::Fr::one())]; + let expected_stack = stk![V::int(1)]; + let mut ctx = Ctx::default(); + assert!(interpret_one(&Int(overloads::Int::Bls12381Fr), &mut ctx, &mut stack).is_ok()); assert_eq!(stack, expected_stack); } diff --git a/contrib/mir/src/typechecker.rs b/contrib/mir/src/typechecker.rs index 2d586037d90e..d4bb72569993 100644 --- a/contrib/mir/src/typechecker.rs +++ b/contrib/mir/src/typechecker.rs @@ -626,6 +626,18 @@ pub(crate) fn typecheck_instruction<'a>( pop!(); I::Add(overloads::Add::MutezMutez) } + (App(ADD, [], _), [.., T::Bls12381Fr, T::Bls12381Fr]) => { + pop!(); + I::Add(overloads::Add::Bls12381Fr) + } + (App(ADD, [], _), [.., T::Bls12381G1, T::Bls12381G1]) => { + pop!(); + I::Add(overloads::Add::Bls12381G1) + } + (App(ADD, [], _), [.., T::Bls12381G2, T::Bls12381G2]) => { + pop!(); + I::Add(overloads::Add::Bls12381G2) + } (App(ADD, [], _), [.., _, _]) => no_overload!(ADD), (App(ADD, [], _), [_] | []) => no_overload!(ADD, len 2), (App(ADD, expect_args!(0), _), _) => unexpected_micheline!(), @@ -838,7 +850,11 @@ pub(crate) fn typecheck_instruction<'a>( (App(INT, [], _), [.., T::Nat]) => { stack[0] = Type::Int; - I::Int + I::Int(overloads::Int::Nat) + } + (App(INT, [], _), [.., T::Bls12381Fr]) => { + stack[0] = Type::Int; + I::Int(overloads::Int::Bls12381Fr) } (App(INT, [], _), [.., _]) => no_overload!(INT), (App(INT, [], _), []) => no_overload!(INT, len 1), @@ -1955,13 +1971,26 @@ mod typecheck_tests { } #[test] - fn test_int() { + fn test_int_nat() { let mut stack = tc_stk![Type::Nat]; let expected_stack = tc_stk![Type::Int]; let mut ctx = Ctx::default(); assert_eq!( typecheck_instruction(&app!(INT), &mut ctx, &mut stack), - Ok(Int) + Ok(Int(overloads::Int::Nat)) + ); + assert_eq!(stack, expected_stack); + assert_eq!(ctx.gas.milligas(), Gas::default().milligas() - 440); + } + + #[test] + fn test_int_bls12_381_fr() { + let mut stack = tc_stk![Type::Bls12381Fr]; + let expected_stack = tc_stk![Type::Int]; + let mut ctx = Ctx::default(); + assert_eq!( + typecheck_instruction(&app!(INT), &mut ctx, &mut stack), + Ok(Int(overloads::Int::Bls12381Fr)) ); assert_eq!(stack, expected_stack); assert_eq!(ctx.gas.milligas(), Gas::default().milligas() - 440); @@ -2218,6 +2247,45 @@ mod typecheck_tests { ); } + #[test] + fn test_add_bls12_381_fr() { + let mut stack = tc_stk![Type::Bls12381Fr, Type::Bls12381Fr]; + let expected_stack = tc_stk![Type::Bls12381Fr]; + let mut ctx = Ctx::default(); + assert_eq!( + typecheck_instruction(&app!(ADD), &mut ctx, &mut stack), + Ok(Add(overloads::Add::Bls12381Fr)) + ); + assert_eq!(stack, expected_stack); + assert_eq!(ctx.gas.milligas(), Gas::default().milligas() - 440); + } + + #[test] + fn test_add_bls12_381_g1() { + let mut stack = tc_stk![Type::Bls12381G1, Type::Bls12381G1]; + let expected_stack = tc_stk![Type::Bls12381G1]; + let mut ctx = Ctx::default(); + assert_eq!( + typecheck_instruction(&app!(ADD), &mut ctx, &mut stack), + Ok(Add(overloads::Add::Bls12381G1)) + ); + assert_eq!(stack, expected_stack); + assert_eq!(ctx.gas.milligas(), Gas::default().milligas() - 440); + } + + #[test] + fn test_add_bls12_381_g2() { + let mut stack = tc_stk![Type::Bls12381G2, Type::Bls12381G2]; + let expected_stack = tc_stk![Type::Bls12381G2]; + let mut ctx = Ctx::default(); + assert_eq!( + typecheck_instruction(&app!(ADD), &mut ctx, &mut stack), + Ok(Add(overloads::Add::Bls12381G2)) + ); + assert_eq!(stack, expected_stack); + assert_eq!(ctx.gas.milligas(), Gas::default().milligas() - 440); + } + #[test] fn test_loop() { let mut stack = tc_stk![Type::Int, Type::Bool]; -- GitLab