Merge branch 'main' into devint

This commit is contained in:
Dmytro Sydorchenko
2023-10-13 14:23:53 -04:00
22 changed files with 1238 additions and 216 deletions
+6
View File
@@ -0,0 +1,6 @@
{
"leap-dev":{
"target":"main",
"prerelease":false
}
}
+3 -3
View File
@@ -1,11 +1,11 @@
{
"ubuntu18": {
"dockerfile": ".cicd/platforms/ubuntu18.Dockerfile"
},
"ubuntu20": {
"dockerfile": ".cicd/platforms/ubuntu20.Dockerfile"
},
"ubuntu22": {
"dockerfile": ".cicd/platforms/ubuntu22.Dockerfile"
},
"ubuntu22-llvm": {
"dockerfile": ".cicd/platforms/ubuntu22-llvm.Dockerfile"
}
}
-31
View File
@@ -1,31 +0,0 @@
FROM ubuntu:bionic
RUN apt-get update && apt-get upgrade -y && \
DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential \
g++-8 \
curl \
ninja-build \
software-properties-common \
zlib1g-dev \
pkg-config \
libboost-all-dev \
libcurl4-gnutls-dev
RUN curl -L https://cmake.org/files/v3.13/cmake-3.13.5.tar.gz | tar zx && \
cd cmake-3.13.5 && \
./configure && \
make -j$(nproc) install && \
cd .. && \
rm -rf cmake-3.13.5
RUN add-apt-repository ppa:git-core/ppa && apt update && apt install -y git
RUN curl -L https://www.python.org/ftp/python/3.10.6/Python-3.10.6.tgz | tar zx && \
cd Python* && \
./configure --enable-optimizations --prefix=/usr && \
make -j$(nproc) install && \
cd .. && \
rm -rf Python*
ENV CC=gcc-8
ENV CXX=g++-8
+23
View File
@@ -0,0 +1,23 @@
FROM ubuntu:jammy
RUN apt-get update && apt-get upgrade -y && \
DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential \
cmake \
wget \
git \
ninja-build \
python3 \
pkg-config \
libboost-all-dev \
libcurl4-gnutls-dev \
lsb-release \
software-properties-common \
gnupg \
clang-tidy
RUN wget https://apt.llvm.org/llvm.sh
RUN chmod +x llvm.sh
RUN ./llvm.sh 16
ENV CC=clang-16
ENV CXX=clang++-16
+44 -9
View File
@@ -7,6 +7,17 @@ on:
- "release/*"
pull_request:
workflow_dispatch:
inputs:
override-leap-dev:
description: Override leap-dev target
type: string
override-leap-dev-prerelease:
type: choice
description: Override leap-dev prelease
options:
- default
- true
- false
permissions:
packages: write
@@ -53,14 +64,38 @@ jobs:
push: true
tags: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
file: ${{fromJSON(needs.d.outputs.p)[matrix.platform].dockerfile}}
versions:
name: Determine Versions
runs-on: ubuntu-latest
outputs:
leap-dev-target: ${{steps.versions.outputs.leap-dev-target}}
leap-dev-prerelease: ${{steps.versions.outputs.leap-dev-prerelease}}
steps:
- name: Setup versions from input or defaults
id: versions
env:
GH_TOKEN: ${{github.token}}
run: |
DEFAULTS_JSON=$(curl -sSfL $(gh api https://api.github.com/repos/${{github.repository}}/contents/.cicd/defaults.json?ref=${{github.sha}} --jq .download_url))
echo leap-dev-target=$(echo "$DEFAULTS_JSON" | jq -r '."leap-dev".target') >> $GITHUB_OUTPUT
echo leap-dev-prerelease=$(echo "$DEFAULTS_JSON" | jq -r '."leap-dev".prerelease') >> $GITHUB_OUTPUT
if [[ "${{inputs.override-leap-dev}}" != "" ]]; then
echo leap-dev-target=${{inputs.override-leap-dev}} >> $GITHUB_OUTPUT
fi
if [[ "${{inputs.override-leap-dev-prerelease}}" == +(true|false) ]]; then
echo leap-dev-prerelease=${{inputs.override-leap-dev-prerelease}} >> $GITHUB_OUTPUT
fi
Build:
name: Build & Test
needs: [d, build-platforms]
needs: [d, build-platforms, versions]
if: always() && needs.d.result == 'success' && (needs.build-platforms.result == 'success' || needs.build-platforms.result == 'skipped')
strategy:
fail-fast: false
matrix:
platform: [ubuntu18, ubuntu20, ubuntu22]
platform: [ubuntu20, ubuntu22, ubuntu22-llvm]
runs-on: ["self-hosted", "enf-x86-beefy"]
container: ${{fromJSON(needs.d.outputs.p)[matrix.platform].image}}
steps:
@@ -69,15 +104,15 @@ jobs:
submodules: recursive
- name: Download leap-dev.deb (Ubuntu 20 only)
if: matrix.platform == 'ubuntu20'
uses: AntelopeIO/asset-artifact-download-action@v2
uses: AntelopeIO/asset-artifact-download-action@v3
with:
owner: AntelopeIO
repo: leap
file: 'leap-dev.*(x86_64|amd64).deb'
target: 4.0
target: '${{needs.versions.outputs.leap-dev-target}}'
prereleases: ${{fromJSON(needs.versions.outputs.leap-dev-prerelease)}}
artifact-name: leap-dev-ubuntu20-amd64
container-package: experimental-binaries
token: ${{github.token}}
- name: Install leap-dev.deb (Ubuntu 20 only)
if: matrix.platform == 'ubuntu20'
run: |
@@ -92,13 +127,13 @@ jobs:
make -j $(nproc)
cd tests
ctest -j $(nproc) --output-on-failure
- name: Package (Ubuntu 18 only)
if: matrix.platform == 'ubuntu18'
- name: Package (Ubuntu 20 only)
if: matrix.platform == 'ubuntu20'
run: |
cd build/packages
bash generate_package.sh deb ubuntu amd64
- name: Upload (Ubuntu 18 only)
if: matrix.platform == 'ubuntu18'
- name: Upload (Ubuntu 20 only)
if: matrix.platform == 'ubuntu20'
uses: actions/upload-artifact@v3
with:
name: cdt_ubuntu_package_amd64
+1 -1
View File
@@ -9,4 +9,4 @@
url = https://github.com/AntelopeIO/cdt-libcxx
[submodule "libraries/native/softfloat"]
path = libraries/native/softfloat
url = https://github.com/AntelopeIO/berkeley-softfloat-3
url = https://github.com/AntelopeIO/berkeley-softfloat-3
+1
View File
@@ -38,6 +38,7 @@ The instructions below assume that you are building on Ubuntu 20.04.
apt-get update && apt-get install \
build-essential \
clang \
clang-tidy \
cmake \
git \
libxml2-dev \
+71 -118
View File
@@ -1,23 +1,22 @@
---
content_title: Crypto Extensions
content_title: Crypto Extensions API
---
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`: sha3` hash function using `SHA3 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.
Antelope blockchain implements cryptographic functions for operations on points on elliptic curves, computing hashes
of big integers, big integer modular exponentiation, and other operations useful for implementing
cryptographic algorithms in your contracts.
## Prerequisites
In order to use the Crypto Extensions API you need to activate a protocol feature `CRYPTO_PRIMITIVES`
in `nodeos`. To do this you should call the following command in your command line:
- In `nodeos`, activate protocol feature `CRYPTO_PRIMITIVES` (`68d6405cb8df3de95bd834ebb408196578500a9f818ff62ccc68f60b932f7d82`)
- In smart contract code, include `crypto_ext.hpp`
`"cleos push action eosio activate ["6bcb40a24e49c26d0a60513b6aeb8551d264e4717f306b81a37a5afb3b47cedc"] -p eosio@active"`
## C Format
And you need to include in the source code of your contract the following header: [crypto_ext.hpp](https://github.com/AntelopeIO/cdt/blob/main/libraries/eosiolib/core/eosio/crypto_ext.hpp)
The header declares following basic plain C functions which implement the core functionality:
## Plain C API
- `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 curve `alt_bn128`, store the result in `result`, and return `0` if success otherwise `-1`
@@ -40,154 +39,92 @@ 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. Return `0` 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
Also, the header contains a set of handy C++ wrappers to simplify the contracts code.
### Types
## C++ API
`ec_point` type was added to represent `G1` and `G2` points on the elliptic curve.
`ec_point_view` type was added to provide a read-only interface for access to `G1` and `G2` points data.
### Data Types
```c++
/**
* Abstracts mutable G1 and G2 points
*
*/
// 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
*/
std::vector<char> x; // x coordinate
std::vector<char> y; // y coordinate
// Construct from two coordinates represented by big integers
ec_point(std::vector<char>& x_, std::vector<char>& y_);
/**
* Construct a point given a serialized point
*
* @param p - The serialized point
*/
// Construct from a serialized point
ec_point(std::vector<char>& p);
/**
* Return serialzed point containing only x and y
*/
// Return a serialized point containing only x and y
std::vector<char> serialized() const;
};
/**
* Abstracts read-only G1 and G2 points
*/
// 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
*/
// 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
*/
// Construct from two coordinates. Their sizes must be equal
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
*/
// Construct from a serialized point
ec_point_view(const std::vector<char>& p);
/**
* Construct a point view from a point
*
* @param p - The point
*/
// Construct a point view from a point
ec_point_view(const ec_point<Size>& p);
/**
* Return serialzed point containing only x and y
*/
// Return serialized 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>;
// Big integer.
using bigint = std::vector<char>;
```
### Methods
- `alt_bn128_add`
- Addition operation on the elliptic curve `alt_bn128`
```c++
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`
- Scalar multiplication operation on the elliptic curve `alt_bn128`
```c++
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`
- Optimal-Ate pairing check elliptic curve `alt_bn128`
```c++
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`
- Big integer modular exponentiation returns `( BASE^EXP ) % MOD`
```c++
int32_t mod_exp( const bigint& base, const bigint& exp, const bigint& mod, bigint& result )
```
Take bigints as input
Please take a look into a [crypto_ext.hpp](https://github.com/AntelopeIO/cdt/blob/main/libraries/eosiolib/core/eosio/crypto_ext.hpp)
header file, it contains more wrappers and helper functions which may be useful in your code.
### Examples
- `alt_bn128_add`
```c++
std::vector<char> x1, y1, x2, y2;
std::vector<char> x1, y1, x2, y2; // Declare coordinates for points on an elliptic curve
// point
// Create the points on the curve
eosio::g1_point point1 {x1, y1};
eosio::g1_point point2 {x2, y2};
// Add two points and get a third point on the curve as result
auto result = eosio::alt_bn128_add(point1, point2);
// view
// Do the same addition but with g1_point_view data types
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);
@@ -195,32 +132,45 @@ Take bigints as input
- `alt_bn128_mul`
```c++
std::vector<char> x, y, scaler;
// Declare coordinates for a point on an elliptic curve and a big integer
std::vector<char> x, y, scalar;
eosio::bigint s {scalar};
// point
// Create the point object with given coordinates
eosio::g1_point g1_point {x, y};
// Multiply the point with a big integer and get a point on the curve as result
auto result = eosio::alt_bn128_mul(g1_point, s);
// view
// Do the same multiplication but with g1_point_view data type
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`
```c++
// Declare coordinates for the pairs of points on an elliptic curve
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
// Create the point object by given coordinates
// First pair
eosio::g1_point g1_a {g1_a_x, g1_a_y};
eosio::g2_point g2_a {g2_a_x, g2_a_y};
// Second pair
eosio::g1_point g1_b {g1_b_x, g1_b_y};
eosio::g2_point g2_b {g2_b_x, g2_b_y};
// Create the pairs object
std::vector<std::pair<eosio::g1_point, eosio::g2_point>> pairs { {g1_a, g2_a}, {g1_b, g2_b} };
// Perform the pairing check
// Return:
// -1 if there is an error
// 1 if the points not in a target group
// 0 if the points in a target group
auto result = eosio::alt_bn128_pair(pairs);
// view
// Do the same pairing check but with g1_point_view and g2_point_view data types
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()};
@@ -231,11 +181,14 @@ Take bigints as input
- `mod_exp`
```c++
// Declare big integer variables for the base, the exponent and the modulo
std::vector<char> base, exp, modulo;
eosio::bigint base_val {base};
eosio::bigint exp_val {exp};
eosio::bigint modulo_val {modulo};
// Declare and init a big integer variable for the result of exponentiation
eosio::bigint result( modulo.size(), '\0' );
// Perform the exponentiation
// return -1 if there is an error otherwise 0
auto rc = eosio::mod_exp(base_val, exp_val, modulo_val, result);
```
+21
View File
@@ -0,0 +1,21 @@
# Roadmap for CDT
## Summary Milestone 5
Top priority is clean-up of the code and optimizing for support. Target Date for Milestone 5 is May/June 2024.
- Remove AntlerProj repos from build and archive AntlerProj
- Move to C++20 - allow contracts to compile C++20
- Vanilla Clang/LLVM
- Upgrade to LLVM
## Antler
We lack the resources to complete the Antler project and support it going forward. Removing dependencies will simplify the build process and simplify things.
## Move to C++20
Allow contracts to compile C++20. In addition to the benefits from the latest language features. Currently, ENF maintains an additional fork of one of our upstream dependencies for EOS EVM simply to get around the fact that the upstream assumes C++20 but we cannot build C++20 code in our contracts.
## Vanilla Clang/LLVM
Try eosio extension free llvm and if it works with no issues then remove extensions to Clang/LLVM. The hope we will enable us to use Vanilla versions of the packages. This will allow us to use the latest, and will lead to improvements in functionality and performance.
## Upgrade to LLVM 16
Upgrade to the latest
@@ -0,0 +1,40 @@
#pragma once
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
__attribute__((eosio_wasm_import))
int32_t bls_g1_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g2_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g1_mul(const char* point, uint32_t point_len, const char* scalar, uint32_t scalar_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g2_mul(const char* point, uint32_t point_len, const char* scalar, uint32_t scalar_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g1_exp(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g2_exp(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_pairing(const char* g1_points, uint32_t g1_points_len, const char* g2_points, uint32_t g2_points_len, uint32_t n, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g1_map(const char* e, uint32_t e_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g2_map(const char* e, uint32_t e_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_fp_mod(const char* s, uint32_t s_len, char* res, uint32_t res_len);
#ifdef __cplusplus
}
#endif
@@ -732,11 +732,21 @@ class multi_index
_multidx->modify( *itr, payer, std::forward<Lambda&&>(updater) );
}
template<typename Lambda>
void update( const_iterator itr, eosio::name payer, Lambda&& updater ) {
modify( itr, payer, std::forward<Lambda>(updater) );
}
template<typename Lambda>
void modify( const T& obj, eosio::name payer, Lambda&& updater ) {
_multidx->modify( obj, payer, std::forward<Lambda&&>(updater) );
}
template<typename Lambda>
void update( T& obj, eosio::name payer, Lambda&& updater ) {
_multidx->update( obj, payer, std::forward<Lambda&&>(updater) );
}
const_iterator erase( const_iterator itr ) {
eosio::check( itr != cend(), "cannot pass end iterator to erase" );
@@ -748,6 +758,10 @@ class multi_index
return itr;
}
const_iterator remove( const_iterator itr ) {
return erase(itr);
}
eosio::name get_code()const { return _multidx->get_code(); }
uint64_t get_scope()const { return _multidx->get_scope(); }
@@ -841,6 +855,56 @@ class multi_index
return *ptr;
} /// load_object_by_primary_iterator
template<typename Lambda>
void modify_object(T& obj, name payer, Lambda&& updater) {
using namespace _multi_index_detail;
auto& objitem = static_cast<item&>(obj);
eosio::check( objitem.__idx == this, "object passed to modify is not in multi_index" );
eosio::check( _code == current_receiver(), "cannot modify objects in table of another contract" ); // Quick fix for mutating db using multi_index that shouldn't allow mutation. Real fix can come in RC2.
auto secondary_keys = make_extractor_tuple::get_extractor_tuple(indices_type{}, obj);
uint64_t pk = to_raw_key(obj.primary_key());
updater( obj );
eosio::check( pk == to_raw_key(obj.primary_key()), "updater cannot change primary key when modifying an object" );
size_t size = pack_size( obj );
//using malloc/free here potentially is not exception-safe, although WASM doesn't support exceptions
void* buffer = max_stack_buffer_size < size ? malloc(size) : alloca(size);
datastream<char*> ds( (char*)buffer, size );
ds << obj;
internal_use_do_not_use::db_update_i64( objitem.__primary_itr, payer.value, buffer, size );
if ( max_stack_buffer_size < size ) {
free( buffer );
}
if( pk >= _next_primary_key )
_next_primary_key = (pk >= no_available_primary_key) ? no_available_primary_key : (pk + 1);
bluegrass::meta::for_each(indices_type{}, [&](auto idx){
typedef std::tuple_element_t<const_index, decltype(idx)> index_type;
auto secondary = index_type::extract_secondary_key( obj );
if( memcmp( &std::get<index_type::index_number>(secondary_keys), &secondary, sizeof(secondary) ) != 0 ) {
auto indexitr = objitem.__iters[index_type::number()];
if( indexitr < 0 ) {
typename index_type::secondary_key_type temp_secondary_key;
indexitr = objitem.__iters[index_type::number()]
= secondary_index_db_functions<typename index_type::secondary_key_type>::db_idx_find_primary( _code.value, _scope, index_type::name(), pk, temp_secondary_key );
}
secondary_index_db_functions<typename index_type::secondary_key_type>::db_idx_update( indexitr, payer.value, secondary );
}
} );
}
public:
/**
* Constructs an instance of a Multi-Index table.
@@ -1531,6 +1595,7 @@ class multi_index
eosio::check( objitem.__idx == this, "object passed to iterator_to is not in multi_index" );
return {this, &objitem};
}
/**
* Adds a new object (i.e., row) to the table.
* @ingroup multiindex
@@ -1613,6 +1678,48 @@ class multi_index
return {this, ptr};
}
/**
* Adds a new object (i.e., row) to the table, alias for emplace()
* @ingroup multiindex
*
* @param payer - Account name of the payer for the Storage usage of the new object
* @param constructor - Lambda function that does an in-place initialization of the object to be created in the table
*
* @pre A multi index table has been instantiated
* @post A new object is created in the Multi-Index table, with a unique primary key (as specified in the object). The object is serialized and written to the table. If the table does not exist, it is created.
* @post Secondary indices are updated to refer to the newly added object. If the secondary index tables do not exist, they are created.
* @post The payer is charged for the storage usage of the new object and, if the table (and secondary index tables) must be created, for the overhead of the table creation.
*
* @return A primary key iterator to the newly created object
*
* Exception - The account is not authorized to write to the table.
*
* Example:
*
* @code
* // This assumes the code from the constructor example. Replace myaction() {...}
*
* void myaction() {
* address_index addresses(_self, _self.value); // code, scope
* // add to table, first argument is account to bill for storage
* addresses.insert(_self, [&](auto& address) {
* address.account_name = "dan"_n;
* address.first_name = "Daniel";
* address.last_name = "Larimer";
* address.street = "1 EOS Way";
* address.city = "Blacksburg";
* address.state = "VA";
* });
* }
* }
* EOSIO_DISPATCH( addressbook, (myaction) )
* @endcode
*/
template<typename Lambda>
const_iterator insert( name payer, Lambda&& constructor ) {
return emplace(payer, std::forward<Lambda>(constructor));
}
/**
* Modifies an existing object in a table.
* @ingroup multiindex
@@ -1660,6 +1767,51 @@ class multi_index
modify( *itr, payer, std::forward<Lambda&&>(updater) );
}
/**
* Updates an existing object in a table, alias for modify()
* @ingroup multiindex
*
* @param itr - an iterator pointing to the object to be updated
* @param payer - account name of the payer for the storage usage of the updated row
* @param updater - lambda function that updates the target object
*
* @pre itr points to an existing element
* @pre payer is a valid account that is authorized to execute the action and be billed for storage usage.
*
* @post The updated object is serialized, then replaces the existing object in the table.
* @post Secondary indices are updated; the primary key of the updated object is not changed.
* @post The payer is charged for the storage usage of the updated object.
* @post If payer is the same as the existing payer, payer only pays for the usage difference between existing and updated object (and is refunded if this difference is negative).
* @post If payer is different from the existing payer, the existing payer is refunded for the storage usage of the existing object.
*
* Exceptions:
* If called with an invalid precondition, execution is aborted.
*
* Example:
*
* @code
* // This assumes the code from the constructor example. Replace myaction() {...}
*
* void myaction() {
* // create reference to address_index - see emplace example
* // add dan account to table - see emplace example
*
* auto itr = addresses.find("dan"_n);
* eosio::check(itr != addresses.end(), "Address for account not found");
* addresses.update( itr, account payer, [&]( auto& address ) {
* address.city = "San Luis Obispo";
* address.state = "CA";
* });
* }
* }
* EOSIO_DISPATCH( addressbook, (myaction) )
* @endcode
*/
template<typename Lambda>
void update( const_iterator itr, name payer, Lambda&& updater ) {
modify( itr, payer, std::forward<Lambda>(updater) );
}
/**
* Modifies an existing object in a table.
* @ingroup multiindex
@@ -1703,53 +1855,55 @@ class multi_index
*/
template<typename Lambda>
void modify( const T& obj, name payer, Lambda&& updater ) {
using namespace _multi_index_detail;
T& mutable_obj = const_cast<T&>(obj);
const auto& objitem = static_cast<const item&>(obj);
eosio::check( objitem.__idx == this, "object passed to modify is not in multi_index" );
auto& mutableitem = const_cast<item&>(objitem);
eosio::check( _code == current_receiver(), "cannot modify objects in table of another contract" ); // Quick fix for mutating db using multi_index that shouldn't allow mutation. Real fix can come in RC2.
modify_object(mutable_obj, payer, std::forward<Lambda>(updater));
}
auto secondary_keys = make_extractor_tuple::get_extractor_tuple(indices_type{}, obj);
uint64_t pk = _multi_index_detail::to_raw_key(obj.primary_key());
auto& mutableobj = const_cast<T&>(obj); // Do not forget the auto& otherwise it would make a copy and thus not update at all.
updater( mutableobj );
eosio::check( pk == _multi_index_detail::to_raw_key(obj.primary_key()), "updater cannot change primary key when modifying an object" );
size_t size = pack_size( obj );
//using malloc/free here potentially is not exception-safe, although WASM doesn't support exceptions
void* buffer = max_stack_buffer_size < size ? malloc(size) : alloca(size);
datastream<char*> ds( (char*)buffer, size );
ds << obj;
internal_use_do_not_use::db_update_i64( objitem.__primary_itr, payer.value, buffer, size );
if ( max_stack_buffer_size < size ) {
free( buffer );
}
if( pk >= _next_primary_key )
_next_primary_key = (pk >= no_available_primary_key) ? no_available_primary_key : (pk + 1);
bluegrass::meta::for_each(indices_type{}, [&](auto idx){
typedef std::tuple_element_t<const_index, decltype(idx)> index_type;
auto secondary = index_type::extract_secondary_key( obj );
if( memcmp( &std::get<index_type::index_number>(secondary_keys), &secondary, sizeof(secondary) ) != 0 ) {
auto indexitr = mutableitem.__iters[index_type::number()];
if( indexitr < 0 ) {
typename index_type::secondary_key_type temp_secondary_key;
indexitr = mutableitem.__iters[index_type::number()]
= secondary_index_db_functions<typename index_type::secondary_key_type>::db_idx_find_primary( _code.value, _scope, index_type::name(), pk, temp_secondary_key );
}
secondary_index_db_functions<typename index_type::secondary_key_type>::db_idx_update( indexitr, payer.value, secondary );
}
} );
/**
* Updates an existing object in a table, alias for modify()
* @ingroup multiindex
*
* @param obj - a reference to the object to be updated
* @param payer - account name of the payer for the storage usage of the updated row
* @param updater - lambda function that updates the target object
*
* @pre obj is an existing object in the table
* @pre payer is a valid account that is authorized to execute the action and be billed for storage usage.
*
* @post The modified object is serialized, then replaces the existing object in the table.
* @post Secondary indices are updated; the primary key of the updated object is not changed.
* @post The payer is charged for the storage usage of the updated object.
* @post If payer is the same as the existing payer, payer only pays for the usage difference between existing and updated object (and is refunded if this difference is negative).
* @post If payer is different from the existing payer, the existing payer is refunded for the storage usage of the existing object.
*
* Exceptions:
* If called with an invalid precondition, execution is aborted.
*
* Example:
*
* @code
* // This assumes the code from the constructor example. Replace myaction() {...}
*
* void myaction() {
* // create reference to address_index - see emplace example
* // add dan account to table - see emplace example
*
* auto itr = addresses.find("dan"_n);
* eosio::check(itr != addresses.end(), "Address for account not found");
* addresses.update( *itr, payer, [&]( auto& address ) {
* address.city = "San Luis Obispo";
* address.state = "CA";
* });
* eosio::check(itr->city == "San Luis Obispo", "Lock arf, Address not modified");
* }
* }
* EOSIO_DISPATCH( addressbook, (myaction) )
* @endcode
*/
template<typename Lambda>
void update( T& obj, name payer, Lambda&& updater ) {
modify_object(obj, payer, std::forward<Lambda>(updater));
}
/**
@@ -1902,6 +2056,46 @@ class multi_index
return itr;
}
/**
* Deletes an existing object from a table using its primary key, alias for erase()
* @ingroup multiindex
*
* @param itr - An iterator pointing to the object to be removed
*
* @pre itr points to an existing element
* @post The object is removed from the table and all associated storage is reclaimed.
* @post Secondary indices associated with the table are updated.
* @post The existing payer for storage usage of the object is refunded for the table and secondary indices usage of the removed object, and if the table and indices are removed, for the associated overhead.
*
* @return For the signature with `const_iterator`, returns a pointer to the object following the removed object.
*
* Exceptions:
* The object to be removed is not in the table.
* The action is not authorized to modify the table.
* The given iterator is invalid.
*
* Example:
*
* @code
* // This assumes the code from the constructor example. Replace myaction() {...}
*
* void myaction() {
* // create reference to address_index - see emplace example
* // add dan account to table - see emplace example
*
* auto itr = addresses.find("dan"_n);
* eosio::check(itr != addresses.end(), "Address for account not found");
* addresses.delete( itr );
* eosio::check(itr != addresses.end(), "Everting lock arf, Address not erased properly");
* }
* }
* EOSIO_ABI( addressbook, (myaction) )
* @endcode
*/
const_iterator remove( const_iterator itr ) {
return erase(itr);
}
/**
* Remove an existing object from a table using its primary key.
* @ingroup multiindex
@@ -1965,5 +2159,41 @@ class multi_index
_items_vector.erase(--(itr2.base()));
}
/**
* Remove an existing object from a table using its primary key, alias for erase()
* @ingroup multiindex
*
* @param obj - Object to be removed
*
* @pre obj is an existing object in the table
* @post The object is removed from the table and all associated storage is reclaimed.
* @post Secondary indices associated with the table are updated.
* @post The existing payer for storage usage of the object is refunded for the table and secondary indices usage of the removed object, and if the table and indices are removed, for the associated overhead.
*
* Exceptions:
* The object to be removed is not in the table.
* The action is not authorized to modify the table.
* The given iterator is invalid.
*
* Example:
*
* @code
* // This assumes the code from the constructor example. Replace myaction() {...}
*
* void myaction() {
* auto itr = addresses.find("dan"_n);
* eosio::check(itr != addresses.end(), "Record is not found");
* addresses.remove(*itr);
* itr = addresses.find("dan"_n);
* eosio::check(itr == addresses.end(), "Record is not deleted");
* }
* }
* EOSIO_DISPATCH( addressbook, (myaction) )
* @endcode
*/
void remove( const T& obj ) {
erase(obj);
}
};
} /// eosio
@@ -0,0 +1,161 @@
#pragma once
#include "fixed_bytes.hpp"
#include "varint.hpp"
#include "serialize.hpp"
#include <array>
#include <vector>
namespace eosio {
namespace internal_use_do_not_use {
extern "C" {
__attribute__((eosio_wasm_import))
int32_t bls_g1_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g2_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g1_mul(const char* point, uint32_t point_len, const char* scalar, uint32_t scalar_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g2_mul(const char* point, uint32_t point_len, const char* scalar, uint32_t scalar_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g1_exp(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g2_exp(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_pairing(const char* g1_points, uint32_t g1_points_len, const char* g2_points, uint32_t g2_points_len, uint32_t n, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g1_map(const char* e, uint32_t e_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_g2_map(const char* e, uint32_t e_len, char* res, uint32_t res_len);
__attribute__((eosio_wasm_import))
int32_t bls_fp_mod(const char* s, uint32_t s_len, char* res, uint32_t res_len);
}
}
using bls_scalar = std::array<char, 32>;
using bls_fp = std::array<char, 48>;
using bls_s = std::array<char, 64>;
using bls_fp2 = std::array<bls_fp, 2>;
using bls_g1 = std::array<char, 144>;
using bls_g2 = std::array<char, 288>;
using bls_gt = std::array<char, 576>;
int32_t bls_g1_add(const bls_g1& op1, const bls_g1& op2, bls_g1& res) {
return internal_use_do_not_use::bls_g1_add(
op1.data(),
sizeof(bls_g1),
op2.data(),
sizeof(bls_g1),
res.data(),
sizeof(bls_g1)
);
}
int32_t bls_g2_add(const bls_g2& op1, const bls_g2& op2, bls_g2& res) {
return internal_use_do_not_use::bls_g2_add(
op1.data(),
sizeof(bls_g2),
op2.data(),
sizeof(bls_g2),
res.data(),
sizeof(bls_g2)
);
}
int32_t bls_g1_mul(const bls_g1& point, const bls_scalar& scalar, bls_g1& res) {
return internal_use_do_not_use::bls_g1_mul(
point.data(),
sizeof(bls_g1),
scalar.data(),
sizeof(bls_scalar),
res.data(),
sizeof(bls_g1)
);
}
int32_t bls_g2_mul(const bls_g2& point, const bls_scalar& scalar, bls_g2& res) {
return internal_use_do_not_use::bls_g2_mul(
point.data(),
sizeof(bls_g2),
scalar.data(),
sizeof(bls_scalar),
res.data(),
sizeof(bls_g2)
);
}
int32_t bls_g1_exp(const bls_g1 points[], const bls_scalar scalars[], const uint32_t num, bls_g1& res) {
return internal_use_do_not_use::bls_g1_exp(
num ? points[0].data() : nullptr,
num * sizeof(bls_g1),
num ? scalars[0].data() : nullptr,
num * sizeof(bls_scalar),
num,
res.data(),
sizeof(bls_g1)
);
}
int32_t bls_g2_exp(const bls_g2 points[], const bls_scalar scalars[], const uint32_t num, bls_g2& res) {
return internal_use_do_not_use::bls_g2_exp(
num ? points[0].data() : nullptr,
num * sizeof(bls_g2),
num ? scalars[0].data() : nullptr,
num * sizeof(bls_scalar),
num,
res.data(),
sizeof(bls_g2)
);
}
int32_t bls_pairing(const bls_g1 g1_points[], const bls_g2 g2_points[], const uint32_t num, bls_gt& res) {
return internal_use_do_not_use::bls_pairing(
num ? g1_points[0].data() : nullptr,
num * sizeof(bls_g1),
num ? g2_points[0].data() : nullptr,
num * sizeof(bls_g2),
num,
res.data(),
sizeof(bls_gt)
);
}
int32_t bls_g1_map(const bls_fp& e, bls_g1& res) {
return internal_use_do_not_use::bls_g1_map(
e.data(),
sizeof(bls_fp),
res.data(),
sizeof(bls_g1)
);
}
int32_t bls_g2_map(const bls_fp2& e, bls_g2& res) {
return internal_use_do_not_use::bls_g2_map(
e[0].data(),
sizeof(bls_fp2),
res.data(),
sizeof(bls_g2)
);
}
int32_t bls_fp_mod(const bls_s& s, bls_fp& res) {
return internal_use_do_not_use::bls_fp_mod(
s.data(),
sizeof(bls_s),
res.data(),
sizeof(bls_fp)
);
}
}
@@ -65,11 +65,6 @@ namespace bluegrass { namespace meta {
template <typename T>
constexpr bool pass_type() { return true; }
template <typename>
constexpr bool is_callable_impl(...) {
return false;
}
template <typename T>
struct wrapper_t {
using type = T;
@@ -16,7 +16,7 @@ if (NOT ${found_project})
ExternalProject_Add(
catch2_external_proj
GIT_REPOSITORY "https://github.com/catchorg/Catch2"
GIT_TAG "v2.12.2"
GIT_TAG "v2.13.10"
SOURCE_DIR @CATCH2_DIRECTORY@/catch2
BINARY_DIR @CATCH2_DIRECTORY@/catch2
BUILD_ALWAYS 0
+51 -1
View File
@@ -935,4 +935,54 @@ int32_t mod_exp( const char* base, uint32_t base_len, const char* exp, uint32_t
void sha3( const char* data, uint32_t data_len, char* hash, uint32_t hash_len, int32_t keccak ) {
intrinsics::get().call<intrinsics::sha3>(data, data_len, hash, hash_len, keccak);
}
}
int32_t bls_g1_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_g1_add>(op1, op1_len, op2, op2_len, res, res_len);
}
int32_t bls_g2_add(const char* op1, uint32_t op1_len, const char* op2, uint32_t op2_len, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_g2_add>(op1, op1_len, op2, op2_len, res, res_len);
}
int32_t bls_g1_mul(const char* point, uint32_t point_len, const char* scalar, uint32_t scalar_len, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_g1_mul>(point, point_len, scalar, scalar_len, res, res_len);
}
int32_t bls_g2_mul(const char* point, uint32_t point_len, const char* scalar, uint32_t scalar_len, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_g2_mul>(point, point_len, scalar, scalar_len, res, res_len);
}
int32_t bls_g1_exp(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_g1_exp>(points, points_len, scalars, scalars_len, n, res, res_len);
}
int32_t bls_g2_exp(const char* points, uint32_t points_len, const char* scalars, uint32_t scalars_len, uint32_t n, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_g2_exp>(points, points_len, scalars, scalars_len, n, res, res_len);
}
int32_t bls_pairing(const char* g1_points, uint32_t g1_points_len, const char* g2_points, uint32_t g2_points_len, uint32_t n, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_pairing>(g1_points, g1_points_len, g1_points, g1_points_len, n, res, res_len);
}
int32_t bls_g1_map(const char* e, uint32_t e_len, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_g1_map>(e, e_len, res, res_len);
}
int32_t bls_g2_map(const char* e, uint32_t e_len, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_g2_map>(e, e_len, res, res_len);
}
int32_t bls_fp_mod(const char* s, uint32_t s_len, char* res, uint32_t res_len)
{
return intrinsics::get().call<intrinsics::bls_fp_mod>(s, s_len, res, res_len);
}
@@ -4,6 +4,7 @@
#include <eosio/chain.h>
#include <eosio/crypto.h>
#include <eosio/crypto_ext.h>
#include <eosio/crypto_bls_ext.h>
#include <eosio/db.h>
#include <eosio/permission.h>
#include <eosio/print.h>
@@ -172,7 +173,17 @@ intrinsic_macro(k1_recover) \
intrinsic_macro(alt_bn128_add) \
intrinsic_macro(alt_bn128_mul) \
intrinsic_macro(alt_bn128_pair) \
intrinsic_macro(mod_exp)
intrinsic_macro(mod_exp) \
intrinsic_macro(bls_g1_add) \
intrinsic_macro(bls_g2_add) \
intrinsic_macro(bls_g1_mul) \
intrinsic_macro(bls_g2_mul) \
intrinsic_macro(bls_g1_exp) \
intrinsic_macro(bls_g2_exp) \
intrinsic_macro(bls_pairing) \
intrinsic_macro(bls_g1_map) \
intrinsic_macro(bls_g2_map) \
intrinsic_macro(bls_fp_mod)
+108
View File
@@ -0,0 +1,108 @@
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/abi_serializer.hpp>
#include <fc/variant_object.hpp>
#include <contracts.hpp>
using namespace eosio;
using namespace eosio::testing;
using namespace eosio::chain;
using namespace eosio::testing;
using namespace fc;
using mvo = fc::mutable_variant_object;
struct bls_primitives_tester : tester {
bls_primitives_tester() {
create_accounts( { "test"_n } );
produce_block();
set_code( "eosio"_n, contracts::bls_primitives_test_wasm() );
set_abi( "eosio"_n, contracts::bls_primitives_test_abi().data() );
produce_blocks();
}
};
BOOST_AUTO_TEST_SUITE(bls_primitives_tests)
BOOST_FIXTURE_TEST_CASE( g1_add_test, bls_primitives_tester ) try {
push_action("eosio"_n, "testg1add"_n, "test"_n, mvo()
("op1", "160c53fd9087b35cf5ff769967fc1778c1a13b14c7954f1547e7d0f3cd6aaef040f4db21cc6eceed75fb0b9e417701127122e70cd593acba8efd18791a63228cce250757135f59dd945140502958ac51c05900ad3f8c1c0e6aa20850fc3ebc0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615")
("op2", "160c53fd9087b35cf5ff769967fc1778c1a13b14c7954f1547e7d0f3cd6aaef040f4db21cc6eceed75fb0b9e417701127122e70cd593acba8efd18791a63228cce250757135f59dd945140502958ac51c05900ad3f8c1c0e6aa20850fc3ebc0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615")
("res", "2b90dabdf4613e10d269d70050e61bdc53c6d01ac517ad33cd8e82799d5515dfba05bc172fd280e2a73ff01aca77e30cbf82182b9005141106ef83a6d33dcda8bece738c9f9d6313f7e05945fd92c23a208efbe7a2048c6250f7f14df9f5c215e244ce19aa2759751dfb31f234c644189d4b0eae26beb2ba29a380a052b058a380b3005a7f18391cd44411a0f87d7817"));
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( g2_add_test, bls_primitives_tester ) try {
push_action("eosio"_n, "testg2add"_n, "test"_n, mvo()
("op1", "100a9402a28ff2f51a96b48726fbf5b380e52a3eb593a8a1e9ae3c1a9d9994986b36631863b7676fd7bc50439291810506f6239e75c0a9a5c360cdbc9dc5a0aa067886e2187eb13b67b34185ccb61a1b478515f20eedb6c2f3ed6073092a92114a4c4960f80a734c5a9c365e1ffa7c595a630aaa6c85e6e75f490d6ee9b5efbba225eff075a9d307e5da807e8efd83005db064df92fcc0addc61142b0a27aa18a0ebe43b6aacad863aa33dc94e5c4979edca3ca4505817e7f21bde63a1c22b0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
("op2", "100a9402a28ff2f51a96b48726fbf5b380e52a3eb593a8a1e9ae3c1a9d9994986b36631863b7676fd7bc50439291810506f6239e75c0a9a5c360cdbc9dc5a0aa067886e2187eb13b67b34185ccb61a1b478515f20eedb6c2f3ed6073092a92114a4c4960f80a734c5a9c365e1ffa7c595a630aaa6c85e6e75f490d6ee9b5efbba225eff075a9d307e5da807e8efd83005db064df92fcc0addc61142b0a27aa18a0ebe43b6aacad863aa33dc94e5c4979edca3ca4505817e7f21bde63a1c22b0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
("res", "1987cff592d8ae5c83ba9e9a1a016afd3a4e80d646e10a1274ba259b60a405c189945d07b3608d4d339a96429d60f80d8290d66f4e963c0e8c00e35db541ab46e93148fd7e41449f0be0a1883e36e4b56cf87121991d6d4778d499fdf1501c09a9220f11cdfe60560b15d7e6ec33825a8d9ce209fe8e20391d32210ba83dbd77ce4cd6019ca50465f8f5fed4a8a631048739c8d9b8fdc26a962b24f0306f8293a00d72d37fb2fb1b0643d9a8453cbf6a520463a54e25e8c42134d6798d7cce00949892c0f015e698b4386dbc3ef4f9b2b4c61454d90acdcfbf921adcd26bdf77454bdee1eb52a70fcab501fd1cfb0701ba60c9be25f9815bb9c32856144e543140d7c977d4585b0d75467b929db892f2da957948a1b02ecee537bcc742855716"));
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( g1_mul_test, bls_primitives_tester ) try {
push_action("eosio"_n, "testg1mul"_n, "test"_n, mvo()
("point", "160c53fd9087b35cf5ff769967fc1778c1a13b14c7954f1547e7d0f3cd6aaef040f4db21cc6eceed75fb0b9e417701127122e70cd593acba8efd18791a63228cce250757135f59dd945140502958ac51c05900ad3f8c1c0e6aa20850fc3ebc0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615")
("scalar", "2a000000000000002a000000000000002a000000000000002a00000000000000")
("res", "de3e7eeee055abe12a480e58411508d51a356ff6692b14b43426d22cc354cd5d7469c41e0f1f5e40503c91e11419a30285cb057a62c93e2caaaff6c9c1dbc8f88c0a122157f51a617ce0e2890442cd9ce004a8ba972442e61bce9dabf1c6780c191984ae3c11ef21884a536f0d3450974df37295e9579d16cdb8dfdf9252091ca3cd9d05f4c6e645535add05ac197b08"));
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( g2_mul_test, bls_primitives_tester ) try {
push_action("eosio"_n, "testg2mul"_n, "test"_n, mvo()
("point", "100a9402a28ff2f51a96b48726fbf5b380e52a3eb593a8a1e9ae3c1a9d9994986b36631863b7676fd7bc50439291810506f6239e75c0a9a5c360cdbc9dc5a0aa067886e2187eb13b67b34185ccb61a1b478515f20eedb6c2f3ed6073092a92114a4c4960f80a734c5a9c365e1ffa7c595a630aaa6c85e6e75f490d6ee9b5efbba225eff075a9d307e5da807e8efd83005db064df92fcc0addc61142b0a27aa18a0ebe43b6aacad863aa33dc94e5c4979edca3ca4505817e7f21bde63a1c22b0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
("scalar", "2a000000000000002a000000000000002a000000000000002a00000000000000")
("res", "aa25f3f539b6f3215318d81b22d14bf9108294790e8a50545a404ae2057278304d8c3b5844271202b757767d1555a106ede90a9967cdc27b527d4a5720efda79a68b17072ad9402ed373ce9a2d28f5496106fc4cd23234b083181e8325734417f8330d2ced14040b815a006f7f905361f654d483c45abb90b4a958b4ca20ee2bb97cc1c9b6ff45644539abb32149610f33858c88450dad3d2adb82df72f9ed9c42dc2ef78e17f5a2a1abd0468853d55f05f6458179fdf5671db784795a686c0ffae139afaed0212d18d615b0ff90a9deba090f723190521dc8c822621b0a7e70a03b9f3faaeb862846dccd418855d70406fc57e73783c2da92433c1a3873640217539ec7c01f3d354506d86db49fddad225e82421506d99c19b749170aa4f805"));
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( g1_exp_test, bls_primitives_tester ) try {
push_action("eosio"_n, "testg1exp"_n, "test"_n, mvo()
("points", "160c53fd9087b35cf5ff769967fc1778c1a13b14c7954f1547e7d0f3cd6aaef040f4db21cc6eceed75fb0b9e417701127122e70cd593acba8efd18791a63228cce250757135f59dd945140502958ac51c05900ad3f8c1c0e6aa20850fc3ebc0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615160c53fd9087b35cf5ff769967fc1778c1a13b14c7954f1547e7d0f3cd6aaef040f4db21cc6eceed75fb0b9e417701127122e70cd593acba8efd18791a63228cce250757135f59dd945140502958ac51c05900ad3f8c1c0e6aa20850fc3ebc0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615")
("scalars", "2a000000000000002a000000000000002a000000000000002a000000000000002a000000000000002a000000000000002a000000000000002a00000000000000")
("res", "9e80ed609e62978a3a7f0d6bf57e1df4070725c1bf4dab43a6b710adef7450fb41f0cf14a7895ec26fd8c830c327cc0e2c8fe7687d23ff84647b47bbad04cf77625dee1049e53ad5162fe772278e5fe3ceb0bdc472f31952343da7b75532f7016613af892092131ad77d13afc8c9192487ac19f8454ad932653145f06e25790d26b23ac6b83025326f3397efbd845511"));
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( g2_exp_test, bls_primitives_tester ) try {
push_action("eosio"_n, "testg2exp"_n, "test"_n, mvo()
("points", "100a9402a28ff2f51a96b48726fbf5b380e52a3eb593a8a1e9ae3c1a9d9994986b36631863b7676fd7bc50439291810506f6239e75c0a9a5c360cdbc9dc5a0aa067886e2187eb13b67b34185ccb61a1b478515f20eedb6c2f3ed6073092a92114a4c4960f80a734c5a9c365e1ffa7c595a630aaa6c85e6e75f490d6ee9b5efbba225eff075a9d307e5da807e8efd83005db064df92fcc0addc61142b0a27aa18a0ebe43b6aacad863aa33dc94e5c4979edca3ca4505817e7f21bde63a1c22b0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100a9402a28ff2f51a96b48726fbf5b380e52a3eb593a8a1e9ae3c1a9d9994986b36631863b7676fd7bc50439291810506f6239e75c0a9a5c360cdbc9dc5a0aa067886e2187eb13b67b34185ccb61a1b478515f20eedb6c2f3ed6073092a92114a4c4960f80a734c5a9c365e1ffa7c595a630aaa6c85e6e75f490d6ee9b5efbba225eff075a9d307e5da807e8efd83005db064df92fcc0addc61142b0a27aa18a0ebe43b6aacad863aa33dc94e5c4979edca3ca4505817e7f21bde63a1c22b0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
("scalars", "2a000000000000002a000000000000002a000000000000002a000000000000002a000000000000002a000000000000002a000000000000002a00000000000000")
("res", "595a2cbaa4315ecc0dd9838a81712e0cfb88cb2c4468640ff382abb321b3a9bedebb0aad985a9057f664fc52eb52cd194b1c9611b25ef4281e439a52d1832813decd66c22440821f0288dcb7a82151386aa0240e943b6905e61619be2e11c208fa03df16e11a1b1368abac90598bb237f785701d5d1d5cb0af6934ed633d366de28703431b8d70899d92797689207c0cd35c345460f971dff5d648d9ddec8f5fabef99b15ea7c4440ac1564d6e0326076f32a4ec9cf0d10059593d64afd35c03d10f16794821628b565c9319f4af3c96b98c4fb11bc0c04172bb57372531f6e76798142d4b00488adbea850a2649a305b71fa389c3c226f2df4a58c8bce5d90698452f4126046be0c82d8817b64162a53787f1cb73af27d969adc626c1392716"));
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( pairing_test, bls_primitives_tester ) try {
push_action("eosio"_n, "testpairing"_n, "test"_n, mvo()
("g1_points", "160c53fd9087b35cf5ff769967fc1778c1a13b14c7954f1547e7d0f3cd6aaef040f4db21cc6eceed75fb0b9e417701127122e70cd593acba8efd18791a63228cce250757135f59dd945140502958ac51c05900ad3f8c1c0e6aa20850fc3ebc0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615160c53fd9087b35cf5ff769967fc1778c1a13b14c7954f1547e7d0f3cd6aaef040f4db21cc6eceed75fb0b9e417701127122e70cd593acba8efd18791a63228cce250757135f59dd945140502958ac51c05900ad3f8c1c0e6aa20850fc3ebc0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615160c53fd9087b35cf5ff769967fc1778c1a13b14c7954f1547e7d0f3cd6aaef040f4db21cc6eceed75fb0b9e417701127122e70cd593acba8efd18791a63228cce250757135f59dd945140502958ac51c05900ad3f8c1c0e6aa20850fc3ebc0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615")
("g2_points", "100a9402a28ff2f51a96b48726fbf5b380e52a3eb593a8a1e9ae3c1a9d9994986b36631863b7676fd7bc50439291810506f6239e75c0a9a5c360cdbc9dc5a0aa067886e2187eb13b67b34185ccb61a1b478515f20eedb6c2f3ed6073092a92114a4c4960f80a734c5a9c365e1ffa7c595a630aaa6c85e6e75f490d6ee9b5efbba225eff075a9d307e5da807e8efd83005db064df92fcc0addc61142b0a27aa18a0ebe43b6aacad863aa33dc94e5c4979edca3ca4505817e7f21bde63a1c22b0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100a9402a28ff2f51a96b48726fbf5b380e52a3eb593a8a1e9ae3c1a9d9994986b36631863b7676fd7bc50439291810506f6239e75c0a9a5c360cdbc9dc5a0aa067886e2187eb13b67b34185ccb61a1b478515f20eedb6c2f3ed6073092a92114a4c4960f80a734c5a9c365e1ffa7c595a630aaa6c85e6e75f490d6ee9b5efbba225eff075a9d307e5da807e8efd83005db064df92fcc0addc61142b0a27aa18a0ebe43b6aacad863aa33dc94e5c4979edca3ca4505817e7f21bde63a1c22b0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100a9402a28ff2f51a96b48726fbf5b380e52a3eb593a8a1e9ae3c1a9d9994986b36631863b7676fd7bc50439291810506f6239e75c0a9a5c360cdbc9dc5a0aa067886e2187eb13b67b34185ccb61a1b478515f20eedb6c2f3ed6073092a92114a4c4960f80a734c5a9c365e1ffa7c595a630aaa6c85e6e75f490d6ee9b5efbba225eff075a9d307e5da807e8efd83005db064df92fcc0addc61142b0a27aa18a0ebe43b6aacad863aa33dc94e5c4979edca3ca4505817e7f21bde63a1c22b0bfdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
("res", "af587ca8f5f0760b888e4ec66748623d1b13986547b5de2042ce89233c2c837bbb080329a505285c948d8bb4c88a5914ae216a64db582ba084178db4364a7b3843ef7fb9056a90526d27dc9e252b38600fc54ce7a5ec15771c555816edc26d0166e75d3315789c846387c8c234b1c98b50baf233b7312aa317ae56a2bfa170b1bc43f0e046b4a1f45cb7aacea7d0ae0320496e3960d4dbc2039027ba8cfe1ca120ea98fa94cf25034ccb5e74033f447b837a78b03affd44b87f865f3d713000de78ab5629dbde8d0c8b7a28941717be3ebd23924cf16897144bb69730f68bff5a109fc2e6d563b15e2eb883cf4becd11edcbc2ec4402c93249389ed612fa0396ed6eadcbe4d703667d46b0150ee3a5158caef956791e4f527e1312c8402f8509acf7001dc0dc311549d76398c247e79b737b614d0a6663f7dbdb314e5b51eace14457ee7b1f3f54d5987c16c8f89d1022d91d4649f5f6a204047077e5791a654cd2277506cd0af77f9ea789278b364c115ec07ba14390a9c22d59aa9c97a9c09ce025b5e14443f3c4e4cd602ef34105fadd82837fc5ce60a461e6ea11b13ae67b82e3366a2b2d1bbe78b2579173b3c0c5aed88b2949403060c3e065782bcb742c55c559e75e373293d80dec54120773d80144b21b353ead58dc8427e5b9cbd0c1431f1a74caf5f57c4b55b89810029cdd24ef4a029797ced68ff882492a8f55f31fe52217356366983e35d2a5640e818cc8bddf9274de0100e624a6bf03e2b9ff22f8dda09a46b50b1b305cb6adfa2ae775febbce4a2b507cd2390db968ceb13"));
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( g1_map_test, bls_primitives_tester ) try {
push_action("eosio"_n, "testg1map"_n, "test"_n, mvo()
("e", "c93f817b159bdf8404dc378514f845192bbae4faac7f4a568924f2d9725125000489408fd796461c288900add00d4618")
("res", "d8e09005badb694b1e5dba8476ba3012cd2bf0c472ee1811ac9b34c869638b47e669bce16933e98ce9b129f83d93d71890d6fd13b77d4ad8df1a5f1c6b81df2b3f305721b7b7874cd81eba23ca05e8bc974b14f7e4c2c77cbdf321c340ba4903a2a46af290abe078e426f913e492b8d9b997232dbe6198aea719a31e73b40e110c4efa9e42d737a42883e0ca5f344d02"));
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( g2_map_test, bls_primitives_tester ) try {
push_action("eosio"_n, "testg2map"_n, "test"_n, mvo()
("e", "d4f2cfec99387809574fcc2dba105603d950d490e2bebe0c212c05e16b784745ef4fe8e70b554d0a52fe0bed5ea6690ade2348eb8972a96740a430df162d920e175f5923a76d18650ea24a8ec06d414c6d1d218d673dac3619a1a5c142785708")
("res", "9968ae9e9bf3d22ec6c9670efa64ea23d4966b41bb25f76ea2ef71b96fa35e031adb866b3df234065b9aa72d0b12ab14978678279eb944f05b5af53d91e700b57aa87076727def2e9f2fba3cf6784a25591ae1669c2cf15cdcf038b826d1e81178bd7b59b7e911e0c2d11d6805756222201e3364f8010fb651939eca63f7e77709042ee1030cd938f53905a714e815112a7dfeed207757d30382f69617014bc683a175d0dfbd74f2684de26c771f3f55a538e6d2f969eb282bddfec4fc08dd18f37df0889292f288dff631b02f07b88134410fd86526d234d75b9a329bc9a8b6e71c7ad516b87af9717d962cba5d2b19fd1b77746f1e484a54e6aec81ede148f01e2c8283c598a4976182d2ce287fe6888e23996ce03b03ce6709e4aa8e66416"));
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( sig_verify_test, bls_primitives_tester ) try {
push_action("eosio"_n, "verify"_n, "test"_n, mvo()
("pk", "90ace8f520a5e056eab099d4e6a6f761a8f51301e1e15910908453007d94e33f8e86b834808dcb5323313153be066d01d49660f594a805ad9a4249d0af4190407e3e221e1d6fdad866e022308357776ed5e396777c7f7dfd020e7d736511ac06fdff02000000097602000cc40b00f4ebba58c7535798485f455752705358ce776dec56a2971a075c93e480fac35ef615")
("sig", "3c38a59a6c016fb598d8da531e205e4d8e0953868675760f8333c7fee725d81ddf246db75792eb7cf0ab8aeba051800babf407ddd8ec721db83fe1b1098b9334bf45ad63f10cf5a6b56b60f74b391615d7373088d182711358a6032f8c31fe1694ff3f3254a7e02e3e2811ce0becdec6031b193b5541d577b49cdb6cf09f919917b09776b1f05c977ffa17c2de876205f402f7e4fb00896cb9b3df1a25f761239e5625ddaab4bfacce8e6c505c13eb73632b12cedd30b0804fe29f317015c307ec2dfe48cb5060d84fd2c2756f41ae79f4c0a3a37ba62b22877b23042bb30a063d4ad3255de844545e89f0886041b513410df52d380fac23c31277997381115651c02014a9aeeaaec85c34b81a93ee73cd712ce241f394dc860ea5e792b0f50e"));
} FC_LOG_AND_RETHROW()
BOOST_AUTO_TEST_SUITE_END()
+3
View File
@@ -23,6 +23,9 @@ namespace eosio::testing {
static std::vector<uint8_t> crypto_primitives_test_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/crypto_primitives_tests.wasm"); }
static std::vector<char> crypto_primitives_test_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/crypto_primitives_tests.abi"); }
static std::vector<uint8_t> bls_primitives_test_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/bls_primitives_tests.wasm"); }
static std::vector<char> bls_primitives_test_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/bls_primitives_tests.abi"); }
static std::vector<uint8_t> get_code_hash_write_test_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/get_code_hash_write.wasm"); }
static std::vector<char> get_code_hash_write_test_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/get_code_hash_write.abi"); }
static std::vector<uint8_t> get_code_hash_read_test_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/get_code_hash_read.wasm"); }
+1
View File
@@ -7,6 +7,7 @@ add_contract(explicit_nested_tests explicit_nested_tests explicit_nested_tests.c
add_contract(transfer_contract transfer_contract transfer.cpp)
add_contract(minimal_tests minimal_tests minimal_tests.cpp)
add_contract(crypto_primitives_tests crypto_primitives_tests crypto_primitives_tests.cpp)
add_contract(bls_primitives_tests bls_primitives_tests bls_primitives_tests.cpp)
add_contract(get_code_hash_tests get_code_hash_write get_code_hash_write.cpp)
add_contract(get_code_hash_tests get_code_hash_read get_code_hash_read.cpp)
add_contract(name_pk_tests name_pk_tests name_pk_tests.cpp)
@@ -0,0 +1,361 @@
#include <eosio/eosio.hpp>
#include <eosio/crypto.hpp>
#include <eosio/crypto_ext.hpp>
#include <eosio/crypto_bls_ext.hpp>
#include <endian.h>
using namespace eosio;
namespace bls12_381 {
class sha256 {
public:
sha256(): m_blocklen(0), m_bitlen(0) {
m_state[0] = 0x6a09e667;
m_state[1] = 0xbb67ae85;
m_state[2] = 0x3c6ef372;
m_state[3] = 0xa54ff53a;
m_state[4] = 0x510e527f;
m_state[5] = 0x9b05688c;
m_state[6] = 0x1f83d9ab;
m_state[7] = 0x5be0cd19;
}
void update(const uint8_t * data, size_t length) {
for(size_t i = 0 ; i < length ; i++) {
m_data[m_blocklen++] = data[i];
if (m_blocklen == 64) {
transform();
// End of the block
m_bitlen += 512;
m_blocklen = 0;
}
}
}
inline void update(const char* data, size_t length) {
update(reinterpret_cast<const uint8_t*>(data), length);
}
inline void update(const std::string &data) {
update(reinterpret_cast<const char*>(data.data()), data.size());
}
std::array<uint8_t, 32> digest() {
std::array<uint8_t, 32> hash;
pad();
revert(hash);
return hash;
}
void digest(uint8_t* dst) {
std::array<uint8_t, 32>* phash = reinterpret_cast<std::array<uint8_t, 32>*>(dst);
pad();
revert(*phash);
}
//static string toString(const array<uint8_t, 32>& digest);
private:
uint8_t m_data[64];
uint32_t m_blocklen;
uint64_t m_bitlen;
uint32_t m_state[8]; //A, B, C, D, E, F, G, H
static constexpr std::array<uint32_t, 64> K = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,
0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,
0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,
0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,
0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,
0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,
0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,
0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,
0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
static uint32_t rotr(uint32_t x, uint32_t n) {
return (x >> n) | (x << (32 - n));
}
static uint32_t choose(uint32_t e, uint32_t f, uint32_t g) {
return (e & f) ^ (~e & g);
}
static uint32_t majority(uint32_t a, uint32_t b, uint32_t c) {
return (a & (b | c)) | (b & c);
}
static uint32_t sig0(uint32_t x) {
return sha256::rotr(x, 7) ^ sha256::rotr(x, 18) ^ (x >> 3);
}
static uint32_t sig1(uint32_t x) {
return sha256::rotr(x, 17) ^ sha256::rotr(x, 19) ^ (x >> 10);
}
void transform() {
uint32_t maj, xorA, ch, xorE, sum, newA, newE, m[64];
uint32_t state[8];
for(uint8_t i = 0, j = 0; i < 16; i++, j += 4) {
// Split data in 32 bit blocks for the 16 first words
m[i] = (m_data[j] << 24) | (m_data[j + 1] << 16) | (m_data[j + 2] << 8) | (m_data[j + 3]);
}
for(uint8_t k = 16 ; k < 64; k++) {
// Remaining 48 blocks
m[k] = sha256::sig1(m[k - 2]) + m[k - 7] + sha256::sig0(m[k - 15]) + m[k - 16];
}
for(uint8_t i = 0 ; i < 8 ; i++) {
state[i] = m_state[i];
}
for(uint8_t i = 0; i < 64; i++) {
maj = sha256::majority(state[0], state[1], state[2]);
xorA = sha256::rotr(state[0], 2) ^ sha256::rotr(state[0], 13) ^ sha256::rotr(state[0], 22);
ch = choose(state[4], state[5], state[6]);
xorE = sha256::rotr(state[4], 6) ^ sha256::rotr(state[4], 11) ^ sha256::rotr(state[4], 25);
sum = m[i] + K[i] + state[7] + ch + xorE;
newA = xorA + maj + sum;
newE = state[3] + sum;
state[7] = state[6];
state[6] = state[5];
state[5] = state[4];
state[4] = newE;
state[3] = state[2];
state[2] = state[1];
state[1] = state[0];
state[0] = newA;
}
for(uint8_t i = 0 ; i < 8 ; i++) {
m_state[i] += state[i];
}
}
void pad() {
uint64_t i = m_blocklen;
uint8_t end = m_blocklen < 56 ? 56 : 64;
m_data[i++] = 0x80; // Append a bit 1
while(i < end) {
m_data[i++] = 0x00; // Pad with zeros
}
if(m_blocklen >= 56) {
transform();
memset(m_data, 0, 56);
}
// Append to the padding the total message's length in bits and transform.
m_bitlen += m_blocklen * 8;
m_data[63] = m_bitlen;
m_data[62] = m_bitlen >> 8;
m_data[61] = m_bitlen >> 16;
m_data[60] = m_bitlen >> 24;
m_data[59] = m_bitlen >> 32;
m_data[58] = m_bitlen >> 40;
m_data[57] = m_bitlen >> 48;
m_data[56] = m_bitlen >> 56;
transform();
}
void revert(std::array<uint8_t, 32>& hash) {
// SHA uses big endian byte ordering
// Revert all bytes
for(uint8_t i = 0 ; i < 4 ; i++) {
for(uint8_t j = 0 ; j < 8 ; j++) {
hash[i + (j * 4)] = (m_state[j] >> (24 - i * 8)) & 0x000000ff;
}
}
}
};
} // namespace bls12_381
class [[eosio::contract]] bls_primitives_tests : public contract{
public:
using contract::contract;
[[eosio::action]]
void testg1add(const std::vector<char>& op1, const std::vector<char>& op2, const std::vector<char>& res) {
check(op1.size() == std::tuple_size<bls_g1>::value, "wrong op1 size passed");
check(op2.size() == std::tuple_size<bls_g1>::value, "wrong op2 size passed");
bls_g1 r;
bls_g1_add(*reinterpret_cast<const bls_g1*>(op1.data()), *reinterpret_cast<const bls_g1*>(op2.data()), r);
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g1_add test failed");
}
[[eosio::action]]
void testg2add(const std::vector<char>& op1, const std::vector<char>& op2, const std::vector<char>& res) {
bls_g2 r;
bls_g2_add(*reinterpret_cast<const bls_g2*>(op1.data()), *reinterpret_cast<const bls_g2*>(op2.data()), r);
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g2_add test failed");
}
[[eosio::action]]
void testg1mul(const std::vector<char>& point, const std::vector<char>& scalar, const std::vector<char>& res) {
bls_g1 r;
bls_g1_mul(*reinterpret_cast<const bls_g1*>(point.data()), *reinterpret_cast<const bls_scalar*>(scalar.data()), r);
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g1_mul test failed");
}
[[eosio::action]]
void testg2mul(const std::vector<char>& point, const std::vector<char>& scalar, const std::vector<char>& res) {
bls_g2 r;
bls_g2_mul(*reinterpret_cast<const bls_g2*>(point.data()), *reinterpret_cast<const bls_scalar*>(scalar.data()), r);
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g2_mul test failed");
}
[[eosio::action]]
void testg1exp(const std::vector<char>& points, const std::vector<char>& scalars, const std::vector<char>& res) {
auto num = scalars.size()/sizeof(bls_scalar);
check(points.size()/sizeof(bls_g1) == num, "number of elements in points and scalars must be equal");
bls_g1 r;
bls_g1_exp(reinterpret_cast<const bls_g1*>(points.data()), reinterpret_cast<const bls_scalar*>(scalars.data()), num, r);
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g1_exp test failed");
}
[[eosio::action]]
void testg2exp(const std::vector<char>& points, const std::vector<char>& scalars, const std::vector<char>& res) {
auto num = scalars.size()/sizeof(bls_scalar);
check(points.size()/sizeof(bls_g2) == num, "number of elements in points and scalars must be equal");
bls_g2 r;
bls_g2_exp(reinterpret_cast<const bls_g2*>(points.data()), reinterpret_cast<const bls_scalar*>(scalars.data()), num, r);
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g2_exp test failed");
}
[[eosio::action]]
void testpairing(const std::vector<char>& g1_points, const std::vector<char>& g2_points, const std::vector<char>& res) {
auto num = g2_points.size()/sizeof(bls_g2);
check(g1_points.size()/sizeof(bls_g1) == num, "number of elements in g1_points and g2_points must be equal");
bls_gt r;
bls_pairing(reinterpret_cast<const bls_g1*>(g1_points.data()), reinterpret_cast<const bls_g2*>(g2_points.data()), num, r);
check(std::equal(res.begin(), res.end(), r.begin()), "bls_pairing test failed");
}
[[eosio::action]]
void testg1map(const std::vector<char>& e, const std::vector<char>& res) {
bls_g1 r;
bls_g1_map(*reinterpret_cast<const bls_fp*>(e.data()), r);
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g1_map test failed");
}
[[eosio::action]]
void testg2map(const std::vector<char>& e, const std::vector<char>& res) {
bls_g2 r;
bls_g2_map(*reinterpret_cast<const bls_fp2*>(e.data()), r);
check(std::equal(res.begin(), res.end(), r.begin()), "bls_g2_map test failed");
}
// Construct an extensible-output function based on SHA256
void xmd_sh256(
char *buf,
int buf_len,
const uint8_t *in,
int in_len,
const char *dst,
int dst_len
) {
const unsigned int SHA256HashSize = 32;
const unsigned int SHA256_Message_Block_Size = 64;
const unsigned ell = (buf_len + SHA256HashSize - 1) / SHA256HashSize;
if (buf_len < 0 || ell > 255 || dst_len > 255) {
return;
}
const uint8_t Z_pad[SHA256_Message_Block_Size] = { 0, };
const uint8_t l_i_b_0_str[] = {
static_cast<uint8_t>(buf_len >> 8),
static_cast<uint8_t>(buf_len & 0xff),
0,
static_cast<uint8_t>(dst_len)
};
const uint8_t *dstlen_str = l_i_b_0_str + 3;
uint8_t b_0[SHA256HashSize];
bls12_381::sha256 sha;
sha.update(Z_pad, SHA256_Message_Block_Size);
sha.update(in, in_len);
sha.update(l_i_b_0_str, 3);
sha.update(dst, dst_len);
sha.update(dstlen_str, 1);
sha.digest(b_0);
uint8_t b_i[SHA256HashSize + 1] = { 0, };
for (unsigned i = 1; i <= ell; ++i) {
for (unsigned j = 0; j < SHA256HashSize; ++j) {
b_i[j] = b_0[j] ^ b_i[j];
}
b_i[SHA256HashSize] = i;
bls12_381::sha256 s;
s.update(b_i, SHA256HashSize + 1);
s.update(dst, dst_len);
s.update(dstlen_str, 1);
s.digest(b_i);
const int rem_after = buf_len - i * SHA256HashSize;
const int copy_len = SHA256HashSize + (rem_after < 0 ? rem_after : 0);
memcpy(buf + (i - 1) * SHA256HashSize, b_i, copy_len);
}
}
bls_s scalar_fromBE(const bls_s& in) {
std::array<uint64_t, 8> out;
for(uint64_t i = 0; i < 8; i++) {
uint64_t temp;
memcpy(&temp, &in[in.size() - i*8 - 8], sizeof(uint64_t));
out[i] = htobe64(temp);
}
return reinterpret_cast<bls_s&&>(std::move(out));
}
void g2_fromMessage(const std::vector<uint8_t>& msg, const std::string& dst, bls_g2& res) {
std::array<bls_s, 4> buf;
xmd_sh256(buf.data()->data(), sizeof(buf), msg.data(), msg.size(), dst.data(), dst.length());
bls_s k;
bls_fp2 t;
bls_g2 p, q;
k = scalar_fromBE(buf[0]);
bls_fp_mod(k, t[0]);
k = scalar_fromBE(buf[1]);
bls_fp_mod(k, t[1]);
bls_g2_map(t, p);
k = scalar_fromBE(buf[2]);
bls_fp_mod(k, t[0]);
k = scalar_fromBE(buf[3]);
bls_fp_mod(k, t[1]);
bls_g2_map(t, q);
bls_g2_add(p, q, res);
}
const std::string CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_";
const std::vector<uint8_t> G1_ONE_NEG = {0x16, 0x0c, 0x53, 0xfd, 0x90, 0x87, 0xb3, 0x5c, 0xf5, 0xff, 0x76, 0x99, 0x67, 0xfc, 0x17, 0x78, 0xc1, 0xa1, 0x3b, 0x14, 0xc7, 0x95, 0x4f, 0x15, 0x47, 0xe7, 0xd0, 0xf3, 0xcd, 0x6a, 0xae, 0xf0, 0x40, 0xf4, 0xdb, 0x21, 0xcc, 0x6e, 0xce, 0xed, 0x75, 0xfb, 0x0b, 0x9e, 0x41, 0x77, 0x01, 0x12, 0x3a, 0x88, 0x18, 0xf3, 0x2a, 0x6c, 0x52, 0xff, 0x70, 0x02, 0x3b, 0x38, 0xe4, 0x9c, 0x89, 0x92, 0x55, 0xd0, 0xa9, 0x9f, 0x8d, 0x73, 0xd7, 0x89, 0x2a, 0xc1, 0x44, 0xa3, 0x5b, 0xf3, 0xca, 0x12, 0x17, 0x53, 0x4b, 0x96, 0x76, 0x1b, 0xff, 0x3c, 0x30, 0x44, 0x77, 0xe9, 0xed, 0xd2, 0x44, 0x0e, 0xfd, 0xff, 0x02, 0x00, 0x00, 0x00, 0x09, 0x76, 0x02, 0x00, 0x0c, 0xc4, 0x0b, 0x00, 0xf4, 0xeb, 0xba, 0x58, 0xc7, 0x53, 0x57, 0x98, 0x48, 0x5f, 0x45, 0x57, 0x52, 0x70, 0x53, 0x58, 0xce, 0x77, 0x6d, 0xec, 0x56, 0xa2, 0x97, 0x1a, 0x07, 0x5c, 0x93, 0xe4, 0x80, 0xfa, 0xc3, 0x5e, 0xf6, 0x15};
const std::vector<uint8_t> GT_ONE = {0xfd, 0xff, 0x02, 0x00, 0x00, 0x00, 0x09, 0x76, 0x02, 0x00, 0x0c, 0xc4, 0x0b, 0x00, 0xf4, 0xeb, 0xba, 0x58, 0xc7, 0x53, 0x57, 0x98, 0x48, 0x5f, 0x45, 0x57, 0x52, 0x70, 0x53, 0x58, 0xce, 0x77, 0x6d, 0xec, 0x56, 0xa2, 0x97, 0x1a, 0x07, 0x5c, 0x93, 0xe4, 0x80, 0xfa, 0xc3, 0x5e, 0xf6, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
std::vector<uint8_t> msg = {51, 23, 56, 93, 212, 129, 128, 27, 251, 12, 42, 129, 210, 9, 34, 98};
[[eosio::action]]
void verify(const std::vector<char>& pk, const std::vector<char>& sig) {
bls_g1 g1_points[2];
bls_g2 g2_points[2];
memcpy(g1_points[0].data(), G1_ONE_NEG.data(), sizeof(bls_g1));
memcpy(g2_points[0].data(), sig.data(), sizeof(bls_g2));
bls_g2 p_msg;
g2_fromMessage(msg, CIPHERSUITE_ID, p_msg);
memcpy(g1_points[1].data(), pk.data(), sizeof(bls_g1));
memcpy(g2_points[1].data(), p_msg.data(), sizeof(bls_g2));
bls_gt r;
bls_pairing(g1_points, g2_points, 2, r);
check(0 == memcmp(r.data(), GT_ONE.data(), sizeof(bls_gt)), "bls signature verify failed");
}
};
@@ -204,6 +204,60 @@ namespace _test_multi_index
auto itr2 = table.find(ssn);
eosio::check(itr2 == table.end(), "idx64_general - table.erase()");
}
// insert, update and remove by iterator
{
const uint64_t ssn = 421;
auto new_person = table.insert(payer, [&](auto &r)
{
r.id = ssn;
r.sec = "bob"_n.value; });
table.update(new_person, payer, [&](auto &r)
{ r.sec = "billy"_n.value; });
auto itr1 = table.find(ssn);
eosio::check(itr1 != table.end() && itr1->sec == "billy"_n.value, "idx64_general - table.update()");
table.remove(itr1);
auto itr2 = table.find(ssn);
eosio::check(itr2 == table.end(), "idx64_general - table.remove()");
}
// insert, update and remove by object
{
const uint64_t ssn = 421;
auto new_person = table.insert(payer, [&](auto &r)
{
r.id = ssn;
r.sec = "bob"_n.value; });
table.update(new_person, payer, [&](auto &r)
{ r.sec = "billy"_n.value; });
const auto& person_object = table.get(ssn);
auto& mutable_person = const_cast<record&>(person_object);
table.remove(mutable_person);
auto itr2 = table.find(ssn);
eosio::check(itr2 == table.end(), "idx64_general - table.remove()");
}
// insert, update and remove by const object
{
const uint64_t ssn = 421;
auto new_person = table.insert(payer, [&](auto &r)
{
r.id = ssn;
r.sec = "bob"_n.value; });
table.update(new_person, payer, [&](auto &r)
{ r.sec = "billy"_n.value; });
const auto& person_object = table.get(ssn);
table.remove(person_object);
auto itr2 = table.find(ssn);
eosio::check(itr2 == table.end(), "idx64_general - table.remove()");
}
}
template <uint64_t TableName>
+1 -1
View File
@@ -1 +1 @@
add_subdirectory(wabt)
add_subdirectory(wabt)