Page MenuHomePhabricator

No OneTemporary

diff --git a/src/chain.cpp b/src/chain.cpp
index 8e61e0ec2..c2d3439e3 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -1,143 +1,143 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
void CChain::SetTip(CBlockIndex &block) {
CBlockIndex *pindex = &block;
vChain.resize(pindex->nHeight + 1);
while (pindex && vChain[pindex->nHeight] != pindex) {
vChain[pindex->nHeight] = pindex;
pindex = pindex->pprev;
}
}
std::vector<BlockHash> LocatorEntries(const CBlockIndex *index) {
int step = 1;
std::vector<BlockHash> have;
if (index == nullptr) {
return have;
}
have.reserve(32);
while (index) {
have.emplace_back(index->GetBlockHash());
if (index->nHeight == 0) {
break;
}
// Exponentially larger steps back, plus the genesis block.
int height = std::max(index->nHeight - step, 0);
// Use skiplist.
index = index->GetAncestor(height);
if (have.size() > 10) {
step *= 2;
}
}
return have;
}
CBlockLocator GetLocator(const CBlockIndex *index) {
- return CBlockLocator{std::move(LocatorEntries(index))};
+ return CBlockLocator{LocatorEntries(index)};
}
CBlockLocator CChain::GetLocator() const {
return ::GetLocator(Tip());
}
const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
if (pindex == nullptr) {
return nullptr;
}
if (pindex->nHeight > Height()) {
pindex = pindex->GetAncestor(Height());
}
while (pindex && !Contains(pindex)) {
pindex = pindex->pprev;
}
return pindex;
}
CBlockIndex *CChain::FindEarliestAtLeast(int64_t nTime, int height) const {
std::pair<int64_t, int> blockparams = std::make_pair(nTime, height);
std::vector<CBlockIndex *>::const_iterator lower = std::lower_bound(
vChain.begin(), vChain.end(), blockparams,
[](CBlockIndex *pBlock,
const std::pair<int64_t, int> &_blockparams) -> bool {
return pBlock->GetBlockTimeMax() < _blockparams.first ||
pBlock->nHeight < _blockparams.second;
});
return (lower == vChain.end() ? nullptr : *lower);
}
arith_uint256 GetBlockProof(const CBlockIndex &block) {
arith_uint256 bnTarget;
bool fNegative;
bool fOverflow;
bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
if (fNegative || fOverflow || bnTarget == 0) {
return 0;
}
// We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
// as it's too large for an arith_uint256. However, as 2**256 is at least as
// large as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) /
// (bnTarget+1)) + 1, or ~bnTarget / (bnTarget+1) + 1.
return (~bnTarget / (bnTarget + 1)) + 1;
}
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to,
const CBlockIndex &from,
const CBlockIndex &tip,
const Consensus::Params &params) {
arith_uint256 r;
int sign = 1;
if (to.nChainWork > from.nChainWork) {
r = to.nChainWork - from.nChainWork;
} else {
r = from.nChainWork - to.nChainWork;
sign = -1;
}
r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
if (r.bits() > 63) {
return sign * std::numeric_limits<int64_t>::max();
}
return sign * int64_t(r.GetLow64());
}
/**
* Find the last common ancestor two blocks have.
* Both pa and pb must be non null.
*/
const CBlockIndex *LastCommonAncestor(const CBlockIndex *pa,
const CBlockIndex *pb) {
if (pa->nHeight > pb->nHeight) {
pa = pa->GetAncestor(pb->nHeight);
} else if (pb->nHeight > pa->nHeight) {
pb = pb->GetAncestor(pa->nHeight);
}
while (pa != pb && pa && pb) {
if (pa->pskip && pb->pskip && pa->pskip != pb->pskip) {
pa = pa->pskip;
pb = pb->pskip;
assert(pa->nHeight == pb->nHeight);
} else {
pa = pa->pprev;
pb = pb->pprev;
}
}
// Eventually all chain branches meet at the genesis block.
assert(pa == pb);
return pa;
}
bool AreOnTheSameFork(const CBlockIndex *pa, const CBlockIndex *pb) {
if (pa->nHeight > pb->nHeight) {
pa = pa->GetAncestor(pb->nHeight);
} else if (pb->nHeight > pa->nHeight) {
pb = pb->GetAncestor(pa->nHeight);
}
return pa == pb;
}
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 9ed059718..696312c20 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -1,126 +1,126 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 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 BITCOIN_PRIMITIVES_BLOCK_H
#define BITCOIN_PRIMITIVES_BLOCK_H
#include <primitives/blockhash.h>
#include <primitives/transaction.h>
#include <serialize.h>
#include <uint256.h>
#include <util/time.h>
/**
* Nodes collect new transactions into a block, hash them into a hash tree, and
* scan through nonce values to make the block's hash satisfy proof-of-work
* requirements. When they solve the proof-of-work, they broadcast the block to
* everyone and the block is added to the block chain. The first transaction in
* the block is a special one that creates a new coin owned by the creator of
* the block.
*/
class CBlockHeader {
public:
// header
int32_t nVersion;
BlockHash hashPrevBlock;
uint256 hashMerkleRoot;
uint32_t nTime;
uint32_t nBits;
uint32_t nNonce;
CBlockHeader() { SetNull(); }
SERIALIZE_METHODS(CBlockHeader, obj) {
READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot,
obj.nTime, obj.nBits, obj.nNonce);
}
void SetNull() {
nVersion = 0;
hashPrevBlock = BlockHash();
hashMerkleRoot.SetNull();
nTime = 0;
nBits = 0;
nNonce = 0;
}
bool IsNull() const { return (nBits == 0); }
BlockHash GetHash() const;
NodeSeconds Time() const {
return NodeSeconds{std::chrono::seconds{nTime}};
}
int64_t GetBlockTime() const { return (int64_t)nTime; }
};
class CBlock : public CBlockHeader {
public:
// network and disk
std::vector<CTransactionRef> vtx;
// memory only
mutable bool fChecked;
CBlock() { SetNull(); }
CBlock(const CBlockHeader &header) {
SetNull();
*(static_cast<CBlockHeader *>(this)) = header;
}
SERIALIZE_METHODS(CBlock, obj) {
READWRITEAS(CBlockHeader, obj);
READWRITE(obj.vtx);
}
void SetNull() {
CBlockHeader::SetNull();
vtx.clear();
fChecked = false;
}
CBlockHeader GetBlockHeader() const {
CBlockHeader block;
block.nVersion = nVersion;
block.hashPrevBlock = hashPrevBlock;
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block;
}
std::string ToString() const;
};
/**
* Describes a place in the block chain to another node such that if the other
* node doesn't have the same branch, it can find a recent common trunk. The
* further back it is, the further before the fork it may be.
*/
struct CBlockLocator {
std::vector<BlockHash> vHave;
CBlockLocator() {}
- explicit CBlockLocator(const std::vector<BlockHash> &vHaveIn)
- : vHave(vHaveIn) {}
+ explicit CBlockLocator(std::vector<BlockHash> &&vHaveIn)
+ : vHave(std::move(vHaveIn)) {}
SERIALIZE_METHODS(CBlockLocator, obj) {
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(nVersion);
}
READWRITE(obj.vHave);
}
void SetNull() { vHave.clear(); }
bool IsNull() const { return vHave.empty(); }
};
#endif // BITCOIN_PRIMITIVES_BLOCK_H
diff --git a/src/seeder/bitcoin.cpp b/src/seeder/bitcoin.cpp
index aedb0ce4b..f234782e0 100644
--- a/src/seeder/bitcoin.cpp
+++ b/src/seeder/bitcoin.cpp
@@ -1,311 +1,312 @@
// Copyright (c) 2017-2020 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <seeder/bitcoin.h>
#include <chainparams.h>
#include <clientversion.h>
#include <common/args.h>
#include <hash.h>
#include <netbase.h>
#include <primitives/blockhash.h>
#include <seeder/db.h>
#include <seeder/messagewriter.h>
#include <serialize.h>
#include <uint256.h>
#include <util/sock.h>
#include <util/time.h>
#include <algorithm>
#define BITCOIN_SEED_NONCE 0x0539a019ca550825ULL
void CSeederNode::Send() {
if (!sock) {
return;
}
if (vSend.empty()) {
return;
}
int nBytes = sock->Send(&vSend[0], vSend.size(), 0);
if (nBytes > 0) {
vSend.erase(vSend.begin(), vSend.begin() + nBytes);
} else {
sock.reset();
}
}
PeerMessagingState CSeederNode::ProcessMessage(std::string strCommand,
CDataStream &recv) {
// tfm::format(std::cout, "%s: RECV %s\n", ToString(you),
// strCommand);
if (strCommand == NetMsgType::VERSION) {
int64_t nTime;
CService addrMe;
uint64_t nNonce = 1;
uint64_t nServiceInt;
recv >> nVersion >> nServiceInt >> nTime;
yourServices = ServiceFlags(nServiceInt);
// Ignore the addrMe service bits sent by the peer
recv.ignore(8);
recv >> addrMe;
// The version message includes information about the sending node
// which we don't use:
// - 8 bytes (service bits)
// - 16 bytes (ipv6 address)
// - 2 bytes (port)
recv.ignore(26);
recv >> nNonce;
recv >> strSubVer;
recv >> nStartingHeight;
vSend.SetVersion(std::min(nVersion, PROTOCOL_VERSION));
MessageWriter::WriteMessage(vSend, NetMsgType::VERACK);
return PeerMessagingState::AwaitingMessages;
}
if (strCommand == NetMsgType::VERACK) {
vRecv.SetVersion(std::min(nVersion, PROTOCOL_VERSION));
// tfm::format(std::cout, "\n%s: version %i\n", ToString(you),
// nVersion);
if (vAddr) {
MessageWriter::WriteMessage(vSend, NetMsgType::GETADDR);
std::vector<BlockHash> locatorHash(
1, Params().Checkpoints().mapCheckpoints.rbegin()->second);
MessageWriter::WriteMessage(vSend, NetMsgType::GETHEADERS,
- CBlockLocator(locatorHash), uint256());
+ CBlockLocator(std::move(locatorHash)),
+ uint256());
doneAfter = Now<NodeSeconds>() + GetTimeout();
} else {
doneAfter = Now<NodeSeconds>() + 1s;
}
return PeerMessagingState::AwaitingMessages;
}
if (strCommand == NetMsgType::ADDR && vAddr) {
std::vector<CAddress> vAddrNew;
recv >> vAddrNew;
// tfm::format(std::cout, "%s: got %i addresses\n",
// ToString(you),
// (int)vAddrNew.size());
auto now = Now<NodeSeconds>();
std::vector<CAddress>::iterator it = vAddrNew.begin();
if (vAddrNew.size() > 1) {
if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
doneAfter > now + 1s) {
doneAfter = now + 1s;
}
}
while (it != vAddrNew.end()) {
CAddress &addr = *it;
// tfm::format(std::cout, "%s: got address %s\n",
// ToString(you),
// addr.ToString(), (int)(vAddr->size()));
it++;
if (addr.nTime <= NodeSeconds{100000000s} ||
addr.nTime > now + 10min) {
addr.nTime = now - 5 * 24h;
}
if (addr.nTime > now - 7 * 24h) {
vAddr->push_back(addr);
}
// tfm::format(std::cout, "%s: added address %s (#%i)\n",
// ToString(you),
// addr.ToString(), (int)(vAddr->size()));
if (vAddr->size() > ADDR_SOFT_CAP) {
doneAfter = NodeSeconds{1s};
return PeerMessagingState::Finished;
}
}
return PeerMessagingState::AwaitingMessages;
}
return PeerMessagingState::AwaitingMessages;
}
bool CSeederNode::ProcessMessages() {
if (vRecv.empty()) {
return false;
}
const CMessageHeader::MessageMagic netMagic = Params().NetMagic();
do {
CDataStream::iterator pstart = std::search(
vRecv.begin(), vRecv.end(), BEGIN(netMagic), END(netMagic));
uint32_t nHeaderSize =
GetSerializeSize(CMessageHeader(netMagic), vRecv.GetVersion());
if (vRecv.end() - pstart < nHeaderSize) {
if (vRecv.size() > nHeaderSize) {
vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
}
break;
}
vRecv.erase(vRecv.begin(), pstart);
std::vector<std::byte> vHeaderSave(vRecv.begin(),
vRecv.begin() + nHeaderSize);
CMessageHeader hdr(netMagic);
vRecv >> hdr;
if (!hdr.IsValidWithoutConfig(netMagic)) {
// tfm::format(std::cout, "%s: BAD (invalid header)\n",
// ToString(you));
ban = 100000;
return true;
}
std::string strCommand = hdr.GetCommand();
unsigned int nMessageSize = hdr.nMessageSize;
if (nMessageSize > MAX_SIZE) {
// tfm::format(std::cout, "%s: BAD (message too large)\n",
// ToString(you));
ban = 100000;
return true;
}
if (nMessageSize > vRecv.size()) {
vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
break;
}
if (vRecv.GetVersion() >= 209) {
uint256 hash = Hash(Span{vRecv}.first(nMessageSize));
if (memcmp(hash.begin(), hdr.pchChecksum,
CMessageHeader::CHECKSUM_SIZE) != 0) {
continue;
}
}
std::vector<std::byte> vec{vRecv.begin(), vRecv.begin() + nMessageSize};
CDataStream vMsg(MakeUCharSpan(vec), vRecv.GetType(),
vRecv.GetVersion());
vRecv.ignore(nMessageSize);
if (ProcessMessage(strCommand, vMsg) == PeerMessagingState::Finished) {
return true;
}
// tfm::format(std::cout, "%s: done processing %s\n",
// ToString(you),
// strCommand);
} while (1);
return false;
}
CSeederNode::CSeederNode(const CService &ip, std::vector<CAddress> *vAddrIn)
: vSend(SER_NETWORK, 0), vRecv(SER_NETWORK, 0), nHeaderStart(-1),
nMessageStart(-1), nVersion(0), vAddr(vAddrIn), ban(0),
doneAfter(NodeSeconds{0s}), you(ip),
yourServices(ServiceFlags(NODE_NETWORK)) {
if (GetTime() > 1329696000) {
vSend.SetVersion(209);
vRecv.SetVersion(209);
}
}
bool CSeederNode::Run() {
// FIXME: This logic is duplicated with CConnman::ConnectNode for no
// good reason.
bool connected = false;
proxyType proxy;
if (you.IsValid()) {
bool proxyConnectionFailed = false;
if (GetProxy(you.GetNetwork(), proxy)) {
sock = CreateSock(proxy.proxy);
if (!sock) {
return false;
}
connected = ConnectThroughProxy(
proxy, you.ToStringIP(), you.GetPort(), *sock, nConnectTimeout,
proxyConnectionFailed);
} else {
// no proxy needed (none set for target network)
sock = CreateSock(you);
if (!sock) {
return false;
}
// no proxy needed (none set for target network)
connected =
ConnectSocketDirectly(you, *sock, nConnectTimeout, false);
}
}
if (!connected) {
// tfm::format(std::cout, "Cannot connect to %s\n",
// ToString(you));
sock.reset();
return false;
}
// Write version message
// Don't include the time in CAddress serialization. See D14753.
uint64_t nLocalServices = 0;
uint64_t nLocalNonce = BITCOIN_SEED_NONCE;
uint64_t your_services{yourServices};
uint64_t my_services{ServiceFlags(NODE_NETWORK)};
uint8_t fRelayTxs = 0;
const std::string clientName = gArgs.GetArg("-uaclientname", CLIENT_NAME);
const std::string clientVersion =
gArgs.GetArg("-uaclientversion", FormatVersion(CLIENT_VERSION));
const std::string userAgent =
FormatUserAgent(clientName, clientVersion, {"seeder"});
MessageWriter::WriteMessage(vSend, NetMsgType::VERSION, PROTOCOL_VERSION,
nLocalServices, GetTime(), your_services, you,
my_services, CService(), nLocalNonce, userAgent,
GetRequireHeight(), fRelayTxs);
Send();
bool res = true;
NodeSeconds now;
while (now = Now<NodeSeconds>(),
ban == 0 &&
(TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0 ||
doneAfter > now) &&
sock) {
char pchBuf[0x10000];
fd_set fdsetRecv;
fd_set fdsetError;
FD_ZERO(&fdsetRecv);
FD_ZERO(&fdsetError);
FD_SET(sock->Get(), &fdsetRecv);
FD_SET(sock->Get(), &fdsetError);
struct timeval wa;
if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) != 0) {
wa.tv_sec = (doneAfter - now).count();
wa.tv_usec = 0;
} else {
wa.tv_sec = GetTimeout().count();
wa.tv_usec = 0;
}
int ret =
select(sock->Get() + 1, &fdsetRecv, nullptr, &fdsetError, &wa);
if (ret != 1) {
if (TicksSinceEpoch<std::chrono::seconds>(doneAfter) == 0) {
res = false;
}
break;
}
int nBytes = sock->Recv(pchBuf, sizeof(pchBuf), 0);
int nPos = vRecv.size();
if (nBytes > 0) {
vRecv.resize(nPos + nBytes);
memcpy(&vRecv[nPos], pchBuf, nBytes);
} else if (nBytes == 0) {
// tfm::format(std::cout, "%s: BAD (connection closed
// prematurely)\n",
// ToString(you));
res = false;
break;
} else {
// tfm::format(std::cout, "%s: BAD (connection error)\n",
// ToString(you));
res = false;
break;
}
ProcessMessages();
Send();
}
if (!sock) {
res = false;
}
sock.reset();
return (ban == 0) && res;
}
diff --git a/src/seeder/test/message_writer_tests.cpp b/src/seeder/test/message_writer_tests.cpp
index 961f58073..21d362163 100644
--- a/src/seeder/test/message_writer_tests.cpp
+++ b/src/seeder/test/message_writer_tests.cpp
@@ -1,92 +1,92 @@
// Copyright (c) 2020 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <hash.h>
#include <primitives/block.h>
#include <protocol.h>
#include <seeder/messagewriter.h>
#include <streams.h>
#include <version.h>
#include <boost/test/unit_test.hpp>
#include <string>
#include <vector>
BOOST_AUTO_TEST_SUITE(message_writer_tests)
template <typename... Args>
static void CheckMessage(CDataStream &expectedMessage, std::string command,
Args &&...args) {
CDataStream message(SER_NETWORK, PROTOCOL_VERSION);
MessageWriter::WriteMessage(message, command, std::forward<Args>(args)...);
BOOST_CHECK_EQUAL(message.size(), expectedMessage.size());
for (size_t i = 0; i < message.size(); i++) {
BOOST_CHECK_EQUAL(uint8_t(message[i]), uint8_t(expectedMessage[i]));
}
}
BOOST_AUTO_TEST_CASE(simple_header_and_payload_message_writer_test) {
SelectParams(CBaseChainParams::MAIN);
int64_t now = GetTime();
uint64_t nonce = 0;
uint64_t serviceFlags = uint64_t(ServiceFlags(NODE_NETWORK));
CService service;
CAddress addrTo(service, ServiceFlags(NODE_NETWORK));
CAddress addrFrom(service, ServiceFlags(NODE_NETWORK));
std::string user_agent = "/Bitcoin ABC:0.0.0(seeder)/";
int start_height = 1;
CDataStream versionPayload(SER_NETWORK, PROTOCOL_VERSION);
versionPayload << PROTOCOL_VERSION << serviceFlags << now << addrTo
<< addrFrom << nonce << user_agent << start_height;
CMessageHeader versionhdr(Params().NetMagic(), NetMsgType::VERSION,
versionPayload.size());
uint256 hash = Hash(versionPayload);
memcpy(versionhdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
CDataStream expectedVersion(SER_NETWORK, PROTOCOL_VERSION);
expectedVersion << versionhdr << versionPayload;
CheckMessage(expectedVersion, NetMsgType::VERSION, PROTOCOL_VERSION,
serviceFlags, now, addrTo, addrFrom, nonce, user_agent,
start_height);
}
BOOST_AUTO_TEST_CASE(header_empty_payload_message_writer_test) {
SelectParams(CBaseChainParams::MAIN);
CMessageHeader verackHeader(Params().NetMagic(), NetMsgType::VERACK, 0);
CDataStream expectedVerack(SER_NETWORK, PROTOCOL_VERSION);
// This is an empty payload, but is still necessary for the checksum
std::vector<uint8_t> payload;
uint256 hash = Hash(payload);
memcpy(verackHeader.pchChecksum, hash.begin(),
CMessageHeader::CHECKSUM_SIZE);
expectedVerack << verackHeader;
CheckMessage(expectedVerack, NetMsgType::VERACK);
}
BOOST_AUTO_TEST_CASE(write_getheaders_message_test) {
SelectParams(CBaseChainParams::MAIN);
CDataStream payload(SER_NETWORK, PROTOCOL_VERSION);
BlockHash bhash(uint256S(
"0000000099f5509b5f36b1926bcf82b21d936ebeadee811030dfbbb7fae915d7"));
std::vector<BlockHash> vlocator(1, bhash);
- CBlockLocator locatorhash(vlocator);
+ CBlockLocator locatorhash(std::move(vlocator));
payload << locatorhash << uint256();
uint256 hash = Hash(payload);
CMessageHeader msgHeader(Params().NetMagic(), NetMsgType::GETHEADERS,
payload.size());
memcpy(msgHeader.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
CDataStream expectedMsg(SER_NETWORK, PROTOCOL_VERSION);
expectedMsg << msgHeader << payload;
CheckMessage(expectedMsg, NetMsgType::GETHEADERS, locatorhash, uint256());
}
BOOST_AUTO_TEST_SUITE_END()

File Metadata

Mime Type
text/x-diff
Expires
Thu, May 22, 01:51 (13 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5866292
Default Alt Text
(23 KB)

Event Timeline