Skip to content

Latest commit

 

History

History
663 lines (559 loc) · 35.5 KB

cap-0059.md

File metadata and controls

663 lines (559 loc) · 35.5 KB

Preamble

CAP: 0059
Title: Host functions for BLS12-381
Working Group:
    Owner: Jay Geng <@jayz22>
    Authors: Jay Geng <@jayz22>
    Consulted: Rohit Sinha <@rsinha>, Iftach Haitner <@iftachh>, Tomer Weller <@tomerweller>, Riad S. Wahby <@kwantam>, Nicolas Barry <@MonsieurNicolas>, Anup Pani <@anupsdf>, Naman Kumar <@namankumar>
Status: FCP: Accepted
Created: 2024-08-15
Discussion: https://github.com/stellar/stellar-protocol/discussions/1500
Protocol version: 22

Simple Summary

BLS12-381 is a pairing-friendly elliptic curve which enables a new suite of applications. This CAP proposes a set of new host functions providing access to BLS12-381 curve operations.

Working Group

As described in the preamble section.

Motivation

Pairing friendly elliptic curve operations are the backbone of many advanced Zero Knowledge (ZK) constructions, with a wide array of applications ranging from scaling to identity management.

BLS12-381 is one of the most well-known and widely adopted pairing friendly curves, due to its efficiency and 128-bit security. However, the curve operations are inherently computationally intensive, making them prohibitive to be implemented in a smart contract. Providing an efficient implementation for a well-chosen set of curve and field operations natively inside the Soroban host is crucial for unlocking zero knowledge functionality in smart contracts

Goals Alignment

This CAP is aligned with the following Stellar Network Goals:

  • The Stellar Network should make it easy for developers of Stellar projects to create highly usable products

Abstract

11 new host functions are proposed for performing field and curve operations on BLS12-381. Definitions and the semantics of each new host function, as well as the associated new metering parameters, will be introduced and explained.

Specification

New host functions

{
    "export": "4",
    "name": "bls12_381_g1_add",
    "args": [
        {
            "name": "point1",
            "type": "BytesObject"
        },
        {
            "name": "point2",
            "type": "BytesObject"
        }
    ],
    "return": "BytesObject",
    "docs": "Adds two BLS12-381 G1 points given in bytes format and returns the resulting G1 point in bytes format. G1 serialization format: `be_bytes(X) || be_bytes(Y)` and the most significant three bits of X encodes flags, i.e.  bits(X) = [compression_flag, infinity_flag, sort_flag, bit_3, .. bit_383]",
    "min_supported_protocol": 22
},
{
    "export": "5",
    "name": "bls12_381_g1_mul",
    "args": [
        {
            "name": "point",
            "type": "BytesObject"
        },
        {
            "name": "scalar",
            "type": "U256Val"
        }
    ],
    "return": "BytesObject",
    "docs": "Multiplies a BLS12-381 G1 point by a scalar, and returns the resulting G1 point in bytes format.",
    "min_supported_protocol": 22
},
{
    "export": "6",
    "name": "bls12_381_g1_msm",
    "args": [
        {
            "name": "vp",
            "type": "VecObject"
        },
        {
            "name": "vs",
            "type": "VecObject"
        }
    ],
    "return": "BytesObject",
    "docs": "Performs multi-scalar-multiplication (inner product) on a vector of BLS12-381 G1 points by a vector of scalars, and returns the resulting G1 point in bytes format.",
    "min_supported_protocol": 22
},
{
    "export": "7",
    "name": "bls12_381_map_fp_to_g1",
    "args": [
        {
            "name": "fp",
            "type": "BytesObject"
        }
    ],
    "return": "BytesObject",
    "docs": "Maps a BLS12-381 field element (Fp) to G1 point. The input is a BytesObject containing Fp serialized in big-endian order",
    "min_supported_protocol": 22
},
{
    "export": "8",
    "name": "bls12_381_hash_to_g1",
    "args": [
        {
            "name": "msg",
            "type": "BytesObject"
        },
        {
            "name": "dst",
            "type": "BytesObject"
        }
    ],
    "return": "BytesObject",
    "docs": "Hashes a message to a BLS12-381 G1 point, with implementation following the specification in [Hashing to Elliptic Curves](https://datatracker.ietf.org/doc/html/rfc9380) (ciphersuite 'BLS12381G1_XMD:SHA-256_SSWU_RO_'). `dst` is the domain separation tag that will be concatenated with the `msg` during hashing, it is intended to keep hashing inputs of different applications separate. It is required `0 < len(dst_bytes) < 256`. DST **must** be chosen with care to avoid compromising the application's security properties. Refer to section 3.1 in the RFC on requirements of DST.",
    "min_supported_protocol": 22
},
{
    "export": "9",
    "name": "bls12_381_g2_add",
    "args": [
        {
            "name": "point1",
            "type": "BytesObject"
        },
        {
            "name": "point2",
            "type": "BytesObject"
        }
    ],
    "return": "BytesObject",
    "docs": "Adds two BLS12-381 G2 points given in bytes format and returns the resulting G2 point in bytes format. G2 serialization format: be_bytes(X_c1) || be_bytes(X_c0) || be_bytes(Y_c1) || be_bytes(Y_c0), and the most significant three bits of X_c1 are flags i.e. bits(X_c1) = [compression_flag, infinity_flag, sort_flag, bit_3, .. bit_383]",
    "min_supported_protocol": 22
},
{
    "export": "a",
    "name": "bls12_381_g2_mul",
    "args": [
        {
            "name": "point",
            "type": "BytesObject"
        },
        {
            "name": "scalar",
            "type": "U256Val"
        }
    ],
    "return": "BytesObject",
    "docs": "Multiplies a BLS12-381 G2 point by a scalar, and returns the resulting G2 point in bytes format.",
    "min_supported_protocol": 22
},
{
    "export": "b",
    "name": "bls12_381_g2_msm",
    "args": [
        {
            "name": "vp",
            "type": "VecObject"
        },
        {
            "name": "vs",
            "type": "VecObject"
        }
    ],
    "return": "BytesObject",
    "docs": "Performs multi-scalar-multiplication (inner product) on a BLS12-381 G2 point by a vector of scalars, and returns the resulting G2 point in bytes format.",
    "min_supported_protocol": 22
},
{
    "export": "c",
    "name": "bls12_381_map_fp2_to_g2",
    "args": [
        {
            "name": "fp2",
            "type": "BytesObject"
        }
    ],
    "return": "BytesObject",
    "docs": "Maps a BLS12-381 quadratic extension field element (Fp2) to G2 point. Fp2 serialization format: be_bytes(c1) || be_bytes(c0)",
    "min_supported_protocol": 22
},
{
    "export": "d",
    "name": "bls12_381_hash_to_g2",
    "args": [
        {
            "name": "msg",
            "type": "BytesObject"
        },
        {
            "name": "dst",
            "type": "BytesObject"
        }
    ],
    "return": "BytesObject",
    "docs": "Hashes a message to a BLS12-381 G2 point, with implementation following the specification in [Hashing to Elliptic Curves](https://datatracker.ietf.org/doc/html/rfc9380) (ciphersuite 'BLS12381G2_XMD:SHA-256_SSWU_RO_'). `dst` is the domain separation tag that will be concatenated with the `msg` during hashing, it is intended to keep hashing inputs of different applications separate. It is required `0 < len(dst_bytes) < 256`. DST **must** be chosen with care to avoid compromising the application's security properties. Refer to section 3.1 in the RFC on requirements of DST.",
    "min_supported_protocol": 22
},
{
    "export": "e",
    "name": "bls12_381_multi_pairing_check",
    "args": [
        {
            "name": "vp1",
            "type": "VecObject"
        },
        {
            "name": "vp2",
            "type": "VecObject"
        }
    ],
    "return": "Bool",
    "docs": "performs pairing operation on a vector of `G1` and a vector of `G2` points, return true if the result equals `1_fp12`",
    "min_supported_protocol": 22
},
{
    "export": "f",
    "name": "bls12_381_fr_add",
    "args": [
        {
            "name": "lhs",
            "type": "U256Val"
        },
        {
            "name": "rhs",
            "type": "U256Val"
        }
    ],
    "return": "U256Val",
    "docs": "performs addition `(lhs + rhs) mod r` between two BLS12-381 scalar elements",
    "min_supported_protocol": 22
},
{
    "export": "g",
    "name": "bls12_381_fr_sub",
    "args": [
        {
            "name": "lhs",
            "type": "U256Val"
        },
        {
            "name": "rhs",
            "type": "U256Val"
        }
    ],
    "return": "U256Val",
    "docs": "performs subtraction `(lhs - rhs) mod r` between two BLS12-381 scalar elements",
    "min_supported_protocol": 22
},
{
    "export": "h",
    "name": "bls12_381_fr_mul",
    "args": [
        {
            "name": "lhs",
            "type": "U256Val"
        },
        {
            "name": "rhs",
            "type": "U256Val"
        }
    ],
    "return": "U256Val",
    "docs": "performs multiplication `(lhs * rhs) mod r` between two BLS12-381 scalar elements",
    "min_supported_protocol": 22
},
{
    "export": "i",
    "name": "bls12_381_fr_pow",
    "args": [
        {
            "name": "lhs",
            "type": "U256Val"
        },
        {
            "name": "rhs",
            "type": "U64Val"
        }
    ],
    "return": "U256Val",
    "docs": "performs exponentiation of a BLS12-381 scalar element with a u64 exponent i.e. `lhs.exp(rhs) mod r`",
    "min_supported_protocol": 22
},
{
    "export": "j",
    "name": "bls12_381_fr_inv",
    "args": [
        {
            "name": "lhs",
            "type": "U256Val"
        }
    ],
    "return": "U256Val",
    "docs": "performs inversion of a BLS12-381 scalar element",
    "min_supported_protocol": 22
}

XDR changes

diff --git a/Stellar-contract-config-setting.x b/Stellar-contract-config-setting.x
index 52cc022..b8ba009 100644
--- a/Stellar-contract-config-setting.x
+++ b/Stellar-contract-config-setting.x
@@ -188,7 +188,54 @@ enum ContractCostType {
     // point on a 256-bit elliptic curve
     Sec1DecodePointUncompressed = 43,
     // Cost of verifying an ECDSA Secp256r1 signature
-    VerifyEcdsaSecp256r1Sig = 44
+    VerifyEcdsaSecp256r1Sig = 44,
+
+    // Cost of encoding a BLS12-381 Fp (base field element)
+    Bls12381EncodeFp = 45,
+    // Cost of decoding a BLS12-381 Fp (base field element)
+    Bls12381DecodeFp = 46,
+    // Cost of validating a G1 point lies on the curve and belongs to the correct subgroup
+    Bls12381G1Validate = 47,
+    // Cost of validating a G2 point lies on the curve and belongs to the correct subgroup
+    Bls12381G2Validate = 48,
+    // Cost of converting a BLS12-381 G1 point from projective to affine coordinates
+    Bls12381G1ProjectiveToAffine = 49,
+    // Cost of converting a BLS12-381 G2 point from projective to affine coordinates
+    Bls12381G2ProjectiveToAffine = 50,
+    // Cost of performing BLS12-381 G1 point addition
+    Bls12381G1Add = 51,
+    // Cost of performing BLS12-381 G1 scalar multiplication
+    Bls12381G1Mul = 52,
+    // Cost of performing BLS12-381 G1 multi-scalar multiplication (MSM)
+    Bls12381G1Msm = 53,
+    // Cost of mapping a BLS12-381 Fp field element to a G1 point
+    Bls12381MapFpToG1 = 54,
+    // Cost of hashing to a BLS12-381 G1 point
+    Bls12381HashToG1 = 55,
+    // Cost of performing BLS12-381 G2 point addition
+    Bls12381G2Add = 56,
+    // Cost of performing BLS12-381 G2 scalar multiplication
+    Bls12381G2Mul = 57,
+    // Cost of performing BLS12-381 G2 multi-scalar multiplication (MSM)
+    Bls12381G2Msm = 58,
+    // Cost of mapping a BLS12-381 Fp2 field element to a G2 point
+    Bls12381MapFp2ToG2 = 59,
+    // Cost of hashing to a BLS12-381 G2 point
+    Bls12381HashToG2 = 60,
+    // Cost of performing BLS12-381 pairing operation
+    Bls12381Pairing = 61,
+    // Cost of converting a BLS12-381 scalar element from U256
+    Bls12381FrFromU256 = 62,
+    // Cost of converting a BLS12-381 scalar element to U256
+    Bls12381FrToU256 = 63,
+    // Cost of performing BLS12-381 scalar element addition/subtraction
+    Bls12381FrAddSub = 64,
+    // Cost of performing BLS12-381 scalar element multiplication
+    Bls12381FrMul = 65,
+    // Cost of performing BLS12-381 scalar element exponentiation
+    Bls12381FrPow = 66,
+    // Cost of performing BLS12-381 scalar element inversion
+    Bls12381FrInv = 67
 };

Semantics

Field and groups

fp - field element in the base field. Encoding rule: big-endian encoding of the underlying unsigned 48-byte integer.

fp2- field element in the quadratic extension of the base prime field. Encoding rule: concatenation of the two encoded-components c1 and c0 i.e. be_encode(c1) || be_encode(c0)

fp12 - field element in the 12-degree prime extension field. This is the output from the pairing operation. fp12 is only used as intermediary and encoding is not needed.

fr - scalar. A scalar has maximum length of 32 bytes. fr is represented with an U256Val.

G1 - group containing points over the base prime field that satisfy the curve equation, plus point at infinity. Encoding rule: concatenation of the two encoded-coordinates (uncompressed form), each being an fp, i.e. be_encode(X) || be_encode(Y)

G2 - group containing points over the quadratic extension of the base prime field that satisfy the curve equation, plus the point at infinity. Encoding rule: concatenation of the two encoded-coordinates (uncompressed form), each following fp2 encoding rule, i.e. be_encode(X_c1) || be_encode(X_c0) || be_encode(Y_c1) || be_encode(Y_c0)

New host functions introduced

Below is a detailed specification of every new host functions introduced, the new costs involved, as well as the new error conditions introduced. It is important to note that these functions exist in the larger context of the runtime, which has a set of restrains already in place and described in previous CAPs. Specification here only covers new behaviors (including costs and errors) unique to these functions.

bls12_381_g1_add

Description: perform point addition in G1.

Cost: covers the cost of decoding (Bls12381DecodeFp) and validating (Bls12381G1Validate) G1 points, point addition (Bls12381G1Add), conversion of from projective to affine space (Bls12381G1ProjectiveToAffine), and encoding the result to bytes Bls12381EncodeFp.

Error condition: if the input bytes contained in the BytesObject do not decode into valid G1 points or do not conform the specified encoding standard.

  • Bytes length is not equal to 96
  • The compression flag (the most significant bit) is set.
  • The infinity flag (the second most significant bit) is set, but the remaining bits are not all zero.
  • The sort flag (the third most significant bit) is set.
  • Either input point does not belong on the G1 curve.
  • Either input point does not belong to the correct subgroup.
bls12_381_g1_mul

Description perform scalar multiplication in G1.

Cost: includes decoding G1 point, converting fr from U256 (Bls12381FrFromU256), point multiplication Bls12381G1Mul, converting the point from project to affine and encoding the result into bytes.

Error condition: if the input BytesObject does not decode into a valid G1 points or does not conform the specified encoding standard.

  • Bytes length is not equal to 96
  • The compression flag (the most significant bit) is set.
  • The infinity flag (the second most significant bit) is set, but the remaining bits are not all zero.
  • The sort flag (the third most significant bit) is set.
  • Either input point does not belong on the G1 curve.
  • Either input point does not belong to the correct subgroup.
bls12_381_g1_msm

Description perform multi-scalar-multiplication (MSM) in G1.

Cost: includes decoding of the G1 vector, the fr vector, and the MSM operation Bls12381G1Msm, and encoding of the resulting G1 point.

Error condition:

  1. if the two vectors have different lengths
  2. if the length of either vector is zero.
  3. if any point in the G1 points vector does not does not decode into a valid G1 points or does not conform the specified encoding standard.
  • Bytes length is not equal to 96
  • The compression flag (the most significant bit) is set.
  • The infinity flag (the second most significant bit) is set, but the remaining bits are not all zero.
  • The sort flag (the third most significant bit) is set.
  • Either input point does not belong on the G1 curve.
  • Either input point does not belong to the correct subgroup.
bls12_381_map_fp_to_g1

Description: maps an fp to a point in G1.

Cost: includes decoding of the G1 point, the mapping cost Bls12381MapFpToG1, and encoding of the resulting G1 point.

Error condition: if the input BytesObject does not serialize to a valid fp

  • Bytes length is not equal to 48
bls12_381_hash_to_g1

Description: hashes a message (a sequence of bytes) into a point in G1. following the specification in Hashing to Elliptic Curves under ciphersuite 'BLS12381G1_XMD:SHA-256_SSWU_RO_', using

  • expand_msg_xmd with sha256 for uniformly random byte string generation
  • hash_to_curve to encode the byte string to points in G1, using "simplified SWU for AB == 0" as the underneath mapping method

dst is the domain separation tag that will be concatenated with the msg during hashing, it is intended to keep hashing inputs of different applications separate. It is required 0 < len(dst_bytes) < 256. DST must be chosen with care to avoid compromising the application's security properties. Refer to section 3.1 in the RFC on requirements of DST.

Cost: covered by Bls12381HashToG1.

Error condition: if the byte length of dst is 0 or greater than 255.

bls12_381_g2_add

Description: perform point addition in G2.

Cost: covers the cost of decoding (Bls12381DecodeFp) and validating (Bls12381G2Validate) G2 points, point addition (Bls12381G2Add), conversion of from projective to affine space (Bls12381G2ProjectiveToAffine), and encoding the result to bytes Bls12381EncodeFp.

Error condition: if the input bytes contained in the BytesObject do not decode into valid G2 points or do not conform the specified encoding standard.

  • Bytes length is not equal to 192
  • The compression flag (the most significant bit) is set.
  • The infinity flag (the second most significant bit) is set, but the remaining bits are not all zero.
  • The sort flag (the third most significant bit) is set.
  • Either input point does not belong on the G2 curve.
  • Either input point does not belong to the correct subgroup.
bls12_381_g2_mul

Description perform scalar multiplication in G2.

Cost: includes decoding G2 point, converting fr from U256 (Bls12381FrFromU256), point multiplication Bls12381G2Mul, converting the point from project to affine and encoding the result into bytes.

Error condition: if the input BytesObject does not decode into a valid G2 points or does not conform the specified encoding standard.

  • Bytes length is not equal to 192
  • The compression flag (the most significant bit) is set.
  • The infinity flag (the second most significant bit) is set, but the remaining bits are not all zero.
  • The sort flag (the third most significant bit) is set.
  • Either input point does not belong on the G2 curve.
  • Either input point does not belong to the correct subgroup.
bls12_381_g2_msm

Description perform multi-scalar-multiplication (MSM) in G2.

Cost: includes decoding of the G2 vector, the fr vector, and the MSM operation Bls12381G2Msm, and encoding of the resulting G2 point.

Error condition:

  1. if the two vectors have different lengths
  2. if the length of either vector is zero.
  3. if any point in the G2 points vector does not does not decode into a valid G2 points or does not conform the specified encoding standard.
  • Bytes length is not equal to 192
  • The compression flag (the most significant bit) is set.
  • The infinity flag (the second most significant bit) is set, but the remaining bits are not all zero.
  • The sort flag (the third most significant bit) is set.
  • Either input point does not belong on the G2 curve.
  • Either input point does not belong to the correct subgroup.
bls12_381_map_fp2_to_g2

Description: maps an fp2 to a point in G2.

Cost: includes decoding of the G2 point, the mapping cost Bls12381MapFpToG2, and encoding of the resulting G2 point.

Error condition: if the input BytesObject does not serialize to a valid fp2

  • Bytes length is not equal to 96
bls12_381_hash_to_g2

Description: hashes a message (a sequence of bytes) into a point in G2. following the specification in Hashing to Elliptic Curves under ciphersuite 'BLS12381G2_XMD:SHA-256_SSWU_RO_', using

  • expand_msg_xmd with sha256 for uniformly random byte string generation
  • hash_to_curve to encode the byte string to points in G1, using "simplified SWU for AB == 0" as the underneath mapping method

dst is the domain separation tag that will be concatenated with the msg during hashing, it is intended to keep hashing inputs of different applications separate. It is required 0 < len(dst_bytes) < 256. DST must be chosen with care to avoid compromising the application's security properties. Refer to section 3.1 in the RFC on requirements of DST.

Cost: covered by Bls12381HashToG1.

Error condition: if the byte length of dst is 0 or greater than 255.

bls12_381_multi_pairing_check

Description: performs pairing operation on a vector of G1 and a vector of G2 points, returns true if the result equals 1_fp12, otherwise returns false.

Cost: includes deserialization of the point vectors (in G1 and G2 respectively), cost of performing the pairing operation Bls12381Pairing.

Error conditions:

  1. two input vectors have different length
  2. either input vector has zero length
  3. any element in the G1 vector does not decode into a valid G1 points or does not conform the specified encoding standard.
  • Bytes length is not equal to 96
  • The compression flag (the most significant bit) is set.
  • The infinity flag (the second most significant bit) is set, but the remaining bits are not all zero.
  • The sort flag (the third most significant bit) is set.
  • Either input point does not belong on the G1 curve.
  • Either input point does not belong to the correct subgroup.
  1. any element in the G2 vector does not decode into a valid G2 points or does not conform the specified encoding standard.
  • Bytes length is not equal to 192
  • The compression flag (the most significant bit) is set.
  • The infinity flag (the second most significant bit) is set, but the remaining bits are not all zero.
  • The sort flag (the third most significant bit) is set.
  • Either input point does not belong on the G2 curve.
  • Either input point does not belong to the correct subgroup.
bls12_381_fr_add

Description: performs addition (lhs + rhs) mod r between two fr.

Cost: conversion of fr from U256 (Bls12381FrFromU256), scalar addition Bls12381FrAddSub.

Error condition: None

bls12_381_fr_sub

Description: performs subtraction (lhs - rhs) mod r between two fr.

Cost: conversion and scalar subtraction Bls12381FrAddSub.

Error condition: None

bls12_381_fr_mul

Description: performs multiplication (lhs * rhs) mod r between two fr.

Cost: conversion and scalar multiplication Bls12381FrMul.

Error condition: None

bls12_381_fr_pow

Description: performs exponentiation lhs.exp(rhs) mod r between fr and an u64 exponent.

Cost: conversion and scalar exponentiation Bls12381FrPow.

Error condition: None

bls12_381_fr_inv

Description: performs inversion on fr.

Cost: conversion and scalar inversion Bls12381FrInv.

Error condition: if the provided input fr is zero.

New metering CostTypes introduced

  • Bls12381EncodeFp - Cost of encoding a BLS12-381 Fp (base field element). Encoding includes the necessary conversion from the internal representation into integer form (e.g. Montgomery reduction), and serialization into bytes. Type: constant.
  • Bls12381DecodeFp - Cost of decoding a BLS12-381 Fp (base field element). Decoding includes deserialization from bytes into integer, and the necessary conversion from the integer form to the internal representation (e.g. Montgomery multiplication). Type: constant.
  • Bls12381G1Validate - Cost of validating a G1 point lies on the curve and belongs to the correct subgroup. Type: constant.
  • Bls12381G2Validate - Cost of validating a G2 point lies on the curve and belongs to the correct subgroup. Type: constant.
  • Bls12381G1ProjectiveToAffine - Cost of converting a BLS12-381 G1 point from projective to affine coordinates. Type: constant.
  • Bls12381G2ProjectiveToAffine - Cost of converting a BLS12-381 G2 point from projective to affine coordinates. Type: constant.
  • Bls12381G1Add - Cost of performing BLS12-381 G1 point addition. Type: constant.
  • Bls12381G1Mul - Cost of performing BLS12-381 G1 scalar multiplication. Type: constant.
  • Bls12381G1Msm - Cost of performing BLS12-381 G1 multi-scalar multiplication (MSM). Type: linear w.r.t the length of the input vectors.
  • Bls12381MapFpToG1 - Cost of mapping a BLS12-381 Fp field element to a G1 point. Type: constant.
  • Bls12381HashToG1 - Cost of hashing a message (a byte array) to a BLS12-381 G1 point. Type: linear w.r.t. the byte length.
  • Bls12381G2Add - Cost of performing BLS12-381 G2 point addition. Type: constant.
  • Bls12381G2Mul - Cost of performing BLS12-381 G2 scalar multiplication. Type: constant.
  • Bls12381G2Msm - Cost of performing BLS12-381 G2 multi-scalar multiplication (MSM). Type: linear w.r.t the length of the input vectors.
  • Bls12381MapFp2ToG2 - Cost of mapping a BLS12-381 Fp2 field element to a G2 point. Type: constant.
  • Bls12381HashToG2 - Cost of hashing a message (a byte array) to a BLS12-381 G2 point. Type: linear w.r.t. the byte length.
  • Bls12381Pairing - Cost of performing BLS12-381 pairing operation. Type: linear w.r.t to the length of the input vectors.
  • Bls12381FrFromU256 - Cost of converting a BLS12-381 scalar element from U256. This includes necessary conversion from the integer form to the internal representation (e.g. Montgomery multiplication). Type: constant.
  • Bls12381FrToU256 - Cost of converting a BLS12-381 scalar element to U256. This includes the necessary conversion from the internal representation into integer form (e.g. Montgomery reduction). Type: constant.
  • Bls12381FrAddSub - Cost of performing BLS12-381 scalar element addition/subtraction. Type: constant.
  • Bls12381FrMul - Cost of performing BLS12-381 scalar element multiplication. Type: constant.
  • Bls12381FrPow - Cost of performing BLS12-381 scalar element exponentiation. Type: linear w.r.t number of bits in the u64 exponent excluding leading zeros.
  • Bls12381FrInv - Cost of performing BLS12-381 scalar element inversion. Type: constant.

Tweak to the budget charging formula

When a cost model is evaluated multiple times with the same input, an internal optimization is bulk charging. Consider the following linear model Y = a + scaled_b * X, where X and Y are model input and output, a is a regular constant, scaled_b is a scaled constant with extra bits of precision. The current sequence of computation 1. compute m = scaled_b * X 2. unscale the result unscale(m), 3 add the unscaled output to a.

In the current protocol, applying bulk model charging directly multiplies the iteration count I to the evaluated model output i.e. I * Y. In the new protocol, the iteration count is applied to individual term before computing the sum, i.e. I * a + I * scaled_b * X, this simple tweak helps increasing the budget bulk charge accuracy, by preserving precision during the intermediate computation of the linear term.

Design Rationale

Function list choice

The list of host functions follows closely what has been proposed in eip-2537, and has been adopted by Ethereum, with many proven ZKP use cases.

The proposed list includes two additional "hash to curve" functions which performs hashing arbitrary message to curve points: bls12_381_hash_to_g1 and bls12_381_hash_to_g2, which follow the IETF hash-to-curve standard as specified in rfc9380.

U256Val for scalar

All field and group elements mentioned in the host functions are represented as BytesObject, with encoding rule specified in fields and groups, except for the scalar element. Since the scalar can be up to 32-bytes, with same semantics as an unsigned integer, using U256Val is the natural choice. Extracting bytes in the correct format can be tricky and error prone, depending on the underlying implementation (for example it is common for field elements implementations to store the montgomery backend number for better computation efficiency, extracting the bytes require performing the reduction first). Using U256Val also takes advantage of the internal small value optimization which reduces storage space for small numbers, see value type repertoire.

No plain "pairing" function

The multi-pairing-check function is provided in instead of a direct pairing function. This is also inline with the choice of eip-2537.

Most applications requiring pairing also performs comparison of pairing results, such as BLS signature verification, or verification of zk-SNARKs. The pairing comparison e(a, b) == e(c, d) can be converted to a multi-pairing evaluation of e(a, b) * e(-c, d) == 1. The main benefit is cost saving, since final exponentiation (the most expensive part of pairing) only needs to be performed on the final result. Not providing the plain pairing function also simplifies the host interface, since it eliminates the need to serialize and return the pairing result in fp12, which is 576 bytes long, and prevents contract from unknowingly opting into the expensive pattern (in terms of both compute and storage).

Choice of the cost types

The new metering cost types broadly follow the selection criteria outlined in cap-0046-10. The set is designed to efficiently represent distinct, non-overlapping units of computation, ensuring optimal separation of work components.

Encode/Decode

The only two cost types representing encoding/decoding are of the base field element Bls12381EncodeFp and Bls12381DecodeFp, since all field and group elements can be composed of the base elements. (En)Decoding G1 is (en)decoding two fp separately, same for fp2. G2 contains two fp2, that are (en)decoded separately. fr is also represented as a field element of a less order, thus (en)decoding work is strictly less than on an fp (and thus okay to use fp as an moderate overestimation for it).

Our encoding/decoding follows the original spec.

Contract panic on error

While not particular to, or introduced by this proposal, it is important to point out that if any error occurs whiling calling a host function, the host will trap the guest VM, which terminates the execution of the guest contract. A host error can span a wide range of reasons, such as running out-of-budget or trying to access an invalid object reference, most of which aren't recoverable for the contract (the try_call function allows calling a contract function in fallible ways, i.e. return Void on non-internal errors). This design is to ensure the integrity of the execution runtime (see cap-0046-01 and cap-0046-03 for details).

Therefore the new error conditions introduced in this proposal (see New host functions introduced) intend to make sure these are actual errors (not a legitimate false condition), or they are important for safeguarding the host's runtime integrity. (The pairing function for example does not error on a failed pairing check, it returns true/false).

There are only two types of new errors introduced: 1. Decoding errors and 2. input vector length errors.

On the former, it is a crucial step and a standard practice to ensure all cryptographic inputs are properly formed and conforms to the specified standards. A malformed input is likely to be a mistake in the contract, or a malicious attempt at the underlying runtime (e.g. a DOS attempt to make runtime perform work without charging). (Note also the underlying library implementation most likely also performs all the checks and errors if they fail. We are just front loading them on the host as an extra safety measure, and to provide a better error code/message.) If there is an legitimate use case for badly-encoded input, those checks should also be easy to implement on the sdk/guest side.

On the latter, mismatched vector size, or a zero-sized vector input is most likely mistake in contract logic, and one that is easy to mitigate by including proper sdk/guest side checks.

Protocol Upgrade Transition

The proposed host functions will become available protocol 22, i.e. with "min_supported_protocol": 22 in the interface definition. For protocol_version <= 21, attempting to import any of these function definitions in the WASM will lead to a linking error during Vm instantiation time.

Backwards Incompatibilities

This CAP does not introduce any backward incompatibilities.

Resource Utilization

The performance impact of the new host functions have been captured by the new CostType described above. The cpu and memory consumption need to be calibrated carefully on each new CostType to ensure that the cost of running BLS host functions are metered properly and subject to the network limits. Final calibration numbers are TBD.

Security Concerns

The main security concerns include

  • Logic correctness. The proposed set of functions cover a wide range of cryptographic operations, which rely on correctness of 3rd party implementations. Incorrect implementation or failure to cover certain corner case potentially be exploitable vulnerabilities.
  • Denial of service. Since the proposed operations are computationally intensive, failure to properly calibrate any part, or to properly account for an extra-expensive path, could lead to the actual computation time significantly exceeding the metered costs, thus potentially lead to denial of service.

Test Cases

Besides thorough unit and integration tests that are standard to any protocol implementation, in addition, we will be adding external test vectors as reference, these include:

  • Ethereum BLS12-381 test vectors. This shall cover the 11 major host functions that overlap with Ethereum's precompile (eip-2537).
  • Hashing to Elliptic Curves RFC provided test vectors for BLS12-381 G1 and BLS12-381 G2. These shall cover the two hash-to-curve functions we added.

Implementation

An initial prototype of BLS12-381 host functions, SDK, and an example custom account contract with BLS signature has been implemented: