Skip to main content

Crypto Extensions

As of v3.0 crypto host functions were extended to include

  • mod_exp: Big integer modular exponentiation
  • alt_bn128_add, alt_bn128_mul, alt_bn128_pair: Add, multiply, and pairing check functions for the alt_bn128 elliptic curve
  • blake2_f: BLAKE2b F compression function
  • sha3: sha3hash function usingSHA3 NIST`
  • Keccak256: sha3 hash function using SHA3 Keccak
  • k1_recover: Safe ECDSA uncompressed pubkey recover for the secp256k1 curve

In v3.0, C format was supported; in v3.1, C++ format was added for better data abstraction.

Prerequisites

  • In nodeop, activate protocol feature CRYPTO_PRIMITIVES (68d6405cb8df3de95bd834ebb408196578500a9f818ff62ccc68f60b932f7d82)
  • In smart contract code, include crypto_ext.hpp

C Format

C‑API functionDescriptionReturn
int32_t alt_bn128_add(const char* op1, uint32_t op1_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;const char* op2, uint32_t op2_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;char* result, uint32_t result_len)Add two G1 points on alt_bn128 and store the serialized result in result.0 success
‑1 error
int32_t alt_bn128_mul(const char* g1, uint32_t g1_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;const char* scalar, uint32_t scalar_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;char* result, uint32_t result_len)Scalar‑multiply a G1 point by scalar; writes serialized G1 (32 B x, 32 B y) to result.0 success
‑1 error
int32_t alt_bn128_pair(const char* pairs, uint32_t pairs_len)Optimal‑Ate pairing check on alt_bn128 for the serialized G1/G2 pair list.0 pairing = true
1 pairing = false
‑1 error
int32_t mod_exp(const char* base, uint32_t base_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;const char* exp, uint32_t exp_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;const char* mod, uint32_t mod_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;char* result, uint32_t result_len)Compute (base^exp) mod mod; big‑int result written to result.0 success
‑1 error
int32_t blake2_f(uint32_t rounds,<br />&nbsp;&nbsp;&nbsp;&nbsp;const char* state, uint32_t state_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;const char* msg, uint32_t msg_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;const char* t0, uint32_t t0_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;const char* t1, uint32_t t1_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;int32_t final,<br />&nbsp;&nbsp;&nbsp;&nbsp;char* result, uint32_t result_len)BLAKE2b compression function F.0 success
‑1 error
sysio::checksum256 sha3(const char* data, uint32_t length)Return SHA‑3 (NIST) hash of data.256‑bit digest
void assert_sha3(const char* data, uint32_t length,<br />&nbsp;&nbsp;&nbsp;&nbsp;const sysio::checksum256& hash)Abort if sha3(data)hash.
sysio::checksum256 keccak(const char* data, uint32_t length)Return SHA‑3 Keccak hash of data.256‑bit digest
void assert_keccak(const char* data, uint32_t length,<br />&nbsp;&nbsp;&nbsp;&nbsp;const sysio::checksum256& hash)Abort if keccak(data)hash.
int32_t k1_recover(const char* sig, uint32_t sig_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;const char* dig, uint32_t dig_len,<br />&nbsp;&nbsp;&nbsp;&nbsp;char* pub, uint32_t pub_len)Recover uncompressed secp256k1 public key from signature sig over digest dig; writes key to pub.0 success
‑1 error

C++ Format

C++ types were added to represent G1 and G2 points (read and write) and views (read-only), and represent big integers. Their definitions are

Types

   /**
* Abstracts mutable G1 and G2 points
*
*/
template <std::size_t Size = 32>
struct ec_point {
/**
* Bytes of the x coordinate
*/
std::vector<char> x;

/**
* Bytes of the y coordinate
*/
std::vector<char> y;

/**
* Construct a point given x and y
*
* @param x_ - The x coordinate, a vector of chars
* @param y_ - The y coordinate, a vector of chars
*/
ec_point(std::vector<char>& x_, std::vector<char>& y_);

/**
* Construct a point given a serialized point
*
* @param p - The serialized point
*/
ec_point(std::vector<char>& p);

/**
* Return serialzed point containing only x and y
*/
std::vector<char> serialized() const;
};

/**
* Abstracts read-only G1 and G2 points
*/
template <std::size_t Size = 32>
struct ec_point_view {
/**
* Pointer to the x coordinate
*/
const char* x;

/**
* Pointer to the y coordinate
*/
const char* y;

/**
* Number of bytes in each of x and y
*/
uint32_t size;

/**
* Construct a point view from x and y
*
* @param x_ - The x coordinate, poiter to chars
* @param x_size - x's size
* @param y_ - The y coordinate, poiter to chars
* @param y_size - y's size
*/
ec_point_view(const char* x_, uint32_t x_size, const char* y_, uint32_t y_size);

/**
* Construct a point view from a serialized point
*
* @param p - The serialized point
*/
ec_point_view(const std::vector<char>& p);

/**
* Construct a point view from a point
*
* @param p - The point
*/
ec_point_view(const ec_point<Size>& p);

/**
* Return serialzed point containing only x and y
*/
std::vector<char> serialized() const;
};

static constexpr size_t g1_coordinate_size = 32;
static constexpr size_t g2_coordinate_size = 64;

using g1_point = ec_point<g1_coordinate_size>;
using g2_point = ec_point<g2_coordinate_size>;
using g1_point_view = ec_point_view<g1_coordinate_size>;
using g2_point_view = ec_point_view<g2_coordinate_size>;

/**
* Big integer.
*
* @ingroup crypto
*/
using bigint = std::vector<char>;

Methods

  • alt_bn128_add
    template <typename T>
g1_point alt_bn128_add( const T& op1, const T& op2 )

Take two G1 points or G1 views as input and return a G1 point.

  • alt_bn128_mul
   template <typename T>
g1_point alt_bn128_mul( const T& g1, const bigint& scalar)

Take a G1 point or view and a bigint as input and return a G1 point

  • alt_bn128_pair
   template <typename G1_T, typename G2_T>
int32_t alt_bn128_pair( const std::vector<std::pair<G1_T, G2_T>>& pairs )

Take a pair of G1 and G2 as input.

  • mod_exp
   int32_t mod_exp( const bigint& base, const bigint& exp, const bigint& mod, bigint& result )

Take bigints as input

Examples

  • alt_bn128_add
   std::vector<char> x1, y1, x2, y2;

// point
sysio::g1_point point1 {x1, y1};
sysio::g1_point point2 {x2, y2};
auto result = sysio::alt_bn128_add(point1, point2);

// view
sysio::g1_point_view point_view1 {x1.data(), x1.size(), y1.data(), y1.size()};
sysio::g1_point_view point_view2 {x2.data(), x2.size(), y2.data(), y2.size()};
result = sysio::alt_bn128_add(point_view1, point_view2);
  • alt_bn128_mul
   std::vector<char> x, y, scaler;
sysio::bigint s {scalar};

// point
sysio::g1_point g1_point {x, y};
auto result = sysio::alt_bn128_mul(g1_point, s);

// view
sysio::g1_point_view g1_view {x.data(), x.size(), y.data(), y.size()};
result = sysio::alt_bn128_mul(g1_view, s);
  • alt_bn128_pair
   std::vector<char> g1_a_x, g1_a_y, g2_a_x, g2_a_y, g1_b_x, g1_b_y, g2_b_x, g2_b_y;


// point
sysio::g1_point g1_a {g1_a_x, g1_a_y};
sysio::g2_point g2_a {g2_a_x, g2_a_y};
sysio::g1_point g1_b {g1_b_x, g1_b_y};
sysio::g2_point g2_b {g2_b_x, g2_b_y};
std::vector<std::pair<sysio::g1_point, sysio::g2_point>> pairs { {g1_a, g2_a}, {g1_b, g2_b} };
auto result = sysio::alt_bn128_pair(pairs);

// view
sysio::g1_point_view g1_view_a {g1_a_x.data(), g1_a_x.size(), g1_a_y.data(), g1_a_y.size()};
sysio::g2_point_view g2_view_a {g2_a_x.data(), g2_a_x.size(), g2_a_y.data(), g2_a_y.size()};
sysio::g1_point_view g1_view_b {g1_b_x.data(), g1_b_x.size(), g1_b_y.data(), g1_b_y.size()};
sysio::g2_point_view g2_view_b {g2_b_x.data(), g2_b_x.size(), g2_b_y.data(), g2_b_y.size()};
std::vector<std::pair<sysio::g1_point_view, sysio::g2_point_view>> view_pairs { {g1_a, g2_a}, {g1_b, g2_b} };
result = sysio::alt_bn128_pair(view_pairs);
  • mod_exp
   std::vector<char> base, exp, modulo;
sysio::bigint base_val {base};
sysio::bigint exp_val {exp};
sysio::bigint modulo_val {modulo};
sysio::bigint result( modulo.size(), '\0' );

auto rc = sysio::mod_exp(base_val, exp_val, modulo_val, result);