Crypto Extensions
As of v3.0
crypto host functions were extended to include
mod_exp
: Big integer modular exponentiationalt_bn128_add
,alt_bn128_mul
,alt_bn128_pair
: Add, multiply, and pairing check functions for thealt_bn128
elliptic curveblake2_f
:BLAKE2b F
compression functionsha3
: sha3hash function using
SHA3 NIST`Keccak256
:sha3
hash function usingSHA3 Keccak
k1_recover
: SafeECDSA
uncompressed pubkey recover for thesecp256k1
curve
In v3.0
, C
format was supported; in v3.1
, C++
format was added for better data abstraction.
Prerequisites
- In
nodeop
, activate protocol featureCRYPTO_PRIMITIVES
(68d6405cb8df3de95bd834ebb408196578500a9f818ff62ccc68f60b932f7d82
) - In smart contract code, include
crypto_ext.hpp
C Format
C‑API function | Description | Return |
---|---|---|
int32_t alt_bn128_add(const char* op1, uint32_t op1_len,<br /> const char* op2, uint32_t op2_len,<br /> 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 /> const char* scalar, uint32_t scalar_len,<br /> 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 = true1 pairing = false‑1 error |
int32_t mod_exp(const char* base, uint32_t base_len,<br /> const char* exp, uint32_t exp_len,<br /> const char* mod, uint32_t mod_len,<br /> 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 /> const char* state, uint32_t state_len,<br /> const char* msg, uint32_t msg_len,<br /> const char* t0, uint32_t t0_len,<br /> const char* t1, uint32_t t1_len,<br /> int32_t final,<br /> 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 /> 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 /> const sysio::checksum256& hash) | Abort if keccak(data) ≠ hash . | — |
int32_t k1_recover(const char* sig, uint32_t sig_len,<br /> const char* dig, uint32_t dig_len,<br /> 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);