From dcf255818067985b666703ba01069ea3ce0733d0 Mon Sep 17 00:00:00 2001 From: Cameron Cooper Date: Thu, 16 Jun 2022 10:34:13 -0500 Subject: [PATCH] added ops for bls g1/g2 and pow --- src/bls_ops.rs | 373 ++++++++++++++++++++++++++++++++++++++++++++ src/chia_dialect.rs | 24 ++- src/f_table.rs | 22 ++- src/lib.rs | 1 + src/more_ops.rs | 46 +----- src/op_utils.rs | 48 ++++++ src/test_ops.rs | 197 ++++++++++++++++++++++- 7 files changed, 664 insertions(+), 47 deletions(-) create mode 100644 src/bls_ops.rs diff --git a/src/bls_ops.rs b/src/bls_ops.rs new file mode 100644 index 00000000..13f3d24b --- /dev/null +++ b/src/bls_ops.rs @@ -0,0 +1,373 @@ +use crate::allocator::{Allocator, NodePtr}; +use crate::cost::{check_cost, Cost}; +use crate::node::Node; +use crate::number::number_from_u8; +use crate::op_utils::{ + arg_count, atom, check_arg_count, int_atom, mod_group_order, new_atom_and_cost, + number_to_scalar, +}; +use crate::reduction::EvalErr; +use crate::reduction::Response; +use bls12_381::hash_to_curve::{ExpandMsgXmd, HashToCurve}; +use bls12_381::{ + multi_miller_loop, G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Gt, +}; + +const BLS_G1_SUBTRACT_BASE_COST: Cost = 132332; +const BLS_G1_SUBTRACT_COST_PER_ARG: Cost = 1362553; +const BLS_G1_MULTIPLY_BASE_COST: Cost = 2154347; +const BLS_G1_MULTIPLY_COST_PER_BYTE: Cost = 12; +const BLS_G1_NEGATE_BASE_COST: Cost = 470779; +const BLS_G2_ADD_BASE_COST: Cost = 45440; +const BLS_G2_ADD_COST_PER_ARG: Cost = 5544581; +const BLS_G2_SUBTRACT_BASE_COST: Cost = 146290; +const BLS_G2_SUBTRACT_COST_PER_ARG: Cost = 5495272; +const BLS_G2_MULTIPLY_BASE_COST: Cost = 10078145; +const BLS_G2_MULTIPLY_COST_PER_BYTE: Cost = 12; +const BLS_G2_NEGATE_BASE_COST: Cost = 1881699; +const BLS_GT_ADD_BASE_COST: Cost = 60118; +const BLS_GT_ADD_COST_PER_ARG: Cost = 62655353; +const BLS_GT_SUBTRACT_BASE_COST: Cost = 42927; +const BLS_GT_SUBTRACT_COST_PER_ARG: Cost = 63060911; +const BLS_GT_MULTIPLY_BASE_COST: Cost = 34026598; +const BLS_GT_MULTIPLY_COST_PER_BYTE: Cost = 12; +const BLS_GT_NEGATE_BASE_COST: Cost = 21787950; +const BLS_PAIRING_BASE_COST: Cost = 4999087; +const BLS_PAIRING_COST_PER_ARG: Cost = 4515438; +const BLS_MAP_TO_G1_BASE_COST: Cost = 610907; +const BLS_MAP_TO_G1_COST_PER_BYTE: Cost = 122; +const BLS_MAP_TO_G1_COST_PER_DST_BYTE: Cost = 135; +const BLS_MAP_TO_G2_BASE_COST: Cost = 3380023; +const BLS_MAP_TO_G2_COST_PER_BYTE: Cost = 122; +const BLS_MAP_TO_G2_COST_PER_DST_BYTE: Cost = 135; + +// TODO: add unit test +fn g1_atom(node: Node) -> Result { + let blob = atom(node.clone(), "G1 atom")?; + if blob.len() != 48 { + return node.err(&format!( + "atom is not G1 size, got {}: Length of bytes object not equal to 48", + hex::encode(blob) + )); + } + + match G1Affine::from_compressed(blob.try_into().expect("G1 slice is not 48 bytes")).into() { + Some(point) => Ok(point), + _ => node.err("atom is not a G1 point"), + } +} + +// TODO: add unit test +fn g2_atom(node: Node) -> Result { + let blob = atom(node.clone(), "G2 atom")?; + if blob.len() != 96 { + return node.err(&format!( + "atom is not G2 size, got {}: Length of bytes object not equal to 96", + hex::encode(blob) + )); + } + + match G2Affine::from_compressed(blob.try_into().expect("G2 slice is not 96 bytes")).into() { + Some(point) => Ok(point), + _ => node.err("atom is not a G2 point"), + } +} + +// TODO: add unit test +fn gt_atom(node: Node) -> Result { + let blob = atom(node.clone(), "Gt atom")?; + if blob.len() != 288 { + return node.err(&format!( + "atom is not Gt size, got {}: Length of bytes object not equal to 288", + hex::encode(blob) + )); + } + + match Gt::from_compressed(blob.try_into().expect("Gt slice is not 288 bytes")).into() { + Some(point) => Ok(point), + _ => node.err(&format!("atom is not a Gt point {}", hex::encode(blob))), + } +} + +pub fn op_bls_g1_subtract(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + let mut cost = BLS_G1_SUBTRACT_BASE_COST; + check_cost(a, cost, max_cost)?; + let mut total: G1Projective = G1Projective::identity(); + let mut is_first = true; + for arg in &args { + let point = g1_atom(arg)?; + cost += BLS_G1_SUBTRACT_COST_PER_ARG; + check_cost(a, cost, max_cost)?; + if is_first { + total = G1Projective::from(point); + } else { + total -= point; + }; + is_first = false; + } + let total: G1Affine = total.into(); + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +pub fn op_bls_g1_multiply(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + check_arg_count(&args, 2, "bls_g1_multiply")?; + + let mut cost = BLS_G1_MULTIPLY_BASE_COST; + check_cost(a, cost, max_cost)?; + + let mut total = G1Projective::from(g1_atom(args.first()?)?); + let args = args.rest()?; + let scalar_buf = int_atom(args.first()?, "bls_g1_multiply")?; + cost += scalar_buf.len() as Cost * BLS_G1_MULTIPLY_COST_PER_BYTE; + check_cost(a, cost, max_cost)?; + + total *= number_to_scalar(mod_group_order(number_from_u8(scalar_buf))); + + let total: G1Affine = total.into(); + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +pub fn op_bls_g1_negate(a: &mut Allocator, input: NodePtr, _max_cost: Cost) -> Response { + let args = Node::new(a, input); + check_arg_count(&args, 1, "bls_g1_negate")?; + let point = g1_atom(args.first()?)?; + let total = -point; + new_atom_and_cost(a, BLS_G1_NEGATE_BASE_COST, &total.to_compressed()) +} + +pub fn op_bls_g2_add(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + let mut cost = BLS_G2_ADD_BASE_COST; + let mut total: G2Projective = G2Projective::identity(); + for arg in &args { + let point = g2_atom(arg)?; + cost += BLS_G2_ADD_COST_PER_ARG; + check_cost(a, cost, max_cost)?; + total += &point; + } + let total: G2Affine = total.into(); + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +pub fn op_bls_g2_subtract(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + let mut cost = BLS_G2_SUBTRACT_BASE_COST; + let mut total: G2Projective = G2Projective::identity(); + let mut is_first = true; + for arg in &args { + let point = g2_atom(arg)?; + cost += BLS_G2_SUBTRACT_COST_PER_ARG; + check_cost(a, cost, max_cost)?; + if is_first { + total = G2Projective::from(point); + } else { + total -= point; + }; + is_first = false; + } + let total: G2Affine = total.into(); + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +pub fn op_bls_g2_multiply(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + check_arg_count(&args, 2, "op_bls_g2_multiply")?; + + let mut cost = BLS_G2_MULTIPLY_BASE_COST; + check_cost(a, cost, max_cost)?; + + let mut total = G2Projective::from(g2_atom(args.first()?)?); + let args = args.rest()?; + let scalar_buf = int_atom(args.first()?, "bls_g2_multiply")?; + cost += scalar_buf.len() as Cost * BLS_G2_MULTIPLY_COST_PER_BYTE; + check_cost(a, cost, max_cost)?; + + total *= number_to_scalar(mod_group_order(number_from_u8(scalar_buf))); + + let total: G2Affine = total.into(); + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +pub fn op_bls_g2_negate(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + check_arg_count(&args, 1, "bls_g2_negate")?; + let cost = BLS_G2_NEGATE_BASE_COST; + check_cost(a, cost, max_cost)?; + let point = g2_atom(args.first()?)?; + let total = -point; + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +pub fn op_bls_map_to_g1(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + let ac = arg_count(&args, 2); + if !(1..=2).contains(&ac) { + return args.err("bls_map_to_g1 takes exactly 1 or 2 arguments"); + } + let mut cost: Cost = BLS_MAP_TO_G1_BASE_COST; + + let msg = atom(args.first()?, "bls_map_to_g1")?; + let args = args.rest()?; + cost += msg.len() as Cost * BLS_MAP_TO_G1_COST_PER_BYTE; + check_cost(a, cost, max_cost)?; + + let dst: &[u8] = if ac == 2 { + atom(args.first()?, "bls_map_to_g1")? + } else { + b"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_" + }; + + cost += dst.len() as Cost * BLS_MAP_TO_G1_COST_PER_DST_BYTE; + check_cost(a, cost, max_cost)?; + + let point = >>::hash_to_curve(msg, dst); + new_atom_and_cost(a, cost, &G1Affine::from(point).to_compressed()) +} + +pub fn op_bls_map_to_g2(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + let ac = arg_count(&args, 2); + if !(1..=2).contains(&ac) { + return args.err("bls_map_to_g2 takes exactly 1 or 2 arguments"); + } + let mut cost: Cost = BLS_MAP_TO_G2_BASE_COST; + check_cost(a, cost, max_cost)?; + + let msg = atom(args.first()?, "bls_map_to_g2")?; + let args = args.rest()?; + cost += msg.len() as Cost * BLS_MAP_TO_G2_COST_PER_BYTE; + + let dst: &[u8] = if ac == 2 { + atom(args.first()?, "bls_map_to_g2")? + } else { + b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_" + }; + + cost += dst.len() as Cost * BLS_MAP_TO_G2_COST_PER_DST_BYTE; + check_cost(a, cost, max_cost)?; + + let point = >>::hash_to_curve(msg, dst); + new_atom_and_cost(a, cost, &G2Affine::from(point).to_compressed()) +} + +pub fn op_bls_gt_add(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + let mut cost = BLS_GT_ADD_BASE_COST; + let mut total: Gt = Gt::identity(); + for arg in &args { + let point = gt_atom(arg)?; + cost += BLS_GT_ADD_COST_PER_ARG; + check_cost(a, cost, max_cost)?; + total += &point; + } + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +pub fn op_bls_gt_subtract(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + let mut cost = BLS_GT_SUBTRACT_BASE_COST; + let mut total: Gt = Gt::identity(); + let mut is_first = true; + for arg in &args { + let point = gt_atom(arg)?; + cost += BLS_GT_SUBTRACT_COST_PER_ARG; + check_cost(a, cost, max_cost)?; + if is_first { + total = point; + } else { + total -= point; + }; + is_first = false; + } + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +pub fn op_bls_gt_multiply(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + check_arg_count(&args, 2, "op_bls_gt_multiply")?; + let mut cost = BLS_GT_MULTIPLY_BASE_COST; + check_cost(a, cost, max_cost)?; + + let mut total = Gt::from(gt_atom(args.first()?)?); + let args = args.rest()?; + + let scalar_buf = int_atom(args.first()?, "bls_gt_multiply")?; + cost += scalar_buf.len() as Cost * BLS_GT_MULTIPLY_COST_PER_BYTE; + check_cost(a, cost, max_cost)?; + + total *= number_to_scalar(mod_group_order(number_from_u8(scalar_buf))); + + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +pub fn op_bls_gt_negate(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + check_arg_count(&args, 1, "bls_gt_negate")?; + let cost = BLS_GT_NEGATE_BASE_COST; + check_cost(a, cost, max_cost)?; + let point = gt_atom(args.first()?)?; + let total = -point; + new_atom_and_cost(a, cost, &total.to_compressed()) +} + +// TODO: add unit test +fn extract_point(points: Node) -> Result<(G1Affine, G2Prepared), EvalErr> { + check_arg_count(&points, 2, "pairing")?; + let p = g1_atom(points.first()?)?; + let points = points.rest()?; + let q = g2_atom(points.first()?)?; + Ok((p, G2Prepared::from(q))) +} + +// TODO: add unit test +fn extract_points( + mut args: Node, + max_cost: u64, +) -> Result<(Vec<(G1Affine, G2Prepared)>, u64), EvalErr> { + let mut cost = 0; + let mut items = Vec::<(G1Affine, G2Prepared)>::new(); + + while !args.nullp() { + cost += BLS_PAIRING_COST_PER_ARG; + check_cost(&Allocator::new(), cost, max_cost)?; + items.push(extract_point(args.first()?)?); + args = args.rest()?; + } + + if items.is_empty() { + return args.err("bls_pairing expects a non-empty list of pairs"); + } + + Ok((items, cost)) +} + +// This function accepts either two parameters, G1 and G2 and treats them as a single item +// or a (single) list of pairs (G1Point G2Point) +pub fn op_bls_pairing(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { + let args = Node::new(a, input); + let mut cost = BLS_PAIRING_BASE_COST; + let mut items = Vec::<(G1Affine, G2Prepared)>::new(); + let ac = arg_count(&args, 2); + + if ac == 1 { + let (points, additional_cost) = extract_points(args.first()?, max_cost - cost)?; + cost += additional_cost; + check_cost(&Allocator::new(), cost, max_cost)?; + items.extend(points); + } else if ac == 2 { + cost += BLS_PAIRING_COST_PER_ARG; + check_cost(a, cost, max_cost)?; + items.push(extract_point(args)?); + } else { + return args.err("bls_pairing takes exactly 1 list of pairs or 2 atoms"); + } + + let mut item_refs = Vec::<(&G1Affine, &G2Prepared)>::new(); + for (p, q) in &items { + item_refs.push((p, q)); + } + let total = multi_miller_loop(&item_refs).final_exponentiation(); + new_atom_and_cost(a, cost, &total.to_compressed()) +} diff --git a/src/chia_dialect.rs b/src/chia_dialect.rs index 2afc4052..e1a396ac 100644 --- a/src/chia_dialect.rs +++ b/src/chia_dialect.rs @@ -1,4 +1,11 @@ use crate::allocator::{Allocator, NodePtr}; +use crate::bls_ops::{ + op_bls_g1_multiply, op_bls_g1_negate, op_bls_g1_subtract, op_bls_g2_add, op_bls_g2_multiply, + op_bls_g2_negate, + op_bls_g2_subtract, /*, op_bls_gt_add, op_bls_gt_multiply, op_bls_gt_negate, + op_bls_gt_subtract*/ + op_bls_map_to_g1, op_bls_map_to_g2, /*op_bls_pairing,*/ +}; use crate::core_ops::{op_cons, op_eq, op_first, op_if, op_listp, op_raise, op_rest}; use crate::cost::Cost; use crate::dialect::{Dialect, Operators}; @@ -106,7 +113,22 @@ impl Dialect for ChiaDialect { _ => match extension { Operators::BLS => match b[0] { 48 => op_coinid, - // TODO: add BLS operators here + 49 => op_bls_g1_subtract, + 50 => op_bls_g1_multiply, + 51 => op_bls_g1_negate, + 52 => op_bls_g2_add, + 53 => op_bls_g2_subtract, + 54 => op_bls_g2_multiply, + 55 => op_bls_g2_negate, + /* + 56 => op_bls_gt_add, + 57 => op_bls_gt_subtract, + 58 => op_bls_gt_multiply, + 59 => op_bls_gt_negate, + 60 => op_bls_pairing, + */ + 61 => op_bls_map_to_g1, + 62 => op_bls_map_to_g2, _ => { return unknown_operator(allocator, o, argument_list, self.flags, max_cost); } diff --git a/src/f_table.rs b/src/f_table.rs index c2c7ac9c..d2e40c71 100644 --- a/src/f_table.rs +++ b/src/f_table.rs @@ -1,6 +1,12 @@ use std::collections::HashMap; use crate::allocator::{Allocator, NodePtr}; +use crate::bls_ops::{ + op_bls_g1_multiply, op_bls_g1_negate, op_bls_g1_subtract, op_bls_g2_add, op_bls_g2_multiply, + op_bls_g2_negate, /*op_bls_gt_add, op_bls_gt_subtract, op_bls_gt_multiply, + op_bls_gt_negate, op_bls_pairing, */ + op_bls_g2_subtract, +}; use crate::core_ops::{op_cons, op_eq, op_first, op_if, op_listp, op_raise, op_rest}; use crate::cost::Cost; use crate::more_ops::{ @@ -15,7 +21,7 @@ type OpFn = fn(&mut Allocator, NodePtr, Cost) -> Response; pub type FLookup = [Option; 256]; pub fn opcode_by_name(name: &str) -> Option { - let opcode_lookup: [(OpFn, &str); 29] = [ + let opcode_lookup: [(OpFn, &str); 36] = [ (op_if, "op_if"), (op_cons, "op_cons"), (op_first, "op_first"), @@ -45,6 +51,20 @@ pub fn opcode_by_name(name: &str) -> Option { (op_any, "op_any"), (op_all, "op_all"), (op_div, "op_div"), + (op_bls_g1_subtract, "op_bls_g1_subtract"), + (op_bls_g1_multiply, "op_bls_g1_multiply"), + (op_bls_g1_negate, "op_bls_g1_negate"), + (op_bls_g2_add, "op_bls_g2_add"), + (op_bls_g2_subtract, "op_bls_g2_subtract"), + (op_bls_g2_multiply, "op_bls_g2_multiply"), + (op_bls_g2_negate, "op_bls_g2_negate"), + /* + (op_bls_gt_add, "op_bls_gt_add"), + (op_bls_gt_subtract, "op_bls_gt_subtract"), + (op_bls_gt_multiply, "op_bls_gt_multiply"), + (op_bls_gt_negate, "op_bls_gt_negate"), + (op_bls_pairing, "op_bls_pairing"), + */ ]; let name: &[u8] = name.as_ref(); for (f, op) in opcode_lookup.iter() { diff --git a/src/lib.rs b/src/lib.rs index 34184ae7..2bfc7e4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod allocator; +pub mod bls_ops; pub mod chia_dialect; pub mod core_ops; pub mod cost; diff --git a/src/more_ops.rs b/src/more_ops.rs index 14cffde7..f2a8d9a1 100644 --- a/src/more_ops.rs +++ b/src/more_ops.rs @@ -5,22 +5,18 @@ use std::ops::BitAndAssign; use std::ops::BitOrAssign; use std::ops::BitXorAssign; -use lazy_static::lazy_static; - use crate::allocator::{Allocator, NodePtr, SExp}; use crate::cost::{check_cost, Cost}; use crate::err_utils::err; use crate::node::Node; use crate::number::{number_from_u8, ptr_from_number, Number}; use crate::op_utils::{ - arg_count, atom, check_arg_count, i32_atom, int_atom, two_ints, u32_from_u8, + arg_count, atom, check_arg_count, i32_atom, int_atom, mod_group_order, new_atom_and_cost, + number_to_scalar, two_ints, u32_from_u8, MALLOC_COST_PER_BYTE, }; use crate::reduction::{Reduction, Response}; use crate::sha2::{Digest, Sha256}; -// We ascribe some additional cost per byte for operations that allocate new atoms -const MALLOC_COST_PER_BYTE: Cost = 10; - const ARITH_BASE_COST: Cost = 99; const ARITH_COST_PER_ARG: Cost = 320; const ARITH_COST_PER_BYTE: Cost = 3; @@ -144,11 +140,6 @@ fn test_limbs_for_int() { limb_test_helper(&[0x80, 0, 0, 0, 0, 0, 0, 0]); } -fn new_atom_and_cost(a: &mut Allocator, cost: Cost, buf: &[u8]) -> Response { - let c = buf.len() as Cost * MALLOC_COST_PER_BYTE; - Ok(Reduction(cost + c, a.new_atom(buf)?)) -} - fn malloc_cost(a: &Allocator, cost: Cost, ptr: NodePtr) -> Reduction { let c = a.atom(ptr).len() as Cost * MALLOC_COST_PER_BYTE; Reduction(cost + c, ptr) @@ -790,39 +781,6 @@ pub fn op_all(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response { Ok(Reduction(cost, total.node)) } -lazy_static! { - static ref GROUP_ORDER: Number = { - let order_as_bytes = &[ - 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, - 0xd8, 0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x01, - ]; - let n = BigUint::from_bytes_be(order_as_bytes); - n.into() - }; -} - -fn mod_group_order(n: Number) -> Number { - let order = GROUP_ORDER.clone(); - let mut remainder = n.mod_floor(&order); - if remainder.sign() == Sign::Minus { - remainder += order; - } - remainder -} - -fn number_to_scalar(n: Number) -> Scalar { - let (sign, as_u8): (Sign, Vec) = n.to_bytes_le(); - let mut scalar_array: [u8; 32] = [0; 32]; - scalar_array[..as_u8.len()].clone_from_slice(&as_u8[..]); - let exp: Scalar = Scalar::from_bytes(&scalar_array).unwrap(); - if sign == Sign::Minus { - exp.neg() - } else { - exp - } -} - pub fn op_pubkey_for_exp(a: &mut Allocator, input: NodePtr, _max_cost: Cost) -> Response { let args = Node::new(a, input); check_arg_count(&args, 1, "pubkey_for_exp")?; diff --git a/src/op_utils.rs b/src/op_utils.rs index a5531797..21e3b00d 100644 --- a/src/op_utils.rs +++ b/src/op_utils.rs @@ -1,7 +1,17 @@ +use crate::allocator::Allocator; +use crate::cost::Cost; use crate::err_utils::err; use crate::node::Node; use crate::number::{number_from_u8, Number}; use crate::reduction::EvalErr; +use crate::reduction::{Reduction, Response}; +use bls12_381::Scalar; +use lazy_static::lazy_static; +use num_bigint::{BigUint, Sign}; +use num_integer::Integer; + +// We ascribe some additional cost per byte for operations that allocate new atoms +pub const MALLOC_COST_PER_BYTE: Cost = 10; pub fn check_arg_count(args: &Node, expected: usize, name: &str) -> Result<(), EvalErr> { if arg_count(args, expected) != expected { @@ -373,3 +383,41 @@ impl<'a> Node<'a> { err(self.node, msg) } } + +pub fn number_to_scalar(n: Number) -> Scalar { + let (sign, as_u8): (Sign, Vec) = n.to_bytes_le(); + let mut scalar_array: [u8; 32] = [0; 32]; + scalar_array[..as_u8.len()].clone_from_slice(&as_u8[..]); + let exp: Scalar = Scalar::from_bytes(&scalar_array).unwrap(); + if sign == Sign::Minus { + exp.neg() + } else { + exp + } +} + +pub fn new_atom_and_cost(a: &mut Allocator, cost: Cost, buf: &[u8]) -> Response { + let c = buf.len() as Cost * MALLOC_COST_PER_BYTE; + Ok(Reduction(cost + c, a.new_atom(buf)?)) +} + +pub fn mod_group_order(n: Number) -> Number { + let order = GROUP_ORDER.clone(); + let mut remainder = n.mod_floor(&order); + if remainder.sign() == Sign::Minus { + remainder += order; + } + remainder +} + +lazy_static! { + static ref GROUP_ORDER: Number = { + let order_as_bytes = &[ + 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, + 0xd8, 0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x01, + ]; + let n = BigUint::from_bytes_be(order_as_bytes); + n.into() + }; +} diff --git a/src/test_ops.rs b/src/test_ops.rs index 72813fa4..c71faaae 100644 --- a/src/test_ops.rs +++ b/src/test_ops.rs @@ -1,4 +1,9 @@ use crate::allocator::{Allocator, NodePtr, SExp}; +use crate::bls_ops::{ + op_bls_g1_multiply, op_bls_g1_negate, op_bls_g1_subtract, op_bls_g2_add, op_bls_g2_multiply, + op_bls_g2_negate, op_bls_g2_subtract, op_bls_gt_add, op_bls_gt_multiply, op_bls_gt_negate, + op_bls_gt_subtract, op_bls_map_to_g1, op_bls_map_to_g2, op_bls_pairing, +}; use crate::core_ops::{op_cons, op_eq, op_first, op_if, op_listp, op_raise, op_rest}; use crate::cost::Cost; use crate::more_ops::{ @@ -877,6 +882,167 @@ coinid 0x1234500000000000000000000000000000000000000000000000000000000000 0x6789 coinid 0x1234500000000000000000000000000000000000000000000000000000000000 0x6789abcdef000000000000000000000000000000000000000000000000000000 0x010000000000000000 => FAIL coinid 0x1234500000000000000000000000000000000000000000000000000000000000 0x6789abcdef000000000000000000000000000000000000000000000000000000 -1 => FAIL coinid 0x1234500000000000000000000000000000000000000000000000000000000000 0x6789abcdef000000000000000000000000000000000000000000000000000000 0x00001234 => FAIL + +; bls g1 subtraction +; expects (G1point G1point ...) +bls_g1_subtract 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb 0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e => 0xb7f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb | 2857918 +; identity +bls_g1_subtract => 0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | 132812 +; G1 point has invalid length +bls_g1_subtract 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6 => FAIL +bls_g1_subtract 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00 => FAIL +bls_g1_subtract 0 => FAIL +bls_g1_subtract ( 1 2 3 ) => FAIL + +; bls g1 multiplication +; expects (G1point scalar) +bls_g1_multiply 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb 2 => 0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e | 2154839 +; missing scalar argument +bls_g1_multiply 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb => FAIL +; G1 point has invalid length +bls_g1_multiply 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6 => FAIL +bls_g1_multiply 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00 => FAIL +; missing/invalid arguments +bls_g1_multiply => FAIL +bls_g1_multiply 0 => FAIL +bls_g1_multiply ( 1 2 3 ) => FAIL +; too many arguments +bls_g1_multiply 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb 2 3 => FAIL + +; bls g1 negate +; expects (G1Point) +bls_g1_negate 0xb7f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb => 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb | 471259 +; G1 point has invalid length +bls_g1_negate 0xb7f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6 => FAIL +bls_g1_negate 0xb7f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bbdd => FAIL +bls_g1_negate 0 => FAIL +; invalid number of arguments +bls_g1_negate 0xb7f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb 0xb7f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb => FAIL +bls_g1_negate => FAIL +bls_g1_negate ( 1 2 3 ) => FAIL + +; bls g2 add +; expects (G2Point G2Point G2Point ...) +bls_g2_add 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => 0xaa4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053 | 11135562 +bls_g2_add => 0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | 46400 +; G2 point has invalid length +bls_g2_add 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bd => FAIL +bls_g2_add 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb800 => FAIL +bls_g2_add 0 => FAIL +bls_g2_add ( 1 2 3 ) => FAIL + +; bls g2 subtract +bls_g2_subtract 0xaa4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8| 11137794 +bls_g2_subtract => 0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | 147250 +; G2 point has invalid length +bls_g2_subtract 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bd => FAIL +bls_g2_subtract 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb800 => FAIL +bls_g2_subtract 0 => FAIL +bls_g2_subtract ( 1 2 3 ) => FAIL + +; bls g2 multiply +; expects (G2Point scalar) +bls_g2_multiply 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 2 => 0xaa4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053 | 10079117 +; invalid number of arguments +bls_g2_multiply 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => FAIL +bls_g2_multiply 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 2 3 => FAIL +bls_g2_multiply => FAIL +; G2 point has invalid length +bls_g2_multiply 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bd => FAIL +bls_g2_multiply 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb800 => FAIL +bls_g2_multiply 0 => FAIL +bls_g2_multiply ( 1 2 3 ) => FAIL + +; bls g2 negate +bls_g2_negate 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 | 1882659 +bls_g2_negate 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bd => FAIL +bls_g2_negate 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8dd => FAIL +bls_g2_negate 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => FAIL +bls_g2_negate 0 => FAIL +bls_g2_negate ( 1 2 3 ) => FAIL + +; bls map to g1 +; expects (seed [dest_str]) +bls_map_to_g1 "abcdef0123456789" => 0x8dd8e3a9197ddefdc25dde980d219004d6aa130d1af9b1808f8b2b004ae94484ac62a08a739ec7843388019a79c437b0 | 619144 +bls_map_to_g1 "abcdef0123456789" "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_" => 0x8dd8e3a9197ddefdc25dde980d219004d6aa130d1af9b1808f8b2b004ae94484ac62a08a739ec7843388019a79c437b0 | 619144 +bls_map_to_g1 "abcdef0123456789" "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_AUG_" => 0x88e7302bf1fa8fcdecfb96f6b81475c3564d3bcaf552ccb338b1c48b9ba18ab7195c5067fe94fb216478188c0a3bef4a | 619144 +bls_map_to_g1 0x010203 => 0xadb922ec02a0bd4c2343c9c473b4c0e4780d608c72ee934421a14743ecf26594631484626ef620ee05aec38e3a3396ed | 617558 +; invalid number of arguments +bls_map_to_g1 => FAIL +bls_map_to_g1 1337 42 10 => FAIL +; invalid arguments +bls_map_to_g1 ( "hello" ) => FAIL +bls_map_to_g1 ( "foo" "bar" ) => FAIL +bls_map_to_g1 (()) => FAIL + +; bls map to g2 +; expects (seed [dest_str]) +bls_map_to_g2 "abcdef0123456789" => 0x8ee1ff66094b8975401c86ad424076d97fed9c2025db5f9dfde6ed455c7bff34b55e96379c1f9ee3c173633587f425e50aed3e807c6c7cd7bed35d40542eee99891955b2ea5321ebde37172e2c01155138494c2d725b03c02765828679bf011e | 3388740 +bls_map_to_g2 "abcdef0123456789" "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_" => 0x8ee1ff66094b8975401c86ad424076d97fed9c2025db5f9dfde6ed455c7bff34b55e96379c1f9ee3c173633587f425e50aed3e807c6c7cd7bed35d40542eee99891955b2ea5321ebde37172e2c01155138494c2d725b03c02765828679bf011e | 3388740 +bls_map_to_g2 "abcdef0123456789" "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_" => 0x92596412844e12c4733b5a6bfc5727cde4c20b345665d2de99de163266f3ba6a944c6c0fdd9d9fe57b9a4acb769bf3780456f8aab4cd41a70836dba57a5278a85fbd18eb96a2b56cfbda853186c9d190c43e63bc3e6a181aed692e97bbdb1944 | 3388740 +bls_map_to_g2 0x010203 => 0x87f659cdaec686301669dad946d8631de1321cfd0e029bff3a63d8a348dc031fbad956eeee2578f400e6a8a26edadd7905c7dea8ab74b03bd21919e20ce90a2376952fd2bef0a525fe94cc9e6da0fe242604933efe5c5716ef2a51822fc5a4d4 | 3387154 +; invalid number of arguments +bls_map_to_g2 => FAIL +bls_map_to_g2 1337 42 10 => FAIL +; invalid arguments +bls_map_to_g2 ( "hello" ) => FAIL +bls_map_to_g2 ( "foo" "bar" ) => FAIL +bls_map_to_g2 (()) => FAIL + +; bls gt add +bls_gt_add 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447a 0x9100d0de870ac98fe02aa99ee57c0f5115ac9f3eb722fa4b0bdc9302f0885d01db5d1bb8ae4adc5bd53ab8c4b1c4919708ce8b0b57634a36a6c31e2a58161b899b9ca0c0a040f44e527eb7a940bc78ce86322b86e22963425ebe3794132f398313290d7dce4bc1d57dee34e7aa7932e53b6d22dc74feadf466f07a93ea6896ef3f66d97f2532a233ec78d87854aa4e2d0a95869786ca16342e5c848e22a9551e9f1e087b3368e87980e4682fb480d7d46b3d91e7fbaba42cd5c7a662efc36fdd1881f5546a06346f05860dcbeb6598f757bfed4f15658f475287975cba5cd21408ff689cb858df5b74ec00a303fafe2c12665a36f394c2d106525012d8e03813ef403547a6c59f048dbbb4bf19148d34abe0deba332e677ec2d478e3c1258f9f => 0xc502b03d12b9230ed2a431d807b81bd18671ebf78380dd3cf490506187996e7c72f53c3914c76342a38a536ffaed47830c9db625a7aac25034517eb8743b5868a3803b37b94374e35f152f922ba423fb8e9b3d2b2bbf9dd602558ca5237d37420bd06236e9bd188437adc14d42728c6e7177399b6b5908687f491f91ee6cca3a391ef6c098cbeaee83d962fa604a718a0eab6a8b1420007a88412ab65de0d04feecca0302e7806761483410365b5e771fce7e5431230ad5e9e1c280e8953c68d0eef9fa162e25bd305f36d77d8fede115c807c0805968129f15c1ad8489c32c41cb49418b4aef52390900720b6d8b02c014e367f06f92bb039aedcdd4df65fc05a0d985b4ca6b79aa2254a6c605eb424048fa7f6117b8d4da8522cd9c767b045 | 125373704 +bls_gt_add 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c49844 => FAIL +bls_gt_add 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447aaa => FAIL +bls_gt_add => 0x800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | 62998 +bls_gt_add 0 => FAIL +bls_gt_add ( 1 2 3 ) => FAIL + +; bls gt subtract +bls_gt_subtract 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447a 0x9100d0de870ac98fe02aa99ee57c0f5115ac9f3eb722fa4b0bdc9302f0885d01db5d1bb8ae4adc5bd53ab8c4b1c4919708ce8b0b57634a36a6c31e2a58161b899b9ca0c0a040f44e527eb7a940bc78ce86322b86e22963425ebe3794132f398313290d7dce4bc1d57dee34e7aa7932e53b6d22dc74feadf466f07a93ea6896ef3f66d97f2532a233ec78d87854aa4e2d0a95869786ca16342e5c848e22a9551e9f1e087b3368e87980e4682fb480d7d46b3d91e7fbaba42cd5c7a662efc36fdd1881f5546a06346f05860dcbeb6598f757bfed4f15658f475287975cba5cd21408ff689cb858df5b74ec00a303fafe2c12665a36f394c2d106525012d8e03813ef403547a6c59f048dbbb4bf19148d34abe0deba332e677ec2d478e3c1258f9f => 0x99f26337d205fb469cd6bd15c3d5a04dc88784fbb3d0b2dbdea54d43b2b73f2cbb12d58386a8703e0f948226e47ee89d06fba23eb7c5af0d9f80940ca771b6ffd5857baaf222eb95a7d2809d61bfe02e1bfd1b68ff02f0b8102ae1c2d5d5ab1a11b8b424cd48bf38fcef68083b0b0ec5c81a93b330ee1a677d0d15ff7b984e8978ef48881e32fac91b93b47333e2ba5703350f55a7aefcd3c31b4fcb6ce5771cc6a0e9786ab5973320c806ad360829107ba810c5a09ffdd9be2291a0c25a99a204c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631 | 126167629 +bls_gt_subtract 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c49844 => FAIL +bls_gt_subtract 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447aaa => FAIL +bls_gt_subtract => 0x800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | 45807 +bls_gt_subtract 0 => FAIL +bls_gt_subtract ( 1 2 3 ) => FAIL + +; bls gt multiply +bls_gt_multiply 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447a 5 => 0xcd550e95255c998facf5bb439a5ac22f9dacbc466754e917d1ffb23f1c386a2ba2bc2595bd158bbbf90a3404f6817d460d4d470520be480031843909c3529654491cb56f5c24800cd4bf74038485605bd88af3485eb276da2d8c5dc31db4ee1609d1efb8ec7829c630c93a45e8e546b3178c701e32971a5bdb4c00a8c56a83d9215bbb820328b3c332df56a34d3e10a20795d34b18da7700d600318a38b59d977cc08bddefa7ca690b2f46a8588d710c25be0b509d27daa385aa574784775aa31267b02a828f90546fc98b517074f26bbf188f9cfc2a79fcf0bccd698c51f1c4a339124a2e450f62807811618e1afa0118f3be26e1330e9fd5ab7b96a41340bae2ab44320a92ee553d365d5f0241fb44c9ec4107b048817104a6813fb9876bf9 | 34029490 +bls_gt_multiply 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447a => FAIL +bls_gt_multiply => FAIL +bls_gt_multiply 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c49844 => FAIL +bls_gt_multiply 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447aaa => FAIL +bls_gt_multiply ( 1 2 3 ) => FAIL + +; bls gt negate +bls_gt_negate 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447a => 0x99f26337d205fb469cd6bd15c3d5a04dc88784fbb3d0b2dbdea54d43b2b73f2cbb12d58386a8703e0f948226e47ee89d06fba23eb7c5af0d9f80940ca771b6ffd5857baaf222eb95a7d2809d61bfe02e1bfd1b68ff02f0b8102ae1c2d5d5ab1a11b8b424cd48bf38fcef68083b0b0ec5c81a93b330ee1a677d0d15ff7b984e8978ef48881e32fac91b93b47333e2ba5703350f55a7aefcd3c31b4fcb6ce5771cc6a0e9786ab5973320c806ad360829107ba810c5a09ffdd9be2291a0c25a99a204c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631 | 21790830 +bls_gt_negate 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c49844 => FAIL +bls_gt_negate 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447aee => FAIL +bls_gt_negate 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447a 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447a => FAIL +bls_gt_negate 0 => FAIL +bls_gt_negate ( 1 2 3 ) => FAIL + +; bls pairing +bls_pairing 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447a | 9517405 +bls_pairing ((0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8)) => 0x800eaeb26779eb53ae44eaa07f760c899befc6893fb45fe3888b855d43f9b6f763992a7b2aab8fc1aa6a7dd91b80c20e13056fab81ba378cab9b13a99bd9f5d78ef1cfda01622729bf5e520394f115f602aee495b2510f47a9d41e3d2a29ff9108485dc56c3727614e2c3fae08409e119c5cb7d1c296f857ea23bca17b18a79aa5bcb776932105369e6b4b8ccc1cf05416cc029491d0e9c6880057ead66635ba9dd6620c88cf7b8c4668cbf3c0a8cd13a303ef3910b40225fbdc6e5f3da51109153b90c6ec777c0148f70c51d0bbafb5c2ed630bbddbbeba4ab3f6f94329cffa79b103f9aaf1ba3428f60fdbd2efc6bc0abf2c63d5c0ddcb449534ea73312e1028caa6adc6dbdd7a88316a34f94300e04a1d55da016f81e0bc1ab6c7c498447a | 9517405 +bls_pairing ((0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8) (0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8)) => 0xc502b03d12b9230ed2a431d807b81bd18671ebf78380dd3cf490506187996e7c72f53c3914c76342a38a536ffaed47830c9db625a7aac25034517eb8743b5868a3803b37b94374e35f152f922ba423fb8e9b3d2b2bbf9dd602558ca5237d37420bd06236e9bd188437adc14d42728c6e7177399b6b5908687f491f91ee6cca3a391ef6c098cbeaee83d962fa604a718a0eab6a8b1420007a88412ab65de0d04feecca0302e7806761483410365b5e771fce7e5431230ad5e9e1c280e8953c68d0eef9fa162e25bd305f36d77d8fede115c807c0805968129f15c1ad8489c32c41cb49418b4aef52390900720b6d8b02c014e367f06f92bb039aedcdd4df65fc05a0d985b4ca6b79aa2254a6c605eb424048fa7f6117b8d4da8522cd9c767b045 | 14032843 +bls_pairing 0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => 0x9100d0de870ac98fe02aa99ee57c0f5115ac9f3eb722fa4b0bdc9302f0885d01db5d1bb8ae4adc5bd53ab8c4b1c4919708ce8b0b57634a36a6c31e2a58161b899b9ca0c0a040f44e527eb7a940bc78ce86322b86e22963425ebe3794132f398313290d7dce4bc1d57dee34e7aa7932e53b6d22dc74feadf466f07a93ea6896ef3f66d97f2532a233ec78d87854aa4e2d0a95869786ca16342e5c848e22a9551e9f1e087b3368e87980e4682fb480d7d46b3d91e7fbaba42cd5c7a662efc36fdd1881f5546a06346f05860dcbeb6598f757bfed4f15658f475287975cba5cd21408ff689cb858df5b74ec00a303fafe2c12665a36f394c2d106525012d8e03813ef403547a6c59f048dbbb4bf19148d34abe0deba332e677ec2d478e3c1258f9f | 9517405 +; invalid number of arguments +bls_pairing ((0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8) (0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8)) 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => FAIL +; invalid arguments +bls_pairing 0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => FAIL +bls_pairing ((0 1 2)) => FAIL +bls_pairing 0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4eee 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8 => FAIL +bls_pairing 0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bd => FAIL +bls_pairing 0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8ee => FAIL +bls_pairing 0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4eee 0xb3e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8ee => FAIL +bls_pairing 0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4eee => FAIL +bls_pairing 0 => FAIL +bls_pairing 0 () => FAIL +bls_pairing () => FAIL +bls_pairing () () => FAIL +bls_pairing () 0x010203 => FAIL +bls_pairing ( 1 2 3 ) => FAIL + "#; fn parse_atom(a: &mut Allocator, v: &str) -> NodePtr { @@ -945,6 +1111,21 @@ fn parse_atom(a: &mut Allocator, v: &str) -> NodePtr { "softfork" => a.new_atom(&[36]).unwrap(), "coinid" => a.new_atom(&[48]).unwrap(), + + "bls_g1_subtract" => a.new_atom(&[49]).unwrap(), + "bls_g1_multiply" => a.new_atom(&[50]).unwrap(), + "bls_g1_negate" => a.new_atom(&[51]).unwrap(), + "bls_g2_add" => a.new_atom(&[52]).unwrap(), + "bls_g2_subtract" => a.new_atom(&[53]).unwrap(), + "bls_g2_multiply" => a.new_atom(&[54]).unwrap(), + "bls_g2_negate" => a.new_atom(&[55]).unwrap(), + "bls_gt_add" => a.new_atom(&[56]).unwrap(), + "bls_gt_subtract" => a.new_atom(&[57]).unwrap(), + "bls_gt_multiply" => a.new_atom(&[58]).unwrap(), + "bls_gt_negate" => a.new_atom(&[59]).unwrap(), + "bls_pairing" => a.new_atom(&[60]).unwrap(), + "bls_map_to_g1" => a.new_atom(&[61]).unwrap(), + "bls_map_to_g2" => a.new_atom(&[62]).unwrap(), _ => { panic!("atom not supported \"{}\"", v); } @@ -1092,8 +1273,22 @@ fn test_ops() { ("not", op_not as Opf), ("any", op_any as Opf), ("all", op_all as Opf), - // part of the BLS extension + //the BLS extension ("coinid", op_coinid as Opf), + ("bls_g1_subtract", op_bls_g1_subtract as Opf), + ("bls_g1_multiply", op_bls_g1_multiply as Opf), + ("bls_g1_negate", op_bls_g1_negate as Opf), + ("bls_g2_add", op_bls_g2_add as Opf), + ("bls_g2_subtract", op_bls_g2_subtract as Opf), + ("bls_g2_multiply", op_bls_g2_multiply as Opf), + ("bls_g2_negate", op_bls_g2_negate as Opf), + ("bls_map_to_g1", op_bls_map_to_g1 as Opf), + ("bls_map_to_g2", op_bls_map_to_g2 as Opf), + ("bls_gt_add", op_bls_gt_add as Opf), + ("bls_gt_subtract", op_bls_gt_subtract as Opf), + ("bls_gt_multiply", op_bls_gt_multiply as Opf), + ("bls_gt_negate", op_bls_gt_negate as Opf), + ("bls_pairing", op_bls_pairing as Opf), ]); for t in TEST_CASES.split("\n") {