From 2c18172af16fa347de10251c8268514c7b526cdb Mon Sep 17 00:00:00 2001 From: Julian Fleischer Date: Thu, 27 Sep 2018 15:05:40 +0200 Subject: [PATCH] WIP x WIP clang-format WIP x --- src/Makefile.am | 7 +++ src/esperanza/proposer_logic.cpp | 63 ++++++++++++++++++++++ src/esperanza/proposer_logic.h | 28 ++++++++++ src/esperanza/walletextension.cpp | 10 +--- src/esperanza/walletextension.h | 5 +- src/primitives/block.h | 2 + src/proposer/blockproposer.cpp | 29 ++++++++++ src/proposer/blockproposer.h | 72 +++++++++++++++++++++++++ src/proposer/chaininterface.cpp | 50 ++++++++++++++++++ src/proposer/chaininterface.h | 88 +++++++++++++++++++++++++++++++ src/proposer/networkinterface.cpp | 21 ++++++++ src/proposer/networkinterface.h | 27 ++++++++++ src/proposer/proposer.cpp | 87 ++++++++++++++---------------- src/proposer/proposer.h | 53 +++++++++---------- src/proposer/transactionpicker.h | 3 +- 15 files changed, 456 insertions(+), 89 deletions(-) create mode 100644 src/esperanza/proposer_logic.cpp create mode 100644 src/esperanza/proposer_logic.h create mode 100644 src/proposer/blockproposer.cpp create mode 100644 src/proposer/blockproposer.h create mode 100644 src/proposer/chaininterface.cpp create mode 100644 src/proposer/chaininterface.h create mode 100644 src/proposer/networkinterface.cpp create mode 100644 src/proposer/networkinterface.h diff --git a/src/Makefile.am b/src/Makefile.am index 0e61265a45..db4462b395 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -150,6 +150,9 @@ UNITE_CORE_H = \ policy/policy.h \ policy/rbf.h \ pow.h \ + proposer/blockproposer.h \ + proposer/chaininterface.h \ + proposer/networkinterface.h \ proposer/proposer.h \ proposer/proposer_init.h \ proposer/transactionpicker.h \ @@ -265,6 +268,9 @@ libunite_server_a_SOURCES = \ policy/policy.cpp \ policy/rbf.cpp \ pow.cpp \ + proposer/chaininterface.cpp \ + proposer/networkinterface.cpp \ + proposer/transactionpicker.cpp \ rest.cpp \ rpc/blockchain.cpp \ rpc/esperanza.cpp \ @@ -313,6 +319,7 @@ libunite_wallet_a_SOURCES = \ esperanza/stakevalidation.cpp \ esperanza/walletextension.cpp \ key/mnemonic/mnemonic.cpp \ + proposer/blockproposer.cpp \ proposer/proposer.cpp \ proposer/proposer_init.cpp \ proposer/transactionpicker.cpp \ diff --git a/src/esperanza/proposer_logic.cpp b/src/esperanza/proposer_logic.cpp new file mode 100644 index 0000000000..11ea9575e3 --- /dev/null +++ b/src/esperanza/proposer_logic.cpp @@ -0,0 +1,63 @@ +// Copyright (c) 2018 The unit-e core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include +#include + +namespace esperanza { + +CWallet *wallet; +// +// std::shared_ptr ProposeBlock( +// const CChainParams &chainParams, CWallet *wallet, +// const BlockProposalRequest &blockProposalRequest) { +// +// CScript coinbaseScript; +// BlockAssembler blockAssembler(chainParams); +// std::unique_ptr blockTemplate = +// blockAssembler.CreateNewBlock(coinbaseScript, /* fMineWitnessTx */ +// true); +// +// if (!blockTemplate) { +// // did not get block template +// return nullptr; +// } +// +// WalletExtension &walletExt = wallet->GetWalletExtension(); +// +// // CreateCoinStake() +// // SignBlock() +// +// const CBlock &block = blockTemplate->block; +// auto sharedBlock = std::make_shared(block); +// +// if (!CheckBlock(block)) { +// // failed PoS validation +// return nullptr; +// } +// +// if (!::ProcessNewBlock(chainParams, sharedBlock, +// /* fForceProcessing */ true, +// /* fNewBlock out */ nullptr)) { +// return nullptr; +// } +// return sharedBlock; +//} +// +// class BlockAssemblerAdapter { +// +// private: +// BlockAssembler blockAssembler; +// +// +// +//}; + +} // namespace esperanza diff --git a/src/esperanza/proposer_logic.h b/src/esperanza/proposer_logic.h new file mode 100644 index 0000000000..6508b3d611 --- /dev/null +++ b/src/esperanza/proposer_logic.h @@ -0,0 +1,28 @@ +// Copyright (c) 2018 The unit-e core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include + +#ifndef UNIT_E_ESPERANZA_PROPOSER_LOGIC_H +#define UNIT_E_ESPERANZA_PROPOSER_LOGIC_H + +class CWallet; + +namespace esperanza { +// +// struct BlockProposalRequest { +// int64_t blockTime; +// uint64_t blockHeight; +// uint64_t targetDifficulty; +//}; +// +////! \brief tries to propose a block using the given block proposal request +// std::shared_ptr ProposeBlock(const CChainParams &, CWallet *, +// const BlockProposalRequest &); + +} // namespace esperanza + +#endif // UNIT_E_PROPOSER_LOGIC_H diff --git a/src/esperanza/walletextension.cpp b/src/esperanza/walletextension.cpp index 7ed7489722..e83a52816c 100644 --- a/src/esperanza/walletextension.cpp +++ b/src/esperanza/walletextension.cpp @@ -143,7 +143,7 @@ bool WalletExtension::SelectCoinsForStaking( bool WalletExtension::CreateCoinStake(unsigned int nBits, int64_t nTime, int nBlockHeight, int64_t nFees, ::CMutableTransaction &txNew, - ::CKey &key) { + ::CKey &keyOut) { CBlockIndex *pindexPrev = chainActive.Tip(); arith_uint256 bnTargetPerCoinDay; bnTargetPerCoinDay.SetCompact(nBits); @@ -212,7 +212,7 @@ bool WalletExtension::CreateCoinStake(unsigned int nBits, int64_t nTime, break; // only support pay to address (pay to pubkey hash) } - if (!m_enclosingWallet->GetKey(spendId, key)) { + if (!m_enclosingWallet->GetKey(spendId, keyOut)) { LogPrint(BCLog::PROPOSING, "%s: Failed to get key for kernel type=%d.\n", __func__, whichType); @@ -362,12 +362,6 @@ bool WalletExtension::CreateCoinStake(unsigned int nBits, int64_t nTime, return true; } -bool WalletExtension::SignBlock(::CBlockTemplate *pblocktemplate, int nHeight, - int64_t nSearchTime) { - // UNIT-E: todo - return false; -} - bool WalletExtension::SetMasterKeyFromSeed(const key::mnemonic::Seed &seed, std::string &error) { const std::string walletFileName = m_enclosingWallet->GetName(); diff --git a/src/esperanza/walletextension.h b/src/esperanza/walletextension.h index 6dbc857b26..f019bdd567 100644 --- a/src/esperanza/walletextension.h +++ b/src/esperanza/walletextension.h @@ -72,10 +72,7 @@ class WalletExtension { bool CreateCoinStake(unsigned int nBits, int64_t nTime, int nBlockHeight, int64_t nFees, ::CMutableTransaction &txNew, - ::CKey &key); - - bool SignBlock(::CBlockTemplate *pblocktemplate, int nHeight, - int64_t nSearchTime); + ::CKey &keyOut); bool SetMasterKeyFromSeed(const key::mnemonic::Seed &seed, std::string &error); diff --git a/src/primitives/block.h b/src/primitives/block.h index 1228319c1e..e104986fb5 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -92,6 +92,8 @@ class CBlock : public CBlockHeader *((CBlockHeader*)this) = header; } + CBlock(const CBlock &block) = default; + ADD_SERIALIZE_METHODS; template diff --git a/src/proposer/blockproposer.cpp b/src/proposer/blockproposer.cpp new file mode 100644 index 0000000000..c9170d8af5 --- /dev/null +++ b/src/proposer/blockproposer.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2018 The unit-e core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "blockproposer.h" + +namespace proposer { + +class BlockProposerImpl : public BlockProposer { + + private: + ChainInterface &m_chain; + + public: + BlockProposerImpl(ChainInterface &chain) : m_chain(chain) {} + + std::shared_ptr ProposeBlock( + const ProposeBlockParameters ¶meters) { + //m_chain.ProcessNewBlock(nullptr); + return nullptr; + }; +}; + +std::shared_ptr BlockProposer::MakeBlockProposer( + ChainInterface &chain) { + return std::shared_ptr(new BlockProposerImpl(chain)); +} + +} // namespace proposer diff --git a/src/proposer/blockproposer.h b/src/proposer/blockproposer.h new file mode 100644 index 0000000000..c25943f8f0 --- /dev/null +++ b/src/proposer/blockproposer.h @@ -0,0 +1,72 @@ +// Copyright (c) 2018 The unit-e core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef UNIT_E_PROPOSER_BLOCKPROPOSER_H +#define UNIT_E_PROPOSER_BLOCKPROPOSER_H + +#include + +#include + +#include + +class CBlock; +class CWallet; + +namespace proposer { + +//! \brief a component for proposing new blocks. +//! +//! The block proposer will build and propose a block, given a wallet +//! that has enough stake. +//! +//! The BlockProposer is different from the Proposer in proposer.cpp. +//! That one is managing concurrency (number of staking threads), +//! availability of wallets, balance, etc. The BlockProposer is used +//! to actually propose a block once we know that we have the means to +//! do so. +//! +//! This class is an interface. +class BlockProposer { + + public: + struct ProposeBlockParameters { + //! \brief the height to propose the block for. + //! + //! The height of a block is encoded inside the coinbase transaction. + //! This is defined in BIP34 (Block v2, Height in Coinbase). + //! This also helps ensuring that the coinbase transaction has a + //! unique hash, hence prevent BIP30 (Duplicate transactions) from + //! applying. + //! + //! Block height is up to 2^31 which is enough to support one block + //! every second for 68 years. This is because block height used to + //! be signed and the signbit is now overloaded in some places to + //! signal a coinstake transaction in various serializations of + //! coins / UTXOs. + uint32_t blockHeight; + + //! \brief the block time to propose the block with. + int64_t blockTime; + + //! \brief the wallet to draw funds for staking from. + //! + //! The stake to propose with is drawn from the given wallet. The + //! amount of stake will increase the chances of proposing since + //! a certain difficulty threshold has to be met in order to do so. + CWallet *wallet; + }; + + virtual std::shared_ptr ProposeBlock( + const ProposeBlockParameters &) = 0; + + virtual ~BlockProposer() = default; + + //! \brief Factory method for creating a BlockProposer + static std::shared_ptr MakeBlockProposer(ChainInterface &); +}; + +} // namespace proposer + +#endif // UNIT_E_PROPOSER_BLOCKPROPOSER_H diff --git a/src/proposer/chaininterface.cpp b/src/proposer/chaininterface.cpp new file mode 100644 index 0000000000..cd2711fda5 --- /dev/null +++ b/src/proposer/chaininterface.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2018 The unit-e core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include + +namespace proposer { + +class ChainAdapter final : public ChainInterface { + + CCriticalSection& GetLock() const override { + return cs_main; + } + + uint32_t GetHeight() const override { + const int height = chainActive.Height(); + if (height < 0) { + throw std::runtime_error("no active chain yet"); + } + return static_cast(height); + }; + + std::unique_ptr GetTip() const override { + const CBlockIndex *tip = chainActive.Tip(); + if (tip == nullptr) { + throw std::runtime_error("no active chain yet"); + } + return MakeUnique(tip->GetBlockHeader()); + }; + + bool ProcessNewBlock(std::shared_ptr pblock) override { + bool newBlock; + return ::ProcessNewBlock(::Params(), pblock, true, &newBlock); + }; + + ::SyncStatus GetInitialBlockDownloadStatus() const override { + return ::GetInitialBlockDownloadStatus(); + } +}; + +std::shared_ptr ChainInterface::MakeChainInterface() { + return std::shared_ptr(new ChainAdapter()); +} + +} // namespace proposer diff --git a/src/proposer/chaininterface.h b/src/proposer/chaininterface.h new file mode 100644 index 0000000000..dc01bc1bc7 --- /dev/null +++ b/src/proposer/chaininterface.h @@ -0,0 +1,88 @@ +// Copyright (c) 2018 The unit-e core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef UNIT_E_CHAININTERFACE_H +#define UNIT_E_CHAININTERFACE_H + +#include +#include + +#include +#include +#include + +class CBlock; +class CBlockHeader; + +namespace proposer { + +//! \brief an interface to the current blockchain's state. +//! +//! Proposing a block requires access to the current chain state. A lot +//! of these mechanisms are free functions in bitcoin which are super +//! hard to control for example in unit tests. Thus this interface is +//! defined to encapsulate all that free floating stuff behind a single +//! API. Inspiration for this has been drawn from a proposed Chain +//! interface in bitcoin to separate Wallet and Node from each other. +//! See: https://github.com/bitcoin/bitcoin/pull/14437 - in particular +//! https://github.com/ryanofsky/bitcoin/blob/45b23efaada081a7be9e255df59670f4704c45d1/src/interfaces/chain.h +//! +//! This class is an interface as in it is an abstract class with +//! only virtual members but it is also meant as a particular API +//! to a piece of bitcoin infrastructure, hence the name. +//! I would have named this "Chain" but I am hoping for the above +//! mentioned refactoring to be included into bitcoin and synced +//! downstream into unit-e eventually which would make this superfluous. +class ChainInterface { + + public: + virtual CCriticalSection& GetLock() const = 0; + + //! \brief returns the height of the currently active chain. + //! + //! If the chain contains only the genesis block then this method + //! returns 0 (the height of the genesis block). Note that there are + //! N + 1 blocks in a chain of height N. + //! + //! Throws an exception if there is no chain yet. This can only be + //! the case if the chain interface is invoked before the node has + //! just started up and didn't have a chance to load blockchain from + //! disk. While designing this API this was considered to be better + //! behavior than simply leaving it undefined. + //! + //! This function is a drop-in replacement for + //! ::chainActive.Height() + virtual uint32_t GetHeight() const = 0; + + //! \brief returns the currently active chain's tip. + //! + //! Returns a shared pointer to the block which is at the currently + //! active chains tip. If the chain contains only the genesis block + //! then a pointer to that is returned. + //! + //! Throws an exception if there is no chain yet. This can only be + //! the case if the chain interface is invoked before the node has + //! just started up and didn't have a chance to load blockchain from + //! disk. While designing this API this was considered to be better + //! behavior than simply leaving it undefined. + //! + //! This function is a replacement for + //! ::chainActive.Tip()->GetBlockHeader() + virtual std::unique_ptr GetTip() const = 0; + + //! \brief add a new block at the current active chains tip. + virtual bool ProcessNewBlock(std::shared_ptr pblock) = 0; + + //! \brief Check the current status of the initial block download. + virtual ::SyncStatus GetInitialBlockDownloadStatus() const = 0; + + virtual ~ChainInterface() = default; + + //! \brief Factory method for creating a ChainInterface. + static std::shared_ptr MakeChainInterface(); +}; + +} // namespace proposer + +#endif // UNIT_E_CHAININTERFACE_H diff --git a/src/proposer/networkinterface.cpp b/src/proposer/networkinterface.cpp new file mode 100644 index 0000000000..4b58493269 --- /dev/null +++ b/src/proposer/networkinterface.cpp @@ -0,0 +1,21 @@ +// Copyright (c) 2018 The unit-e core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include + +namespace proposer { + +class NetworkAdapter : public NetworkInterface { + + public: + int64_t GetTime() const override { return GetAdjustedTime(); } +}; + +std::shared_ptr NetworkInterface::MakeNetworkInterface() { + return std::shared_ptr(new NetworkAdapter()); +} + +} // namespace proposer diff --git a/src/proposer/networkinterface.h b/src/proposer/networkinterface.h new file mode 100644 index 0000000000..acc285b160 --- /dev/null +++ b/src/proposer/networkinterface.h @@ -0,0 +1,27 @@ +// Copyright (c) 2018 The unit-e core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef UNIT_E_PROPOSER_NETWORKINTERFACE_H +#define UNIT_E_PROPOSER_NETWORKINTERFACE_H + +#include + +#include + +namespace proposer { + +//! \brief +class NetworkInterface { + + public: + virtual int64_t GetTime() const = 0; + + virtual ~NetworkInterface() = default; + + static std::shared_ptr MakeNetworkInterface(); +}; + +} // namespace proposer + +#endif // UNIT_E_PROPOSER_NETWORKINTERFACE_H diff --git a/src/proposer/proposer.cpp b/src/proposer/proposer.cpp index bf8befff8f..d0c0c8c742 100644 --- a/src/proposer/proposer.cpp +++ b/src/proposer/proposer.cpp @@ -1,3 +1,5 @@ +#include + // Copyright (c) 2018 The unit-e core developers // Copyright (c) 2017 The Particl developers // Distributed under the MIT software license, see the accompanying @@ -7,14 +9,11 @@ #include
#include -#include -#include #include #include