Skip to content

Commit

Permalink
Merge pull request #1588 from AntelopeIO/GH-1523-finalizer-set-transi…
Browse files Browse the repository at this point in the history
…tion

IF: Modify set_finalizer host function struct type
  • Loading branch information
heifner authored Sep 1, 2023
2 parents b5c2ef5 + 060b5ba commit 8fad42e
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 57 deletions.
1 change: 1 addition & 0 deletions libraries/chain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ add_library( eosio_chain
${CHAIN_WEBASSEMBLY_SOURCES}

authority.cpp
finalizer_set.cpp
trace.cpp
transaction_metadata.cpp
protocol_state_object.cpp
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1980,6 +1980,7 @@ struct controller_impl {
void set_finalizers_impl(const finalizer_set& fin_set) {
// TODO store in chainbase
current_finalizer_set = fin_set;
++current_finalizer_set.generation;
}

/**
Expand Down
23 changes: 23 additions & 0 deletions libraries/chain/finalizer_set.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <eosio/chain/finalizer_set.hpp>
#include <eosio/chain/finalizer_authority.hpp>
#include <fc/crypto/bls_public_key.hpp>

namespace eosio::chain {

/**
* These definitions are all here to avoid including bls_public_key.hpp which includes <bls12-381/bls12-381.hpp>
* and pulls in bls12-381 types. This keeps bls12-381 out of libtester.
*/

finalizer_set::finalizer_set() = default;
finalizer_set::~finalizer_set() = default;

finalizer_set::finalizer_set(const finalizer_set&) = default;
finalizer_set::finalizer_set(finalizer_set&&) noexcept = default;

finalizer_set& finalizer_set::operator=(const finalizer_set&) = default;
finalizer_set& finalizer_set::operator=(finalizer_set&&) noexcept = default;

auto finalizer_set::operator<=>(const finalizer_set&) const = default;

} /// eosio::chain
3 changes: 2 additions & 1 deletion libraries/chain/include/eosio/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ static_assert(maximum_tracked_dpos_confirmations >= ((max_producers * 2 / 3) + 1
/**
* Maximum number of finalizers in the finalizer set
*/
const static int max_finalizers = max_producers;
const static size_t max_finalizers = 64*1024;
const static size_t max_finalizer_description_size = 256;

/**
* The number of blocks produced per round is based upon all producers having a chance
Expand Down
19 changes: 19 additions & 0 deletions libraries/chain/include/eosio/chain/finalizer_authority.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <fc/crypto/bls_public_key.hpp>
#include <string>

namespace eosio::chain {

struct finalizer_authority {

std::string description;
uint64_t fweight = 0; // weight that this finalizer's vote has for meeting fthreshold
fc::crypto::blslib::bls_public_key public_key;

auto operator<=>(const finalizer_authority&) const = default;
};

} /// eosio::chain

FC_REFLECT( eosio::chain::finalizer_authority, (description)(fweight)(public_key) )
70 changes: 25 additions & 45 deletions libraries/chain/include/eosio/chain/finalizer_set.hpp
Original file line number Diff line number Diff line change
@@ -1,59 +1,39 @@
#pragma once

#include <eosio/chain/config.hpp>
#include <eosio/chain/types.hpp>
#include <chainbase/chainbase.hpp>
#include <eosio/chain/authority.hpp>
#include <eosio/chain/snapshot.hpp>

#include <fc/crypto/bls_public_key.hpp>

namespace eosio::chain {

struct finalizer_authority {
struct finalizer_authority;

struct finalizer_set {
finalizer_set();
~finalizer_set();

finalizer_set(const finalizer_set&);
finalizer_set(finalizer_set&&) noexcept;

std::string description;
uint64_t fweight = 0; // weight that this finalizer's vote has for meeting fthreshold
fc::crypto::blslib::bls_public_key public_key;
finalizer_set& operator=(const finalizer_set&);
finalizer_set& operator=(finalizer_set&&) noexcept;

friend bool operator == ( const finalizer_authority& lhs, const finalizer_authority& rhs ) {
return tie( lhs.description, lhs.fweight, lhs.public_key ) == tie( rhs.description, rhs.fweight, rhs.public_key );
}
friend bool operator != ( const finalizer_authority& lhs, const finalizer_authority& rhs ) {
return !(lhs == rhs);
}
auto operator<=>(const finalizer_set&) const;

uint32_t generation = 0; ///< sequentially incrementing version number
uint64_t fthreshold = 0; ///< vote fweight threshold to finalize blocks
std::vector<finalizer_authority> finalizers; ///< Instant Finality voter set
};

struct finalizer_set {
finalizer_set() = default;

finalizer_set( uint32_t version, uint64_t fthreshold, std::initializer_list<finalizer_authority> finalizers )
:version(version)
,fthreshold(fthreshold)
,finalizers(finalizers)
{}

uint32_t version = 0; ///< sequentially incrementing version number
uint64_t fthreshold = 0; // vote fweight threshold to finalize blocks
vector<finalizer_authority> finalizers; // Instant Finality voter set

friend bool operator == ( const finalizer_set& a, const finalizer_set& b )
{
if( a.version != b.version ) return false;
if( a.fthreshold != b.fthreshold ) return false;
if ( a.finalizers.size() != b.finalizers.size() ) return false;
for( uint32_t i = 0; i < a.finalizers.size(); ++i )
if( ! (a.finalizers[i] == b.finalizers[i]) ) return false;
return true;
}

friend bool operator != ( const finalizer_set& a, const finalizer_set& b )
{
return !(a==b);
}
using finalizer_set_ptr = std::shared_ptr<finalizer_set>;

/**
* Block Header Extension Compatibility
*/
struct hs_finalizer_set_extension : finalizer_set {
static constexpr uint16_t extension_id() { return 2; } // TODO 3 instead?
static constexpr bool enforce_unique() { return true; }
};

} /// eosio::chain

FC_REFLECT( eosio::chain::finalizer_authority, (description)(fweight)(public_key) )
FC_REFLECT( eosio::chain::finalizer_set, (version)(fthreshold)(finalizers) )
FC_REFLECT( eosio::chain::finalizer_set, (generation)(fthreshold)(finalizers) )
FC_REFLECT_DERIVED( eosio::chain::hs_finalizer_set_extension, (eosio::chain::finalizer_set), )
42 changes: 31 additions & 11 deletions libraries/chain/webassembly/privileged.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <eosio/chain/resource_limits.hpp>
#include <eosio/chain/apply_context.hpp>
#include <eosio/chain/finalizer_set.hpp>
#include <eosio/chain/finalizer_authority.hpp>

#include <fc/io/datastream.hpp>

Expand Down Expand Up @@ -151,29 +152,45 @@ namespace eosio { namespace chain { namespace webassembly {
}
}

// format for packed_finalizer_set
struct abi_finalizer_authority {
std::string description;
uint64_t fweight = 0; // weight that this finalizer's vote has for meeting fthreshold
std::array<uint8_t, 144> public_key_g1_jacobian;
};
struct abi_finalizer_set {
uint64_t fthreshold = 0;
std::vector<abi_finalizer_authority> finalizers;
};

void interface::set_finalizers(span<const char> packed_finalizer_set) {
EOS_ASSERT(!context.trx_context.is_read_only(), wasm_execution_error, "set_proposed_finalizers not allowed in a readonly transaction");
EOS_ASSERT(!context.trx_context.is_read_only(), wasm_execution_error, "set_finalizers not allowed in a readonly transaction");
fc::datastream<const char*> ds( packed_finalizer_set.data(), packed_finalizer_set.size() );
finalizer_set finset;
fc::raw::unpack(ds, finset);
vector<finalizer_authority> & finalizers = finset.finalizers;
abi_finalizer_set abi_finset;
fc::raw::unpack(ds, abi_finset);

std::vector<abi_finalizer_authority>& finalizers = abi_finset.finalizers;

// TODO: check version and increment it or verify correct
EOS_ASSERT( finalizers.size() <= config::max_finalizers, wasm_execution_error, "Finalizer set exceeds the maximum finalizer count for this chain" );
EOS_ASSERT( finalizers.size() > 0, wasm_execution_error, "Finalizer set cannot be empty" );

std::set<fc::crypto::blslib::bls_public_key> unique_finalizer_keys;
#warning REVIEW: Is checking for unique finalizer descriptions at all relevant?
std::set<std::string> unique_finalizers;
std::set<bls12_381::g1> unique_finalizer_keys;
uint64_t f_weight_sum = 0;

finalizer_set finset;
finset.fthreshold = abi_finset.fthreshold;
for (const auto& f: finalizers) {
EOS_ASSERT( f.description.size() <= config::max_finalizer_description_size, wasm_execution_error,
"Finalizer description greater than ${s}", ("s", config::max_finalizer_description_size) );
f_weight_sum += f.fweight;
unique_finalizer_keys.insert(f.public_key);
unique_finalizers.insert(f.description);
std::optional<bls12_381::g1> pk = bls12_381::g1::fromJacobianBytesLE(f.public_key_g1_jacobian);
EOS_ASSERT( pk, wasm_execution_error, "Invalid public key for: ${d}", ("d", f.description) );
finset.finalizers.push_back(finalizer_authority{.description = std::move(f.description),
.fweight = f.fweight,
.public_key{fc::crypto::blslib::bls_public_key{*pk}}});
unique_finalizer_keys.insert(*pk);
}

EOS_ASSERT( finalizers.size() == unique_finalizers.size(), wasm_execution_error, "Duplicate finalizer description in finalizer set" );
EOS_ASSERT( finalizers.size() == unique_finalizer_keys.size(), wasm_execution_error, "Duplicate finalizer bls key in finalizer set" );
EOS_ASSERT( finset.fthreshold > f_weight_sum / 2, wasm_execution_error, "Finalizer set threshold cannot be met by finalizer weights" );

Expand Down Expand Up @@ -254,3 +271,6 @@ namespace eosio { namespace chain { namespace webassembly {
});
}
}}} // ns eosio::chain::webassembly

FC_REFLECT(eosio::chain::webassembly::abi_finalizer_authority, (description)(fweight)(public_key_g1_jacobian));
FC_REFLECT(eosio::chain::webassembly::abi_finalizer_set, (fthreshold)(finalizers));

0 comments on commit 8fad42e

Please sign in to comment.