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

beefy types #1773

Merged
merged 5 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
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