Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IF: Add setfinalizer action to eosio.bios #33

Merged
merged 16 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .cicd/defaults.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"leap-dev":{
"target":"3",
"target":"hotstuff_integration",
"prerelease":false
},
"cdt":{
"target":"3",
"target":"hotstuff_integration",
"prerelease":false
}
}
7 changes: 3 additions & 4 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,16 @@ jobs:
echo cdt-prerelease=${{inputs.override-cdt-prerelease}} >> $GITHUB_OUTPUT
fi
- name: Download cdt
uses: AntelopeIO/asset-artifact-download-action@v2
uses: AntelopeIO/asset-artifact-download-action@v3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should also change the download below to v3,

- name: Download leap-dev
uses: AntelopeIO/asset-artifact-download-action@v2

Also, v3 does not require the token in our usage, so you can remove lines

token: ${{github.token}}

token: ${{github.token}}

with:
owner: AntelopeIO
repo: cdt
file: 'cdt_.*amd64.deb'
target: '${{steps.versions.outputs.cdt-target}}'
prereleases: ${{fromJSON(steps.versions.outputs.cdt-prerelease)}}
artifact-name: cdt_ubuntu_package_amd64
token: ${{github.token}}
- name: Download leap-dev
uses: AntelopeIO/asset-artifact-download-action@v2
uses: AntelopeIO/asset-artifact-download-action@v3
with:
owner: AntelopeIO
repo: leap
Expand All @@ -81,9 +80,9 @@ jobs:
prereleases: ${{fromJSON(steps.versions.outputs.leap-dev-prerelease)}}
artifact-name: leap-dev-ubuntu20-amd64
container-package: experimental-binaries
token: ${{github.token}}
- name: Install packages
run: |
sudo apt-get update && sudo apt-get upgrade -y
sudo apt install ./*.deb
sudo apt-get install cmake
rm ./*.deb
Expand Down
42 changes: 42 additions & 0 deletions contracts/eosio.bios/include/eosio.bios/eosio.bios.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <eosio/eosio.hpp>
#include <eosio/fixed_bytes.hpp>
#include <eosio/privileged.hpp>
#include <eosio/instant_finality.hpp>
#include <eosio/producer_schedule.hpp>

namespace eosiobios {
Expand Down Expand Up @@ -66,6 +67,38 @@ namespace eosiobios {
(schedule_version)(new_producers))
};

/**
* finalizer_authority
*
* The public bls key and proof of possession of private key signature,
* and vote weight of a finalizer.
*/
constexpr size_t max_finalizers = 64*1024;
constexpr size_t max_finalizer_description_size = 256;

struct finalizer_authority {
std::string description;
uint64_t weight = 0; // weight that this finalizer's vote has for meeting threshold
std::string public_key; // public key of the finalizer in base64 format
std::string pop; // proof of possession of private key in base64 format

// explicit serialization macro is not necessary, used here only to improve compilation time
EOSLIB_SERIALIZE(finalizer_authority, (description)(weight)(public_key)(pop))
};

/**
* finalizer_policy
*
* List of finalizer authorties along with the threshold
*/
struct finalizer_policy {
uint64_t threshold = 0; // quorum threshold
std::vector<finalizer_authority> finalizers;

// explicit serialization macro is not necessary, used here only to improve compilation time
EOSLIB_SERIALIZE(finalizer_policy, (threshold)(finalizers));
};

/**
* The `eosio.bios` is the first sample of system contract provided by `block.one` through the EOSIO platform. It is a minimalist system contract because it only supplies the actions that are absolutely critical to bootstrap a chain and nothing more. This allows for a chain agnostic approach to bootstrapping a chain.
*
Expand Down Expand Up @@ -190,6 +223,15 @@ namespace eosiobios {
[[eosio::action]]
void onerror( ignore<uint128_t> sender_id, ignore<std::vector<char>> sent_trx );

/**
* Propose new finalizer policy that, unless superseded by a later
* finalizer policy, will eventually become the active finalizer policy.
*
* @param finalizer_policy - proposed finalizer policy
*/
[[eosio::action]]
void setfinalizer( const finalizer_policy& finalizer_policy );

/**
* Set privilege action allows to set privilege status for an account (turn it on/off).
* @param account - the account to set the privileged status for.
Expand Down
52 changes: 52 additions & 0 deletions contracts/eosio.bios/src/eosio.bios.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include <eosio.bios/eosio.bios.hpp>
#include <eosio/crypto_bls_ext.hpp>

#include <unordered_set>

namespace eosiobios {

Expand All @@ -17,6 +20,55 @@ void bios::setabi( name account, const std::vector<char>& abi ) {
}
}

void bios::setfinalizer( const finalizer_policy& finalizer_policy ) {
// exensive checks are performed to make sure setfinalizer host function
// will never fail

require_auth( get_self() );

check(finalizer_policy.finalizers.size() <= max_finalizers, "number of finalizers exceeds the maximum allowed");
check(finalizer_policy.finalizers.size() > 0, "require at least one finalizer");

eosio::abi_finalizer_policy abi_finalizer_policy;
abi_finalizer_policy.fthreshold = finalizer_policy.threshold;
abi_finalizer_policy.finalizers.reserve(finalizer_policy.finalizers.size());

const std::string pk_prefix = "PUB_BLS";
const std::string sig_prefix = "SIG_BLS";

std::unordered_set<std::string> unique_finalizer_keys;
uint64_t weight_sum = 0;

for (const auto& f: finalizer_policy.finalizers) {
check(f.description.size() <= max_finalizer_description_size, "Finalizer description greater than max allowed size");

// basic key format checks
check(f.public_key.substr(0, pk_prefix.length()) == pk_prefix, "public key not started with PUB_BLS");
check(f.pop.substr(0, sig_prefix.length()) == sig_prefix, "proof of possession signature not started with SIG_BLS");

// duplicate key check
check(unique_finalizer_keys.insert(f.public_key).second, "duplicate public keys");

// check overflow
check(std::numeric_limits<uint64_t>::max() - weight_sum >= f.weight, "sum of weights causes uint64_t overflow");
weight_sum += f.weight;

// decode_bls_public_key_to_g1 and decode_bls_signature_to_g2
// will throw ("check" function fails) if keys are not valid
const auto pk = eosio::decode_bls_public_key_to_g1(f.public_key);
const auto signature = eosio::decode_bls_signature_to_g2(f.pop);
// proof of possession of private key check
check(eosio::bls_pop_verify(pk, signature), "proof of possession failed");

std::vector<char> pk_vector(pk.begin(), pk.end());
abi_finalizer_policy.finalizers.emplace_back(eosio::abi_finalizer_authority{f.description, f.weight, std::move(pk_vector)});
arhag marked this conversation as resolved.
Show resolved Hide resolved
}

check(finalizer_policy.threshold > weight_sum / 2, "finalizer policy threshold cannot be met by finalizer weights");

set_finalizers(std::move(abi_finalizer_policy));
}

void bios::onerror( ignore<uint128_t>, ignore<std::vector<char>> ) {
check( false, "the onerror action cannot be called directly" );
}
Expand Down
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.5)

set(EOSIO_VERSION_MIN "3.1")
set(EOSIO_VERSION_SOFT_MAX "4.1")
set(EOSIO_VERSION_SOFT_MAX "5.0")
# set(EOSIO_VERSION_HARD_MAX "")

find_package(leap)
Expand Down
Loading