generated from Warchant/cmake-hunter-seed
-
Notifications
You must be signed in to change notification settings - Fork 36
Block producer #119
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
Merged
Merged
Block producer #119
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# | ||
#Copyright Soramitsu Co., Ltd.All Rights Reserved. | ||
#SPDX - License - Identifier : Apache - 2.0 | ||
# | ||
|
||
add_library(block_producer | ||
impl/block_producer_impl.cpp | ||
) | ||
target_link_libraries(block_producer | ||
bls_provider | ||
outcome | ||
buffer | ||
address | ||
clock | ||
interpreter | ||
tipset | ||
ipfs_datastore_in_memory | ||
) |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
*/ | ||
|
||
#include "common/outcome.hpp" | ||
#include "primitives/address/address.hpp" | ||
#include "primitives/block/block.hpp" | ||
#include "primitives/ticket/epost_ticket.hpp" | ||
#include "primitives/ticket/ticket.hpp" | ||
#include "vm/indices/indices.hpp" | ||
|
||
namespace fc::blockchain::production { | ||
/** | ||
* @class Generating new blocks for chain's tipset | ||
*/ | ||
class BlockProducer { | ||
protected: | ||
using Block = primitives::block::Block; | ||
using Address = primitives::address::Address; | ||
using EPostProof = primitives::ticket::EPostProof; | ||
using Ticket = primitives::ticket::Ticket; | ||
using Indices = vm::indices::Indices; | ||
|
||
public: | ||
virtual ~BlockProducer() = default; | ||
|
||
/** | ||
* @brief Generate new block | ||
* @param miner_address - source address | ||
* @param parent_tipset_id - id of the parent tipset | ||
* @param proof - evidence of mining permission | ||
* @param ticket - used ticket for election round | ||
* @return Generated full block | ||
*/ | ||
virtual outcome::result<Block> generate( | ||
Address miner_address, | ||
const CID &parent_tipset_id, | ||
EPostProof proof, | ||
Ticket ticket, | ||
std::shared_ptr<Indices> indices) = 0; | ||
}; | ||
|
||
/** | ||
* @enum Block production errors | ||
*/ | ||
enum class BlockProducerError { | ||
PARENT_TIPSET_NOT_FOUND = 1, | ||
PARENT_TIPSET_INVALID_CONTENT | ||
}; | ||
} // namespace fc::blockchain::production | ||
|
||
OUTCOME_HPP_DECLARE_ERROR(fc::blockchain::production, BlockProducerError); |
161 changes: 161 additions & 0 deletions
161
core/blockchain/production/impl/block_producer_impl.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
/** | ||
* Copyright Soramitsu Co., Ltd. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include "blockchain/production/impl/block_producer_impl.hpp" | ||
|
||
#include <vector> | ||
|
||
#include <gsl/span> | ||
#include "clock/chain_epoch_clock.hpp" | ||
#include "codec/cbor/cbor.hpp" | ||
#include "common/visitor.hpp" | ||
#include "primitives/cid/cid_of_cbor.hpp" | ||
#include "storage/amt/amt.hpp" | ||
#include "storage/ipfs/impl/in_memory_datastore.hpp" | ||
|
||
namespace fc::blockchain::production { | ||
using clock::Time; | ||
using codec::cbor::decode; | ||
using crypto::signature::BlsSignature; | ||
using crypto::signature::Secp256k1Signature; | ||
using primitives::block::BlockHeader; | ||
using storage::amt::Amt; | ||
using storage::amt::Root; | ||
using storage::ipfs::InMemoryDatastore; | ||
using vm::message::SignedMessage; | ||
using vm::message::UnsignedMessage; | ||
|
||
BlockProducerImpl::BlockProducerImpl( | ||
std::shared_ptr<IpfsDatastore> data_store, | ||
std::shared_ptr<MessageStorage> message_store, | ||
std::shared_ptr<UTCClock> utc_clock, | ||
std::shared_ptr<ChainEpochClock> epoch_clock, | ||
std::shared_ptr<WeightCalculator> weight_calculator, | ||
std::shared_ptr<BlsProvider> crypto_provider, | ||
std::shared_ptr<Interpreter> interpreter) | ||
: data_storage_{std::move(data_store)}, | ||
message_storage_{std::move(message_store)}, | ||
clock_{std::move(utc_clock)}, | ||
epoch_{std::move(epoch_clock)}, | ||
chain_weight_calculator_{std::move(weight_calculator)}, | ||
bls_provider_{std::move(crypto_provider)}, | ||
vm_interpreter_{std::move(interpreter)} {} | ||
|
||
outcome::result<BlockProducer::Block> BlockProducerImpl::generate( | ||
primitives::address::Address miner_address, | ||
const CID &parent_tipset_id, | ||
EPostProof proof, | ||
Ticket ticket, | ||
std::shared_ptr<Indices> indices) { | ||
OUTCOME_TRY(parent_tipset, getTipset(parent_tipset_id)); | ||
OUTCOME_TRY( | ||
vm_result, | ||
vm_interpreter_->interpret(data_storage_, parent_tipset, indices)); | ||
OUTCOME_TRY(parent_weight, | ||
chain_weight_calculator_->calculateWeight(parent_tipset)); | ||
std::vector<SignedMessage> messages = | ||
message_storage_->getTopScored(config::kBlockMaxMessagesCount); | ||
OUTCOME_TRY(msg_meta, getMessagesMeta(messages)); | ||
std::vector<UnsignedMessage> bls_messages; | ||
std::vector<SignedMessage> secp_messages; | ||
std::vector<crypto::bls::Signature> bls_signatures; | ||
for (auto &&message : messages) { | ||
visit_in_place( | ||
message.signature, | ||
[&message, &bls_messages, &bls_signatures]( | ||
const BlsSignature &signature) { | ||
bls_messages.emplace_back(std::move(message.message)); | ||
bls_signatures.push_back(signature); | ||
}, | ||
[&message, &secp_messages](const Secp256k1Signature &signature) { | ||
secp_messages.emplace_back(std::move(message)); | ||
}); | ||
} | ||
OUTCOME_TRY(bls_aggregate_sign, | ||
bls_provider_->aggregateSignatures(bls_signatures)); | ||
Time now = clock_->nowUTC(); | ||
OUTCOME_TRY(current_epoch, epoch_->epochAtTime(now)); | ||
BlockHeader header{ | ||
.miner = std::move(miner_address), | ||
.ticket = ticket, | ||
.epost_proof = std::move(proof), | ||
.parents = std::move(parent_tipset.cids), | ||
.parent_weight = parent_weight, | ||
.height = static_cast<uint64_t>(current_epoch), | ||
.parent_state_root = std::move(vm_result.state_root), | ||
.parent_message_receipts = std::move(vm_result.message_receipts), | ||
.messages = msg_meta.getCID(), | ||
.bls_aggregate = {std::move_iterator(bls_aggregate_sign.begin()), | ||
std::move_iterator(bls_aggregate_sign.end())}, | ||
.timestamp = static_cast<uint64_t>(now.unixTime().count()), | ||
.block_sig = {}, // Block must be signed be Actor Miner | ||
.fork_signaling = 0}; | ||
return Block{.header = std::move(header), | ||
.bls_messages = std::move(bls_messages), | ||
.secp_messages = std::move(secp_messages)}; | ||
} | ||
|
||
outcome::result<BlockProducerImpl::Tipset> BlockProducerImpl::getTipset( | ||
const CID &tipset_id) const { | ||
auto raw_data = data_storage_->get(tipset_id); | ||
if (raw_data.has_error()) { | ||
return BlockProducerError::PARENT_TIPSET_NOT_FOUND; | ||
} | ||
auto tipset = codec::cbor::decode<Tipset>(raw_data.value()); | ||
if (tipset.has_error()) { | ||
return BlockProducerError::PARENT_TIPSET_INVALID_CONTENT; | ||
} | ||
return tipset.value(); | ||
} | ||
|
||
outcome::result<BlockProducerImpl::MsgMeta> | ||
BlockProducerImpl::getMessagesMeta( | ||
const std::vector<SignedMessage> &messages) { | ||
auto bls_backend = std::make_shared<InMemoryDatastore>(); | ||
auto secp_backend = std::make_shared<InMemoryDatastore>(); | ||
Amt bls_messages_amt{bls_backend}; | ||
Amt secp_messages_amt{secp_backend}; | ||
std::vector<SignedMessage> bls_messages; | ||
std::vector<SignedMessage> secp_messages; | ||
for (const auto &msg : messages) { | ||
visit_in_place( | ||
msg.signature, | ||
[&msg, &bls_messages](const BlsSignature &signature) { | ||
std::ignore = signature; | ||
bls_messages.push_back(msg); | ||
}, | ||
[&msg, &secp_messages](const Secp256k1Signature &signature) { | ||
std::ignore = signature; | ||
secp_messages.push_back(msg); | ||
}); | ||
} | ||
for (size_t index = 0; index < bls_messages.size(); ++index) { | ||
OUTCOME_TRY(message_cid, | ||
primitives::cid::getCidOfCbor(bls_messages.at(index))); | ||
OUTCOME_TRY(bls_messages_amt.setCbor(index, message_cid)); | ||
} | ||
for (size_t index = 0; index < secp_messages.size(); ++index) { | ||
OUTCOME_TRY(message_cid, | ||
primitives::cid::getCidOfCbor(secp_messages.at(index))); | ||
OUTCOME_TRY(secp_messages_amt.setCbor(index, message_cid)); | ||
} | ||
OUTCOME_TRY(bls_root_cid, bls_messages_amt.flush()); | ||
OUTCOME_TRY(secp_root_cid, secp_messages_amt.flush()); | ||
MsgMeta msg_meta{}; | ||
msg_meta.bls_messages = bls_root_cid; | ||
msg_meta.secpk_messages = secp_root_cid; | ||
return msg_meta; | ||
turuslan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} // namespace fc::blockchain::production | ||
|
||
OUTCOME_CPP_DEFINE_CATEGORY(fc::blockchain::production, BlockProducerError, e) { | ||
using fc::blockchain::production::BlockProducerError; | ||
switch (e) { | ||
case (BlockProducerError::PARENT_TIPSET_NOT_FOUND): | ||
return "Block Generator: failed to load parent tipset"; | ||
case (BlockProducerError::PARENT_TIPSET_INVALID_CONTENT): | ||
return "Block Generator: failed to decode parent tipset content"; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/** | ||
* Copyright Soramitsu Co., Ltd. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <memory> | ||
|
||
#include "blockchain/message_pool/message_storage.hpp" | ||
#include "blockchain/production/block_producer.hpp" | ||
#include "blockchain/weight_calculator.hpp" | ||
#include "clock/chain_epoch_clock.hpp" | ||
#include "clock/utc_clock.hpp" | ||
#include "crypto/bls/bls_provider.hpp" | ||
#include "primitives/block/block.hpp" | ||
#include "primitives/tipset/tipset.hpp" | ||
#include "storage/ipfs/datastore.hpp" | ||
#include "vm/interpreter/interpreter.hpp" | ||
|
||
namespace fc::blockchain::production { | ||
namespace config { | ||
// Max messages count in the Block | ||
constexpr size_t kBlockMaxMessagesCount = 1000; | ||
} // namespace config | ||
|
||
/** | ||
* @class Block Generator implementation | ||
*/ | ||
class BlockProducerImpl : public BlockProducer { | ||
protected: | ||
using MessageStorage = blockchain::message_pool::MessageStorage; | ||
using WeightCalculator = blockchain::weight::WeightCalculator; | ||
using ChainEpochClock = clock::ChainEpochClock; | ||
using UTCClock = clock::UTCClock; | ||
using BlsProvider = crypto::bls::BlsProvider; | ||
using MsgMeta = primitives::block::MsgMeta; | ||
using Tipset = primitives::tipset::Tipset; | ||
using IpfsDatastore = storage::ipfs::IpfsDatastore; | ||
using SignedMessage = vm::message::SignedMessage; | ||
using Interpreter = vm::interpreter::Interpreter; | ||
|
||
public: | ||
/** | ||
* @brief Construct new Block Generator | ||
* @param data_store | ||
*/ | ||
explicit BlockProducerImpl( | ||
std::shared_ptr<IpfsDatastore> data_store, | ||
std::shared_ptr<MessageStorage> message_store, | ||
std::shared_ptr<UTCClock> utc_clock, | ||
std::shared_ptr<ChainEpochClock> epoch_clock, | ||
std::shared_ptr<WeightCalculator> weight_calculator, | ||
std::shared_ptr<BlsProvider> crypto_provider, | ||
std::shared_ptr<Interpreter> interpreter); | ||
|
||
outcome::result<Block> generate(Address miner_address, | ||
const CID &parent_tipset_id, | ||
EPostProof proof, | ||
Ticket ticket, | ||
std::shared_ptr<Indices> indices) override; | ||
|
||
private: | ||
std::shared_ptr<IpfsDatastore> data_storage_; | ||
std::shared_ptr<MessageStorage> message_storage_; | ||
std::shared_ptr<UTCClock> clock_; | ||
std::shared_ptr<ChainEpochClock> epoch_; | ||
std::shared_ptr<WeightCalculator> chain_weight_calculator_; | ||
std::shared_ptr<BlsProvider> bls_provider_; | ||
std::shared_ptr<Interpreter> vm_interpreter_; | ||
|
||
/** | ||
* @brief Load tipset from IPFS storage by CID | ||
* @param tipset_id - CID of the tipset | ||
* @return requested tipset or appropriate error | ||
*/ | ||
outcome::result<Tipset> getTipset(const CID &tipset_id) const; | ||
|
||
/** | ||
* @brief Generate messages meta-data | ||
* @param messages - messages to include in the new Block | ||
* @return Generated meta-data | ||
*/ | ||
static outcome::result<MsgMeta> getMessagesMeta( | ||
const std::vector<SignedMessage> &messages); | ||
}; | ||
} // namespace fc::blockchain::production |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.