Skip to content

Commit

Permalink
beefy types (#1773)
Browse files Browse the repository at this point in the history
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Co-authored-by: kamilsa <kamilsa16@gmail.com>
  • Loading branch information
turuslan and kamilsa authored Aug 31, 2023
1 parent 4e3275d commit 2d79dc3
Show file tree
Hide file tree
Showing 14 changed files with 258 additions and 11 deletions.
53 changes: 53 additions & 0 deletions core/consensus/beefy/sig.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "consensus/beefy/types.hpp"
#include "crypto/ecdsa_provider.hpp"
#include "crypto/hasher/hasher_impl.hpp"

namespace kagome::consensus::beefy {
inline common::Hash256 prehash(const Commitment &commitment) {
// TODO(turuslan): #1768, scale encode to hash
return crypto::HasherImpl{}.keccak_256(scale::encode(commitment).value());
}

inline bool verify(const crypto::EcdsaProvider &ecdsa,
const VoteMessage &vote) {
auto r = ecdsa.verifyPrehashed(
prehash(vote.commitment), vote.signature, vote.id);
return r and r.value();
}

inline size_t threshold(size_t n) {
return n == 0 ? 0 : n - (n - 1) / 3;
}

inline bool verify(const crypto::EcdsaProvider &ecdsa,
const BeefyJustification &justification_v1,
const ValidatorSet &validators) {
auto &justification = boost::get<SignedCommitment>(justification_v1);
if (justification.commitment.validator_set_id != validators.id) {
return false;
}
auto total = validators.validators.size();
if (justification.signatures.size() != total) {
return false;
}
auto prehashed = prehash(justification.commitment);
size_t valid = 0;
for (size_t i = 0; i < total; ++i) {
if (auto &sig = justification.signatures[i]) {
if (auto r = ecdsa.verifyPrehashed(
prehashed, *sig, validators.validators[i]);
r and r.value()) {
++valid;
}
}
}
return valid >= threshold(total);
}
} // namespace kagome::consensus::beefy
114 changes: 114 additions & 0 deletions core/consensus/beefy/types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "common/unused.hpp"
#include "crypto/ecdsa_types.hpp"
#include "primitives/authority.hpp"

/**
* Test
* ConsensusDigest
* 0x0108020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a10390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f270700000000000000
* BeefyJustification
* 0x01046d68803af1ad0102f711a7c08e589a1006e4f20c8853b12b5214a57a08cbb4c72cf2ce47000000070000000000000004c002000000080e0fa849fcd9ecfed1b1312e7a17bb4db4ec02761ac760b01a9fc7365c2f55a059125b6217943b561aa27c8b1f990eee1cc9b72ff6f4d6ddde467e33dd02142500f016a7aa597346546f0e799016c8a5302c7a6dce286c513bd69c60e1e77b1e2f6bff5c269369b4ede6fd6e41b32186faff8773158708b16a35d2afcdc9aeeaa500
*/

namespace kagome::consensus::beefy {
using MmrRootHash = common::Hash256;

struct ValidatorSet {
SCALE_TIE(2);

std::vector<crypto::EcdsaPublicKey> validators;
primitives::AuthoritySetId id;
};

using ConsensusDigest =
boost::variant<Unused<0>,
ValidatorSet, // AuthoritiesChange
primitives::AuthorityIndex, // OnDisabled
MmrRootHash>;

using PayloadId = common::Blob<2>;

struct Commitment {
SCALE_TIE(3);

std::vector<std::pair<PayloadId, common::Buffer>> payload;
primitives::BlockNumber block_number;
primitives::AuthoritySetId validator_set_id;
};

struct VoteMessage {
SCALE_TIE(3);

Commitment commitment;
crypto::EcdsaPublicKey id;
crypto::EcdsaSignature signature;
};

struct SignedCommitment {
Commitment commitment;
std::vector<std::optional<crypto::EcdsaSignature>> signatures;
};
scale::ScaleEncoderStream &operator<<(scale::ScaleEncoderStream &s,
const SignedCommitment &v) {
s << v.commitment;
size_t count = 0;
common::Buffer bits;
// https://github.com/paritytech/substrate/blob/55bb6298e74d86be12732fd0f120185ee8fbfe97/primitives/consensus/beefy/src/commitment.rs#L149-L152
bits.resize(v.signatures.size() / 8 + 1);
auto i = 0;
for (auto &sig : v.signatures) {
if (sig) {
++count;
bits[i / 8] |= 1 << (7 - i % 8);
}
++i;
}
s << bits;
s << static_cast<uint32_t>(v.signatures.size());
s << scale::CompactInteger{count};
for (auto &sig : v.signatures) {
if (sig) {
s << *sig;
}
}
return s;
}
scale::ScaleDecoderStream &operator>>(scale::ScaleDecoderStream &s,
SignedCommitment &v) {
s >> v.commitment;
common::Buffer bits;
s >> bits;
size_t expected_count = 0;
for (auto byte : bits) {
for (; byte; byte >>= 1) {
expected_count += byte & 1;
}
}
uint32_t total = 0;
s >> total;
if (bits.size() * 8 < total) {
scale::raise(scale::DecodeError::NOT_ENOUGH_DATA);
}
scale::CompactInteger actual_count;
s >> actual_count;
if (actual_count != expected_count) {
scale::raise(scale::DecodeError::TOO_MANY_ITEMS);
}
v.signatures.resize(total);
for (size_t i = 0; i < total; ++i) {
if ((bits[i / 8] & (1 << (7 - i % 8))) != 0) {
s >> v.signatures[i].emplace();
}
}
return s;
}

using BeefyJustification = boost::variant<Unused<0>, SignedCommitment>;
} // namespace kagome::consensus::beefy
5 changes: 2 additions & 3 deletions core/runtime/binaryen/module/module_instance_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "runtime/binaryen/memory_impl.hpp"
#include "runtime/binaryen/module/module_impl.hpp"
#include "runtime/common/runtime_transaction_error.hpp"
#include "runtime/memory_provider.hpp"

#include <binaryen/wasm-interpreter.h>
Expand Down Expand Up @@ -68,8 +69,6 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::runtime::binaryen,
return "An error occurred during an export call execution";
case ModuleInstanceImpl::Error::CAN_NOT_OBTAIN_GLOBAL:
return "Failed to obtain a global value";
case ModuleInstanceImpl::Error::NO_EXPORT_FUNCTION:
return "No export function";
}
return "Unknown ModuleInstance error";
}
Expand Down Expand Up @@ -110,7 +109,7 @@ namespace kagome::runtime::binaryen {
module_instance_->wasm.getExportOrNull(wasm::Name{name.data()});
nullptr == res) {
SL_DEBUG(logger_, "The requested function {} not found", name);
return Error::NO_EXPORT_FUNCTION;
return RuntimeTransactionError::EXPORT_FUNCTION_NOT_FOUND;
}

try {
Expand Down
1 change: 0 additions & 1 deletion core/runtime/binaryen/module/module_instance_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ namespace kagome::runtime::binaryen {
UNEXPECTED_EXIT = 1,
EXECUTION_ERROR,
CAN_NOT_OBTAIN_GLOBAL,
NO_EXPORT_FUNCTION
};

ModuleInstanceImpl(InstanceEnvironment &&env,
Expand Down
2 changes: 2 additions & 0 deletions core/runtime/common/runtime_transaction_error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::runtime, RuntimeTransactionError, e) {
switch (e) {
case E::NO_TRANSACTIONS_WERE_STARTED:
return "no transactions were started";
case E::EXPORT_FUNCTION_NOT_FOUND:
return "Export function not found";
}
return "unknown TransactionError";
}
1 change: 1 addition & 0 deletions core/runtime/common/runtime_transaction_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace kagome::runtime {
*/
enum class RuntimeTransactionError { // 0 is reserved for success
NO_TRANSACTIONS_WERE_STARTED = 1,
EXPORT_FUNCTION_NOT_FOUND,
};
} // namespace kagome::runtime

Expand Down
21 changes: 21 additions & 0 deletions core/runtime/runtime_api/beefy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "consensus/beefy/types.hpp"

namespace kagome::runtime {
class BeefyApi {
public:
virtual ~BeefyApi() = default;

/**
* Get validator set if beefy is supported.
*/
virtual outcome::result<std::optional<consensus::beefy::ValidatorSet>>
validatorSet(const primitives::BlockHash &block) = 0;
};
} // namespace kagome::runtime
8 changes: 8 additions & 0 deletions core/runtime/runtime_api/impl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ target_link_libraries(babe_api
executor
)

add_library(beefy_api
beefy.cpp
)
target_link_libraries(beefy_api
executor
runtime_transaction_error
)

add_library(block_builder_api
block_builder.cpp
)
Expand Down
29 changes: 29 additions & 0 deletions core/runtime/runtime_api/impl/beefy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#include "runtime/runtime_api/impl/beefy.hpp"

#include "runtime/common/runtime_transaction_error.hpp"
#include "runtime/executor.hpp"

namespace kagome::runtime {
BeefyApiImpl::BeefyApiImpl(std::shared_ptr<Executor> executor)
: executor_{std::move(executor)} {
BOOST_ASSERT(executor_);
}

outcome::result<std::optional<consensus::beefy::ValidatorSet>>
BeefyApiImpl::validatorSet(const primitives::BlockHash &block) {
auto r = executor_->callAt<consensus::beefy::ValidatorSet>(
block, "BeefyApi_validator_set");
if (r) {
return std::move(r.value());
}
if (r.error() == RuntimeTransactionError::EXPORT_FUNCTION_NOT_FOUND) {
return std::nullopt;
}
return r.error();
}
} // namespace kagome::runtime
23 changes: 23 additions & 0 deletions core/runtime/runtime_api/impl/beefy.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "runtime/runtime_api/beefy.hpp"

namespace kagome::runtime {
class Executor;

class BeefyApiImpl : public BeefyApi {
public:
BeefyApiImpl(std::shared_ptr<Executor> executor);

outcome::result<std::optional<consensus::beefy::ValidatorSet>> validatorSet(
const primitives::BlockHash &block) override;

private:
std::shared_ptr<Executor> executor_;
};
} // namespace kagome::runtime
2 changes: 1 addition & 1 deletion core/runtime/runtime_api/impl/lru.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "utils/safe_object.hpp"

namespace kagome::runtime {
constexpr auto DISABLE_RUNTIME_LRU = true;
constexpr auto DISABLE_RUNTIME_LRU = false;

/**
* Cache runtime calls without arguments.
Expand Down
5 changes: 2 additions & 3 deletions core/runtime/wavm/module_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "host_api/host_api.hpp"
#include "log/profiling_logger.hpp"
#include "runtime/common/runtime_transaction_error.hpp"
#include "runtime/memory_provider.hpp"
#include "runtime/module_repository.hpp"
#include "runtime/trie_storage_provider.hpp"
Expand Down Expand Up @@ -70,8 +71,6 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::runtime::wavm,
switch (e) {
case E::WRONG_ARG_COUNT:
return "The provided function argument count should equal to 2";
case E::FUNC_NOT_FOUND:
return "The requested function not found";
case E::EXECUTION_ERROR:
return "An error occurred during wasm call execution; Check the logs for "
"more information";
Expand Down Expand Up @@ -117,7 +116,7 @@ namespace kagome::runtime::wavm {
WAVM::Runtime::getInstanceExport(instance_, name.data()));
if (!function) {
SL_DEBUG(logger_, "The requested function {} not found", name);
return Error::FUNC_NOT_FOUND;
return RuntimeTransactionError::EXPORT_FUNCTION_NOT_FOUND;
}
const WAVM::IR::FunctionType functionType =
WAVM::Runtime::getFunctionType(function);
Expand Down
3 changes: 1 addition & 2 deletions core/runtime/wavm/module_instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ namespace kagome::runtime::wavm {
public std::enable_shared_from_this<ModuleInstanceImpl> {
public:
enum class Error {
FUNC_NOT_FOUND = 1,
WRONG_ARG_COUNT,
WRONG_ARG_COUNT = 1,
EXECUTION_ERROR,
WRONG_RETURN_TYPE
};
Expand Down
2 changes: 1 addition & 1 deletion core/utils/lru_encoded.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace kagome {
if (weak) {
shared = weak->get().lock();
// check collisions (size_t is weak hash)
if (*shared != v) {
if (shared and *shared != v) {
shared.reset();
}
}
Expand Down

0 comments on commit 2d79dc3

Please sign in to comment.