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
nodeos
, activate protocol featureCRYPTO_PRIMITIVES
(68d6405cb8df3de95bd834ebb408196578500a9f818ff62ccc68f60b932f7d82
) - In smart contract code, include
crypto_ext.hpp
C Format
int32_t alt_bn128_add( const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* result, uint32_t result_len )
Perform addition operation on the elliptic curvealt_bn128
, store the result inresult
, and return0
if success otherwise-1
int32_t alt_bn128_mul( const char* g1, uint32_t g1_len, const char* scalar, uint32_t scalar_len, char* result, uint32_t result_len )
Perform scalar multiplication operation on the elliptic curvealt_bn128
int32_t alt_bn128_pair( const char* pairs, uint32_t pairs_len )
Perform Optimal-Ate pairing check elliptic curvealt_bn128
, and return0
iftrue
and successful,1
iffalse
, otherwise-1
int32_t mod_exp( const char* base, uint32_t base_len, const char* exp, uint32_t exp_len, const char* mod, uint32_t mod_len, char* result, uint32_t result_len )
Calculate( BASE^EXP ) % MOD
, store inresult
, and return0
if successful, otherwise-1
int32_t blake2_f( uint32_t rounds, const char* state, uint32_t state_len, const char* msg, uint32_t msg_len, const char* t0_offset, uint32_t t0_len, const char* t1_offset, uint32_t t1_len, int32_t final, char* result, uint32_t result_len)
Implement BLAKE2 compression functionF
. Return0
if success otherwise-1
eosio::checksum256 sha3(const char* data, uint32_t length)
Return hash ofdata
usingSHA3 NIST
void assert_sha3(const char* data, uint32_t length, const eosio::checksum256& hash)
Test if the SHA3 hash generated from data matches the provided digesteosio::checksum256 keccak(const char* data, uint32_t length)
Return hash ofdata
usingSHA3 Keccak
- `void assert_keccak(const char* data, uint32_t length, const eosio::checksum256& hash) Test if the SHA3 keccak hash generated from data matches the provided digest
int32_t k1_recover( const char* sig, uint32_t sig_len, const char* dig, uint32_t dig_len, char* pub, uint32_t pub_len )
Calculates the uncompressed public key used for a given signature on a given digest. Return0
if success otherwise-1
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
eosio::g1_point point1 {x1, y1};
eosio::g1_point point2 {x2, y2};
auto result = eosio::alt_bn128_add(point1, point2);
// view
eosio::g1_point_view point_view1 {x1.data(), x1.size(), y1.data(), y1.size()};
eosio::g1_point_view point_view2 {x2.data(), x2.size(), y2.data(), y2.size()};
result = eosio::alt_bn128_add(point_view1, point_view2);
alt_bn128_mul
std::vector<char> x, y, scaler;
eosio::bigint s {scalar};
// point
eosio::g1_point g1_point {x, y};
auto result = eosio::alt_bn128_mul(g1_point, s);
// view
eosio::g1_point_view g1_view {x.data(), x.size(), y.data(), y.size()};
result = eosio::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
eosio::g1_point g1_a {g1_a_x, g1_a_y};
eosio::g2_point g2_a {g2_a_x, g2_a_y};
eosio::g1_point g1_b {g1_b_x, g1_b_y};
eosio::g2_point g2_b {g2_b_x, g2_b_y};
std::vector<std::pair<eosio::g1_point, eosio::g2_point>> pairs { {g1_a, g2_a}, {g1_b, g2_b} };
auto result = eosio::alt_bn128_pair(pairs);
// view
eosio::g1_point_view g1_view_a {g1_a_x.data(), g1_a_x.size(), g1_a_y.data(), g1_a_y.size()};
eosio::g2_point_view g2_view_a {g2_a_x.data(), g2_a_x.size(), g2_a_y.data(), g2_a_y.size()};
eosio::g1_point_view g1_view_b {g1_b_x.data(), g1_b_x.size(), g1_b_y.data(), g1_b_y.size()};
eosio::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<eosio::g1_point_view, eosio::g2_point_view>> view_pairs { {g1_a, g2_a}, {g1_b, g2_b} };
result = eosio::alt_bn128_pair(view_pairs);
mod_exp
std::vector<char> base, exp, modulo;
eosio::bigint base_val {base};
eosio::bigint exp_val {exp};
eosio::bigint modulo_val {modulo};
eosio::bigint result( modulo.size(), '\0' );
auto rc = eosio::mod_exp(base_val, exp_val, modulo_val, result);