diff --git a/README.md b/README.md index 0166e3668a..0378e0cfab 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -<<<<<<< HEAD BGL Core integration/staging tree -===================================== What is BGL? ---------------- @@ -141,4 +139,3 @@ Reporting a vulnerability ------------ See [SECURITY.md](SECURITY.md) ->>>>>>> 67f232b5d... Squashed 'src/secp256k1/' changes from b19c000063..2ed54da18a diff --git a/configure.ac b/configure.ac index 567d98ebea..90a055816b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,10 @@ AC_PREREQ([2.69]) -define(_CLIENT_VERSION_MAJOR, 21) -define(_CLIENT_VERSION_MINOR, 99) -define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_MAJOR, 0) +define(_CLIENT_VERSION_MINOR, 1) +define(_CLIENT_VERSION_BUILD, 5) define(_CLIENT_VERSION_RC, 0) -define(_CLIENT_VERSION_IS_RELEASE, false) -define(_COPYRIGHT_YEAR, 2020) +define(_CLIENT_VERSION_IS_RELEASE, true) +define(_COPYRIGHT_YEAR, 2021) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[BGL Core]]) AC_INIT([BGL Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_BUILD)m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/BGL/BGL/issues],[BGL],[https://BGLcore.org/]) diff --git a/src/.changes! b/src/.changes! deleted file mode 100644 index dc99d90a9a..0000000000 --- a/src/.changes! +++ /dev/null @@ -1,6597 +0,0 @@ -diff --git a/src/BGL-tx.cpp b/src/BGL-tx.cpp -index 59cadadc..2ea1091c 100644 ---- a/src/BGL-tx.cpp -+++ b/src/BGL-tx.cpp -@@ -40,7 +40,6 @@ static void SetupBGLTxArgs(ArgsManager &argsman) - { - SetupHelpOptions(argsman); - -- argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-create", "Create new, empty TX.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-json", "Select JSON output", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - argsman.AddArg("-txid", "Output only the hex-encoded transaction id of the resultant transaction.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); -@@ -79,10 +78,6 @@ static void SetupBGLTxArgs(ArgsManager &argsman) - // - static int AppInitRawTx(int argc, char* argv[]) - { --<<<<<<< HEAD:src/BGL-tx.cpp -- // -- // Parameters -- // - SetupBGLTxArgs(gArgs); - std::string error; - if (!gArgs.ParseParameters(argc, argv, error)) { -@@ -100,16 +95,13 @@ static int AppInitRawTx(int argc, char* argv[]) - - fCreateBlank = gArgs.GetBoolArg("-create", false); - -- if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) { -+ if (argc < 2 || HelpRequested(gArgs)) { - // First part of help message is specific to this utility -- std::string strUsage = PACKAGE_NAME " BGL-tx utility version " + FormatFullVersion() + "\n"; -- if (!gArgs.IsArgSet("-version")) { -- strUsage += "\n" -- "Usage: BGL-tx [options] [commands] Update hex-encoded BGL transaction\n" -- "or: BGL-tx [options] -create [commands] Create hex-encoded BGL transaction\n" -- "\n"; -- strUsage += gArgs.GetHelpMessage(); -- } -+ std::string strUsage = PACKAGE_NAME " BGL-tx utility version " + FormatFullVersion() + "\n\n" + -+ "Usage: BGL-tx [options] [commands] Update hex-encoded BGL transaction\n" + -+ "or: BGL-tx [options] -create [commands] Create hex-encoded BGL transaction\n" + -+ "\n"; -+ strUsage += gArgs.GetHelpMessage(); - - tfm::format(std::cout, "%s", strUsage); - -diff --git a/src/Makefile.am b/src/Makefile.am -index 93dd186d..18574188 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -20,9 +20,8 @@ else - LIBUNIVALUE = $(UNIVALUE_LIBS) - endif - --BGL_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) -+BGL_INCLUDES=-I$(builddir) -I$(srcdir)/secp256k1/include $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) - --BGL_INCLUDES += -I$(srcdir)/secp256k1/include - BGL_INCLUDES += $(UNIVALUE_CFLAGS) - - LIBBGL_SERVER=libBGL_server.a -@@ -299,13 +298,14 @@ libBGL_server_a_SOURCES = \ - index/blockfilterindex.cpp \ - index/txindex.cpp \ - init.cpp \ -+ interfaces/chain.cpp \ -+ interfaces/node.cpp \ - miner.cpp \ - net.cpp \ - net_processing.cpp \ - node/coin.cpp \ - node/coinstats.cpp \ - node/context.cpp \ -- node/interfaces.cpp \ - node/psbt.cpp \ - node/transaction.cpp \ - node/ui_interface.cpp \ -@@ -358,13 +358,13 @@ endif - libBGL_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BGL_INCLUDES) $(SQLITE_CFLAGS) - libBGL_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) - libBGL_wallet_a_SOURCES = \ -+ interfaces/wallet.cpp \ - wallet/coincontrol.cpp \ - wallet/context.cpp \ - wallet/crypter.cpp \ - wallet/db.cpp \ - wallet/feebumper.cpp \ - wallet/fees.cpp \ -- wallet/interfaces.cpp \ - wallet/load.cpp \ - wallet/rpcdump.cpp \ - wallet/rpcwallet.cpp \ -diff --git a/src/banman.cpp b/src/banman.cpp -index 5933c1ce..9a829aa2 100644 ---- a/src/banman.cpp -+++ b/src/banman.cpp -@@ -120,20 +120,19 @@ bool BanMan::IsBanned(const CSubNet& sub_net) - - void BanMan::Ban(const CNetAddr& net_addr, int64_t ban_time_offset, bool since_unix_epoch) - { -- if (ban_reason == BanReasonNodeMisbehaving) { -- LOCK(m_cs_banned); -- m_discouraged.insert(net_addr.GetAddrBytes()); -- return; -- } - CSubNet sub_net(net_addr); - Ban(sub_net, ban_time_offset, since_unix_epoch); - } - - void BanMan::Discourage(const CNetAddr& net_addr) - { -+ LOCK(m_cs_banned); -+ m_discouraged.insert(net_addr.GetAddrBytes()); -+} - -- assert(ban_reason == BanReasonManuallyAdded); -- CBanEntry ban_entry(GetTime(), ban_reason); -+void BanMan::Ban(const CSubNet& sub_net, int64_t ban_time_offset, bool since_unix_epoch) -+{ -+ CBanEntry ban_entry(GetTime()); - - int64_t normalized_ban_time_offset = ban_time_offset; - bool normalized_since_unix_epoch = since_unix_epoch; -diff --git a/src/init.cpp b/src/init.cpp -index 53e2c106..ff0ac231 100644 ---- a/src/init.cpp -+++ b/src/init.cpp -@@ -1584,7 +1584,6 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA - - do { - const int64_t load_block_index_start_time = GetTimeMillis(); -- bool is_coinsview_empty; - try { - LOCK(cs_main); - chainman.InitializeChainstate(*Assert(node.mempool)); -@@ -1644,6 +1643,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA - // block tree into BlockIndex()! - bool failed_chainstate_init = false; - -+ - for (CChainState* chainstate : chainman.GetAll()) { - chainstate->InitCoinsDB( - /* cache_size_bytes */ nCoinDBCache, -@@ -1664,25 +1664,30 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA - break; - } - -- // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate -- if (!::ChainstateActive().ReplayBlocks(chainparams)) { -- strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.").translated; -- break; -- } -+ // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate -+ if (!chainstate->ReplayBlocks(chainparams)) { -+ strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate."); -+ failed_chainstate_init = true; -+ break; -+ } - - // The on-disk coinsdb is now in a good state, create the cache - chainstate->InitCoinsCache(nCoinCacheUsage); - assert(chainstate->CanFlushToDisk()); - -- is_coinsview_empty = fReset || fReindexChainState || -- ::ChainstateActive().CoinsTip().GetBestBlock().IsNull(); -- if (!is_coinsview_empty) { -- // LoadChainTip initializes the chain based on CoinsTip()'s best block -- if (!::ChainstateActive().LoadChainTip(chainparams)) { -- strLoadError = _("Error initializing block database").translated; -- break; -+ if (!is_coinsview_empty(chainstate)) { -+ // LoadChainTip initializes the chain based on CoinsTip()'s best block -+ if (!chainstate->LoadChainTip(chainparams)) { -+ strLoadError = _("Error initializing block database"); -+ failed_chainstate_init = true; -+ break; // out of the per-chainstate loop -+ } -+ assert(chainstate->m_chain.Tip() != nullptr); - } -- assert(::ChainActive().Tip() != nullptr); -+ } -+ -+ if (failed_chainstate_init) { -+ break; // out of the chainstate activation do-while - } - } catch (const std::exception& e) { - LogPrintf("%s\n", e.what()); -@@ -1709,23 +1714,10 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA - } - } - -+ bool failed_verification = false; -+ - try { - LOCK(cs_main); -- if (!is_coinsview_empty) { -- uiInterface.InitMessage(_("Verifying blocks...").translated); -- if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) { -- LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n", -- MIN_BLOCKS_TO_KEEP); -- } -- -- CBlockIndex* tip = ::ChainActive().Tip(); -- RPCNotifyBlockChange(true, tip); -- if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) { -- strLoadError = _("The block database contains a block which appears to be from the future. " -- "This may be due to your computer's date and time being set incorrectly. " -- "Only rebuild the block database if you are sure that your computer's date and time are correct").translated; -- break; -- } - - for (CChainState* chainstate : chainman.GetAll()) { - if (!is_coinsview_empty(chainstate)) { -diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h -index 55a07ba1..ebf35077 100644 ---- a/src/interfaces/chain.h -+++ b/src/interfaces/chain.h -@@ -1,4 +1,4 @@ --// Copyright (c) 2018-2020 The BGL Core developers -+// Copyright (c) 2018-2020 The Bitcoin Core developers - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -@@ -35,6 +35,27 @@ namespace interfaces { - class Handler; - class Wallet; - -+//! Helper for findBlock to selectively return pieces of block data. -+class FoundBlock -+{ -+public: -+ FoundBlock& hash(uint256& hash) { m_hash = &hash; return *this; } -+ FoundBlock& height(int& height) { m_height = &height; return *this; } -+ FoundBlock& time(int64_t& time) { m_time = &time; return *this; } -+ FoundBlock& maxTime(int64_t& max_time) { m_max_time = &max_time; return *this; } -+ FoundBlock& mtpTime(int64_t& mtp_time) { m_mtp_time = &mtp_time; return *this; } -+ //! Read block data from disk. If the block exists but doesn't have data -+ //! (for example due to pruning), the CBlock variable will be set to null. -+ FoundBlock& data(CBlock& data) { m_data = &data; return *this; } -+ -+ uint256* m_hash = nullptr; -+ int* m_height = nullptr; -+ int64_t* m_time = nullptr; -+ int64_t* m_max_time = nullptr; -+ int64_t* m_mtp_time = nullptr; -+ CBlock* m_data = nullptr; -+}; -+ - //! Interface giving clients (wallet processes, maybe other analysis tools in - //! the future) ability to access to the chain state, receive notifications, - //! estimate fees, and submit transactions. -@@ -43,12 +64,7 @@ class Wallet; - //! internal workings of the BGL node, and not being very convenient to use. - //! Chain methods should be cleaned up and simplified over time. Examples: - //! --//! * The Chain::lock() method, which lets clients delay chain tip updates --//! should be removed when clients are able to respond to updates --//! asynchronously --//! (https://github.com/BGL/BGL/pull/10973#issuecomment-380101269). --//! --//! * The initMessage() and showProgress() methods which the wallet uses to send -+//! * The initMessages() and showProgress() methods which the wallet uses to send - //! notifications to the GUI should go away when GUI and wallet can directly - //! communicate with each other without going through the node - //! (https://github.com/BGL/BGL/pull/15288#discussion_r253321096). -@@ -69,65 +85,6 @@ class Chain - public: - virtual ~Chain() {} - -- //! Interface for querying locked chain state, used by legacy code that -- //! assumes state won't change between calls. New code should avoid using -- //! the Lock interface and instead call higher-level Chain methods -- //! that return more information so the chain doesn't need to stay locked -- //! between calls. -- class Lock -- { -- public: -- virtual ~Lock() {} -- -- //! Get block hash. Height must be valid or this function will abort. -- virtual uint256 getBlockHash(int height) = 0; -- -- //! Get block time. Height must be valid or this function will abort. -- virtual int64_t getBlockTime(int height) = 0; -- -- //! Get block median time past. Height must be valid or this function -- //! will abort. -- virtual int64_t getBlockMedianTimePast(int height) = 0; -- -- //! Check that the block is available on disk (i.e. has not been -- //! pruned), and contains transactions. -- virtual bool haveBlockOnDisk(int height) = 0; -- -- //! Return height of the first block in the chain with timestamp equal -- //! or greater than the given time and height equal or greater than the -- //! given height, or nullopt if there is no block with a high enough -- //! timestamp and height. Also return the block hash as an optional output parameter -- //! (to avoid the cost of a second lookup in case this information is needed.) -- virtual Optional findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) = 0; -- -- //! Return height of last block in the specified range which is pruned, or -- //! nullopt if no block in the range is pruned. Range is inclusive. -- virtual Optional findPruned(int start_height = 0, Optional stop_height = nullopt) = 0; -- -- //! Return height of the specified block if it is on the chain, otherwise -- //! return the height of the highest block on chain that's an ancestor -- //! of the specified block, or nullopt if there is no common ancestor. -- //! Also return the height of the specified block as an optional output -- //! parameter (to avoid the cost of a second hash lookup in case this -- //! information is desired). -- virtual Optional findFork(const uint256& hash, Optional* height) = 0; -- -- //! Get locator for the current chain tip. -- virtual CBlockLocator getTipLocator() = 0; -- -- //! Return height of the highest block on chain in common with the locator, -- //! which will either be the original block used to create the locator, -- //! or one of its ancestors. -- virtual Optional findLocatorFork(const CBlockLocator& locator) = 0; -- -- //! Check if transaction will be final given chain height current time. -- virtual bool checkFinalTx(const CTransaction& tx) = 0; -- }; -- -- //! Return Lock interface. Chain is locked when this is called, and -- //! unlocked when the returned interface is freed. -- virtual std::unique_ptr lock(bool try_lock = false) = 0; -- - //! Get current chain height, not including genesis block (returns 0 if - //! chain only contains genesis block, nullopt if chain does not contain - //! any blocks) -@@ -163,17 +120,38 @@ public: - //! Check if transaction will be final given chain height current time. - virtual bool checkFinalTx(const CTransaction& tx) = 0; - -- - //! Return whether node has the block and optionally return block metadata - //! or contents. -- //! -- //! If a block pointer is provided to retrieve the block contents, and the -- //! block exists but doesn't have data (for example due to pruning), the -- //! block will be empty and all fields set to null. -- virtual bool findBlock(const uint256& hash, -- CBlock* block = nullptr, -- int64_t* time = nullptr, -- int64_t* max_time = nullptr) = 0; -+ virtual bool findBlock(const uint256& hash, const FoundBlock& block={}) = 0; -+ -+ //! Find first block in the chain with timestamp >= the given time -+ //! and height >= than the given height, return false if there is no block -+ //! with a high enough timestamp and height. Optionally return block -+ //! information. -+ virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block={}) = 0; -+ -+ //! Find next block if block is part of current chain. Also flag if -+ //! there was a reorg and the specified block hash is no longer in the -+ //! current chain, and optionally return block information. -+ virtual bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next={}, bool* reorg=nullptr) = 0; -+ -+ //! Find ancestor of block at specified height and optionally return -+ //! ancestor information. -+ virtual bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out={}) = 0; -+ -+ //! Return whether block descends from a specified ancestor, and -+ //! optionally return ancestor information. -+ virtual bool findAncestorByHash(const uint256& block_hash, -+ const uint256& ancestor_hash, -+ const FoundBlock& ancestor_out={}) = 0; -+ -+ //! Find most recent common ancestor between two blocks and optionally -+ //! return block information. -+ virtual bool findCommonAncestor(const uint256& block_hash1, -+ const uint256& block_hash2, -+ const FoundBlock& ancestor_out={}, -+ const FoundBlock& block1_out={}, -+ const FoundBlock& block2_out={}) = 0; - - //! Look up unspent output information. Returns coins in the mempool and in - //! the current chain UTXO set. Iterates through all the keys in the map and -@@ -184,6 +162,11 @@ public: - //! the specified block hash are verified. - virtual double guessVerificationProgress(const uint256& block_hash) = 0; - -+ //! Return true if data is available for all blocks in the specified range -+ //! of blocks. This checks all blocks that are ancestors of block_hash in -+ //! the height range from min_height to max_height, inclusive. -+ virtual bool hasBlocks(const uint256& block_hash, int min_height = 0, Optional max_height = {}) = 0; -+ - //! Check if transaction is RBF opt in. - virtual RBFTransactionState isRBFOptIn(const CTransaction& tx) = 0; - -@@ -268,7 +251,7 @@ public: - }; - - //! Register handler for notifications. -- virtual std::unique_ptr handleNotifications(Notifications& notifications) = 0; -+ virtual std::unique_ptr handleNotifications(std::shared_ptr notifications) = 0; - - //! Wait for pending notifications to be processed unless block hash points to the current - //! chain tip. -diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp -index 3649e7e6..b571d463 100644 ---- a/src/merkleblock.cpp -+++ b/src/merkleblock.cpp -@@ -9,6 +9,24 @@ - #include - - -+std::vector BitsToBytes(const std::vector& bits) -+{ -+ std::vector ret((bits.size() + 7) / 8); -+ for (unsigned int p = 0; p < bits.size(); p++) { -+ ret[p / 8] |= bits[p] << (p % 8); -+ } -+ return ret; -+} -+ -+std::vector BytesToBits(const std::vector& bytes) -+{ -+ std::vector ret(bytes.size() * 8); -+ for (unsigned int p = 0; p < ret.size(); p++) { -+ ret[p] = (bytes[p / 8] & (1 << (p % 8))) != 0; -+ } -+ return ret; -+} -+ - CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set* txids) - { - header = block.GetBlockHeader(); -diff --git a/src/merkleblock.h b/src/merkleblock.h -index fe68c8cf..2a8fcc9e 100644 ---- a/src/merkleblock.h -+++ b/src/merkleblock.h -@@ -1,5 +1,5 @@ - // Copyright (c) 2009-2010 Satoshi Nakamoto --// Copyright (c) 2009-2018 The Bitcoin Core developers -+// Copyright (c) 2009-2018 The BGL Core developers - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -@@ -13,6 +13,10 @@ - - #include - -+// Helper functions for serialization. -+std::vector BitsToBytes(const std::vector& bits); -+std::vector BytesToBits(const std::vector& bytes); -+ - /** Data structure that represents a partial merkle tree. - * - * It represents a subset of the txid's of a known block, in a way that -@@ -81,27 +85,14 @@ protected: - - public: - -- /** serialization implementation */ -- ADD_SERIALIZE_METHODS; -- -- template -- inline void SerializationOp(Stream& s, Operation ser_action) { -- READWRITE(nTransactions); -- READWRITE(vHash); -- std::vector vBytes; -- if (ser_action.ForRead()) { -- READWRITE(vBytes); -- CPartialMerkleTree &us = *(const_cast(this)); -- us.vBits.resize(vBytes.size() * 8); -- for (unsigned int p = 0; p < us.vBits.size(); p++) -- us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0; -- us.fBad = false; -- } else { -- vBytes.resize((vBits.size()+7)/8); -- for (unsigned int p = 0; p < vBits.size(); p++) -- vBytes[p / 8] |= vBits[p] << (p % 8); -- READWRITE(vBytes); -- } -+ SERIALIZE_METHODS(CPartialMerkleTree, obj) -+ { -+ READWRITE(obj.nTransactions, obj.vHash); -+ std::vector bytes; -+ SER_WRITE(obj, bytes = BitsToBytes(obj.vBits)); -+ READWRITE(bytes); -+ SER_READ(obj, obj.vBits = BytesToBits(bytes)); -+ SER_READ(obj, obj.fBad = false); - } - - /** Construct a partial merkle tree from a list of transaction ids, and a mask that selects a subset of them */ -@@ -157,13 +148,7 @@ public: - - CMerkleBlock() {} - -- ADD_SERIALIZE_METHODS; -- -- template -- inline void SerializationOp(Stream& s, Operation ser_action) { -- READWRITE(header); -- READWRITE(txn); -- } -+ SERIALIZE_METHODS(CMerkleBlock, obj) { READWRITE(obj.header, obj.txn); } - - private: - // Combined constructor to consolidate code -diff --git a/src/miner.cpp b/src/miner.cpp -index 6e47f89f..858948fc 100644 ---- a/src/miner.cpp -+++ b/src/miner.cpp -@@ -39,6 +39,17 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam - return nNewTime - nOldTime; - } - -+void RegenerateCommitments(CBlock& block) -+{ -+ CMutableTransaction tx{*block.vtx.at(0)}; -+ tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block)); -+ block.vtx.at(0) = MakeTransactionRef(tx); -+ -+ GenerateCoinbaseCommitment(block, WITH_LOCK(cs_main, return LookupBlockIndex(block.hashPrevBlock)), Params().GetConsensus()); -+ -+ block.hashMerkleRoot = BlockMerkleRoot(block); -+} -+ - BlockAssembler::Options::Options() { - blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); - nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT; -diff --git a/src/miner.h b/src/miner.h -index e96b2bc4..fe83aaf2 100644 ---- a/src/miner.h -+++ b/src/miner.h -@@ -201,4 +201,7 @@ private: - void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce); - int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); - -+/** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */ -+void RegenerateCommitments(CBlock& block); -+ - #endif // BGL_MINER_H -diff --git a/src/net.cpp b/src/net.cpp -index 6deb5119..5f16143f 100644 ---- a/src/net.cpp -+++ b/src/net.cpp -@@ -354,6 +354,11 @@ CNode* CConnman::FindNode(const CService& addr) - return nullptr; - } - -+bool CConnman::AlreadyConnectedToAddress(const CAddress& addr) -+{ -+ return FindNode(static_cast(addr)) || FindNode(addr.ToStringIPPort()); -+} -+ - bool CConnman::CheckIncomingNonce(uint64_t nonce) - { - LOCK(cs_vNodes); -@@ -630,22 +635,19 @@ bool CNode::ReceiveMsgBytes(Span msg_bytes, bool& complete) - const auto time = GetTime(); - LOCK(cs_vRecv); - nLastRecv = std::chrono::duration_cast(time).count(); -- nRecvBytes += nBytes; -- while (nBytes > 0) { -+ nRecvBytes += msg_bytes.size(); -+ while (msg_bytes.size() > 0) { - // absorb network data -- int handled = m_deserializer->Read(pch, nBytes); -+ int handled = m_deserializer->Read(msg_bytes); - if (handled < 0) { - // Serious header problem, disconnect from the peer. - return false; - } - -- pch += handled; -- nBytes -= handled; -- - if (m_deserializer->Complete()) { - // decompose a transport agnostic CNetMessage from the deserializer - uint32_t out_err_raw_size{0}; -- Optional result{m_deserializer->GetMessage(Params().MessageStart(), time, out_err_raw_size)}; -+ Optional result{m_deserializer->GetMessage(time, out_err_raw_size)}; - if (!result) { - // Message deserialization failed. Drop the message but don't disconnect the peer. - // store the size of the corrupt message -@@ -675,9 +677,9 @@ int V1TransportDeserializer::readHeader(Span msg_bytes) - { - // copy data to temporary parsing buffer - unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos; -- unsigned int nCopy = std::min(nRemaining, nBytes); -+ unsigned int nCopy = std::min(nRemaining, msg_bytes.size()); - -- memcpy(&hdrbuf[nHdrPos], pch, nCopy); -+ memcpy(&hdrbuf[nHdrPos], msg_bytes.data(), nCopy); - nHdrPos += nCopy; - - // if header incomplete, exit -@@ -714,7 +716,7 @@ int V1TransportDeserializer::readHeader(Span msg_bytes) - int V1TransportDeserializer::readData(Span msg_bytes) - { - unsigned int nRemaining = hdr.nMessageSize - nDataPos; -- unsigned int nCopy = std::min(nRemaining, nBytes); -+ unsigned int nCopy = std::min(nRemaining, msg_bytes.size()); - - if (vRecv.size() < nDataPos + nCopy) { - // Allocate up to 256 KiB ahead, but never more than the total message size. -@@ -736,7 +738,7 @@ const uint256& V1TransportDeserializer::GetMessageHash() const - return data_hash; - } - --Optional V1TransportDeserializer::GetMessage(const CMessageHeader::MessageStartChars& message_start, const std::chrono::microseconds time, uint32_t& out_err_raw_size) -+Optional V1TransportDeserializer::GetMessage(const std::chrono::microseconds time, uint32_t& out_err_raw_size) - { - // decompose a single CNetMessage from the TransportDeserializer - Optional msg(std::move(vRecv)); -@@ -1084,7 +1086,6 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { - // on all platforms. Set it again here just to be sure. - SetSocketNoDelay(hSocket); - -- - // Don't accept connections from banned peers. - bool banned = m_banman && m_banman->IsBanned(addr); - if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::PF_NOBAN) && banned) -@@ -1474,7 +1475,10 @@ void CConnman::SocketHandler() - { - bool notify = false; - if (!pnode->ReceiveMsgBytes(Span(pchBuf, nBytes), notify)) -+ pnode->CloseSocketDisconnect(); -+ RecordBytesRecv(nBytes); - if (notify) { -+ size_t nSizeAdded = 0; - auto it(pnode->vRecvMsg.begin()); - for (; it != pnode->vRecvMsg.end(); ++it) { - // vRecvMsg contains only completed CNetMessage -@@ -1591,7 +1595,7 @@ static void ThreadMapPort() - if (externalIPAddress[0]) { - CNetAddr resolved; - if (LookupHost(externalIPAddress, resolved, false)) { -- LogPrintf("UPnP : ExternalIPAddress = %s\n", resolved.ToString()); -+ LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString()); - AddLocal(resolved, LOCAL_UPNP); - } - } else { -@@ -1718,7 +1722,7 @@ void CConnman::ThreadDNSAddressSeed() - { - LOCK(cs_vNodes); - for (const CNode* pnode : vNodes) { -- nRelevant += pnode->fSuccessfullyConnected && !pnode->IsFeelerConn() && !pnode->IsAddrFetchConn() && !pnode->IsManualConn() && !pnode->fInbound; -+ if (pnode->fSuccessfullyConnected && pnode->IsOutboundOrBlockRelayConn()) ++nRelevant; - } - } - if (nRelevant >= 2) { -@@ -1732,7 +1736,6 @@ void CConnman::ThreadDNSAddressSeed() - } - } - } -- seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE; - } - - if (interruptNet) return; -@@ -1744,6 +1747,7 @@ void CConnman::ThreadDNSAddressSeed() - if (!interruptNet.sleep_for(std::chrono::seconds{1})) return; - } while (!fNetworkActive); - } -+ - LogPrintf("Loading addresses from DNS seed %s\n", seed); - if (HaveNameProxy()) { - AddAddrFetch(seed); -@@ -1851,6 +1855,7 @@ void CConnman::ThreadOpenConnections(const std::vector connect) - for (int i = 0; i < 10 && i < nLoop; i++) - { - if (!interruptNet.sleep_for(std::chrono::milliseconds(500))) -+ return; - } - } - if (!interruptNet.sleep_for(std::chrono::milliseconds(500))) -@@ -1962,6 +1967,17 @@ void CConnman::ThreadOpenConnections(const std::vector connect) - int nTries = 0; - while (!interruptNet) - { -+ if (anchor && !m_anchors.empty()) { -+ const CAddress addr = m_anchors.back(); -+ m_anchors.pop_back(); -+ if (!addr.IsValid() || IsLocal(addr) || !IsReachable(addr) || -+ !HasAllDesirableServiceFlags(addr.nServices) || -+ setConnected.count(addr.GetGroup(addrman.m_asmap))) continue; -+ addrConnect = addr; -+ LogPrint(BCLog::NET, "Trying to make an anchor connection to %s\n", addrConnect.ToString()); -+ break; -+ } -+ - // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman, - // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates - // already-connected network ranges, ...) before trying new addrman addresses. -@@ -1969,11 +1985,30 @@ void CConnman::ThreadOpenConnections(const std::vector connect) - if (nTries > 100) - break; - -- CAddrInfo addr = addrman.SelectTriedCollision(); -+ CAddrInfo addr; - -- // SelectTriedCollision returns an invalid address if it is empty. -- if (!fFeeler || !addr.IsValid()) { -- addr = addrman.Select(fFeeler); -+ if (fFeeler) { -+ // First, try to get a tried table collision address. This returns -+ // an empty (invalid) address if there are no collisions to try. -+ addr = addrman.SelectTriedCollision(); -+ -+ if (!addr.IsValid()) { -+ // No tried table collisions. Select a new table address -+ // for our feeler. -+ addr = addrman.Select(true); -+ } else if (AlreadyConnectedToAddress(addr)) { -+ // If test-before-evict logic would have us connect to a -+ // peer that we're already connected to, just mark that -+ // address as Good(). We won't be able to initiate the -+ // connection anyway, so this avoids inadvertently evicting -+ // a currently-connected peer. -+ addrman.Good(addr); -+ // Select a new table address for our feeler instead. -+ addr = addrman.Select(true); -+ } -+ } else { -+ // Not a feeler -+ addr = addrman.Select(); - } - - // Require outbound connections, other than feelers, to be to distinct network groups -@@ -2135,7 +2170,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai - } - if (!pszDest) { - bool banned_or_discouraged = m_banman && (m_banman->IsDiscouraged(addrConnect) || m_banman->IsBanned(addrConnect)); -- if (IsLocal(addrConnect) || FindNode(static_cast(addrConnect)) || banned_or_discouraged || FindNode(addrConnect.ToStringIPPort())) { -+ if (IsLocal(addrConnect) || banned_or_discouraged || AlreadyConnectedToAddress(addrConnect)) { - return; - } - } else if (FindNode(std::string(pszDest))) -@@ -2531,7 +2566,7 @@ void CConnman::Interrupt() - } - } - --void CConnman::Stop() -+void CConnman::StopThreads() - { - if (threadMessageHandler.joinable()) - threadMessageHandler.join(); -@@ -2543,9 +2578,11 @@ void CConnman::Stop() - threadDNSAddressSeed.join(); - if (threadSocketHandler.joinable()) - threadSocketHandler.join(); -+} - -- if (fAddressesInitialized) -- { -+void CConnman::StopNodes() -+{ -+ if (fAddressesInitialized) { - DumpAddresses(); - fAddressesInitialized = false; - -@@ -2560,6 +2597,7 @@ void CConnman::Stop() - } - - // Close sockets -+ LOCK(cs_vNodes); - for (CNode* pnode : vNodes) - pnode->CloseSocketDisconnect(); - for (ListenSocket& hListenSocket : vhListenSocket) -@@ -2568,10 +2606,10 @@ void CConnman::Stop() - LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError())); - - // clean up some globals (to help leak detection) -- for (CNode *pnode : vNodes) { -+ for (CNode* pnode : vNodes) { - DeleteNode(pnode); - } -- for (CNode *pnode : vNodesDisconnected) { -+ for (CNode* pnode : vNodesDisconnected) { - DeleteNode(pnode); - } - vNodes.clear(); -@@ -2585,8 +2623,8 @@ void CConnman::DeleteNode(CNode* pnode) - { - assert(pnode); - bool fUpdateConnectionTime = false; -- m_msgproc->FinalizeNode(pnode->GetId(), fUpdateConnectionTime); -- if(fUpdateConnectionTime) { -+ m_msgproc->FinalizeNode(*pnode, fUpdateConnectionTime); -+ if (fUpdateConnectionTime) { - addrman.Connected(pnode->addr); - } - delete pnode; -@@ -2895,6 +2933,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn - m_conn_type(conn_type_in), - nLocalServices(nLocalServicesIn), - nMyStartingHeight(nMyStartingHeightIn), -+ m_inbound_onion(inbound_onion) - { - hSocket = hSocketIn; - addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn; -diff --git a/src/net.h b/src/net.h -index 792412a6..e0335a52 100644 ---- a/src/net.h -+++ b/src/net.h -@@ -154,7 +154,7 @@ enum class ConnectionType { - * evict only if this longer-known peer is offline. - * - move node addresses from New to Tried table, so that we have more - * connectable addresses in our AddrMan. -- * Note that in the literature ("Eclipse Attacks on Bitcoin’s Peer-to-Peer Network") -+ * Note that in the literature ("Eclipse Attacks on BGL’s Peer-to-Peer Network") - * only the latter feature is referred to as "feeler connections", - * although in our codebase feeler connections encompass test-before-evict as well. - * We make these connections approximately every FEELER_INTERVAL: -@@ -256,16 +256,13 @@ public: - ~CConnman(); - bool Start(CScheduler& scheduler, const Options& options); - -- // TODO: Remove NO_THREAD_SAFETY_ANALYSIS. Lock cs_vNodes before reading the variable vNodes. -- // -- // When removing NO_THREAD_SAFETY_ANALYSIS be aware of the following lock order requirements: -- // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount -- // which locks cs_vNodes. -- // * ProcessMessage locks cs_main and g_cs_orphans before indirectly calling ForEachNode which -- // locks cs_vNodes. -- // -- // Thus the implicit locking order requirement is: (1) cs_main, (2) g_cs_orphans, (3) cs_vNodes. -- void Stop() NO_THREAD_SAFETY_ANALYSIS; -+ void StopThreads(); -+ void StopNodes(); -+ void Stop() -+ { -+ StopThreads(); -+ StopNodes(); -+ }; - - void Interrupt(); - bool GetNetworkActive() const { return fNetworkActive; }; -@@ -445,6 +442,12 @@ private: - CNode* FindNode(const std::string& addrName); - CNode* FindNode(const CService& addr); - -+ /** -+ * Determine whether we're already connected to a given address, in order to -+ * avoid initiating duplicate connections. -+ */ -+ bool AlreadyConnectedToAddress(const CAddress& addr); -+ - bool AttemptToEvictConnection(); - CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type); - void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const; -@@ -621,7 +624,7 @@ public: - virtual bool ProcessMessages(CNode* pnode, std::atomic& interrupt) = 0; - virtual bool SendMessages(CNode* pnode) = 0; - virtual void InitializeNode(CNode* pnode) = 0; -- virtual void FinalizeNode(NodeId id, bool& update_connection_time) = 0; -+ virtual void FinalizeNode(const CNode& node, bool& update_connection_time) = 0; - - protected: - /** -@@ -757,7 +760,7 @@ public: - /** read and deserialize data, advances msg_bytes data pointer */ - virtual int Read(Span& msg_bytes) = 0; - // decomposes a message from the context -- virtual Optional GetMessage(const CMessageHeader::MessageStartChars& message_start, std::chrono::microseconds time, uint32_t& out_err) = 0; -+ virtual Optional GetMessage(std::chrono::microseconds time, uint32_t& out_err) = 0; - virtual ~TransportDeserializer() {} - }; - -@@ -791,8 +794,9 @@ private: - } - - public: -- V1TransportDeserializer(const NodeId node_id, int nTypeIn, int nVersionIn) -- : m_node_id(node_id), -+ V1TransportDeserializer(const CChainParams& chain_params, const NodeId node_id, int nTypeIn, int nVersionIn) -+ : m_chain_params(chain_params), -+ m_node_id(node_id), - hdrbuf(nTypeIn, nVersionIn), - vRecv(nTypeIn, nVersionIn) - { -@@ -820,12 +824,16 @@ public: - } - return ret; - } -- Optional GetMessage(const CMessageHeader::MessageStartChars& message_start, std::chrono::microseconds time, uint32_t& out_err_raw_size) override; -+ Optional GetMessage(std::chrono::microseconds time, uint32_t& out_err_raw_size) override; - }; - - /** The TransportSerializer prepares messages for the network transport - */ -+class TransportSerializer { -+public: -+ // prepare message for transport (header construction, error-correction computation, payload encryption, etc.) - virtual void prepareForTransport(CSerializedNetMsg& msg, std::vector& header) = 0; -+ virtual ~TransportSerializer() {} - }; - - class V1TransportSerializer : public TransportSerializer { -@@ -841,7 +849,7 @@ class CNode - - public: - std::unique_ptr m_deserializer; -- std::unique_ptr m_serializer; -+ std::unique_ptr m_serializer; - - // socket - std::atomic nServices{NODE_NONE}; -@@ -986,8 +994,8 @@ public: - std::vector vAddrToSend; - std::unique_ptr m_addr_known{nullptr}; - bool fGetAddr{false}; -- int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0}; -- int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0}; -+ std::chrono::microseconds m_next_addr_send GUARDED_BY(cs_sendProcessing){0}; -+ std::chrono::microseconds m_next_local_addr_send GUARDED_BY(cs_sendProcessing){0}; - - // List of block ids we still have announce. - // There is no final sorting before sending, as they are always sent immediately -diff --git a/src/net_processing.cpp b/src/net_processing.cpp -index 3c09e2de..03da79ff 100644 ---- a/src/net_processing.cpp -+++ b/src/net_processing.cpp -@@ -451,7 +451,7 @@ struct Peer { - /** Work queue of items requested by this peer **/ - std::deque m_getdata_requests GUARDED_BY(m_getdata_requests_mutex); - -- explicit Peer(NodeId id) : m_id(id) {} -+ Peer(NodeId id) : m_id(id) {} - }; - - using PeerRef = std::shared_ptr; -@@ -479,7 +479,8 @@ static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUS - nPreferredDownload -= state->fPreferredDownload; - - // Whether this node should be marked as a preferred download node. -- state->fPreferredDownload = (!node.fInbound || node.HasPermission(PF_NOBAN)) && !node.IsAddrFetchConn() && !node.fClient; -+ state->fPreferredDownload = (!node.IsInboundConn() || node.HasPermission(PF_NOBAN)) && !node.IsAddrFetchConn() && !node.fClient; -+ - nPreferredDownload += state->fPreferredDownload; - } - -@@ -494,7 +495,9 @@ static void PushNodeVersion(CNode& pnode, CConnman& connman, int64_t nTime) - NodeId nodeid = pnode.GetId(); - CAddress addr = pnode.addr; - -- CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices)); -+ CAddress addrYou = addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible() ? -+ addr : -+ CAddress(CService(), addr.nServices); - CAddress addrMe = CAddress(CService(), nLocalNodeServices); - - connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe, -@@ -765,7 +768,11 @@ void PeerManager::AddTxAnnouncement(const CNode& node, const GenTxid& gtxid, std - // Too many queued announcements from this peer - return; - } -+ const CNodeState* state = State(nodeid); -+ -+ // Decide the TxRequestTracker parameters for this announcement: - // - "preferred": if fPreferredDownload is set (= outbound, or PF_NOBAN permission) -+ // - "reqtime": current time plus delays for: - // - NONPREF_PEER_TX_DELAY for announcements from non-preferred connections - // - TXID_RELAY_DELAY for txid announcements while wtxid peers are available - // - OVERLOADED_PEER_TX_DELAY for announcements from peers which have at least -@@ -773,7 +780,7 @@ void PeerManager::AddTxAnnouncement(const CNode& node, const GenTxid& gtxid, std - auto delay = std::chrono::microseconds{0}; - const bool preferred = state->fPreferredDownload; - if (!preferred) delay += NONPREF_PEER_TX_DELAY; -- if (!state->m_wtxid_relay && g_wtxid_relay_peers > 0) delay += TXID_RELAY_DELAY; -+ if (!gtxid.IsWtxid() && g_wtxid_relay_peers > 0) delay += TXID_RELAY_DELAY; - const bool overloaded = !node.HasPermission(PF_RELAY) && - m_txrequest.CountInFlight(nodeid) >= MAX_PEER_TX_REQUEST_IN_FLIGHT; - if (overloaded) delay += OVERLOADED_PEER_TX_DELAY; -@@ -829,7 +836,8 @@ void PeerManager::ReattemptInitialBroadcast(CScheduler& scheduler) const - scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta); - } - --void PeerManager::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) { -+void PeerManager::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) { -+ NodeId nodeid = node.GetId(); - fUpdateConnectionTime = false; - LOCK(cs_main); - int misbehavior{0}; -@@ -2018,6 +2026,7 @@ void PeerManager::ProcessOrphanTx(std::set& orphan_work_set) - // https://github.com/BGL/BGL/issues/8279 for details. - // We can remove this restriction (and always add wtxids to - // the filter even for witness stripped transactions) once -+ // wtxid-based relay is broadly deployed. - // See also comments in https://github.com/BGL/BGL/pull/18044#discussion_r443419034 - // for concerns around weakening security of unupgraded nodes - // if we start doing this too early. -@@ -2299,7 +2308,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat - { - m_connman.SetServices(pfrom.addr, nServices); - } -- if (!pfrom.IsInboundConn() && !pfrom.IsFeelerConn() && !pfrom.IsManualConn() && !HasAllDesirableServiceFlags(nServices)) -+ if (pfrom.ExpectServicesFromConn() && !HasAllDesirableServiceFlags(nServices)) - { - LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom.GetId(), nServices, GetDesirableServiceFlags(nServices)); - pfrom.fDisconnect = true; -@@ -2398,14 +2407,8 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat - // empty and no one will know who we are, so these mechanisms are - // important to help us connect to the network. - // -- // We also update the addrman to record connection success for -- // these peers (which include OUTBOUND_FULL_RELAY and FEELER -- // connections) so that addrman will have an up-to-date notion of -- // which peers are online and available. -- // -- // We skip these operations for BLOCK_RELAY peers to avoid -- // potentially leaking information about our BLOCK_RELAY -- // connections via the addrman or address relay. -+ // We skip this for BLOCK_RELAY peers to avoid potentially leaking -+ // information about our BLOCK_RELAY connections via address relay. - if (fListen && !::ChainstateActive().IsInitialBlockDownload()) - { - CAddress addr = GetLocalAddress(&pfrom.addr, pfrom.GetLocalServices()); -@@ -2424,9 +2427,23 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat - // Get recent addresses - m_connman.PushMessage(&pfrom, CNetMsgMaker(greatest_common_version).Make(NetMsgType::GETADDR)); - pfrom.fGetAddr = true; -+ } - -- // Moves address from New to Tried table in Addrman, resolves -- // tried-table collisions, etc. -+ if (!pfrom.IsInboundConn()) { -+ // For non-inbound connections, we update the addrman to record -+ // connection success so that addrman will have an up-to-date -+ // notion of which peers are online and available. -+ // -+ // While we strive to not leak information about block-relay-only -+ // connections via the addrman, not moving an address to the tried -+ // table is also potentially detrimental because new-table entries -+ // are subject to eviction in the event of addrman collisions. We -+ // mitigate the information-leak by never calling -+ // CAddrMan::Connected() on block-relay-only peers; see -+ // FinalizeNode(). -+ // -+ // This moves an address from New to Tried table in Addrman, -+ // resolves tried-table collisions, etc. - m_connman.MarkAddressGood(pfrom.addr); - } - -@@ -3059,6 +3076,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat - } - } else { - if (state.GetResult() != TxValidationResult::TX_WITNESS_STRIPPED) { -+ // We can add the wtxid of this transaction to our reject filter. - // Do not add txids of witness transactions or witness-stripped - // transactions to the filter, as they can have been malleated; - // adding such txids to the reject filter would potentially -@@ -3796,6 +3814,7 @@ bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic& interruptMsgP - } - - if (pfrom->fDisconnect) -+ return false; - - // this maintains the order of responses - // and prevents m_getdata_requests to grow unbounded -@@ -4056,7 +4075,7 @@ bool PeerManager::SendMessages(CNode* pto) - - if (pto->RelayAddrsWithConn() && !::ChainstateActive().IsInitialBlockDownload() && pto->m_next_local_addr_send < current_time) { - AdvertiseLocal(pto); -- pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL); -+ pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL); - } - - // -diff --git a/src/net_processing.h b/src/net_processing.h -index 3224c248..a3b3973e 100644 ---- a/src/net_processing.h -+++ b/src/net_processing.h -@@ -12,6 +12,8 @@ - #include - #include - -+class BlockTransactionsRequest; -+class BlockValidationState; - class CBlockHeader; - class CChainParams; - class CTxMemPool; -@@ -19,6 +21,7 @@ class ChainstateManager; - class TxValidationState; - - extern RecursiveMutex cs_main; -+extern RecursiveMutex g_cs_orphans; - - /** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ - static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; -@@ -55,7 +58,7 @@ public: - /** Initialize a peer by adding it to mapNodeState and pushing a message requesting its version */ - void InitializeNode(CNode* pnode) override; - /** Handle removal of a peer by updating various state and removing it from mapNodeState */ -- void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) override; -+ void FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) override; - /** - * Process protocol messages received from a given node - * -@@ -105,6 +108,13 @@ private: - bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, - bool via_compact_block, const std::string& message = ""); - -+ /** -+ * Potentially disconnect and discourage a node based on the contents of a TxValidationState object -+ * -+ * @return Returns true if the peer was punished (probably disconnected) -+ */ -+ bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = ""); -+ - /** Maybe disconnect a peer and discourage future connections from its address. - * - * @param[in] pnode The node to check. -diff --git a/src/netaddress.cpp b/src/netaddress.cpp -index 51cf8d0e..35e9161f 100644 ---- a/src/netaddress.cpp -+++ b/src/netaddress.cpp -@@ -21,8 +21,6 @@ - #include - #include - --// 0xFD + sha256("BGL")[0:5] --static const unsigned char g_internal_prefix[] = { 0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 }; - constexpr size_t CNetAddr::V1_SERIALIZATION_SIZE; - constexpr size_t CNetAddr::MAX_ADDRV2_SIZE; - -@@ -179,15 +177,6 @@ void CNetAddr::SetLegacyIPv6(Span ipv6) - } - - /** -- * Try to make this a dummy address that maps the specified name into IPv6 like -- * so: (0xFD + %sha256("BGL")[0:5]) + %sha256(name)[0:10]. Such dummy -- * addresses have a prefix of fd6b:88c0:8724::/48 and are guaranteed to not be -- * publicly routable as it falls under RFC4193's fc00::/7 subnet allocated to -- * unique-local addresses. -- * -- * CAddrMan uses these fake addresses to keep track of which DNS seeds were -- * used. -- * - * Create an "internal" address that represents a name or FQDN. CAddrMan uses - * these fake addresses to keep track of which DNS seeds were used. - * @returns Whether or not the operation was successful. -@@ -1041,13 +1030,16 @@ static inline int NetmaskBits(uint8_t x) - } - } - --CSubNet::CSubNet(const CNetAddr &addr, const CNetAddr &mask) -+CSubNet::CSubNet(const CNetAddr& addr, const CNetAddr& mask) : CSubNet() - { -- valid = true; -+ valid = (addr.IsIPv4() || addr.IsIPv6()) && addr.m_net == mask.m_net; -+ if (!valid) { -+ return; -+ } - // Check if `mask` contains 1-bits after 0-bits (which is an invalid netmask). - bool zeros_found = false; -- for (size_t i = mask.IsIPv4() ? 12 : 0; i < sizeof(mask.ip); ++i) { -- const int num_bits = NetmaskBits(mask.ip[i]); -+ for (auto b : mask.m_addr) { -+ const int num_bits = NetmaskBits(b); - if (num_bits == -1 || (zeros_found && num_bits != 0)) { - valid = false; - return; -@@ -1058,6 +1050,7 @@ CSubNet::CSubNet(const CNetAddr &addr, const CNetAddr &mask) - } - - assert(mask.m_addr.size() <= sizeof(netmask)); -+ - memcpy(netmask, mask.m_addr.data(), mask.m_addr.size()); - - network = addr; -@@ -1101,9 +1094,11 @@ bool CSubNet::Match(const CNetAddr &addr) const - - std::string CSubNet::ToString() const - { -+ assert(network.m_addr.size() <= sizeof(netmask)); -+ - uint8_t cidr = 0; - -- for (size_t i = network.IsIPv4() ? 12 : 0; i < sizeof(netmask); ++i) { -+ for (size_t i = 0; i < network.m_addr.size(); ++i) { - if (netmask[i] == 0x00) { - break; - } -diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp -deleted file mode 100644 -index 7778012c..00000000 ---- a/src/node/interfaces.cpp -+++ /dev/null -@@ -1,693 +0,0 @@ --// Copyright (c) 2018-2020 The BGL 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 --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#if defined(HAVE_CONFIG_H) --#include --#endif -- --#include --#include -- --using interfaces::BlockTip; --using interfaces::Chain; --using interfaces::FoundBlock; --using interfaces::Handler; --using interfaces::MakeHandler; --using interfaces::Node; --using interfaces::WalletClient; -- --namespace node { --namespace { --class NodeImpl : public Node --{ --public: -- explicit NodeImpl(NodeContext* context) { setContext(context); } -- void initLogging() override { InitLogging(*Assert(m_context->args)); } -- void initParameterInteraction() override { InitParameterInteraction(*Assert(m_context->args)); } -- bilingual_str getWarnings() override { return GetWarnings(true); } -- uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); } -- bool baseInitialize() override -- { -- return AppInitBasicSetup(gArgs) && AppInitParameterInteraction(gArgs) && AppInitSanityChecks() && -- AppInitLockDataDirectory() && AppInitInterfaces(*m_context); -- } -- bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override -- { -- return AppInitMain(m_context_ref, *m_context, tip_info); -- } -- void appShutdown() override -- { -- Interrupt(*m_context); -- Shutdown(*m_context); -- } -- void startShutdown() override -- { -- StartShutdown(); -- // Stop RPC for clean shutdown if any of waitfor* commands is executed. -- if (gArgs.GetBoolArg("-server", false)) { -- InterruptRPC(); -- StopRPC(); -- } -- } -- bool shutdownRequested() override { return ShutdownRequested(); } -- void mapPort(bool use_upnp) override -- { -- if (use_upnp) { -- StartMapPort(); -- } else { -- InterruptMapPort(); -- StopMapPort(); -- } -- } -- bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); } -- size_t getNodeCount(CConnman::NumConnections flags) override -- { -- return m_context->connman ? m_context->connman->GetNodeCount(flags) : 0; -- } -- bool getNodesStats(NodesStats& stats) override -- { -- stats.clear(); -- -- if (m_context->connman) { -- std::vector stats_temp; -- m_context->connman->GetNodeStats(stats_temp); -- -- stats.reserve(stats_temp.size()); -- for (auto& node_stats_temp : stats_temp) { -- stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats()); -- } -- -- // Try to retrieve the CNodeStateStats for each node. -- TRY_LOCK(::cs_main, lockMain); -- if (lockMain) { -- for (auto& node_stats : stats) { -- std::get<1>(node_stats) = -- GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats)); -- } -- } -- return true; -- } -- return false; -- } -- bool getBanned(banmap_t& banmap) override -- { -- if (m_context->banman) { -- m_context->banman->GetBanned(banmap); -- return true; -- } -- return false; -- } -- bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override -- { -- if (m_context->banman) { -- m_context->banman->Ban(net_addr, ban_time_offset); -- return true; -- } -- return false; -- } -- bool unban(const CSubNet& ip) override -- { -- if (m_context->banman) { -- m_context->banman->Unban(ip); -- return true; -- } -- return false; -- } -- bool disconnectByAddress(const CNetAddr& net_addr) override -- { -- if (m_context->connman) { -- return m_context->connman->DisconnectNode(net_addr); -- } -- return false; -- } -- bool disconnectById(NodeId id) override -- { -- if (m_context->connman) { -- return m_context->connman->DisconnectNode(id); -- } -- return false; -- } -- int64_t getTotalBytesRecv() override { return m_context->connman ? m_context->connman->GetTotalBytesRecv() : 0; } -- int64_t getTotalBytesSent() override { return m_context->connman ? m_context->connman->GetTotalBytesSent() : 0; } -- size_t getMempoolSize() override { return m_context->mempool ? m_context->mempool->size() : 0; } -- size_t getMempoolDynamicUsage() override { return m_context->mempool ? m_context->mempool->DynamicMemoryUsage() : 0; } -- bool getHeaderTip(int& height, int64_t& block_time) override -- { -- LOCK(::cs_main); -- if (::pindexBestHeader) { -- height = ::pindexBestHeader->nHeight; -- block_time = ::pindexBestHeader->GetBlockTime(); -- return true; -- } -- return false; -- } -- int getNumBlocks() override -- { -- LOCK(::cs_main); -- return ::ChainActive().Height(); -- } -- uint256 getBestBlockHash() override -- { -- const CBlockIndex* tip = WITH_LOCK(::cs_main, return ::ChainActive().Tip()); -- return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash(); -- } -- int64_t getLastBlockTime() override -- { -- LOCK(::cs_main); -- if (::ChainActive().Tip()) { -- return ::ChainActive().Tip()->GetBlockTime(); -- } -- return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network -- } -- double getVerificationProgress() override -- { -- const CBlockIndex* tip; -- { -- LOCK(::cs_main); -- tip = ::ChainActive().Tip(); -- } -- return GuessVerificationProgress(Params().TxData(), tip); -- } -- bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); } -- bool getReindex() override { return ::fReindex; } -- bool getImporting() override { return ::fImporting; } -- void setNetworkActive(bool active) override -- { -- if (m_context->connman) { -- m_context->connman->SetNetworkActive(active); -- } -- } -- bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); } -- CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override -- { -- FeeCalculation fee_calc; -- CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative); -- if (returned_target) { -- *returned_target = fee_calc.returnedTarget; -- } -- return result; -- } -- CFeeRate getDustRelayFee() override { return ::dustRelayFee; } -- UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override -- { -- JSONRPCRequest req(m_context_ref); -- req.params = params; -- req.strMethod = command; -- req.URI = uri; -- return ::tableRPC.execute(req); -- } -- std::vector listRpcCommands() override { return ::tableRPC.listCommands(); } -- void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); } -- void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); } -- bool getUnspentOutput(const COutPoint& output, Coin& coin) override -- { -- LOCK(::cs_main); -- return ::ChainstateActive().CoinsTip().GetCoin(output, coin); -- } -- WalletClient& walletClient() override -- { -- return *Assert(m_context->wallet_client); -- } -- std::unique_ptr handleInitMessage(InitMessageFn fn) override -- { -- return MakeHandler(::uiInterface.InitMessage_connect(fn)); -- } -- std::unique_ptr handleMessageBox(MessageBoxFn fn) override -- { -- return MakeHandler(::uiInterface.ThreadSafeMessageBox_connect(fn)); -- } -- std::unique_ptr handleQuestion(QuestionFn fn) override -- { -- return MakeHandler(::uiInterface.ThreadSafeQuestion_connect(fn)); -- } -- std::unique_ptr handleShowProgress(ShowProgressFn fn) override -- { -- return MakeHandler(::uiInterface.ShowProgress_connect(fn)); -- } -- std::unique_ptr handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override -- { -- return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn)); -- } -- std::unique_ptr handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override -- { -- return MakeHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn)); -- } -- std::unique_ptr handleNotifyAlertChanged(NotifyAlertChangedFn fn) override -- { -- return MakeHandler(::uiInterface.NotifyAlertChanged_connect(fn)); -- } -- std::unique_ptr handleBannedListChanged(BannedListChangedFn fn) override -- { -- return MakeHandler(::uiInterface.BannedListChanged_connect(fn)); -- } -- std::unique_ptr handleNotifyBlockTip(NotifyBlockTipFn fn) override -- { -- return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) { -- fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()}, -- GuessVerificationProgress(Params().TxData(), block)); -- })); -- } -- std::unique_ptr handleNotifyHeaderTip(NotifyHeaderTipFn fn) override -- { -- return MakeHandler( -- ::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) { -- fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()}, -- /* verification progress is unused when a header was received */ 0); -- })); -- } -- NodeContext* context() override { return m_context; } -- void setContext(NodeContext* context) override -- { -- m_context = context; -- if (context) { -- m_context_ref.Set(*context); -- } else { -- m_context_ref.Clear(); -- } -- } -- NodeContext* m_context{nullptr}; -- util::Ref m_context_ref; --}; -- --bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock& lock) --{ -- if (!index) return false; -- if (block.m_hash) *block.m_hash = index->GetBlockHash(); -- if (block.m_height) *block.m_height = index->nHeight; -- if (block.m_time) *block.m_time = index->GetBlockTime(); -- if (block.m_max_time) *block.m_max_time = index->GetBlockTimeMax(); -- if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast(); -- if (block.m_data) { -- REVERSE_LOCK(lock); -- if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull(); -- } -- return true; --} -- --class NotificationsProxy : public CValidationInterface --{ --public: -- explicit NotificationsProxy(std::shared_ptr notifications) -- : m_notifications(std::move(notifications)) {} -- virtual ~NotificationsProxy() = default; -- void TransactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override -- { -- m_notifications->transactionAddedToMempool(tx, mempool_sequence); -- } -- void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override -- { -- m_notifications->transactionRemovedFromMempool(tx, reason, mempool_sequence); -- } -- void BlockConnected(const std::shared_ptr& block, const CBlockIndex* index) override -- { -- m_notifications->blockConnected(*block, index->nHeight); -- } -- void BlockDisconnected(const std::shared_ptr& block, const CBlockIndex* index) override -- { -- m_notifications->blockDisconnected(*block, index->nHeight); -- } -- void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override -- { -- m_notifications->updatedBlockTip(); -- } -- void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->chainStateFlushed(locator); } -- std::shared_ptr m_notifications; --}; -- --class NotificationsHandlerImpl : public Handler --{ --public: -- explicit NotificationsHandlerImpl(std::shared_ptr notifications) -- : m_proxy(std::make_shared(std::move(notifications))) -- { -- RegisterSharedValidationInterface(m_proxy); -- } -- ~NotificationsHandlerImpl() override { disconnect(); } -- void disconnect() override -- { -- if (m_proxy) { -- UnregisterSharedValidationInterface(m_proxy); -- m_proxy.reset(); -- } -- } -- std::shared_ptr m_proxy; --}; -- --class RpcHandlerImpl : public Handler --{ --public: -- explicit RpcHandlerImpl(const CRPCCommand& command) : m_command(command), m_wrapped_command(&command) -- { -- m_command.actor = [this](const JSONRPCRequest& request, UniValue& result, bool last_handler) { -- if (!m_wrapped_command) return false; -- try { -- return m_wrapped_command->actor(request, result, last_handler); -- } catch (const UniValue& e) { -- // If this is not the last handler and a wallet not found -- // exception was thrown, return false so the next handler can -- // try to handle the request. Otherwise, reraise the exception. -- if (!last_handler) { -- const UniValue& code = e["code"]; -- if (code.isNum() && code.get_int() == RPC_WALLET_NOT_FOUND) { -- return false; -- } -- } -- throw; -- } -- }; -- ::tableRPC.appendCommand(m_command.name, &m_command); -- } -- -- void disconnect() final -- { -- if (m_wrapped_command) { -- m_wrapped_command = nullptr; -- ::tableRPC.removeCommand(m_command.name, &m_command); -- } -- } -- -- ~RpcHandlerImpl() override { disconnect(); } -- -- CRPCCommand m_command; -- const CRPCCommand* m_wrapped_command; --}; -- --class ChainImpl : public Chain --{ --public: -- explicit ChainImpl(NodeContext& node) : m_node(node) {} -- Optional getHeight() override -- { -- LOCK(::cs_main); -- int height = ::ChainActive().Height(); -- if (height >= 0) { -- return height; -- } -- return nullopt; -- } -- Optional getBlockHeight(const uint256& hash) override -- { -- LOCK(::cs_main); -- CBlockIndex* block = LookupBlockIndex(hash); -- if (block && ::ChainActive().Contains(block)) { -- return block->nHeight; -- } -- return nullopt; -- } -- uint256 getBlockHash(int height) override -- { -- LOCK(::cs_main); -- CBlockIndex* block = ::ChainActive()[height]; -- assert(block); -- return block->GetBlockHash(); -- } -- bool haveBlockOnDisk(int height) override -- { -- LOCK(cs_main); -- CBlockIndex* block = ::ChainActive()[height]; -- return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0; -- } -- Optional findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override -- { -- LOCK(cs_main); -- CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height); -- if (block) { -- if (hash) *hash = block->GetBlockHash(); -- return block->nHeight; -- } -- return nullopt; -- } -- CBlockLocator getTipLocator() override -- { -- LOCK(cs_main); -- return ::ChainActive().GetLocator(); -- } -- bool checkFinalTx(const CTransaction& tx) override -- { -- LOCK(cs_main); -- return CheckFinalTx(tx); -- } -- Optional findLocatorFork(const CBlockLocator& locator) override -- { -- LOCK(cs_main); -- if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) { -- return fork->nHeight; -- } -- return nullopt; -- } -- bool findBlock(const uint256& hash, const FoundBlock& block) override -- { -- WAIT_LOCK(cs_main, lock); -- return FillBlock(LookupBlockIndex(hash), block, lock); -- } -- bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override -- { -- WAIT_LOCK(cs_main, lock); -- return FillBlock(ChainActive().FindEarliestAtLeast(min_time, min_height), block, lock); -- } -- bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next, bool* reorg) override { -- WAIT_LOCK(cs_main, lock); -- CBlockIndex* block = ChainActive()[block_height]; -- if (block && block->GetBlockHash() != block_hash) block = nullptr; -- if (reorg) *reorg = !block; -- return FillBlock(block ? ChainActive()[block_height + 1] : nullptr, next, lock); -- } -- bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override -- { -- WAIT_LOCK(cs_main, lock); -- if (const CBlockIndex* block = LookupBlockIndex(block_hash)) { -- if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) { -- return FillBlock(ancestor, ancestor_out, lock); -- } -- } -- return FillBlock(nullptr, ancestor_out, lock); -- } -- bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override -- { -- WAIT_LOCK(cs_main, lock); -- const CBlockIndex* block = LookupBlockIndex(block_hash); -- const CBlockIndex* ancestor = LookupBlockIndex(ancestor_hash); -- if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr; -- return FillBlock(ancestor, ancestor_out, lock); -- } -- bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override -- { -- WAIT_LOCK(cs_main, lock); -- const CBlockIndex* block1 = LookupBlockIndex(block_hash1); -- const CBlockIndex* block2 = LookupBlockIndex(block_hash2); -- const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr; -- // Using & instead of && below to avoid short circuiting and leaving -- // output uninitialized. -- return FillBlock(ancestor, ancestor_out, lock) & FillBlock(block1, block1_out, lock) & FillBlock(block2, block2_out, lock); -- } -- void findCoins(std::map& coins) override { return FindCoins(m_node, coins); } -- double guessVerificationProgress(const uint256& block_hash) override -- { -- LOCK(cs_main); -- return GuessVerificationProgress(Params().TxData(), LookupBlockIndex(block_hash)); -- } -- bool hasBlocks(const uint256& block_hash, int min_height, Optional max_height) override -- { -- // hasBlocks returns true if all ancestors of block_hash in specified -- // range have block data (are not pruned), false if any ancestors in -- // specified range are missing data. -- // -- // For simplicity and robustness, min_height and max_height are only -- // used to limit the range, and passing min_height that's too low or -- // max_height that's too high will not crash or change the result. -- LOCK(::cs_main); -- if (CBlockIndex* block = LookupBlockIndex(block_hash)) { -- if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height); -- for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) { -- // Check pprev to not segfault if min_height is too low -- if (block->nHeight <= min_height || !block->pprev) return true; -- } -- } -- return false; -- } -- RBFTransactionState isRBFOptIn(const CTransaction& tx) override -- { -- if (!m_node.mempool) return IsRBFOptInEmptyMempool(tx); -- LOCK(m_node.mempool->cs); -- return IsRBFOptIn(tx, *m_node.mempool); -- } -- bool hasDescendantsInMempool(const uint256& txid) override -- { -- if (!m_node.mempool) return false; -- LOCK(m_node.mempool->cs); -- auto it = m_node.mempool->GetIter(txid); -- return it && (*it)->GetCountWithDescendants() > 1; -- } -- bool broadcastTransaction(const CTransactionRef& tx, -- const CAmount& max_tx_fee, -- bool relay, -- std::string& err_string) override -- { -- const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, relay, /*wait_callback*/ false); -- // Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures. -- // Note: this will need to be updated if BroadcastTransactions() is updated to return other non-mempool failures -- // that Chain clients do not need to know about. -- return TransactionError::OK == err; -- } -- void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) override -- { -- ancestors = descendants = 0; -- if (!m_node.mempool) return; -- m_node.mempool->GetTransactionAncestry(txid, ancestors, descendants); -- } -- void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) override -- { -- limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); -- limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); -- } -- bool checkChainLimits(const CTransactionRef& tx) override -- { -- if (!m_node.mempool) return true; -- LockPoints lp; -- CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp); -- CTxMemPool::setEntries ancestors; -- auto limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); -- auto limit_ancestor_size = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000; -- auto limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); -- auto limit_descendant_size = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000; -- std::string unused_error_string; -- LOCK(m_node.mempool->cs); -- return m_node.mempool->CalculateMemPoolAncestors( -- entry, ancestors, limit_ancestor_count, limit_ancestor_size, -- limit_descendant_count, limit_descendant_size, unused_error_string); -- } -- CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override -- { -- return ::feeEstimator.estimateSmartFee(num_blocks, calc, conservative); -- } -- unsigned int estimateMaxBlocks() override -- { -- return ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); -- } -- CFeeRate mempoolMinFee() override -- { -- if (!m_node.mempool) return {}; -- return m_node.mempool->GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); -- } -- CFeeRate relayMinFee() override { return ::minRelayTxFee; } -- CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; } -- CFeeRate relayDustFee() override { return ::dustRelayFee; } -- bool havePruned() override -- { -- LOCK(cs_main); -- return ::fHavePruned; -- } -- bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); } -- bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); } -- bool shutdownRequested() override { return ShutdownRequested(); } -- int64_t getAdjustedTime() override { return GetAdjustedTime(); } -- void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); } -- void initWarning(const bilingual_str& message) override { InitWarning(message); } -- void initError(const bilingual_str& message) override { InitError(message); } -- void showProgress(const std::string& title, int progress, bool resume_possible) override -- { -- ::uiInterface.ShowProgress(title, progress, resume_possible); -- } -- std::unique_ptr handleNotifications(std::shared_ptr notifications) override -- { -- return MakeUnique(std::move(notifications)); -- } -- void waitForNotificationsIfTipChanged(const uint256& old_tip) override -- { -- if (!old_tip.IsNull()) { -- LOCK(::cs_main); -- if (old_tip == ::ChainActive().Tip()->GetBlockHash()) return; -- } -- SyncWithValidationInterfaceQueue(); -- } -- std::unique_ptr handleRpc(const CRPCCommand& command) override -- { -- return MakeUnique(command); -- } -- bool rpcEnableDeprecated(const std::string& method) override { return IsDeprecatedRPCEnabled(method); } -- void rpcRunLater(const std::string& name, std::function fn, int64_t seconds) override -- { -- RPCRunLater(name, std::move(fn), seconds); -- } -- int rpcSerializationFlags() override { return RPCSerializationFlags(); } -- util::SettingsValue getRwSetting(const std::string& name) override -- { -- util::SettingsValue result; -- gArgs.LockSettings([&](const util::Settings& settings) { -- if (const util::SettingsValue* value = util::FindKey(settings.rw_settings, name)) { -- result = *value; -- } -- }); -- return result; -- } -- bool updateRwSetting(const std::string& name, const util::SettingsValue& value) override -- { -- gArgs.LockSettings([&](util::Settings& settings) { -- if (value.isNull()) { -- settings.rw_settings.erase(name); -- } else { -- settings.rw_settings[name] = value; -- } -- }); -- return gArgs.WriteSettingsFile(); -- } -- void requestMempoolTransactions(Notifications& notifications) override -- { -- if (!m_node.mempool) return; -- LOCK2(::cs_main, m_node.mempool->cs); -- for (const CTxMemPoolEntry& entry : m_node.mempool->mapTx) { -- notifications.transactionAddedToMempool(entry.GetSharedTx(), 0 /* mempool_sequence */); -- } -- } -- NodeContext& m_node; --}; --} // namespace --} // namespace node -- --namespace interfaces { --std::unique_ptr MakeNode(NodeContext* context) { return MakeUnique(context); } --std::unique_ptr MakeChain(NodeContext& context) { return MakeUnique(context); } --} // namespace interfaces -diff --git a/src/policy/feerate.cpp b/src/policy/feerate.cpp -index 5541b049..04e0e117 100644 ---- a/src/policy/feerate.cpp -+++ b/src/policy/feerate.cpp -@@ -7,8 +7,6 @@ - - #include - --const std::string CURRENCY_UNIT = "BGL"; -- - CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nBytes_) - { - assert(nBytes_ <= uint64_t(std::numeric_limits::max())); -diff --git a/src/policy/feerate.h b/src/policy/feerate.h -index c847b9f0..6c952ff3 100644 ---- a/src/policy/feerate.h -+++ b/src/policy/feerate.h -@@ -11,7 +11,7 @@ - - #include - --const std::string CURRENCY_UNIT = "BGL"; // One formatted unit -+const std::string CURRENCY_UNIT = "BTC"; // One formatted unit - const std::string CURRENCY_ATOM = "sat"; // One indivisible minimum value unit - - /* Used to determine type of fee estimation requested */ -@@ -19,7 +19,7 @@ enum class FeeEstimateMode { - UNSET, //!< Use default settings based on other criteria - ECONOMICAL, //!< Force estimateSmartFee to use non-conservative estimates - CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates -- BGL_KVB, //!< Use BTC/kvB fee rate unit -+ BTC_KVB, //!< Use BTC/kvB fee rate unit - SAT_VB, //!< Use sat/vB fee rate unit - }; - -@@ -65,7 +65,7 @@ public: - friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } - friend bool operator!=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK != b.nSatoshisPerK; } - CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; } -- std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BGL_KVB) const; -+ std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BTC_KVB) const; - - SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); } - }; -diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp -index 6635f7c8..4e33fd6c 100644 ---- a/src/policy/policy.cpp -+++ b/src/policy/policy.cpp -@@ -70,12 +70,6 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType) - return false; - } - -- // Old (non-witness) transaction types are not supported -- if (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH || whichType == TX_SCRIPTHASH) -- { -- return false; -- } -- - return true; - } - -diff --git a/src/policy/policy.h b/src/policy/policy.h -index 414de02d..74cb6c99 100644 ---- a/src/policy/policy.h -+++ b/src/policy/policy.h -@@ -38,11 +38,11 @@ static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20; - static const bool DEFAULT_PERMIT_BAREMULTISIG = true; - /** The maximum number of witness stack items in a standard P2WSH script */ - static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS = 100; --/** The maximum size in bytes of each witness stack item in a standard P2WSH script */ -+/** The maximum size of each witness stack item in a standard P2WSH script */ - static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80; --/** The maximum size in bytes of each witness stack item in a standard BIP 342 script (Taproot, leaf version 0xc0) */ -+/** The maximum size of each witness stack item in a standard BIP 342 script (Taproot, leaf version 0xc0) */ - static const unsigned int MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE = 80; --/** The maximum size in bytes of a standard witnessScript */ -+/** The maximum size of a standard witnessScript */ - static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600; - /** The maximum size of a standard ScriptSig */ - static const unsigned int MAX_STANDARD_SCRIPTSIG_SIZE = 1650; -@@ -105,9 +105,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, - /** - * Check if the transaction is over standard P2WSH resources limit: - * 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements -- * These limits are adequate for multisignatures up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL. -- * -- * Also enforce a maximum stack item size limit and no annexes for tapscript spends. -+ * These limits are adequate for multi-signature up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL, - */ - bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); - -diff --git a/src/protocol.h b/src/protocol.h -index cc56dd7b..afd4b6b9 100644 ---- a/src/protocol.h -+++ b/src/protocol.h -@@ -1,537 +1,465 @@ --// Copyright (c) 2015-2020 The Bitcoin Core developers -+// Copyright (c) 2009-2010 Satoshi Nakamoto -+// Copyright (c) 2009-2019 The Bitcoin Core developers - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - --#ifndef BGL_PREVECTOR_H --#define BGL_PREVECTOR_H -+#ifndef __cplusplus -+#error This header can only be compiled as C++. -+#endif - --#include --#include --#include --#include -- --#include --#include --#include --#include -- --/** Implements a drop-in replacement for std::vector which stores up to N -- * elements directly (without heap allocation). The types Size and Diff are -- * used to store element counts, and can be any unsigned + signed type. -- * -- * Storage layout is either: -- * - Direct allocation: -- * - Size _size: the number of used elements (between 0 and N) -- * - T direct[N]: an array of N elements of type T -- * (only the first _size are initialized). -- * - Indirect allocation: -- * - Size _size: the number of used elements plus N + 1 -- * - Size capacity: the number of allocated elements -- * - T* indirect: a pointer to an array of capacity elements of type T -- * (only the first _size are initialized). -- * -- * The data type T must be movable by memmove/realloc(). Once we switch to C++, -- * move constructors can be used instead. -- */ --template --class prevector { --public: -- typedef Size size_type; -- typedef Diff difference_type; -- typedef T value_type; -- typedef value_type& reference; -- typedef const value_type& const_reference; -- typedef value_type* pointer; -- typedef const value_type* const_pointer; -- -- class iterator { -- T* ptr; -- public: -- typedef Diff difference_type; -- typedef T value_type; -- typedef T* pointer; -- typedef T& reference; -- typedef std::random_access_iterator_tag iterator_category; -- iterator(T* ptr_) : ptr(ptr_) {} -- T& operator*() const { return *ptr; } -- T* operator->() const { return ptr; } -- T& operator[](size_type pos) { return ptr[pos]; } -- const T& operator[](size_type pos) const { return ptr[pos]; } -- iterator& operator++() { ptr++; return *this; } -- iterator& operator--() { ptr--; return *this; } -- iterator operator++(int) { iterator copy(*this); ++(*this); return copy; } -- iterator operator--(int) { iterator copy(*this); --(*this); return copy; } -- difference_type friend operator-(iterator a, iterator b) { return (&(*a) - &(*b)); } -- iterator operator+(size_type n) { return iterator(ptr + n); } -- iterator& operator+=(size_type n) { ptr += n; return *this; } -- iterator operator-(size_type n) { return iterator(ptr - n); } -- iterator& operator-=(size_type n) { ptr -= n; return *this; } -- bool operator==(iterator x) const { return ptr == x.ptr; } -- bool operator!=(iterator x) const { return ptr != x.ptr; } -- bool operator>=(iterator x) const { return ptr >= x.ptr; } -- bool operator<=(iterator x) const { return ptr <= x.ptr; } -- bool operator>(iterator x) const { return ptr > x.ptr; } -- bool operator<(iterator x) const { return ptr < x.ptr; } -- }; -- -- class reverse_iterator { -- T* ptr; -- public: -- typedef Diff difference_type; -- typedef T value_type; -- typedef T* pointer; -- typedef T& reference; -- typedef std::bidirectional_iterator_tag iterator_category; -- reverse_iterator(T* ptr_) : ptr(ptr_) {} -- T& operator*() { return *ptr; } -- const T& operator*() const { return *ptr; } -- T* operator->() { return ptr; } -- const T* operator->() const { return ptr; } -- reverse_iterator& operator--() { ptr++; return *this; } -- reverse_iterator& operator++() { ptr--; return *this; } -- reverse_iterator operator++(int) { reverse_iterator copy(*this); ++(*this); return copy; } -- reverse_iterator operator--(int) { reverse_iterator copy(*this); --(*this); return copy; } -- bool operator==(reverse_iterator x) const { return ptr == x.ptr; } -- bool operator!=(reverse_iterator x) const { return ptr != x.ptr; } -- }; -- -- class const_iterator { -- const T* ptr; -- public: -- typedef Diff difference_type; -- typedef const T value_type; -- typedef const T* pointer; -- typedef const T& reference; -- typedef std::random_access_iterator_tag iterator_category; -- const_iterator(const T* ptr_) : ptr(ptr_) {} -- const_iterator(iterator x) : ptr(&(*x)) {} -- const T& operator*() const { return *ptr; } -- const T* operator->() const { return ptr; } -- const T& operator[](size_type pos) const { return ptr[pos]; } -- const_iterator& operator++() { ptr++; return *this; } -- const_iterator& operator--() { ptr--; return *this; } -- const_iterator operator++(int) { const_iterator copy(*this); ++(*this); return copy; } -- const_iterator operator--(int) { const_iterator copy(*this); --(*this); return copy; } -- difference_type friend operator-(const_iterator a, const_iterator b) { return (&(*a) - &(*b)); } -- const_iterator operator+(size_type n) { return const_iterator(ptr + n); } -- const_iterator& operator+=(size_type n) { ptr += n; return *this; } -- const_iterator operator-(size_type n) { return const_iterator(ptr - n); } -- const_iterator& operator-=(size_type n) { ptr -= n; return *this; } -- bool operator==(const_iterator x) const { return ptr == x.ptr; } -- bool operator!=(const_iterator x) const { return ptr != x.ptr; } -- bool operator>=(const_iterator x) const { return ptr >= x.ptr; } -- bool operator<=(const_iterator x) const { return ptr <= x.ptr; } -- bool operator>(const_iterator x) const { return ptr > x.ptr; } -- bool operator<(const_iterator x) const { return ptr < x.ptr; } -- }; -- -- class const_reverse_iterator { -- const T* ptr; -- public: -- typedef Diff difference_type; -- typedef const T value_type; -- typedef const T* pointer; -- typedef const T& reference; -- typedef std::bidirectional_iterator_tag iterator_category; -- const_reverse_iterator(const T* ptr_) : ptr(ptr_) {} -- const_reverse_iterator(reverse_iterator x) : ptr(&(*x)) {} -- const T& operator*() const { return *ptr; } -- const T* operator->() const { return ptr; } -- const_reverse_iterator& operator--() { ptr++; return *this; } -- const_reverse_iterator& operator++() { ptr--; return *this; } -- const_reverse_iterator operator++(int) { const_reverse_iterator copy(*this); ++(*this); return copy; } -- const_reverse_iterator operator--(int) { const_reverse_iterator copy(*this); --(*this); return copy; } -- bool operator==(const_reverse_iterator x) const { return ptr == x.ptr; } -- bool operator!=(const_reverse_iterator x) const { return ptr != x.ptr; } -- }; -- --private: --#pragma pack(push, 1) -- union direct_or_indirect { -- char direct[sizeof(T) * N]; -- struct { -- char* indirect; -- size_type capacity; -- } indirect_contents; -- }; --#pragma pack(pop) -- alignas(char*) direct_or_indirect _union = {}; -- size_type _size = 0; -- -- static_assert(alignof(char*) % alignof(size_type) == 0 && sizeof(char*) % alignof(size_type) == 0, "size_type cannot have more restrictive alignment requirement than pointer"); -- static_assert(alignof(char*) % alignof(T) == 0, "value_type T cannot have more restrictive alignment requirement than pointer"); -- -- T* direct_ptr(difference_type pos) { return reinterpret_cast(_union.direct) + pos; } -- const T* direct_ptr(difference_type pos) const { return reinterpret_cast(_union.direct) + pos; } -- T* indirect_ptr(difference_type pos) { return reinterpret_cast(_union.indirect_contents.indirect) + pos; } -- const T* indirect_ptr(difference_type pos) const { return reinterpret_cast(_union.indirect_contents.indirect) + pos; } -- bool is_direct() const { return _size <= N; } -- -- void change_capacity(size_type new_capacity) { -- if (new_capacity <= N) { -- if (!is_direct()) { -- T* indirect = indirect_ptr(0); -- T* src = indirect; -- T* dst = direct_ptr(0); -- memcpy(dst, src, size() * sizeof(T)); -- free(indirect); -- _size -= N + 1; -- } -- } else { -- if (!is_direct()) { -- /* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert -- success. These should instead use an allocator or new/delete so that handlers -- are called as necessary, but performance would be slightly degraded by doing so. */ -- _union.indirect_contents.indirect = static_cast(realloc(_union.indirect_contents.indirect, ((size_t)sizeof(T)) * new_capacity)); -- assert(_union.indirect_contents.indirect); -- _union.indirect_contents.capacity = new_capacity; -- } else { -- char* new_indirect = static_cast(malloc(((size_t)sizeof(T)) * new_capacity)); -- assert(new_indirect); -- T* src = direct_ptr(0); -- T* dst = reinterpret_cast(new_indirect); -- memcpy(dst, src, size() * sizeof(T)); -- _union.indirect_contents.indirect = new_indirect; -- _union.indirect_contents.capacity = new_capacity; -- _size += N + 1; -- } -- } -- } -+#ifndef BGL_PROTOCOL_H -+#define BGL_PROTOCOL_H - -- T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); } -- const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); } -+#include -+#include -+#include -+#include -+#include - -- void fill(T* dst, ptrdiff_t count, const T& value = T{}) { -- std::fill_n(dst, count, value); -- } -- -- template -- void fill(T* dst, InputIterator first, InputIterator last) { -- while (first != last) { -- new(static_cast(dst)) T(*first); -- ++dst; -- ++first; -- } -- } -+#include -+#include - -+/** Message header. -+ * (4) message start. -+ * (12) command. -+ * (4) size. -+ * (4) checksum. -+ */ -+class CMessageHeader -+{ - public: -- void assign(size_type n, const T& val) { -- clear(); -- if (capacity() < n) { -- change_capacity(n); -- } -- _size += n; -- fill(item_ptr(0), n, val); -- } -- -- template -- void assign(InputIterator first, InputIterator last) { -- size_type n = last - first; -- clear(); -- if (capacity() < n) { -- change_capacity(n); -- } -- _size += n; -- fill(item_ptr(0), first, last); -- } -- -- prevector() {} -- -- explicit prevector(size_type n) { -- resize(n); -- } -- -- explicit prevector(size_type n, const T& val) { -- change_capacity(n); -- _size += n; -- fill(item_ptr(0), n, val); -- } -- -- template -- prevector(InputIterator first, InputIterator last) { -- size_type n = last - first; -- change_capacity(n); -- _size += n; -- fill(item_ptr(0), first, last); -- } -- -- prevector(const prevector& other) { -- size_type n = other.size(); -- change_capacity(n); -- _size += n; -- fill(item_ptr(0), other.begin(), other.end()); -- } -- -- prevector(prevector&& other) { -- swap(other); -- } -- -- prevector& operator=(const prevector& other) { -- if (&other == this) { -- return *this; -- } -- assign(other.begin(), other.end()); -- return *this; -- } -- -- prevector& operator=(prevector&& other) { -- swap(other); -- return *this; -- } -- -- size_type size() const { -- return is_direct() ? _size : _size - N - 1; -- } -- -- bool empty() const { -- return size() == 0; -- } -- -- iterator begin() { return iterator(item_ptr(0)); } -- const_iterator begin() const { return const_iterator(item_ptr(0)); } -- iterator end() { return iterator(item_ptr(size())); } -- const_iterator end() const { return const_iterator(item_ptr(size())); } -- -- reverse_iterator rbegin() { return reverse_iterator(item_ptr(size() - 1)); } -- const_reverse_iterator rbegin() const { return const_reverse_iterator(item_ptr(size() - 1)); } -- reverse_iterator rend() { return reverse_iterator(item_ptr(-1)); } -- const_reverse_iterator rend() const { return const_reverse_iterator(item_ptr(-1)); } -- -- size_t capacity() const { -- if (is_direct()) { -- return N; -- } else { -- return _union.indirect_contents.capacity; -- } -- } -- -- T& operator[](size_type pos) { -- return *item_ptr(pos); -- } -- -- const T& operator[](size_type pos) const { -- return *item_ptr(pos); -- } -+ static constexpr size_t MESSAGE_START_SIZE = 4; -+ static constexpr size_t COMMAND_SIZE = 12; -+ static constexpr size_t MESSAGE_SIZE_SIZE = 4; -+ static constexpr size_t CHECKSUM_SIZE = 4; -+ static constexpr size_t MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE; -+ static constexpr size_t CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE; -+ static constexpr size_t HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE; -+ typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; -+ -+ explicit CMessageHeader(); -+ -+ /** Construct a P2P message header from message-start characters, a command and the size of the message. -+ * @note Passing in a `pszCommand` longer than COMMAND_SIZE will result in a run-time assertion error. -+ */ -+ CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn); -+ -+ std::string GetCommand() const; -+ bool IsCommandValid() const; -+ -+ SERIALIZE_METHODS(CMessageHeader, obj) { READWRITE(obj.pchMessageStart, obj.pchCommand, obj.nMessageSize, obj.pchChecksum); } -+ -+ char pchMessageStart[MESSAGE_START_SIZE]; -+ char pchCommand[COMMAND_SIZE]; -+ uint32_t nMessageSize; -+ uint8_t pchChecksum[CHECKSUM_SIZE]; -+}; - -- void resize(size_type new_size) { -- size_type cur_size = size(); -- if (cur_size == new_size) { -- return; -- } -- if (cur_size > new_size) { -- erase(item_ptr(new_size), end()); -- return; -- } -- if (new_size > capacity()) { -- change_capacity(new_size); -- } -- ptrdiff_t increase = new_size - cur_size; -- fill(item_ptr(cur_size), increase); -- _size += increase; -- } -+/** -+ * BGL protocol message types. When adding new message types, don't forget -+ * to update allNetMessageTypes in protocol.cpp. -+ */ -+namespace NetMsgType { - -- void reserve(size_type new_capacity) { -- if (new_capacity > capacity()) { -- change_capacity(new_capacity); -- } -- } -+/** -+ * The version message provides information about the transmitting node to the -+ * receiving node at the beginning of a connection. -+ */ -+extern const char* VERSION; -+/** -+ * The verack message acknowledges a previously-received version message, -+ * informing the connecting node that it can begin to send other messages. -+ */ -+extern const char* VERACK; -+/** -+ * The addr (IP address) message relays connection information for peers on the -+ * network. -+ */ -+extern const char* ADDR; -+/** -+ * The addrv2 message relays connection information for peers on the network just -+ * like the addr message, but is extended to allow gossiping of longer node -+ * addresses (see BIP155). -+ */ -+extern const char *ADDRV2; -+/** -+ * The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155). -+ * It also implies that its sender can encode as ADDRV2 and would send ADDRV2 -+ * instead of ADDR to a peer that has signaled ADDRV2 support by sending SENDADDRV2. -+ */ -+extern const char *SENDADDRV2; -+/** -+ * The inv message (inventory message) transmits one or more inventories of -+ * objects known to the transmitting peer. -+ */ -+extern const char* INV; -+/** -+ * The getdata message requests one or more data objects from another node. -+ */ -+extern const char* GETDATA; -+/** -+ * The merkleblock message is a reply to a getdata message which requested a -+ * block using the inventory type MSG_MERKLEBLOCK. -+ * @since protocol version 70001 as described by BIP37. -+ */ -+extern const char* MERKLEBLOCK; -+/** -+ * The getblocks message requests an inv message that provides block header -+ * hashes starting from a particular point in the block chain. -+ */ -+extern const char* GETBLOCKS; -+/** -+ * The getheaders message requests a headers message that provides block -+ * headers starting from a particular point in the block chain. -+ * @since protocol version 31800. -+ */ -+extern const char* GETHEADERS; -+/** -+ * The tx message transmits a single transaction. -+ */ -+extern const char* TX; -+/** -+ * The headers message sends one or more block headers to a node which -+ * previously requested certain headers with a getheaders message. -+ * @since protocol version 31800. -+ */ -+extern const char* HEADERS; -+/** -+ * The block message transmits a single serialized block. -+ */ -+extern const char* BLOCK; -+/** -+ * The getaddr message requests an addr message from the receiving node, -+ * preferably one with lots of IP addresses of other receiving nodes. -+ */ -+extern const char* GETADDR; -+/** -+ * The mempool message requests the TXIDs of transactions that the receiving -+ * node has verified as valid but which have not yet appeared in a block. -+ * @since protocol version 60002. -+ */ -+extern const char* MEMPOOL; -+/** -+ * The ping message is sent periodically to help confirm that the receiving -+ * peer is still connected. -+ */ -+extern const char* PING; -+/** -+ * The pong message replies to a ping message, proving to the pinging node that -+ * the ponging node is still alive. -+ * @since protocol version 60001 as described by BIP31. -+ */ -+extern const char* PONG; -+/** -+ * The notfound message is a reply to a getdata message which requested an -+ * object the receiving node does not have available for relay. -+ * @since protocol version 70001. -+ */ -+extern const char* NOTFOUND; -+/** -+ * The filterload message tells the receiving peer to filter all relayed -+ * transactions and requested merkle blocks through the provided filter. -+ * @since protocol version 70001 as described by BIP37. -+ * Only available with service bit NODE_BLOOM since protocol version -+ * 70011 as described by BIP111. -+ */ -+extern const char* FILTERLOAD; -+/** -+ * The filteradd message tells the receiving peer to add a single element to a -+ * previously-set bloom filter, such as a new public key. -+ * @since protocol version 70001 as described by BIP37. -+ * Only available with service bit NODE_BLOOM since protocol version -+ * 70011 as described by BIP111. -+ */ -+extern const char* FILTERADD; -+/** -+ * The filterclear message tells the receiving peer to remove a previously-set -+ * bloom filter. -+ * @since protocol version 70001 as described by BIP37. -+ * Only available with service bit NODE_BLOOM since protocol version -+ * 70011 as described by BIP111. -+ */ -+extern const char* FILTERCLEAR; -+/** -+ * Indicates that a node prefers to receive new block announcements via a -+ * "headers" message rather than an "inv". -+ * @since protocol version 70012 as described by BIP130. -+ */ -+extern const char* SENDHEADERS; -+/** -+ * The feefilter message tells the receiving peer not to inv us any txs -+ * which do not meet the specified min fee rate. -+ * @since protocol version 70013 as described by BIP133 -+ */ -+extern const char* FEEFILTER; -+/** -+ * Contains a 1-byte bool and 8-byte LE version number. -+ * Indicates that a node is willing to provide blocks via "cmpctblock" messages. -+ * May indicate that a node prefers to receive new block announcements via a -+ * "cmpctblock" message rather than an "inv", depending on message contents. -+ * @since protocol version 70014 as described by BIP 152 -+ */ -+extern const char* SENDCMPCT; -+/** -+ * Contains a CBlockHeaderAndShortTxIDs object - providing a header and -+ * list of "short txids". -+ * @since protocol version 70014 as described by BIP 152 -+ */ -+extern const char* CMPCTBLOCK; -+/** -+ * Contains a BlockTransactionsRequest -+ * Peer should respond with "blocktxn" message. -+ * @since protocol version 70014 as described by BIP 152 -+ */ -+extern const char* GETBLOCKTXN; -+/** -+ * Contains a BlockTransactions. -+ * Sent in response to a "getblocktxn" message. -+ * @since protocol version 70014 as described by BIP 152 -+ */ -+extern const char* BLOCKTXN; -+/** -+ * getcfilters requests compact filters for a range of blocks. -+ * Only available with service bit NODE_COMPACT_FILTERS as described by -+ * BIP 157 & 158. -+ */ -+extern const char* GETCFILTERS; -+/** -+ * cfilter is a response to a getcfilters request containing a single compact -+ * filter. -+ */ -+extern const char* CFILTER; -+/** -+ * getcfheaders requests a compact filter header and the filter hashes for a -+ * range of blocks, which can then be used to reconstruct the filter headers -+ * for those blocks. -+ * Only available with service bit NODE_COMPACT_FILTERS as described by -+ * BIP 157 & 158. -+ */ -+extern const char* GETCFHEADERS; -+/** -+ * cfheaders is a response to a getcfheaders request containing a filter header -+ * and a vector of filter hashes for each subsequent block in the requested range. -+ */ -+extern const char* CFHEADERS; -+/** -+ * getcfcheckpt requests evenly spaced compact filter headers, enabling -+ * parallelized download and validation of the headers between them. -+ * Only available with service bit NODE_COMPACT_FILTERS as described by -+ * BIP 157 & 158. -+ */ -+extern const char* GETCFCHECKPT; -+/** -+ * cfcheckpt is a response to a getcfcheckpt request containing a vector of -+ * evenly spaced filter headers for blocks on the requested chain. -+ */ -+extern const char* CFCHECKPT; -+/** -+ * Indicates that a node prefers to relay transactions via wtxid, rather than -+ * txid. -+ * @since protocol version 70016 as described by BIP 339. -+ */ -+extern const char* WTXIDRELAY; -+}; // namespace NetMsgType -+ -+/* Get a vector of all valid message types (see above) */ -+const std::vector& getAllNetMessageTypes(); -+ -+/** nServices flags */ -+enum ServiceFlags : uint64_t { -+ // NOTE: When adding here, be sure to update serviceFlagToStr too -+ // Nothing -+ NODE_NONE = 0, -+ // NODE_NETWORK means that the node is capable of serving the complete block chain. It is currently -+ // set by all BGL Core non pruned nodes, and is unset by SPV clients or other light clients. -+ NODE_NETWORK = (1 << 0), -+ // NODE_GETUTXO means the node is capable of responding to the getutxo protocol request. -+ // BGL Core does not support this but a patch set called BGL XT does. -+ // See BIP 64 for details on how this is implemented. -+ NODE_GETUTXO = (1 << 1), -+ // NODE_BLOOM means the node is capable and willing to handle bloom-filtered connections. -+ // BGL Core nodes used to support this by default, without advertising this bit, -+ // but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION) -+ NODE_BLOOM = (1 << 2), -+ // NODE_WITNESS indicates that a node can be asked for blocks and transactions including -+ // witness data. -+ NODE_WITNESS = (1 << 3), -+ // NODE_COMPACT_FILTERS means the node will service basic block filter requests. -+ // See BIP157 and BIP158 for details on how this is implemented. -+ NODE_COMPACT_FILTERS = (1 << 6), -+ // NODE_NETWORK_LIMITED means the same as NODE_NETWORK with the limitation of only -+ // serving the last 288 (2 day) blocks -+ // See BIP159 for details on how this is implemented. -+ NODE_NETWORK_LIMITED = (1 << 10), -+ -+ // Bits 24-31 are reserved for temporary experiments. Just pick a bit that -+ // isn't getting used, or one not being used much, and notify the -+ // BGL-development mailing list. Remember that service bits are just -+ // unauthenticated advertisements, so your code must be robust against -+ // collisions and other cases where nodes may be advertising a service they -+ // do not actually support. Other service bits should be allocated via the -+ // BIP process. -+}; - -- void shrink_to_fit() { -- change_capacity(size()); -- } -+/** -+ * Convert service flags (a bitmask of NODE_*) to human readable strings. -+ * It supports unknown service flags which will be returned as "UNKNOWN[...]". -+ * @param[in] flags multiple NODE_* bitwise-OR-ed together -+ */ -+std::vector serviceFlagsToStr(uint64_t flags); - -- void clear() { -- resize(0); -- } -+/** -+ * Gets the set of service flags which are "desirable" for a given peer. -+ * -+ * These are the flags which are required for a peer to support for them -+ * to be "interesting" to us, ie for us to wish to use one of our few -+ * outbound connection slots for or for us to wish to prioritize keeping -+ * their connection around. -+ * -+ * Relevant service flags may be peer- and state-specific in that the -+ * version of the peer may determine which flags are required (eg in the -+ * case of NODE_NETWORK_LIMITED where we seek out NODE_NETWORK peers -+ * unless they set NODE_NETWORK_LIMITED and we are out of IBD, in which -+ * case NODE_NETWORK_LIMITED suffices). -+ * -+ * Thus, generally, avoid calling with peerServices == NODE_NONE, unless -+ * state-specific flags must absolutely be avoided. When called with -+ * peerServices == NODE_NONE, the returned desirable service flags are -+ * guaranteed to not change dependent on state - ie they are suitable for -+ * use when describing peers which we know to be desirable, but for which -+ * we do not have a confirmed set of service flags. -+ * -+ * If the NODE_NONE return value is changed, contrib/seeds/makeseeds.py -+ * should be updated appropriately to filter for the same nodes. -+ */ -+ServiceFlags GetDesirableServiceFlags(ServiceFlags services); - -- iterator insert(iterator pos, const T& value) { -- size_type p = pos - begin(); -- size_type new_size = size() + 1; -- if (capacity() < new_size) { -- change_capacity(new_size + (new_size >> 1)); -- } -- T* ptr = item_ptr(p); -- memmove(ptr + 1, ptr, (size() - p) * sizeof(T)); -- _size++; -- new(static_cast(ptr)) T(value); -- return iterator(ptr); -- } -+/** Set the current IBD status in order to figure out the desirable service flags */ -+void SetServiceFlagsIBDCache(bool status); - -- void insert(iterator pos, size_type count, const T& value) { -- size_type p = pos - begin(); -- size_type new_size = size() + count; -- if (capacity() < new_size) { -- change_capacity(new_size + (new_size >> 1)); -- } -- T* ptr = item_ptr(p); -- memmove(ptr + count, ptr, (size() - p) * sizeof(T)); -- _size += count; -- fill(item_ptr(p), count, value); -- } -+/** -+ * A shortcut for (services & GetDesirableServiceFlags(services)) -+ * == GetDesirableServiceFlags(services), ie determines whether the given -+ * set of service flags are sufficient for a peer to be "relevant". -+ */ -+static inline bool HasAllDesirableServiceFlags(ServiceFlags services) -+{ -+ return !(GetDesirableServiceFlags(services) & (~services)); -+} -+ -+/** -+ * Checks if a peer with the given service flags may be capable of having a -+ * robust address-storage DB. -+ */ -+static inline bool MayHaveUsefulAddressDB(ServiceFlags services) -+{ -+ return (services & NODE_NETWORK) || (services & NODE_NETWORK_LIMITED); -+} - -- template -- void insert(iterator pos, InputIterator first, InputIterator last) { -- size_type p = pos - begin(); -- difference_type count = last - first; -- size_type new_size = size() + count; -- if (capacity() < new_size) { -- change_capacity(new_size + (new_size >> 1)); -- } -- T* ptr = item_ptr(p); -- memmove(ptr + count, ptr, (size() - p) * sizeof(T)); -- _size += count; -- fill(ptr, first, last); -- } -+/** A CService with information about it as peer */ -+class CAddress : public CService -+{ -+ static constexpr uint32_t TIME_INIT{100000000}; - -- inline void resize_uninitialized(size_type new_size) { -- // resize_uninitialized changes the size of the prevector but does not initialize it. -- // If size < new_size, the added elements must be initialized explicitly. -- if (capacity() < new_size) { -- change_capacity(new_size); -- _size += new_size - size(); -- return; -+public: -+ CAddress() : CService{} {}; -+ CAddress(CService ipIn, ServiceFlags nServicesIn) : CService{ipIn}, nServices{nServicesIn} {}; -+ CAddress(CService ipIn, ServiceFlags nServicesIn, uint32_t nTimeIn) : CService{ipIn}, nTime{nTimeIn}, nServices{nServicesIn} {}; -+ -+ SERIALIZE_METHODS(CAddress, obj) -+ { -+ SER_READ(obj, obj.nTime = TIME_INIT); -+ int nVersion = s.GetVersion(); -+ if (s.GetType() & SER_DISK) { -+ READWRITE(nVersion); - } -- if (new_size < size()) { -- erase(item_ptr(new_size), end()); -- } else { -- _size += new_size - size(); -+ if ((s.GetType() & SER_DISK) || -+ (nVersion != INIT_PROTO_VERSION && !(s.GetType() & SER_GETHASH))) { -+ // The only time we serialize a CAddress object without nTime is in -+ // the initial VERSION messages which contain two CAddress records. -+ // At that point, the serialization version is INIT_PROTO_VERSION. -+ // After the version handshake, serialization version is >= -+ // MIN_PEER_PROTO_VERSION and all ADDR messages are serialized with -+ // nTime. -+ READWRITE(obj.nTime); - } -- } -- -- iterator erase(iterator pos) { -- return erase(pos, pos + 1); -- } -- -- iterator erase(iterator first, iterator last) { -- // Erase is not allowed to the change the object's capacity. That means -- // that when starting with an indirectly allocated prevector with -- // size and capacity > N, the result may be a still indirectly allocated -- // prevector with size <= N and capacity > N. A shrink_to_fit() call is -- // necessary to switch to the (more efficient) directly allocated -- // representation (with capacity N and size <= N). -- iterator p = first; -- char* endp = (char*)&(*end()); -- if (!std::is_trivially_destructible::value) { -- while (p != last) { -- (*p).~T(); -- _size--; -- ++p; -- } -+ if (nVersion & ADDRV2_FORMAT) { -+ uint64_t services_tmp; -+ SER_WRITE(obj, services_tmp = obj.nServices); -+ READWRITE(Using>(services_tmp)); -+ SER_READ(obj, obj.nServices = static_cast(services_tmp)); - } else { -- _size -= last - p; -+ READWRITE(Using>(obj.nServices)); - } -- memmove(&(*first), &(*last), endp - ((char*)(&(*last)))); -- return first; -+ READWRITEAS(CService, obj); - } - -- template -- void emplace_back(Args&&... args) { -- size_type new_size = size() + 1; -- if (capacity() < new_size) { -- change_capacity(new_size + (new_size >> 1)); -- } -- new(item_ptr(size())) T(std::forward(args)...); -- _size++; -- } -+ // disk and network only -+ uint32_t nTime{TIME_INIT}; - -- void push_back(const T& value) { -- emplace_back(value); -- } -- -- void pop_back() { -- erase(end() - 1, end()); -- } -+ ServiceFlags nServices{NODE_NONE}; -+}; - -- T& front() { -- return *item_ptr(0); -- } -+/** getdata message type flags */ -+const uint32_t MSG_WITNESS_FLAG = 1 << 30; -+const uint32_t MSG_TYPE_MASK = 0xffffffff >> 2; - -- const T& front() const { -- return *item_ptr(0); -- } -- -- T& back() { -- return *item_ptr(size() - 1); -- } -- -- const T& back() const { -- return *item_ptr(size() - 1); -- } -+/** getdata / inv message types. -+ * These numbers are defined by the protocol. When adding a new value, be sure -+ * to mention it in the respective BIP. -+ */ -+enum GetDataMsg : uint32_t { -+ UNDEFINED = 0, -+ MSG_TX = 1, -+ MSG_BLOCK = 2, -+ MSG_WTX = 5, //!< Defined in BIP 339 -+ // The following can only occur in getdata. Invs always use TX/WTX or BLOCK. -+ MSG_FILTERED_BLOCK = 3, //!< Defined in BIP37 -+ MSG_CMPCT_BLOCK = 4, //!< Defined in BIP152 -+ MSG_WITNESS_BLOCK = MSG_BLOCK | MSG_WITNESS_FLAG, //!< Defined in BIP144 -+ MSG_WITNESS_TX = MSG_TX | MSG_WITNESS_FLAG, //!< Defined in BIP144 -+ // MSG_FILTERED_WITNESS_BLOCK is defined in BIP144 as reserved for future -+ // use and remains unused. -+ // MSG_FILTERED_WITNESS_BLOCK = MSG_FILTERED_BLOCK | MSG_WITNESS_FLAG, -+}; - -- void swap(prevector& other) { -- std::swap(_union, other._union); -- std::swap(_size, other._size); -- } -+/** inv message data */ -+class CInv -+{ -+public: -+ CInv(); -+ CInv(uint32_t typeIn, const uint256& hashIn); - -- ~prevector() { -- if (!std::is_trivially_destructible::value) { -- clear(); -- } -- if (!is_direct()) { -- free(_union.indirect_contents.indirect); -- _union.indirect_contents.indirect = nullptr; -- } -- } -+ SERIALIZE_METHODS(CInv, obj) { READWRITE(obj.type, obj.hash); } - -- bool operator==(const prevector& other) const { -- if (other.size() != size()) { -- return false; -- } -- const_iterator b1 = begin(); -- const_iterator b2 = other.begin(); -- const_iterator e1 = end(); -- while (b1 != e1) { -- if ((*b1) != (*b2)) { -- return false; -- } -- ++b1; -- ++b2; -- } -- return true; -- } -+ friend bool operator<(const CInv& a, const CInv& b); - -- bool operator!=(const prevector& other) const { -- return !(*this == other); -- } -+ std::string GetCommand() const; -+ std::string ToString() const; - -- bool operator<(const prevector& other) const { -- if (size() < other.size()) { -- return true; -- } -- if (size() > other.size()) { -- return false; -- } -- const_iterator b1 = begin(); -- const_iterator b2 = other.begin(); -- const_iterator e1 = end(); -- while (b1 != e1) { -- if ((*b1) < (*b2)) { -- return true; -- } -- if ((*b2) < (*b1)) { -- return false; -- } -- ++b1; -- ++b2; -- } -- return false; -- } -+ // Single-message helper methods -+ bool IsMsgTx() const { return type == MSG_TX; } -+ bool IsMsgBlk() const { return type == MSG_BLOCK; } -+ bool IsMsgWtx() const { return type == MSG_WTX; } -+ bool IsMsgFilteredBlk() const { return type == MSG_FILTERED_BLOCK; } -+ bool IsMsgCmpctBlk() const { return type == MSG_CMPCT_BLOCK; } -+ bool IsMsgWitnessBlk() const { return type == MSG_WITNESS_BLOCK; } - -- size_t allocated_memory() const { -- if (is_direct()) { -- return 0; -- } else { -- return ((size_t)(sizeof(T))) * _union.indirect_contents.capacity; -- } -+ // Combined-message helper methods -+ bool IsGenTxMsg() const -+ { -+ return type == MSG_TX || type == MSG_WTX || type == MSG_WITNESS_TX; - } -- -- value_type* data() { -- return item_ptr(0); -+ bool IsGenBlkMsg() const -+ { -+ return type == MSG_BLOCK || type == MSG_FILTERED_BLOCK || type == MSG_CMPCT_BLOCK || type == MSG_WITNESS_BLOCK; - } - -- const value_type* data() const { -- return item_ptr(0); -- } -+ uint32_t type; -+ uint256 hash; - }; - --#endif // BGL_PREVECTOR_H -+/** Convert a TX/WITNESS_TX/WTX CInv to a GenTxid. */ -+GenTxid ToGenTxid(const CInv& inv); -+ -+#endif // BGL_PROTOCOL_H -diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp -index 2765a090..20a51b74 100644 ---- a/src/rpc/mining.cpp -+++ b/src/rpc/mining.cpp -@@ -1,5 +1,5 @@ - // Copyright (c) 2010 Satoshi Nakamoto --// Copyright (c) 2009-2020 The BGL Core developers -+// Copyright (c) 2009-2020 The Bitcoin Core developers - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -@@ -164,15 +164,23 @@ static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& me - ++nHeight; - blockHashes.push_back(block_hash.GetHex()); - } -- while (nMaxTries > 0 && pblock->nNonce < std::numeric_limits::max() && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus()) && !ShutdownRequested()) { -- ++pblock->nNonce; -- --nMaxTries; -- } -- if (nMaxTries == 0 || ShutdownRequested()) { -- break; -+ } -+ return blockHashes; -+} -+ -+static bool getScriptFromDescriptor(const std::string& descriptor, CScript& script, std::string& error) -+{ -+ FlatSigningProvider key_provider; -+ const auto desc = Parse(descriptor, key_provider, error, /* require_checksum = */ false); -+ if (desc) { -+ if (desc->IsRange()) { -+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptor not accepted. Maybe pass through deriveaddresses first?"); - } -- if (pblock->nNonce == std::numeric_limits::max()) { -- continue; -+ -+ FlatSigningProvider provider; -+ std::vector scripts; -+ if (!desc->Expand(0, key_provider, scripts, provider)) { -+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys")); - } - - // Combo descriptors can have 2 or 4 scripts, so we can't just check scripts.size() == 1 -@@ -187,13 +195,11 @@ static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& me - // Else take the 2nd script, since it is p2pkh - script = scripts.at(1); - } -- std::shared_ptr shared_pblock = std::make_shared(*pblock); -- if (!ProcessNewBlock(Params(), shared_pblock, true, nullptr)) -- throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); -- ++nHeight; -- blockHashes.push_back(pblock->GetHash().GetHex()); -+ -+ return true; -+ } else { -+ return false; - } -- return blockHashes; - } - - static RPCHelpMan generatetodescriptor() -@@ -219,21 +225,11 @@ static RPCHelpMan generatetodescriptor() - const int num_blocks{request.params[0].get_int()}; - const uint64_t max_tries{request.params[2].isNull() ? DEFAULT_MAX_TRIES : request.params[2].get_int()}; - -- FlatSigningProvider key_provider; -+ CScript coinbase_script; - std::string error; -- const auto desc = Parse(request.params[1].get_str(), key_provider, error, /* require_checksum = */ false); -- if (!desc) { -+ if (!getScriptFromDescriptor(request.params[1].get_str(), coinbase_script, error)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error); - } -- if (desc->IsRange()) { -- throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptor not accepted. Maybe pass through deriveaddresses first?"); -- } -- -- FlatSigningProvider provider; -- std::vector coinbase_script; -- if (!desc->Expand(0, key_provider, coinbase_script, provider)) { -- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys")); -- } - - const CTxMemPool& mempool = EnsureMemPool(request.context); - ChainstateManager& chainman = EnsureChainman(request.context); -@@ -246,12 +242,7 @@ static RPCHelpMan generatetodescriptor() - static RPCHelpMan generate() - { - return RPCHelpMan{"generate", "has been replaced by the -generate cli option. Refer to -help for more information.", {}, {}, RPCExamples{""}, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { -- -- if (request.fHelp) { -- throw std::runtime_error(self.ToString()); -- } else { - throw JSONRPCError(RPC_METHOD_NOT_FOUND, self.ToString()); -- } - }}; - } - -@@ -262,8 +253,12 @@ static RPCHelpMan generatetoaddress() - { - {"nblocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated immediately."}, - {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The address to send the newly generated BGL to."}, -+ {"maxtries", RPCArg::Type::NUM, /* default */ ToString(DEFAULT_MAX_TRIES), "How many iterations to try."}, -+ }, -+ RPCResult{ - RPCResult::Type::ARR, "", "hashes of blocks generated", - { -+ {RPCResult::Type::STR_HEX, "", "blockhash"}, - }}, - RPCExamples{ - "\nGenerate 11 blocks to myaddress\n" -@@ -812,6 +807,8 @@ static RPCHelpMan getblocktemplate() - result.pushKV("capabilities", aCaps); - - UniValue aRules(UniValue::VARR); -+ aRules.push_back("csv"); -+ if (!fPreSegWit) aRules.push_back("!segwit"); - UniValue vbavailable(UniValue::VOBJ); - for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { - Consensus::DeploymentPos pos = Consensus::DeploymentPos(j); -diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp -index 554ff7ad..40630496 100644 ---- a/src/rpc/net.cpp -+++ b/src/rpc/net.cpp -@@ -1,4 +1,4 @@ --// Copyright (c) 2009-2020 The BGL Core developers -+// Copyright (c) 2009-2020 The Bitcoin Core developers - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -@@ -288,10 +288,10 @@ static RPCHelpMan addnode() - std::string strCommand; - if (!request.params[1].isNull()) - strCommand = request.params[1].get_str(); -- if (request.fHelp || request.params.size() != 2 || -- (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) -+ if (strCommand != "onetry" && strCommand != "add" && strCommand != "remove") { - throw std::runtime_error( - self.ToString()); -+ } - - NodeContext& node = EnsureNodeContext(request.context); - if(!node.connman) -@@ -497,11 +497,9 @@ static RPCHelpMan getnettotals() - static UniValue GetNetworksInfo() - { - UniValue networks(UniValue::VARR); -- for(int n=0; n(n); -- if(network == NET_UNROUTABLE || network == NET_INTERNAL) -- continue; -+ if (network == NET_UNROUTABLE || network == NET_I2P || network == NET_CJDNS || network == NET_INTERNAL) continue; - proxyType proxy; - UniValue obj(UniValue::VOBJ); - GetProxy(network, proxy); -@@ -630,7 +628,7 @@ static RPCHelpMan setban() - std::string strCommand; - if (!request.params[1].isNull()) - strCommand = request.params[1].get_str(); -- if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) { -+ if (strCommand != "add" && strCommand != "remove") { - throw std::runtime_error(help.ToString()); - } - NodeContext& node = EnsureNodeContext(request.context); -@@ -658,8 +656,7 @@ static RPCHelpMan setban() - - if (strCommand == "add") - { -- if ((isSubnet && node.banman->IsBanned(subNet)) || -- (!isSubnet && node.banman->IsBannedLevel(netAddr) == BanReasonManuallyAdded)) { -+ if (isSubnet ? node.banman->IsBanned(subNet) : node.banman->IsBanned(netAddr)) { - throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); - } - -diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp -index 3fd607bd..40aaf91e 100644 ---- a/src/script/interpreter.cpp -+++ b/src/script/interpreter.cpp -@@ -446,7 +446,7 @@ bool EvalScript(std::vector >& stack, const CScript& - CScript::const_iterator pbegincodehash = script.begin(); - opcodetype opcode; - valtype vchPushValue; -- std::vector vfExec; -+ ConditionStack vfExec; - std::vector altstack; - set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); - if ((sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) && script.size() > MAX_SCRIPT_SIZE) { -@@ -662,7 +662,7 @@ bool EvalScript(std::vector >& stack, const CScript& - { - if (vfExec.empty()) - return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); -- vfExec.back() = !vfExec.back(); -+ vfExec.toggle_top(); - } - break; - -diff --git a/src/script/standard.cpp b/src/script/standard.cpp -index d860b6e7..f2f81664 100644 ---- a/src/script/standard.cpp -+++ b/src/script/standard.cpp -@@ -1,5 +1,5 @@ - // Copyright (c) 2009-2010 Satoshi Nakamoto --// Copyright (c) 2009-2019 The BGL Core developers -+// Copyright (c) 2009-2019 The Bitcoin Core developers - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -@@ -22,11 +22,8 @@ CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast(in)) - ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {} - ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast(in)) {} - --PKHash::PKHash(const CPubKey& pubkey) : uint160(pubkey.GetID()) {} --PKHash::PKHash(const CKeyID& pubkey_id) : uint160(pubkey_id) {} -- --WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : uint160(pubkey.GetID()) {} --WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : uint160(static_cast(pubkey_hash)) {} -+PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {} -+PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {} - - WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {} - WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash(static_cast(pubkey_hash)) {} -diff --git a/src/script/standard.h b/src/script/standard.h -index 41adf11c..9fe9892e 100644 ---- a/src/script/standard.h -+++ b/src/script/standard.h -@@ -1,5 +1,5 @@ - // Copyright (c) 2009-2010 Satoshi Nakamoto --// Copyright (c) 2009-2020 The BGL Core developers -+// Copyright (c) 2009-2020 The Bitcoin Core developers - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -@@ -28,7 +28,7 @@ protected: - - public: - BaseHash() : m_hash() {} -- explicit BaseHash(const HashType& in) : m_hash(in) {} -+ BaseHash(const HashType& in) : m_hash(in) {} - - unsigned char* begin() - { -@@ -90,7 +90,7 @@ class CScriptID : public BaseHash - public: - CScriptID() : BaseHash() {} - explicit CScriptID(const CScript& in); -- explicit CScriptID(const uint160& in) : uint160(in) {} -+ explicit CScriptID(const uint160& in) : BaseHash(in) {} - explicit CScriptID(const ScriptHash& in); - }; - -@@ -114,7 +114,7 @@ extern unsigned nMaxDatacarrierBytes; - * them to be valid. (but old blocks may not comply with) Currently just P2SH, - * but in the future other flags may be added. - * -- * Failing one of these tests may trigger a DoS ban - see CheckInputs() for -+ * Failing one of these tests may trigger a DoS ban - see CheckInputScripts() for - * details. - */ - static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH; -@@ -209,7 +209,7 @@ struct WitnessUnknown - * * WitnessV0KeyHash: TxoutType::WITNESS_V0_KEYHASH destination (P2WPKH) - * * WitnessUnknown: TxoutType::WITNESS_UNKNOWN/WITNESS_V1_TAPROOT destination (P2W???) - * (taproot outputs do not require their own type as long as no wallet support exists) -- * A CTxDestination is the internal data type encoded in a bitcoin address -+ * A CTxDestination is the internal data type encoded in a BGL address - */ - typedef boost::variant CTxDestination; - -diff --git a/src/secp256k1/.gitignore b/src/secp256k1/.gitignore -index 55d325ae..ccdef02b 100644 ---- a/src/secp256k1/.gitignore -+++ b/src/secp256k1/.gitignore -@@ -1,14 +1,15 @@ - bench_inv - bench_ecdh - bench_ecmult -+bench_schnorrsig - bench_sign - bench_verify --bench_schnorr_verify - bench_recover - bench_internal - tests - exhaustive_tests - gen_context -+valgrind_ctime_test - *.exe - *.so - *.a -@@ -30,6 +31,8 @@ libtool - *.lo - *.o - *~ -+*.log -+*.trs - src/libsecp256k1-config.h - src/libsecp256k1-config.h.in - src/ecmult_static_context.h -diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml -index 74f658f4..ce8d6391 100644 ---- a/src/secp256k1/.travis.yml -+++ b/src/secp256k1/.travis.yml -@@ -1,68 +1,108 @@ - language: c --os: linux -+os: -+ - linux -+ - osx -+ -+dist: bionic -+# Valgrind currently supports upto macOS 10.13, the latest xcode of that version is 10.1 -+osx_image: xcode10.1 - addons: - apt: -- packages: libgmp-dev -+ packages: -+ - libgmp-dev -+ - valgrind -+ - libtool-bin - compiler: - - clang - - gcc --cache: -- directories: -- - src/java/guava/ - env: - global: -- - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no JNI=no -- - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar -+ - WIDEMUL=auto BIGNUM=auto STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check WITH_VALGRIND=yes RUN_VALGRIND=no EXTRAFLAGS= HOST= ECDH=no RECOVERY=no SCHNORRSIG=no EXPERIMENTAL=no CTIMETEST=yes BENCH=yes ITERS=2 - matrix: -- - SCALAR=32bit RECOVERY=yes -- - SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes -- - SCALAR=64bit -- - FIELD=64bit RECOVERY=yes -- - FIELD=64bit ENDOMORPHISM=yes -- - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes -- - FIELD=64bit ASM=x86_64 -- - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 -- - FIELD=32bit ENDOMORPHISM=yes -+ - WIDEMUL=int64 RECOVERY=yes -+ - WIDEMUL=int64 ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes -+ - WIDEMUL=int128 -+ - WIDEMUL=int128 RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes -+ - WIDEMUL=int128 ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes -+ - WIDEMUL=int128 ASM=x86_64 - - BIGNUM=no -- - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes -+ - BIGNUM=no RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes - - BIGNUM=no STATICPRECOMPUTATION=no -- - BUILD=distcheck -- - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC -- - EXTRAFLAGS=CFLAGS=-O0 -- - BUILD=check-java JNI=yes ECDH=yes EXPERIMENTAL=yes -+ - BUILD=distcheck WITH_VALGRIND=no CTIMETEST=no BENCH=no -+ - CPPFLAGS=-DDETERMINISTIC -+ - CFLAGS=-O0 CTIMETEST=no -+ - ECMULTGENPRECISION=2 -+ - ECMULTGENPRECISION=8 -+ - RUN_VALGRIND=yes BIGNUM=no ASM=x86_64 ECDH=yes RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes EXTRAFLAGS="--disable-openssl-tests" BUILD= - matrix: - fast_finish: true - include: - - compiler: clang -- env: HOST=i686-linux-gnu ENDOMORPHISM=yes -+ os: linux -+ env: HOST=i686-linux-gnu - addons: - apt: - packages: - - gcc-multilib - - libgmp-dev:i386 -+ - valgrind -+ - libtool-bin -+ - libc6-dbg:i386 - - compiler: clang - env: HOST=i686-linux-gnu -+ os: linux - addons: - apt: - packages: - - gcc-multilib -+ - valgrind -+ - libtool-bin -+ - libc6-dbg:i386 - - compiler: gcc -- env: HOST=i686-linux-gnu ENDOMORPHISM=yes -+ env: HOST=i686-linux-gnu -+ os: linux - addons: - apt: - packages: - - gcc-multilib -+ - valgrind -+ - libtool-bin -+ - libc6-dbg:i386 - - compiler: gcc -+ os: linux - env: HOST=i686-linux-gnu - addons: - apt: - packages: - - gcc-multilib - - libgmp-dev:i386 --before_install: mkdir -p `dirname $GUAVA_JAR` --install: if [ ! -f $GUAVA_JAR ]; then wget $GUAVA_URL -O $GUAVA_JAR; fi -+ - valgrind -+ - libtool-bin -+ - libc6-dbg:i386 -+ # S390x build (big endian system) -+ - compiler: gcc -+ env: HOST=s390x-unknown-linux-gnu ECDH=yes RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes CTIMETEST= -+ arch: s390x -+ -+# We use this to install macOS dependencies instead of the built in `homebrew` plugin, -+# because in xcode earlier than 11 they have a bug requiring updating the system which overall takes ~8 minutes. -+# https://travis-ci.community/t/macos-build-fails-because-of-homebrew-bundle-unknown-command/7296 -+before_install: -+ - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then HOMEBREW_NO_AUTO_UPDATE=1 brew install gmp valgrind gcc@9; fi -+ - before_script: ./autogen.sh -+ -+# travis auto terminates jobs that go for 10 minutes without printing to stdout, but travis_wait doesn't work well with forking programs like valgrind (https://docs.travis-ci.com/user/common-build-problems/#build-times-out-because-no-output-was-received https://github.com/bitcoin-core/secp256k1/pull/750#issuecomment-623476860) - script: -- - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi -- - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi -- - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY --enable-jni=$JNI $EXTRAFLAGS $USE_HOST && make -j2 $BUILD -+ - function keep_alive() { while true; do echo -en "\a"; sleep 60; done } -+ - keep_alive & -+ - ./contrib/travis.sh -+ - kill %keep_alive -+ -+after_script: -+ - cat ./tests.log -+ - cat ./exhaustive_tests.log -+ - cat ./valgrind_ctime_test.log -+ - cat ./bench.log -+ - $CC --version -+ - valgrind --version -diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am -index b55a7f62..023fa606 100644 ---- a/src/secp256k1/Makefile.am -+++ b/src/secp256k1/Makefile.am -@@ -1,13 +1,8 @@ - ACLOCAL_AMFLAGS = -I build-aux/m4 - - lib_LTLIBRARIES = libsecp256k1.la --if USE_JNI --JNI_LIB = libsecp256k1_jni.la --noinst_LTLIBRARIES = $(JNI_LIB) --else --JNI_LIB = --endif - include_HEADERS = include/secp256k1.h -+include_HEADERS += include/secp256k1_preallocated.h - noinst_HEADERS = - noinst_HEADERS += src/scalar.h - noinst_HEADERS += src/scalar_4x64.h -@@ -39,11 +34,11 @@ noinst_HEADERS += src/field_5x52.h - noinst_HEADERS += src/field_5x52_impl.h - noinst_HEADERS += src/field_5x52_int128_impl.h - noinst_HEADERS += src/field_5x52_asm_impl.h --noinst_HEADERS += src/java/org_BGL_NativeSecp256k1.h --noinst_HEADERS += src/java/org_BGL_Secp256k1Context.h -+noinst_HEADERS += src/assumptions.h - noinst_HEADERS += src/util.h - noinst_HEADERS += src/scratch.h - noinst_HEADERS += src/scratch_impl.h -+noinst_HEADERS += src/selftest.h - noinst_HEADERS += src/testrand.h - noinst_HEADERS += src/testrand_impl.h - noinst_HEADERS += src/hash.h -@@ -74,16 +69,19 @@ endif - - libsecp256k1_la_SOURCES = src/secp256k1.c - libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) --libsecp256k1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) $(COMMON_LIB) -+libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) - --libsecp256k1_jni_la_SOURCES = src/java/org_BGL_NativeSecp256k1.c src/java/org_BGL_Secp256k1Context.c --libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) -+if VALGRIND_ENABLED -+libsecp256k1_la_CPPFLAGS += -DVALGRIND -+endif - - noinst_PROGRAMS = - if USE_BENCHMARK - noinst_PROGRAMS += bench_verify bench_sign bench_internal bench_ecmult - bench_verify_SOURCES = src/bench_verify.c - bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) -+# SECP_TEST_INCLUDES are only used here for CRYPTO_CPPFLAGS -+bench_verify_CPPFLAGS = -DSECP256K1_BUILD $(SECP_TEST_INCLUDES) - bench_sign_SOURCES = src/bench_sign.c - bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) - bench_internal_SOURCES = src/bench_internal.c -@@ -99,6 +97,12 @@ if USE_TESTS - noinst_PROGRAMS += tests - tests_SOURCES = src/tests.c - tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) -+if VALGRIND_ENABLED -+tests_CPPFLAGS += -DVALGRIND -+noinst_PROGRAMS += valgrind_ctime_test -+valgrind_ctime_test_SOURCES = src/valgrind_ctime_test.c -+valgrind_ctime_test_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_LIBS) $(COMMON_LIB) -+endif - if !ENABLE_COVERAGE - tests_CPPFLAGS += -DVERIFY - endif -@@ -119,42 +123,12 @@ exhaustive_tests_LDFLAGS = -static - TESTS += exhaustive_tests - endif - --JAVAROOT=src/java --JAVAORG=org/BGL --JAVA_GUAVA=$(srcdir)/$(JAVAROOT)/guava/guava-18.0.jar --CLASSPATH_ENV=CLASSPATH=$(JAVA_GUAVA) --JAVA_FILES= \ -- $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1.java \ -- $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Test.java \ -- $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Util.java \ -- $(JAVAROOT)/$(JAVAORG)/Secp256k1Context.java -- --if USE_JNI -- --$(JAVA_GUAVA): -- @echo Guava is missing. Fetch it via: \ -- wget https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar -O $(@) -- @false -- --.stamp-java: $(JAVA_FILES) -- @echo Compiling $^ -- $(AM_V_at)$(CLASSPATH_ENV) javac $^ -- @touch $@ -- --if USE_TESTS -- --check-java: libsecp256k1.la $(JAVA_GUAVA) .stamp-java -- $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -cp "$(JAVA_GUAVA):$(JAVAROOT)" $(JAVAORG)/NativeSecp256k1Test -- --endif --endif -- - if USE_ECMULT_STATIC_PRECOMPUTATION --CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -+CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -I$(builddir)/src - - gen_context_OBJECTS = gen_context.o - gen_context_BIN = gen_context$(BUILD_EXEEXT) --gen_%.o: src/gen_%.c -+gen_%.o: src/gen_%.c src/libsecp256k1-config.h - $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ - - $(gen_context_BIN): $(gen_context_OBJECTS) -@@ -168,10 +142,10 @@ $(bench_ecmult_OBJECTS): src/ecmult_static_context.h - src/ecmult_static_context.h: $(gen_context_BIN) - ./$(gen_context_BIN) - --CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVAROOT)/$(JAVAORG)/*.class .stamp-java -+CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h - endif - --EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) -+EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h - - if ENABLE_MODULE_ECDH - include src/modules/ecdh/Makefile.am.include -@@ -180,3 +154,11 @@ endif - if ENABLE_MODULE_RECOVERY - include src/modules/recovery/Makefile.am.include - endif -+ -+if ENABLE_MODULE_EXTRAKEYS -+include src/modules/extrakeys/Makefile.am.include -+endif -+ -+if ENABLE_MODULE_SCHNORRSIG -+include src/modules/schnorrsig/Makefile.am.include -+endif -diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md -index bfdc5e05..e0709372 100644 ---- a/src/secp256k1/README.md -+++ b/src/secp256k1/README.md -@@ -1,19 +1,24 @@ - libsecp256k1 - ============ - --[![Build Status](https://travis-ci.org/BGL-core/secp256k1.svg?branch=master)](https://travis-ci.org/BGL-core/secp256k1) -+[![Build Status](https://travis-ci.org/bitcoin-core/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin-core/secp256k1) - --Optimized C library for EC operations on curve secp256k1. -+Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1. - --This library is a work in progress and is being used to research best practices. Use at your own risk. -+This library is intended to be the highest quality publicly available library for cryptography on the secp256k1 curve. However, the primary focus of its development has been for usage in the Bitcoin system and usage unlike Bitcoin's may be less well tested, verified, or suffer from a less well thought out interface. Correct usage requires some care and consideration that the library is fit for your application's purpose. - - Features: - * secp256k1 ECDSA signing/verification and key generation. --* Adding/multiplying private/public keys. --* Serialization/parsing of private keys, public keys, signatures. --* Constant time, constant memory access signing and pubkey generation. --* Derandomized DSA (via RFC6979 or with a caller provided function.) -+* Additive and multiplicative tweaking of secret/public keys. -+* Serialization/parsing of secret keys, public keys, signatures. -+* Constant time, constant memory access signing and public key generation. -+* Derandomized ECDSA (via RFC6979 or with a caller provided function.) - * Very efficient implementation. -+* Suitable for embedded systems. -+* Optional module for public key recovery. -+* Optional module for ECDH key exchange. -+ -+Experimental features have not received enough scrutiny to satisfy the standard of quality of this library but are made available for testing and review by the community. The APIs of these features should not be considered stable. - - Implementation details - ---------------------- -@@ -23,11 +28,12 @@ Implementation details - * Extensive testing infrastructure. - * Structured to facilitate review and analysis. - * Intended to be portable to any system with a C89 compiler and uint64_t support. -+ * No use of floating types. - * Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.") - * Field operations - * Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1). - * Using 5 52-bit limbs (including hand-optimized assembly for x86_64, by Diederik Huys). -- * Using 10 26-bit limbs. -+ * Using 10 26-bit limbs (including hand-optimized assembly for 32-bit ARM, by Wladimir J. van der Laan). - * Field inverses and square roots using a sliding window over blocks of 1s (by Peter Dettman). - * Scalar operations - * Optimized implementation without data-dependent branches of arithmetic modulo the curve's order. -@@ -42,12 +48,14 @@ Implementation details - * Use wNAF notation for point multiplicands. - * Use a much larger window for multiples of G, using precomputed multiples. - * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. -- * Optionally (off by default) use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. -+ * Use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. - * Point multiplication for signing - * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. -- * Access the table with branch-free conditional moves so memory access is uniform. -- * No data-dependent branches -- * The precomputed tables add and eventually subtract points for which no known scalar (private key) is known, preventing even an attacker with control over the private key used to control the data internally. -+ * Intended to be completely free of timing sidechannels for secret-key operations (on reasonable hardware/toolchains) -+ * Access the table with branch-free conditional moves so memory access is uniform. -+ * No data-dependent branches -+ * Optional runtime blinding which attempts to frustrate differential power analysis. -+ * The precomputed tables add and eventually subtract points for which no known scalar (secret key) is known, preventing even an attacker with control over the secret key used to control the data internally. - - Build steps - ----------- -@@ -57,5 +65,40 @@ libsecp256k1 is built using autotools: - $ ./autogen.sh - $ ./configure - $ make -- $ ./tests -+ $ make check - $ sudo make install # optional -+ -+Exhaustive tests -+----------- -+ -+ $ ./exhaustive_tests -+ -+With valgrind, you might need to increase the max stack size: -+ -+ $ valgrind --max-stackframe=2500000 ./exhaustive_tests -+ -+Test coverage -+----------- -+ -+This library aims to have full coverage of the reachable lines and branches. -+ -+To create a test coverage report, configure with `--enable-coverage` (use of GCC is necessary): -+ -+ $ ./configure --enable-coverage -+ -+Run the tests: -+ -+ $ make check -+ -+To create a report, `gcovr` is recommended, as it includes branch coverage reporting: -+ -+ $ gcovr --exclude 'src/bench*' --print-summary -+ -+To create a HTML report with coloured and annotated source code: -+ -+ $ gcovr --exclude 'src/bench*' --html --html-details -o coverage.html -+ -+Reporting a vulnerability -+------------ -+ -+See [SECURITY.md](SECURITY.md) -diff --git a/src/secp256k1/build-aux/m4/BGL_secp.m4 b/src/secp256k1/build-aux/m4/BGL_secp.m4 -deleted file mode 100644 -index ece3d655..00000000 ---- a/src/secp256k1/build-aux/m4/BGL_secp.m4 -+++ /dev/null -@@ -1,89 +0,0 @@ --dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. --AC_DEFUN([SECP_64BIT_ASM_CHECK],[ --AC_MSG_CHECKING(for x86_64 assembly availability) --AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -- #include ]],[[ -- uint64_t a = 11, tmp; -- __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); -- ]])],[has_64bit_asm=yes],[has_64bit_asm=no]) --AC_MSG_RESULT([$has_64bit_asm]) --]) -- --dnl --AC_DEFUN([SECP_OPENSSL_CHECK],[ -- has_libcrypto=no -- m4_ifdef([PKG_CHECK_MODULES],[ -- PKG_CHECK_MODULES([CRYPTO], [libcrypto], [has_libcrypto=yes],[has_libcrypto=no]) -- if test x"$has_libcrypto" = x"yes"; then -- TEMP_LIBS="$LIBS" -- LIBS="$LIBS $CRYPTO_LIBS" -- AC_CHECK_LIB(crypto, main,[AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])],[has_libcrypto=no]) -- LIBS="$TEMP_LIBS" -- fi -- ]) -- if test x$has_libcrypto = xno; then -- AC_CHECK_HEADER(openssl/crypto.h,[ -- AC_CHECK_LIB(crypto, main,[ -- has_libcrypto=yes -- CRYPTO_LIBS=-lcrypto -- AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed]) -- ]) -- ]) -- LIBS= -- fi --if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then -- AC_MSG_CHECKING(for EC functions in libcrypto) -- CPPFLAGS_TEMP="$CPPFLAGS" -- CPPFLAGS="$CRYPTO_CPPFLAGS $CPPFLAGS" -- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -- #include -- #include -- #include -- #include ]],[[ -- # if OPENSSL_VERSION_NUMBER < 0x10100000L -- void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) {(void)sig->r; (void)sig->s;} -- # endif -- -- unsigned int zero = 0; -- const unsigned char *zero_ptr = (unsigned char*)&zero; -- EC_KEY_free(EC_KEY_new_by_curve_name(NID_secp256k1)); -- EC_KEY *eckey = EC_KEY_new(); -- EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1); -- EC_KEY_set_group(eckey, group); -- ECDSA_sign(0, NULL, 0, NULL, &zero, eckey); -- ECDSA_verify(0, NULL, 0, NULL, 0, eckey); -- o2i_ECPublicKey(&eckey, &zero_ptr, 0); -- d2i_ECPrivateKey(&eckey, &zero_ptr, 0); -- EC_KEY_check_key(eckey); -- EC_KEY_free(eckey); -- EC_GROUP_free(group); -- ECDSA_SIG *sig_openssl; -- sig_openssl = ECDSA_SIG_new(); -- d2i_ECDSA_SIG(&sig_openssl, &zero_ptr, 0); -- i2d_ECDSA_SIG(sig_openssl, NULL); -- ECDSA_SIG_get0(sig_openssl, NULL, NULL); -- ECDSA_SIG_free(sig_openssl); -- const BIGNUM *bignum = BN_value_one(); -- BN_is_negative(bignum); -- BN_num_bits(bignum); -- if (sizeof(zero) >= BN_num_bytes(bignum)) { -- BN_bn2bin(bignum, (unsigned char*)&zero); -- } -- ]])],[has_openssl_ec=yes],[has_openssl_ec=no]) -- AC_MSG_RESULT([$has_openssl_ec]) -- CPPFLAGS="$CPPFLAGS_TEMP" --fi --]) -- --dnl --AC_DEFUN([SECP_GMP_CHECK],[ --if test x"$has_gmp" != x"yes"; then -- CPPFLAGS_TEMP="$CPPFLAGS" -- CPPFLAGS="$GMP_CPPFLAGS $CPPFLAGS" -- LIBS_TEMP="$LIBS" -- LIBS="$GMP_LIBS $LIBS" -- AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS="$GMP_LIBS -lgmp"; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])]) -- CPPFLAGS="$CPPFLAGS_TEMP" -- LIBS="$LIBS_TEMP" --fi --]) -diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac -index 3b7a328c..eb3b449b 100644 ---- a/src/secp256k1/configure.ac -+++ b/src/secp256k1/configure.ac -@@ -7,6 +7,11 @@ AH_TOP([#ifndef LIBSECP256K1_CONFIG_H]) - AH_TOP([#define LIBSECP256K1_CONFIG_H]) - AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/]) - AM_INIT_AUTOMAKE([foreign subdir-objects]) -+ -+# Set -g if CFLAGS are not already set, which matches the default autoconf -+# behavior (see PROG_CC in the Autoconf manual) with the exception that we don't -+# set -O2 here because we set it in any case (see further down). -+: ${CFLAGS="-g"} - LT_INIT - - dnl make the compilation flags quiet unless V=1 is used -@@ -19,10 +24,6 @@ AC_PATH_TOOL(RANLIB, ranlib) - AC_PATH_TOOL(STRIP, strip) - AX_PROG_CC_FOR_BUILD - --if test "x$CFLAGS" = "x"; then -- CFLAGS="-g" --fi -- - AM_PROG_CC_C_O - - AC_PROG_CC_C89 -@@ -45,6 +46,7 @@ case $host_os in - if test x$openssl_prefix != x; then - PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" - export PKG_CONFIG_PATH -+ CRYPTO_CPPFLAGS="-I$openssl_prefix/include" - fi - if test x$gmp_prefix != x; then - GMP_CPPFLAGS="-I$gmp_prefix/include" -@@ -63,11 +65,11 @@ case $host_os in - ;; - esac - --CFLAGS="$CFLAGS -W" -+CFLAGS="-W $CFLAGS" - --warn_CFLAGS="-std=c89 -pedantic -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -Wno-long-long -Wno-overlength-strings" -+warn_CFLAGS="-std=c89 -pedantic -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef -Wno-unused-function -Wno-long-long -Wno-overlength-strings" - saved_CFLAGS="$CFLAGS" --CFLAGS="$CFLAGS $warn_CFLAGS" -+CFLAGS="$warn_CFLAGS $CFLAGS" - AC_MSG_CHECKING([if ${CC} supports ${warn_CFLAGS}]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], -@@ -76,7 +78,7 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - ]) - - saved_CFLAGS="$CFLAGS" --CFLAGS="$CFLAGS -fvisibility=hidden" -+CFLAGS="-fvisibility=hidden $CFLAGS" - AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], -@@ -85,80 +87,114 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - ]) - - AC_ARG_ENABLE(benchmark, -- AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is yes)]), -+ AS_HELP_STRING([--enable-benchmark],[compile benchmark [default=yes]]), - [use_benchmark=$enableval], - [use_benchmark=yes]) - - AC_ARG_ENABLE(coverage, -- AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]), -+ AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis [default=no]]), - [enable_coverage=$enableval], - [enable_coverage=no]) - - AC_ARG_ENABLE(tests, -- AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), -+ AS_HELP_STRING([--enable-tests],[compile tests [default=yes]]), - [use_tests=$enableval], - [use_tests=yes]) - - AC_ARG_ENABLE(openssl_tests, -- AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests, if OpenSSL is available (default is auto)]), -+ AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests [default=auto]]), - [enable_openssl_tests=$enableval], - [enable_openssl_tests=auto]) - - AC_ARG_ENABLE(experimental, -- AS_HELP_STRING([--enable-experimental],[allow experimental configure options (default is no)]), -+ AS_HELP_STRING([--enable-experimental],[allow experimental configure options [default=no]]), - [use_experimental=$enableval], - [use_experimental=no]) - - AC_ARG_ENABLE(exhaustive_tests, -- AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]), -+ AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests [default=yes]]), - [use_exhaustive_tests=$enableval], - [use_exhaustive_tests=yes]) - --AC_ARG_ENABLE(endomorphism, -- AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), -- [use_endomorphism=$enableval], -- [use_endomorphism=no]) -- - AC_ARG_ENABLE(ecmult_static_precomputation, -- AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing (default is yes)]), -+ AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing [default=auto]]), - [use_ecmult_static_precomputation=$enableval], - [use_ecmult_static_precomputation=auto]) - - AC_ARG_ENABLE(module_ecdh, -- AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (experimental)]), -+ AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation]), - [enable_module_ecdh=$enableval], - [enable_module_ecdh=no]) - - AC_ARG_ENABLE(module_recovery, -- AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]), -+ AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module [default=no]]), - [enable_module_recovery=$enableval], - [enable_module_recovery=no]) - --AC_ARG_ENABLE(jni, -- AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is no)]), -- [use_jni=$enableval], -- [use_jni=no]) -+AC_ARG_ENABLE(module_extrakeys, -+ AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module (experimental)]), -+ [enable_module_extrakeys=$enableval], -+ [enable_module_extrakeys=no]) - --AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], --[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) -+AC_ARG_ENABLE(module_schnorrsig, -+ AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module (experimental)]), -+ [enable_module_schnorrsig=$enableval], -+ [enable_module_schnorrsig=no]) - --AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto], --[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto]) -- --AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto], --[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto]) -+AC_ARG_ENABLE(external_default_callbacks, -+ AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), -+ [use_external_default_callbacks=$enableval], -+ [use_external_default_callbacks=no]) - --AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto] --[Specify assembly optimizations to use. Default is auto (experimental: arm)])],[req_asm=$withval], [req_asm=auto]) -+dnl Test-only override of the (autodetected by the C code) "widemul" setting. -+dnl Legal values are int64 (for [u]int64_t), int128 (for [unsigned] __int128), and auto (the default). -+AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto]) - --AC_CHECK_TYPES([__int128]) -+AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto], -+[bignum implementation to use [default=auto]])],[req_bignum=$withval], [req_bignum=auto]) -+ -+AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto], -+[assembly optimizations to use (experimental: arm) [default=auto]])],[req_asm=$withval], [req_asm=auto]) -+ -+AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto], -+[window size for ecmult precomputation for verification, specified as integer in range [2..24].] -+[Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.] -+[The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.] -+["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]] -+)], -+[req_ecmult_window=$withval], [req_ecmult_window=auto]) -+ -+AC_ARG_WITH([ecmult-gen-precision], [AS_HELP_STRING([--with-ecmult-gen-precision=2|4|8|auto], -+[Precision bits to tune the precomputed table size for signing.] -+[The size of the table is 32kB for 2 bits, 64kB for 4 bits, 512kB for 8 bits of precision.] -+[A larger table size usually results in possible faster signing.] -+["auto" is a reasonable setting for desktop machines (currently 4). [default=auto]] -+)], -+[req_ecmult_gen_precision=$withval], [req_ecmult_gen_precision=auto]) -+ -+AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind=yes|no|auto], -+[Build with extra checks for running inside Valgrind [default=auto]] -+)], -+[req_valgrind=$withval], [req_valgrind=auto]) -+ -+if test x"$req_valgrind" = x"no"; then -+ enable_valgrind=no -+else -+ AC_CHECK_HEADER([valgrind/memcheck.h], [enable_valgrind=yes], [ -+ if test x"$req_valgrind" = x"yes"; then -+ AC_MSG_ERROR([Valgrind support explicitly requested but valgrind/memcheck.h header not available]) -+ fi -+ enable_valgrind=no -+ ], []) -+fi -+AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"]) - - if test x"$enable_coverage" = x"yes"; then - AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code]) -- CFLAGS="$CFLAGS -O0 --coverage" -- LDFLAGS="--coverage" -+ CFLAGS="-O0 --coverage $CFLAGS" -+ LDFLAGS="--coverage $LDFLAGS" - else -- CFLAGS="$CFLAGS -O3" -+ CFLAGS="-O2 $CFLAGS" - fi - - if test x"$use_ecmult_static_precomputation" != x"no"; then -@@ -176,7 +212,7 @@ if test x"$use_ecmult_static_precomputation" != x"no"; then - - warn_CFLAGS_FOR_BUILD="-Wall -Wextra -Wno-unused-function" - saved_CFLAGS="$CFLAGS" -- CFLAGS="$CFLAGS $warn_CFLAGS_FOR_BUILD" -+ CFLAGS="$warn_CFLAGS_FOR_BUILD $CFLAGS" - AC_MSG_CHECKING([if native ${CC_FOR_BUILD} supports ${warn_CFLAGS_FOR_BUILD}]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], -@@ -188,7 +224,7 @@ if test x"$use_ecmult_static_precomputation" != x"no"; then - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([], [])], - [working_native_cc=yes], -- [working_native_cc=no],[dnl]) -+ [working_native_cc=no],[:]) - - CFLAGS_FOR_BUILD="$CFLAGS" - -@@ -243,63 +279,6 @@ else - esac - fi - --if test x"$req_field" = x"auto"; then -- if test x"set_asm" = x"x86_64"; then -- set_field=64bit -- fi -- if test x"$set_field" = x; then -- SECP_INT128_CHECK -- if test x"$has_int128" = x"yes"; then -- set_field=64bit -- fi -- fi -- if test x"$set_field" = x; then -- set_field=32bit -- fi --else -- set_field=$req_field -- case $set_field in -- 64bit) -- if test x"$set_asm" != x"x86_64"; then -- SECP_INT128_CHECK -- if test x"$has_int128" != x"yes"; then -- AC_MSG_ERROR([64bit field explicitly requested but neither __int128 support or x86_64 assembly available]) -- fi -- fi -- ;; -- 32bit) -- ;; -- *) -- AC_MSG_ERROR([invalid field implementation selection]) -- ;; -- esac --fi -- --if test x"$req_scalar" = x"auto"; then -- SECP_INT128_CHECK -- if test x"$has_int128" = x"yes"; then -- set_scalar=64bit -- fi -- if test x"$set_scalar" = x; then -- set_scalar=32bit -- fi --else -- set_scalar=$req_scalar -- case $set_scalar in -- 64bit) -- SECP_INT128_CHECK -- if test x"$has_int128" != x"yes"; then -- AC_MSG_ERROR([64bit scalar explicitly requested but __int128 support not available]) -- fi -- ;; -- 32bit) -- ;; -- *) -- AC_MSG_ERROR([invalid scalar implementation selected]) -- ;; -- esac --fi -- - if test x"$req_bignum" = x"auto"; then - SECP_GMP_CHECK - if test x"$has_gmp" = x"yes"; then -@@ -343,16 +322,18 @@ no) - ;; - esac - --# select field implementation --case $set_field in --64bit) -- AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation]) -+# select wide multiplication implementation -+case $set_widemul in -+int128) -+ AC_DEFINE(USE_FORCE_WIDEMUL_INT128, 1, [Define this symbol to force the use of the (unsigned) __int128 based wide multiplication implementation]) - ;; --32bit) -- AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation]) -+int64) -+ AC_DEFINE(USE_FORCE_WIDEMUL_INT64, 1, [Define this symbol to force the use of the (u)int64_t based wide multiplication implementation]) -+ ;; -+auto) - ;; - *) -- AC_MSG_ERROR([invalid field implementation]) -+ AC_MSG_ERROR([invalid wide multiplication implementation]) - ;; - esac - -@@ -374,25 +355,50 @@ no) - ;; - esac - --#select scalar implementation --case $set_scalar in --64bit) -- AC_DEFINE(USE_SCALAR_4X64, 1, [Define this symbol to use the 4x64 scalar implementation]) -+#set ecmult window size -+if test x"$req_ecmult_window" = x"auto"; then -+ set_ecmult_window=15 -+else -+ set_ecmult_window=$req_ecmult_window -+fi -+ -+error_window_size=['window size for ecmult precomputation not an integer in range [2..24] or "auto"'] -+case $set_ecmult_window in -+''|*[[!0-9]]*) -+ # no valid integer -+ AC_MSG_ERROR($error_window_size) -+ ;; -+*) -+ if test "$set_ecmult_window" -lt 2 -o "$set_ecmult_window" -gt 24 ; then -+ # not in range -+ AC_MSG_ERROR($error_window_size) -+ fi -+ AC_DEFINE_UNQUOTED(ECMULT_WINDOW_SIZE, $set_ecmult_window, [Set window size for ecmult precomputation]) - ;; --32bit) -- AC_DEFINE(USE_SCALAR_8X32, 1, [Define this symbol to use the 8x32 scalar implementation]) -+esac -+ -+#set ecmult gen precision -+if test x"$req_ecmult_gen_precision" = x"auto"; then -+ set_ecmult_gen_precision=4 -+else -+ set_ecmult_gen_precision=$req_ecmult_gen_precision -+fi -+ -+case $set_ecmult_gen_precision in -+2|4|8) -+ AC_DEFINE_UNQUOTED(ECMULT_GEN_PREC_BITS, $set_ecmult_gen_precision, [Set ecmult gen precision bits]) - ;; - *) -- AC_MSG_ERROR([invalid scalar implementation]) -+ AC_MSG_ERROR(['ecmult gen precision not 2, 4, 8 or "auto"']) - ;; - esac - - if test x"$use_tests" = x"yes"; then - SECP_OPENSSL_CHECK -- if test x"$has_openssl_ec" = x"yes"; then -- if test x"$enable_openssl_tests" != x"no"; then -+ if test x"$enable_openssl_tests" != x"no" && test x"$has_openssl_ec" = x"yes"; then -+ enable_openssl_tests=yes - AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) -- SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" -+ SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS $CRYPTO_CPPFLAGS" - SECP_TEST_LIBS="$CRYPTO_LIBS" - - case $host in -@@ -400,39 +406,17 @@ if test x"$use_tests" = x"yes"; then - SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" - ;; - esac -- fi - else - if test x"$enable_openssl_tests" = x"yes"; then - AC_MSG_ERROR([OpenSSL tests requested but OpenSSL with EC support is not available]) - fi -+ enable_openssl_tests=no - fi - else - if test x"$enable_openssl_tests" = x"yes"; then - AC_MSG_ERROR([OpenSSL tests requested but tests are not enabled]) - fi --fi -- --if test x"$use_jni" != x"no"; then -- AX_JNI_INCLUDE_DIR -- have_jni_dependencies=yes -- if test x"$enable_module_ecdh" = x"no"; then -- have_jni_dependencies=no -- fi -- if test "x$JNI_INCLUDE_DIRS" = "x"; then -- have_jni_dependencies=no -- fi -- if test "x$have_jni_dependencies" = "xno"; then -- if test x"$use_jni" = x"yes"; then -- AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and try again.]) -- fi -- AC_MSG_WARN([jni headers/dependencies not found. jni support disabled]) -- use_jni=no -- else -- use_jni=yes -- for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do -- JNI_INCLUDES="$JNI_INCLUDES -I$JNI_INCLUDE_DIR" -- done -- fi -+ enable_openssl_tests=no - fi - - if test x"$set_bignum" = x"gmp"; then -@@ -440,10 +424,6 @@ if test x"$set_bignum" = x"gmp"; then - SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS" - fi - --if test x"$use_endomorphism" = x"yes"; then -- AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization]) --fi -- - if test x"$set_precomp" = x"yes"; then - AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table]) - fi -@@ -456,21 +436,38 @@ if test x"$enable_module_recovery" = x"yes"; then - AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module]) - fi - --AC_C_BIGENDIAN() -+if test x"$enable_module_schnorrsig" = x"yes"; then -+ AC_DEFINE(ENABLE_MODULE_SCHNORRSIG, 1, [Define this symbol to enable the schnorrsig module]) -+ enable_module_extrakeys=yes -+fi -+ -+# Test if extrakeys is set after the schnorrsig module to allow the schnorrsig -+# module to set enable_module_extrakeys=yes -+if test x"$enable_module_extrakeys" = x"yes"; then -+ AC_DEFINE(ENABLE_MODULE_EXTRAKEYS, 1, [Define this symbol to enable the extrakeys module]) -+fi - - if test x"$use_external_asm" = x"yes"; then - AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used]) - fi - -+if test x"$use_external_default_callbacks" = x"yes"; then -+ AC_DEFINE(USE_EXTERNAL_DEFAULT_CALLBACKS, 1, [Define this symbol if an external implementation of the default callbacks is used]) -+fi -+ - if test x"$enable_experimental" = x"yes"; then - AC_MSG_NOTICE([******]) - AC_MSG_NOTICE([WARNING: experimental build]) - AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) -- AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) -+ AC_MSG_NOTICE([Building extrakeys module: $enable_module_extrakeys]) -+ AC_MSG_NOTICE([Building schnorrsig module: $enable_module_schnorrsig]) - AC_MSG_NOTICE([******]) - else -- if test x"$enable_module_ecdh" = x"yes"; then -- AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.]) -+ if test x"$enable_module_extrakeys" = x"yes"; then -+ AC_MSG_ERROR([extrakeys module is experimental. Use --enable-experimental to allow.]) -+ fi -+ if test x"$enable_module_schnorrsig" = x"yes"; then -+ AC_MSG_ERROR([schnorrsig module is experimental. Use --enable-experimental to allow.]) - fi - if test x"$set_asm" = x"arm"; then - AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.]) -@@ -479,7 +476,6 @@ fi - - AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) - AC_CONFIG_FILES([Makefile libsecp256k1.pc]) --AC_SUBST(JNI_INCLUDES) - AC_SUBST(SECP_INCLUDES) - AC_SUBST(SECP_LIBS) - AC_SUBST(SECP_TEST_LIBS) -@@ -491,7 +487,8 @@ AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) - AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"]) - AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) - AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) --AM_CONDITIONAL([USE_JNI], [test x"$use_jni" = x"yes"]) -+AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"yes"]) -+AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"]) - AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"]) - AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"]) - -@@ -504,21 +501,29 @@ AC_OUTPUT - - echo - echo "Build Options:" --echo " with endomorphism = $use_endomorphism" --echo " with ecmult precomp = $set_precomp" --echo " with jni = $use_jni" --echo " with benchmarks = $use_benchmark" --echo " with coverage = $enable_coverage" --echo " module ecdh = $enable_module_ecdh" --echo " module recovery = $enable_module_recovery" -+echo " with ecmult precomp = $set_precomp" -+echo " with external callbacks = $use_external_default_callbacks" -+echo " with benchmarks = $use_benchmark" -+echo " with tests = $use_tests" -+echo " with openssl tests = $enable_openssl_tests" -+echo " with coverage = $enable_coverage" -+echo " module ecdh = $enable_module_ecdh" -+echo " module recovery = $enable_module_recovery" -+echo " module extrakeys = $enable_module_extrakeys" -+echo " module schnorrsig = $enable_module_schnorrsig" - echo --echo " asm = $set_asm" --echo " bignum = $set_bignum" --echo " field = $set_field" --echo " scalar = $set_scalar" -+echo " asm = $set_asm" -+echo " bignum = $set_bignum" -+echo " ecmult window size = $set_ecmult_window" -+echo " ecmult gen prec. bits = $set_ecmult_gen_precision" -+dnl Hide test-only options unless they're used. -+if test x"$set_widemul" != xauto; then -+echo " wide multiplication = $set_widemul" -+fi - echo --echo " CC = $CC" --echo " CFLAGS = $CFLAGS" --echo " CPPFLAGS = $CPPFLAGS" --echo " LDFLAGS = $LDFLAGS" -+echo " valgrind = $enable_valgrind" -+echo " CC = $CC" -+echo " CFLAGS = $CFLAGS" -+echo " CPPFLAGS = $CPPFLAGS" -+echo " LDFLAGS = $LDFLAGS" - echo -diff --git a/src/secp256k1/contrib/lax_der_parsing.h b/src/secp256k1/contrib/lax_der_parsing.h -index 959fc36e..7eaf63bf 100644 ---- a/src/secp256k1/contrib/lax_der_parsing.h -+++ b/src/secp256k1/contrib/lax_der_parsing.h -@@ -68,7 +68,7 @@ extern "C" { - * This function will accept any valid DER encoded signature, even if the - * encoded numbers are out of range. In addition, it will accept signatures - * which violate the DER spec in various ways. Its purpose is to allow -- * validation of the BGL blockchain, which includes non-DER signatures -+ * validation of the Bitcoin blockchain, which includes non-DER signatures - * from before the network rules were updated to enforce DER. Note that - * the set of supported violations is a strict subset of what OpenSSL will - * accept. -diff --git a/src/secp256k1/libsecp256k1.pc.in b/src/secp256k1/libsecp256k1.pc.in -index a3841a30..694e98ee 100644 ---- a/src/secp256k1/libsecp256k1.pc.in -+++ b/src/secp256k1/libsecp256k1.pc.in -@@ -5,7 +5,7 @@ includedir=@includedir@ - - Name: libsecp256k1 - Description: Optimized C library for EC operations on curve secp256k1 --URL: https://github.com/BGL-core/secp256k1 -+URL: https://github.com/bitcoin-core/secp256k1 - Version: @PACKAGE_VERSION@ - Cflags: -I${includedir} - Libs: -L${libdir} -lsecp256k1 -diff --git a/src/secp256k1/src/java/org_BGL_NativeSecp256k1.h b/src/secp256k1/src/java/org_BGL_NativeSecp256k1.h -deleted file mode 100644 -index 5d10567d..00000000 ---- a/src/secp256k1/src/java/org_BGL_NativeSecp256k1.h -+++ /dev/null -@@ -1,119 +0,0 @@ --/* DO NOT EDIT THIS FILE - it is machine generated */ --#include --#include "include/secp256k1.h" --/* Header for class org_BGL_NativeSecp256k1 */ -- --#ifndef _Included_org_BGL_NativeSecp256k1 --#define _Included_org_BGL_NativeSecp256k1 --#ifdef __cplusplus --extern "C" { --#endif --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_ctx_clone -- * Signature: (J)J -- */ --SECP256K1_API jlong JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1ctx_1clone -- (JNIEnv *, jclass, jlong); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_context_randomize -- * Signature: (Ljava/nio/ByteBuffer;J)I -- */ --SECP256K1_API jint JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1context_1randomize -- (JNIEnv *, jclass, jobject, jlong); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_privkey_tweak_add -- * Signature: (Ljava/nio/ByteBuffer;J)[[B -- */ --SECP256K1_API jobjectArray JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1privkey_1tweak_1add -- (JNIEnv *, jclass, jobject, jlong); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_privkey_tweak_mul -- * Signature: (Ljava/nio/ByteBuffer;J)[[B -- */ --SECP256K1_API jobjectArray JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul -- (JNIEnv *, jclass, jobject, jlong); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_pubkey_tweak_add -- * Signature: (Ljava/nio/ByteBuffer;JI)[[B -- */ --SECP256K1_API jobjectArray JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add -- (JNIEnv *, jclass, jobject, jlong, jint); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_pubkey_tweak_mul -- * Signature: (Ljava/nio/ByteBuffer;JI)[[B -- */ --SECP256K1_API jobjectArray JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul -- (JNIEnv *, jclass, jobject, jlong, jint); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_destroy_context -- * Signature: (J)V -- */ --SECP256K1_API void JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1destroy_1context -- (JNIEnv *, jclass, jlong); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_ecdsa_verify -- * Signature: (Ljava/nio/ByteBuffer;JII)I -- */ --SECP256K1_API jint JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1ecdsa_1verify -- (JNIEnv *, jclass, jobject, jlong, jint, jint); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_ecdsa_sign -- * Signature: (Ljava/nio/ByteBuffer;J)[[B -- */ --SECP256K1_API jobjectArray JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1ecdsa_1sign -- (JNIEnv *, jclass, jobject, jlong); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_ec_seckey_verify -- * Signature: (Ljava/nio/ByteBuffer;J)I -- */ --SECP256K1_API jint JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1ec_1seckey_1verify -- (JNIEnv *, jclass, jobject, jlong); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_ec_pubkey_create -- * Signature: (Ljava/nio/ByteBuffer;J)[[B -- */ --SECP256K1_API jobjectArray JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1ec_1pubkey_1create -- (JNIEnv *, jclass, jobject, jlong); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_ec_pubkey_parse -- * Signature: (Ljava/nio/ByteBuffer;JI)[[B -- */ --SECP256K1_API jobjectArray JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse -- (JNIEnv *, jclass, jobject, jlong, jint); -- --/* -- * Class: org_BGL_NativeSecp256k1 -- * Method: secp256k1_ecdh -- * Signature: (Ljava/nio/ByteBuffer;JI)[[B -- */ --SECP256K1_API jobjectArray JNICALL Java_org_BGL_NativeSecp256k1_secp256k1_1ecdh -- (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen); -- -- --#ifdef __cplusplus --} --#endif --#endif -diff --git a/src/secp256k1/src/java/org_BGL_Secp256k1Context.h b/src/secp256k1/src/java/org_BGL_Secp256k1Context.h -deleted file mode 100644 -index f1e09521..00000000 ---- a/src/secp256k1/src/java/org_BGL_Secp256k1Context.h -+++ /dev/null -@@ -1,22 +0,0 @@ --/* DO NOT EDIT THIS FILE - it is machine generated */ --#include --#include "include/secp256k1.h" --/* Header for class org_BGL_Secp256k1Context */ -- --#ifndef _Included_org_BGL_Secp256k1Context --#define _Included_org_BGL_Secp256k1Context --#ifdef __cplusplus --extern "C" { --#endif --/* -- * Class: org_BGL_Secp256k1Context -- * Method: secp256k1_init_context -- * Signature: ()J -- */ --SECP256K1_API jlong JNICALL Java_org_BGL_Secp256k1Context_secp256k1_1init_1context -- (JNIEnv *, jclass); -- --#ifdef __cplusplus --} --#endif --#endif -diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c -index 67c5c36b..bb4b5b4c 100644 ---- a/src/secp256k1/src/tests.c -+++ b/src/secp256k1/src/tests.c -@@ -2355,7 +2355,7 @@ void test_add_neg_y_diff_x(void) { - * of the sum to be wrong (since infinity has no xy coordinates). - * HOWEVER, if the x-coordinates are different, infinity is the - * wrong answer, and such degeneracies are exposed. This is the -- * root of https://github.com/BGL-core/secp256k1/issues/257 -+ * root of https://github.com/bitcoin-core/secp256k1/issues/257 - * which this test is a regression test for. - * - * These points were generated in sage as -diff --git a/src/serialize.h b/src/serialize.h -index 23292bbc..89d2676f 100644 ---- a/src/serialize.h -+++ b/src/serialize.h -@@ -174,6 +174,8 @@ template const X& ReadWriteAsHelper(const X& x) { return x; } - - #define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__)) - #define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper(obj))) -+#define SER_READ(obj, code) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const::type& obj) { code; }) -+#define SER_WRITE(obj, code) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; }) - - /** - * Implement the Ser and Unser methods needed for implementing a formatter (see Using below). -@@ -511,52 +513,31 @@ struct CustomUintFormatter - template void Ser(Stream& s, I v) - { - if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range"); -- uint64_t raw = htole64(v); -- s.write((const char*)&raw, Bytes); -+ if (BigEndian) { -+ uint64_t raw = htobe64(v); -+ s.write(((const char*)&raw) + 8 - Bytes, Bytes); -+ } else { -+ uint64_t raw = htole64(v); -+ s.write((const char*)&raw, Bytes); -+ } - } - - template void Unser(Stream& s, I& v) - { -- static_assert(std::numeric_limits::max() >= MAX && std::numeric_limits::min() <= 0, "CustomUintFormatter type too small"); -+ using U = typename std::conditional::value, std::underlying_type, std::common_type>::type::type; -+ static_assert(std::numeric_limits::max() >= MAX && std::numeric_limits::min() <= 0, "Assigned type too small"); - uint64_t raw = 0; -- s.read((char*)&raw, Bytes); -- v = le64toh(raw); -+ if (BigEndian) { -+ s.read(((char*)&raw) + 8 - Bytes, Bytes); -+ v = static_cast(be64toh(raw)); -+ } else { -+ s.read((char*)&raw, Bytes); -+ v = static_cast(le64toh(raw)); -+ } - } - }; - --/** Serialization wrapper class for big-endian integers. -- * -- * Use this wrapper around integer types that are stored in memory in native -- * byte order, but serialized in big endian notation. This is only intended -- * to implement serializers that are compatible with existing formats, and -- * its use is not recommended for new data structures. -- * -- * Only 16-bit types are supported for now. -- */ --template --class BigEndian --{ --protected: -- I& m_val; --public: -- explicit BigEndian(I& val) : m_val(val) -- { -- static_assert(std::is_unsigned::value, "BigEndian type must be unsigned integer"); -- static_assert(sizeof(I) == 2 && std::numeric_limits::min() == 0 && std::numeric_limits::max() == std::numeric_limits::max(), "Unsupported BigEndian size"); -- } -- -- template -- void Serialize(Stream& s) const -- { -- ser_writedata16be(s, m_val); -- } -- -- template -- void Unserialize(Stream& s) -- { -- m_val = ser_readdata16be(s); -- } --}; -+template using BigEndianFormatter = CustomUintFormatter; - - /** Formatter for integers in CompactSize format. */ - template -@@ -603,9 +584,6 @@ struct LimitedStringFormatter - } - }; - --template --BigEndian WrapBigEndian(I& n) { return BigEndian(n); } -- - /** Formatter to serialize/deserialize vector elements using another formatter - * - * Example: -@@ -1101,6 +1079,28 @@ inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&& - ::UnserializeMany(s, args...); - } - -+template -+inline void SerRead(Stream& s, CSerActionSerialize ser_action, Type&&, Fn&&) -+{ -+} -+ -+template -+inline void SerRead(Stream& s, CSerActionUnserialize ser_action, Type&& obj, Fn&& fn) -+{ -+ fn(s, std::forward(obj)); -+} -+ -+template -+inline void SerWrite(Stream& s, CSerActionSerialize ser_action, Type&& obj, Fn&& fn) -+{ -+ fn(s, std::forward(obj)); -+} -+ -+template -+inline void SerWrite(Stream& s, CSerActionUnserialize ser_action, Type&&, Fn&&) -+{ -+} -+ - template - inline void WriteVarInt(CSizeComputer &s, I n) - { -diff --git a/src/validation.cpp b/src/validation.cpp -index 05060445..58633e09 100644 ---- a/src/validation.cpp -+++ b/src/validation.cpp -@@ -1,5 +1,5 @@ - // Copyright (c) 2009-2010 Satoshi Nakamoto --// Copyright (c) 2009-2020 The BGL Core developers -+// Copyright (c) 2009-2020 The Bitcoin Core developers - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -@@ -52,7 +52,7 @@ - #include - - #include -- -+ - #define MICRO 0.000001 - #define MILLI 0.001 - -@@ -101,20 +101,19 @@ bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIn - return false; - } - --namespace { --BlockManager g_blockman; --} // anon namespace -+ChainstateManager g_chainman; - --std::unique_ptr g_chainstate; -- --CChainState& ChainstateActive() { -- assert(g_chainstate); -- return *g_chainstate; -+CChainState& ChainstateActive() -+{ -+ LOCK(::cs_main); -+ assert(g_chainman.m_active_chainstate); -+ return *g_chainman.m_active_chainstate; - } - --CChain& ChainActive() { -- assert(g_chainstate); -- return g_chainstate->m_chain; -+CChain& ChainActive() -+{ -+ LOCK(::cs_main); -+ return ::ChainstateActive().m_chain; - } - - /** -@@ -174,8 +173,8 @@ namespace { - CBlockIndex* LookupBlockIndex(const uint256& hash) - { - AssertLockHeld(cs_main); -- BlockMap::const_iterator it = g_blockman.m_block_index.find(hash); -- return it == g_blockman.m_block_index.end() ? nullptr : it->second; -+ BlockMap::const_iterator it = g_chainman.BlockIndex().find(hash); -+ return it == g_chainman.BlockIndex().end() ? nullptr : it->second; - } - - CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) -@@ -450,7 +449,7 @@ namespace { - class MemPoolAccept - { - public: -- explicit MemPoolAccept(CTxMemPool& mempool) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&::ChainstateActive().CoinsTip(), m_pool), -+ MemPoolAccept(CTxMemPool& mempool) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&::ChainstateActive().CoinsTip(), m_pool), - m_limit_ancestors(gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT)), - m_limit_ancestor_size(gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000), - m_limit_descendants(gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)), -@@ -483,7 +482,7 @@ private: - // All the intermediate state that gets passed between the various levels - // of checking a given transaction. - struct Workspace { -- explicit Workspace(const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {} -+ Workspace(const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {} - std::set m_conflicts; - CTxMemPool::setEntries m_all_conflicting; - CTxMemPool::setEntries m_ancestors; -@@ -697,7 +696,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) - return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs"); - } - -- // Check for non-standard witnesses. -+ // Check for non-standard witness in P2WSH - if (tx.HasWitness() && fRequireStandard && !IsWitnessStandard(tx, m_view)) - return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard"); - -@@ -1260,7 +1259,6 @@ void CoinsViews::InitCache() - m_cacheview = MakeUnique(&m_catcherview); - } - -- - CChainState::CChainState(CTxMemPool& mempool, BlockManager& blockman, uint256 from_snapshot_blockhash) - : m_blockman(blockman), - m_mempool(mempool), -@@ -1272,6 +1270,10 @@ void CChainState::InitCoinsDB( - bool should_wipe, - std::string leveldb_name) - { -+ if (!m_from_snapshot_blockhash.IsNull()) { -+ leveldb_name += "_" + m_from_snapshot_blockhash.ToString(); -+ } -+ - m_coins_views = MakeUnique( - leveldb_name, cache_size_bytes, in_memory, should_wipe); - } -@@ -1708,19 +1710,24 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI - return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; - } - --void static FlushBlockFile(bool fFinalize = false) -+static void FlushUndoFile(int block_file, bool finalize = false) - { -- LOCK(cs_LastBlockFile); -+ FlatFilePos undo_pos_old(block_file, vinfoBlockFile[block_file].nUndoSize); -+ if (!UndoFileSeq().Flush(undo_pos_old, finalize)) { -+ AbortNode("Flushing undo file to disk failed. This is likely the result of an I/O error."); -+ } -+} - -+static void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false) -+{ -+ LOCK(cs_LastBlockFile); - FlatFilePos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize); -- FlatFilePos undo_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nUndoSize); -- -- bool status = true; -- status &= BlockFileSeq().Flush(block_pos_old, fFinalize); -- status &= UndoFileSeq().Flush(undo_pos_old, fFinalize); -- if (!status) { -+ if (!BlockFileSeq().Flush(block_pos_old, fFinalize)) { - AbortNode("Flushing block file to disk failed. This is likely the result of an I/O error."); - } -+ // we do not always flush the undo file, as the chain tip may be lagging behind the incoming blocks, -+ // e.g. during IBD or a sync after a node going offline -+ if (!fFinalize || finalize_undo) FlushUndoFile(nLastBlockFile, finalize_undo); - } - - static bool FindUndoPos(BlockValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize); -@@ -1734,6 +1741,14 @@ static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationSt - return error("ConnectBlock(): FindUndoPos failed"); - if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) - return AbortNode(state, "Failed to write undo data"); -+ // rev files are written in block height order, whereas blk files are written as blocks come in (often out of order) -+ // we want to flush the rev (undo) file once we've written the last block, which is indicated by the last height -+ // in the block file info as below; note that this does not catch the case where the undo writes are keeping up -+ // with the block writes (usually when a synced up node is getting newly mined blocks) -- this case is caught in -+ // the FindBlockPos function -+ if (_pos.nFile < nLastBlockFile && static_cast(pindex->nHeight) == vinfoBlockFile[_pos.nFile].nHeightLast) { -+ FlushUndoFile(_pos.nFile, true); -+ } - - // update nUndoPos in block index - pindex->nUndoPos = _pos.nPos; -@@ -2383,9 +2398,7 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C - } - - bilingual_str warning_messages; -- int num_unexpected_version = 0; -- if (!::ChainstateActive().IsInitialBlockDownload()) -- { -+ if (!::ChainstateActive().IsInitialBlockDownload()) { - const CBlockIndex* pindex = pindexNew; - for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { - WarningBitsConditionChecker checker(bit); -@@ -2399,14 +2412,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C - } - } - } -- // Check the version of the last 100 blocks to see if we need to upgrade: -- for (int i = 0; i < 100 && pindex != nullptr; i++) -- { -- int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus()); -- if (pindex->nVersion > VERSIONBITS_LAST_OLD_BLOCK_VERSION && (pindex->nVersion & ~nExpectedVersion) != 0) -- ++num_unexpected_version; -- pindex = pindex->pprev; -- } - } - LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s\n", __func__, - pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion, -@@ -2414,10 +2419,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C - FormatISO8601DateTime(pindexNew->GetBlockTime()), - GuessVerificationProgress(chainParams.TxData(), pindexNew), ::ChainstateActive().CoinsTip().DynamicMemoryUsage() * (1.0 / (1<<20)), ::ChainstateActive().CoinsTip().GetCacheSize(), - !warning_messages.empty() ? strprintf(" warning='%s'", warning_messages.original) : ""); -- -- if (num_unexpected_version > 0) { -- LogPrint(BCLog::VALIDATION, "%d of last 100 blocks have unexpected version\n", num_unexpected_version); -- } - } - - /** Disconnect m_chain's tip. -@@ -3193,8 +3194,13 @@ static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int n - vinfoBlockFile.resize(nFile + 1); - } - -+ bool finalize_undo = false; - if (!fKnown) { - while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) { -+ // when the undo file is keeping up with the block file, we want to flush it explicitly -+ // when it is lagging behind (more blocks arrive than are being connected), we let the -+ // undo block write case handle it -+ finalize_undo = (vinfoBlockFile[nFile].nHeightLast == (unsigned int)ChainActive().Tip()->nHeight); - nFile++; - if (vinfoBlockFile.size() <= nFile) { - vinfoBlockFile.resize(nFile + 1); -@@ -3208,7 +3214,7 @@ static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int n - if (!fKnown) { - LogPrintf("Leaving block file %i: %s\n", nLastBlockFile, vinfoBlockFile[nLastBlockFile].ToString()); - } -- FlushBlockFile(!fKnown); -+ FlushBlockFile(!fKnown, finalize_undo); - nLastBlockFile = nFile; - } - -@@ -3424,7 +3430,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio - if (fCheckpointsEnabled) { - // Don't accept any forks from the main chain prior to last checkpoint. - // GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our -- // g_blockman.m_block_index. -+ // BlockIndex(). - CBlockIndex* pcheckpoint = GetLastCheckpoint(params.Checkpoints()); - if (pcheckpoint && nHeight < pcheckpoint->nHeight) { - LogPrintf("ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__, nHeight); -@@ -4087,6 +4093,7 @@ bool static LoadBlockIndexDB(ChainstateManager& chainman, const CChainParams& ch - chainparams.GetConsensus(), *pblocktree, - ::ChainstateActive().setBlockIndexCandidates)) { - return false; -+ } - - // Load block file info - pblocktree->ReadLastBlockFile(nLastBlockFile); -@@ -4491,26 +4498,15 @@ bool CChainState::RewindBlockIndex(const CChainParams& params) - PruneBlockIndexCandidates(); - - CheckBlockIndex(params.GetConsensus()); -- } -- } - -- return true; --} -- --bool RewindBlockIndex(const CChainParams& params) { -- if (!::ChainstateActive().RewindBlockIndex(params)) { -- return false; -- } -- -- LOCK(cs_main); -- if (::ChainActive().Tip() != nullptr) { -- // FlushStateToDisk can possibly read ::ChainActive(). Be conservative -- // and skip it here, we're about to -reindex-chainstate anyway, so -- // it'll get called a bunch real soon. -- BlockValidationState state; -- if (!::ChainstateActive().FlushStateToDisk(params, state, FlushStateMode::ALWAYS)) { -- LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", state.ToString()); -- return false; -+ // FlushStateToDisk can possibly read ::ChainActive(). Be conservative -+ // and skip it here, we're about to -reindex-chainstate anyway, so -+ // it'll get called a bunch real soon. -+ BlockValidationState state; -+ if (!FlushStateToDisk(params, state, FlushStateMode::ALWAYS)) { -+ LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", state.ToString()); -+ return false; -+ } - } - } - -@@ -4541,8 +4537,6 @@ void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman) - warningcache[b].clear(); - } - fHavePruned = false; -- -- ::ChainstateActive().UnloadBlockIndex(); - } - - bool ChainstateManager::LoadBlockIndex(const CChainParams& chainparams) -@@ -4673,7 +4667,7 @@ void LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFi - // Activate the genesis block so normal node progress can continue - if (hash == chainparams.GetConsensus().hashGenesisBlock) { - BlockValidationState state; -- if (!ActivateBestChain(state, chainparams)) { -+ if (!ActivateBestChain(state, chainparams, nullptr)) { - break; - } - } -@@ -5116,9 +5110,7 @@ bool DumpMempool(const CTxMemPool& pool) - if (!FileCommit(file.Get())) - throw std::runtime_error("FileCommit failed"); - file.fclose(); -- if (!RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat")) { -- throw std::runtime_error("Rename failed"); -- } -+ RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat"); - int64_t last = GetTimeMicros(); - LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*MICRO, (last-mid)*MICRO); - } catch (const std::exception& e) { -diff --git a/src/validation.h b/src/validation.h -index 5b68b6a9..3602e53b 100644 ---- a/src/validation.h -+++ b/src/validation.h -@@ -1,5 +1,5 @@ - // Copyright (c) 2009-2010 Satoshi Nakamoto --// Copyright (c) 2009-2020 The BGL Core developers -+// Copyright (c) 2009-2020 The Bitcoin Core developers - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -@@ -14,6 +14,7 @@ - #include - #include // for ReadLE64 - #include -+#include - #include - #include // For CMessageHeader::MessageStartChars - #include