mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-29 00:04:40 +00:00
Merge branch 'master' into async-ipv6-rpc
This commit is contained in:
commit
415a87ef36
Binary file not shown.
Binary file not shown.
96
doc/Tor.txt
Normal file
96
doc/Tor.txt
Normal file
@ -0,0 +1,96 @@
|
||||
TOR SUPPORT IN BITCOIN
|
||||
======================
|
||||
|
||||
It is possible to run Bitcoin as a Tor hidden service, and connect to such services.
|
||||
|
||||
The following assumes you have a Tor proxy running on port 9050. Many distributions
|
||||
default to having a SOCKS proxy listening on port 9050, but others may not.
|
||||
In particular, the Tor Browser Bundle defaults to listening on a random port. See
|
||||
https://www.torproject.org/docs/faq.html.en#TBBSocksPort for how to properly
|
||||
configure Tor.
|
||||
|
||||
|
||||
1. Run bitcoin behind a Tor proxy
|
||||
---------------------------------
|
||||
|
||||
The first step is running Bitcoin behind a Tor proxy. This will already make all
|
||||
outgoing connections be anonimized, but more is possible.
|
||||
|
||||
-socks=5 SOCKS5 supports connecting-to-hostname, which can be used instead
|
||||
of doing a (leaking) local DNS lookup. SOCKS5 is the default,
|
||||
but SOCKS4 does not support this. (SOCKS4a does, but isn't
|
||||
implemented).
|
||||
|
||||
-proxy=ip:port Set the proxy server. If SOCKS5 is selected (default), this proxy
|
||||
server will be used to try to reach .onion addresses as well.
|
||||
|
||||
-tor=ip:port Set the proxy server to use for tor hidden services. You do not
|
||||
need to set this if it's the same as -proxy. You can use -notor
|
||||
to explicitly disable access to hidden service.
|
||||
|
||||
-dnsseed DNS seeds are not resolved directly when a SOCKS5 proxy server is
|
||||
set. Rather, a short-lived proxy connection to the dns seed
|
||||
hostname is attempted, and peer addresses are requested.
|
||||
|
||||
-listen When using -proxy, listening is disabled by default. If you want
|
||||
to run a hidden service (see next section), you'll need to enable
|
||||
it explicitly.
|
||||
|
||||
-connect=X When behing a Tor proxy, you can specify .onion addresses instead
|
||||
-addnode=X of IP addresses or hostnames in these parameters. It requires
|
||||
-seednode=X SOCKS5. In Tor mode, such addresses can also be exchanged with
|
||||
other P2P nodes.
|
||||
|
||||
In a typical situation, this suffices to run behind a Tor proxy:
|
||||
|
||||
./bitcoin -proxy=127.0.0.1:9050
|
||||
|
||||
|
||||
2. Run a bitcoin hidden server
|
||||
------------------------------
|
||||
|
||||
If you configure your Tor system accordingly, it is possible to make your node also
|
||||
reachable from the Tor network. Add these lines to your /etc/tor/torrc (or equivalent
|
||||
config file):
|
||||
|
||||
HiddenServiceDir /var/lib/tor/bitcoin-service/
|
||||
HiddenServicePort 8333 127.0.0.1:8333
|
||||
|
||||
The directory can be different of course, but (both) 8333's should be equal to your
|
||||
bitcoind's P2P listen port (8333 by default).
|
||||
|
||||
-externalip=X You can tell bitcoin about its publically reachable address using
|
||||
this option, and this can be a .onion address. Given the above
|
||||
configuration, you can find your onion address in
|
||||
/var/lib/tor/bitcoin-service/hostname. Onion addresses are given
|
||||
preference for your node to advertize itself with, for connections
|
||||
coming from unroutable addresses (such as 127.0.0.1, where the
|
||||
Tor proxy typically runs).
|
||||
|
||||
-listen You'll need to enable listening for incoming connections, as this
|
||||
is off by default behind a proxy.
|
||||
|
||||
-discover When -externalip is specified, no attempt is made to discover local
|
||||
IPv4 or IPv6 addresses. If you want to run a dual stack, reachable
|
||||
from both Tor and IPv4 (or IPv6), you'll need to either pass your
|
||||
other addresses using -externalip, or explicitly enable -discover.
|
||||
Note that both addresses of a dual-stack system may be easily
|
||||
linkable using traffic analysis.
|
||||
|
||||
In a typical situation, where you're only reachable via Tor, this should suffice:
|
||||
|
||||
./bitcoind -proxy=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -listen
|
||||
|
||||
(obviously replace the Onion address with your own). If you don't care too much
|
||||
about hiding your node, and want to be reachable on IPv4 as well, additionally
|
||||
specify:
|
||||
|
||||
./bitcoind ... -discover
|
||||
|
||||
and open port 8333 on your firewall (or use -upnp).
|
||||
|
||||
If you only want to use Tor to reach onion addresses, but not use it as a proxy
|
||||
for normal IPv4/IPv6 communication, use:
|
||||
|
||||
./bitcoin -tor=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -discover
|
||||
|
@ -7,7 +7,7 @@ cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP
|
||||
software written by Thomas Bernard.
|
||||
|
||||
|
||||
See readme-qt.rst for instructions on building Bitcoin QT, the
|
||||
See readme-qt.rst for instructions on building Bitcoin-Qt, the
|
||||
graphical user interface.
|
||||
|
||||
WINDOWS BUILD NOTES
|
||||
|
@ -1,10 +1,10 @@
|
||||
Copyright (c) 2009-2012 Bitcoin Developers
|
||||
Distributed under the MIT/X11 software license, see the accompanying file
|
||||
license.txt or http://www.opensource.org/licenses/mit-license.php. This
|
||||
product includes software developed by the OpenSSL Project for use in the
|
||||
OpenSSL Toolkit (http://www.openssl.org/). This product includes cryptographic
|
||||
software written by Eric Young (eay@cryptsoft.com) and UPnP software written by
|
||||
Thomas Bernard.
|
||||
Distributed under the MIT/X11 software license, see the accompanying
|
||||
file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
This product includes software developed by the OpenSSL Project for use in
|
||||
the OpenSSL Toolkit (http://www.openssl.org/). This product includes
|
||||
cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP
|
||||
software written by Thomas Bernard.
|
||||
|
||||
|
||||
Mac OS X bitcoind build instructions
|
||||
@ -12,17 +12,17 @@ Laszlo Hanyecz <solar@heliacal.net>
|
||||
Douglas Huff <dhuff@jrbobdobbs.org>
|
||||
|
||||
|
||||
See readme-qt.rst for instructions on building Bitcoin QT, the
|
||||
See readme-qt.rst for instructions on building Bitcoin-Qt, the
|
||||
graphical user interface.
|
||||
|
||||
Tested on 10.5 and 10.6 intel. PPC is not supported because it's big-endian.
|
||||
Tested on 10.5, 10.6 and 10.7 intel. PPC is not supported because it's big-endian.
|
||||
|
||||
All of the commands should be executed in Terminal.app.. it's in
|
||||
/Applications/Utilities
|
||||
|
||||
You need to install XCode with all the options checked so that the compiler and
|
||||
everything is available in /usr not just /Developer I think it comes on the DVD
|
||||
but you can get the current version from http://developer.apple.com
|
||||
everything is available in /usr not just /Developer. XCode should be available on your OS X
|
||||
install DVD, but if not, you can get the current version from https://developer.apple.com/xcode/
|
||||
|
||||
|
||||
1. Clone the github tree to get the source code:
|
||||
|
@ -16,8 +16,8 @@ To Build
|
||||
cd src/
|
||||
make -f makefile.unix # Headless bitcoin
|
||||
|
||||
See readme-qt.rst for instructions on building Bitcoin QT,
|
||||
the graphical bitcoin.
|
||||
See readme-qt.rst for instructions on building Bitcoin-Qt,
|
||||
the graphical user interface.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
22
src/bignum.h
22
src/bignum.h
@ -122,16 +122,30 @@ public:
|
||||
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
|
||||
}
|
||||
|
||||
void setint64(int64 n)
|
||||
void setint64(int64 sn)
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char pch[sizeof(sn) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fNegative = false;
|
||||
if (n < (int64)0)
|
||||
bool fNegative;
|
||||
uint64 n;
|
||||
|
||||
if (sn < (int64)0)
|
||||
{
|
||||
// We negate in 2 steps to avoid signed subtraction overflow,
|
||||
// i.e. -(-2^63), which is an undefined operation and causes SIGILL
|
||||
// when compiled with -ftrapv.
|
||||
//
|
||||
// Note that uint64_t n = sn, when sn is an int64_t, is a
|
||||
// well-defined operation and n will be equal to sn + 2^64 when sn
|
||||
// is negative.
|
||||
n = sn;
|
||||
n = -n;
|
||||
fNegative = true;
|
||||
} else {
|
||||
n = sn;
|
||||
fNegative = false;
|
||||
}
|
||||
|
||||
bool fLeadingZeroes = true;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
|
@ -2198,6 +2198,23 @@ Value getmemorypool(const Array& params, bool fHelp)
|
||||
}
|
||||
}
|
||||
|
||||
Value getrawmempool(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getrawmempool\n"
|
||||
"Returns all transaction ids in memory pool.");
|
||||
|
||||
vector<uint256> vtxid;
|
||||
mempool.queryHashes(vtxid);
|
||||
|
||||
Array a;
|
||||
BOOST_FOREACH(const uint256& hash, vtxid)
|
||||
a.push_back(hash.ToString());
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
Value getblockhash(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
@ -2321,6 +2338,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "sendfrom", &sendfrom, false },
|
||||
{ "sendmany", &sendmany, false },
|
||||
{ "addmultisigaddress", &addmultisigaddress, false },
|
||||
{ "getrawmempool", &getrawmempool, true },
|
||||
{ "getblock", &getblock, false },
|
||||
{ "getblockhash", &getblockhash, false },
|
||||
{ "gettransaction", &gettransaction, false },
|
||||
|
60
src/db.cpp
60
src/db.cpp
@ -404,66 +404,6 @@ bool CTxDB::ContainsTx(uint256 hash)
|
||||
return Exists(make_pair(string("tx"), hash));
|
||||
}
|
||||
|
||||
bool CTxDB::ReadOwnerTxes(uint160 hash160, int nMinHeight, vector<CTransaction>& vtx)
|
||||
{
|
||||
assert(!fClient);
|
||||
vtx.clear();
|
||||
|
||||
// Get cursor
|
||||
Dbc* pcursor = GetCursor();
|
||||
if (!pcursor)
|
||||
return false;
|
||||
|
||||
unsigned int fFlags = DB_SET_RANGE;
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
if (fFlags == DB_SET_RANGE)
|
||||
ssKey << string("owner") << hash160 << CDiskTxPos(0, 0, 0);
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
|
||||
fFlags = DB_NEXT;
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
else if (ret != 0)
|
||||
{
|
||||
pcursor->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unserialize
|
||||
string strType;
|
||||
uint160 hashItem;
|
||||
CDiskTxPos pos;
|
||||
int nItemHeight;
|
||||
|
||||
try {
|
||||
ssKey >> strType >> hashItem >> pos;
|
||||
ssValue >> nItemHeight;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("%s() : deserialize error", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
// Read transaction
|
||||
if (strType != "owner" || hashItem != hash160)
|
||||
break;
|
||||
if (nItemHeight >= nMinHeight)
|
||||
{
|
||||
vtx.resize(vtx.size()+1);
|
||||
if (!vtx.back().ReadFromDisk(pos))
|
||||
{
|
||||
pcursor->close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pcursor->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex)
|
||||
{
|
||||
assert(!fClient);
|
||||
|
1
src/db.h
1
src/db.h
@ -307,7 +307,6 @@ public:
|
||||
bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
|
||||
bool EraseTxIndex(const CTransaction& tx);
|
||||
bool ContainsTx(uint256 hash);
|
||||
bool ReadOwnerTxes(uint160 hash160, int nHeight, std::vector<CTransaction>& vtx);
|
||||
bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
|
||||
bool ReadDiskTx(uint256 hash, CTransaction& tx);
|
||||
bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
|
||||
|
32
src/init.cpp
32
src/init.cpp
@ -223,6 +223,7 @@ std::string HelpMessage()
|
||||
" -timeout=<n> " + _("Specify connection timeout (in milliseconds)") + "\n" +
|
||||
" -proxy=<ip:port> " + _("Connect through socks proxy") + "\n" +
|
||||
" -socks=<n> " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n" +
|
||||
" -tor=<ip:port> " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n"
|
||||
" -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" +
|
||||
" -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" +
|
||||
" -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" +
|
||||
@ -230,12 +231,12 @@ std::string HelpMessage()
|
||||
" -connect=<ip> " + _("Connect only to the specified node(s)") + "\n" +
|
||||
" -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" +
|
||||
" -externalip=<ip> " + _("Specify your own public address") + "\n" +
|
||||
" -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4 or IPv6)") + "\n" +
|
||||
" -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n" +
|
||||
" -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n" +
|
||||
" -irc " + _("Find peers using internet relay chat (default: 0)") + "\n" +
|
||||
" -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n" +
|
||||
" -bind=<addr> " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" +
|
||||
" -dnsseed " + _("Find peers using DNS lookup (default: 1)") + "\n" +
|
||||
" -dnsseed " + _("Find peers using DNS lookup (default: 1 unless -connect)") + "\n" +
|
||||
" -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
|
||||
" -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
|
||||
" -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)") + "\n" +
|
||||
@ -345,7 +346,7 @@ bool AppInit2()
|
||||
SoftSetBoolArg("-listen", false);
|
||||
}
|
||||
|
||||
if (GetBoolArg("-listen", true)) {
|
||||
if (!GetBoolArg("-listen", true)) {
|
||||
// do not map ports or try to retrieve public IP when not listening (pointless)
|
||||
SoftSetBoolArg("-upnp", false);
|
||||
SoftSetBoolArg("-discover", false);
|
||||
@ -359,6 +360,13 @@ bool AppInit2()
|
||||
// ********************************************************* Step 3: parameter-to-internal-flags
|
||||
|
||||
fDebug = GetBoolArg("-debug");
|
||||
|
||||
// -debug implies fDebug*
|
||||
if (fDebug)
|
||||
fDebugNet = true;
|
||||
else
|
||||
fDebugNet = GetBoolArg("-debugnet");
|
||||
|
||||
bitdb.SetDetach(GetBoolArg("-detachdb", false));
|
||||
|
||||
#if !defined(WIN32) && !defined(QT_GUI)
|
||||
@ -470,8 +478,10 @@ bool AppInit2()
|
||||
}
|
||||
}
|
||||
|
||||
CService addrProxy;
|
||||
bool fProxy = false;
|
||||
if (mapArgs.count("-proxy")) {
|
||||
CService addrProxy = CService(mapArgs["-proxy"], 9050);
|
||||
addrProxy = CService(mapArgs["-proxy"], 9050);
|
||||
if (!addrProxy.IsValid())
|
||||
return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"].c_str()));
|
||||
|
||||
@ -484,6 +494,20 @@ bool AppInit2()
|
||||
#endif
|
||||
SetNameProxy(addrProxy, nSocksVersion);
|
||||
}
|
||||
fProxy = true;
|
||||
}
|
||||
|
||||
// -tor can override normal proxy, -notor disables tor entirely
|
||||
if (!(mapArgs.count("-tor") && mapArgs["-tor"] == "0") && (fProxy || mapArgs.count("-tor"))) {
|
||||
CService addrOnion;
|
||||
if (!mapArgs.count("-tor"))
|
||||
addrOnion = addrProxy;
|
||||
else
|
||||
addrOnion = CService(mapArgs["-tor"], 9050);
|
||||
if (!addrOnion.IsValid())
|
||||
return InitError(strprintf(_("Invalid -tor address: '%s'"), mapArgs["-tor"].c_str()));
|
||||
SetProxy(NET_TOR, addrOnion, 5);
|
||||
SetReachable(NET_TOR);
|
||||
}
|
||||
|
||||
// see Step 2: parameter interactions for more information about these
|
||||
|
@ -129,6 +129,8 @@ void CKey::SetCompressedPubKey()
|
||||
void CKey::Reset()
|
||||
{
|
||||
fCompressedPubKey = false;
|
||||
if (pkey != NULL)
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||
@ -137,6 +139,7 @@ void CKey::Reset()
|
||||
|
||||
CKey::CKey()
|
||||
{
|
||||
pkey = NULL;
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
24
src/main.cpp
24
src/main.cpp
@ -180,8 +180,8 @@ bool AddOrphanTx(const CDataStream& vMsg)
|
||||
// at most 500 megabytes of orphans:
|
||||
if (pvMsg->size() > 5000)
|
||||
{
|
||||
delete pvMsg;
|
||||
printf("ignoring large orphan tx (size: %u, hash: %s)\n", pvMsg->size(), hash.ToString().substr(0,10).c_str());
|
||||
delete pvMsg;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -652,7 +652,15 @@ bool CTxMemPool::remove(CTransaction &tx)
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTxMemPool::queryHashes(std::vector<uint256>& vtxid)
|
||||
{
|
||||
vtxid.clear();
|
||||
|
||||
LOCK(cs);
|
||||
vtxid.reserve(mapTx.size());
|
||||
for (map<uint256, CTransaction>::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
|
||||
vtxid.push_back((*mi).first);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1317,8 +1325,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
|
||||
// This logic is not necessary for memory pool transactions, as AcceptToMemoryPool
|
||||
// already refuses previously-known transaction id's entirely.
|
||||
// This rule applies to all blocks whose timestamp is after March 15, 2012, 0:00 UTC.
|
||||
// On testnet it is enabled as of februari 20, 2012, 0:00 UTC.
|
||||
if (pindex->nTime > 1331769600 || (fTestNet && pindex->nTime > 1329696000))
|
||||
if (pindex->nTime > 1331769600)
|
||||
{
|
||||
BOOST_FOREACH(CTransaction& tx, vtx)
|
||||
{
|
||||
@ -1332,8 +1339,8 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
|
||||
}
|
||||
}
|
||||
|
||||
// BIP16 didn't become active until Apr 1 2012 (Feb 15 on testnet)
|
||||
int64 nBIP16SwitchTime = fTestNet ? 1329264000 : 1333238400;
|
||||
// BIP16 didn't become active until Apr 1 2012
|
||||
int64 nBIP16SwitchTime = 1333238400;
|
||||
bool fStrictPayToScriptHash = (pindex->nTime >= nBIP16SwitchTime);
|
||||
|
||||
//// issue here: it doesn't know the version
|
||||
@ -2419,7 +2426,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
|
||||
pfrom->fSuccessfullyConnected = true;
|
||||
|
||||
printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight);
|
||||
printf("receive version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str());
|
||||
|
||||
cPeerBlockCounts.input(pfrom->nStartingHeight);
|
||||
}
|
||||
@ -2475,7 +2482,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
static uint256 hashSalt;
|
||||
if (hashSalt == 0)
|
||||
hashSalt = GetRandHash();
|
||||
int64 hashAddr = addr.GetHash();
|
||||
uint64 hashAddr = addr.GetHash();
|
||||
uint256 hashRand = hashSalt ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/(24*60*60));
|
||||
hashRand = Hash(BEGIN(hashRand), END(hashRand));
|
||||
multimap<uint256, CNode*> mapMix;
|
||||
@ -3143,7 +3150,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
const CInv& inv = (*pto->mapAskFor.begin()).second;
|
||||
if (!AlreadyHave(txdb, inv))
|
||||
{
|
||||
printf("sending getdata: %s\n", inv.ToString().c_str());
|
||||
if (fDebugNet)
|
||||
printf("sending getdata: %s\n", inv.ToString().c_str());
|
||||
vGetData.push_back(inv);
|
||||
if (vGetData.size() >= 1000)
|
||||
{
|
||||
|
@ -1604,6 +1604,7 @@ public:
|
||||
bool fCheckInputs, bool* pfMissingInputs);
|
||||
bool addUnchecked(CTransaction &tx);
|
||||
bool remove(CTransaction &tx);
|
||||
void queryHashes(std::vector<uint256>& vtxid);
|
||||
|
||||
unsigned long size()
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
size_type max_size(size_type s)
|
||||
{
|
||||
if (s)
|
||||
while (queue.size() >= s)
|
||||
while (queue.size() > s)
|
||||
{
|
||||
set.erase(queue.front());
|
||||
queue.pop_front();
|
||||
|
13
src/net.cpp
13
src/net.cpp
@ -206,6 +206,14 @@ void static AdvertizeLocal()
|
||||
}
|
||||
}
|
||||
|
||||
void SetReachable(enum Network net, bool fFlag)
|
||||
{
|
||||
LOCK(cs_mapLocalHost);
|
||||
vfReachable[net] = fFlag;
|
||||
if (net == NET_IPV6 && fFlag)
|
||||
vfReachable[NET_IPV4] = true;
|
||||
}
|
||||
|
||||
// learn a new local address
|
||||
bool AddLocal(const CService& addr, int nScore)
|
||||
{
|
||||
@ -228,9 +236,7 @@ bool AddLocal(const CService& addr, int nScore)
|
||||
info.nScore = nScore;
|
||||
info.nPort = addr.GetPort() + (fAlready ? 1 : 0);
|
||||
}
|
||||
enum Network net = addr.GetNetwork();
|
||||
vfReachable[net] = true;
|
||||
if (net == NET_IPV6) vfReachable[NET_IPV4] = true;
|
||||
SetReachable(addr.GetNetwork());
|
||||
}
|
||||
|
||||
AdvertizeLocal();
|
||||
@ -543,6 +549,7 @@ void CNode::PushVersion()
|
||||
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
|
||||
CAddress addrMe = GetLocalAddress(&addr);
|
||||
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
|
||||
printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
|
||||
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
|
||||
nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ bool SeenLocal(const CService& addr);
|
||||
bool IsLocal(const CService& addr);
|
||||
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL);
|
||||
bool IsReachable(const CNetAddr &addr);
|
||||
void SetReachable(enum Network net, bool fFlag = true);
|
||||
CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
|
||||
|
||||
|
||||
@ -296,7 +297,8 @@ public:
|
||||
// We're using mapAskFor as a priority queue,
|
||||
// the key is the earliest time the request can be sent
|
||||
int64& nRequestTime = mapAlreadyAskedFor[inv];
|
||||
printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
|
||||
if (fDebugNet)
|
||||
printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
|
||||
|
||||
// Make sure not to reuse time indexes to keep things in the same order
|
||||
int64 nNow = (GetTime() - 1) * 1000000;
|
||||
|
241
src/netbase.cpp
241
src/netbase.cpp
@ -33,9 +33,39 @@ enum Network ParseNetwork(std::string net) {
|
||||
return NET_UNROUTABLE;
|
||||
}
|
||||
|
||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
|
||||
size_t colon = in.find_last_of(':');
|
||||
// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
|
||||
bool fHaveColon = colon != in.npos;
|
||||
bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
|
||||
bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
|
||||
if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
|
||||
char *endp = NULL;
|
||||
int n = strtol(in.c_str() + colon + 1, &endp, 10);
|
||||
if (endp && *endp == 0 && n >= 0) {
|
||||
in = in.substr(0, colon);
|
||||
if (n > 0 && n < 0x10000)
|
||||
portOut = n;
|
||||
}
|
||||
}
|
||||
if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
|
||||
hostOut = in.substr(1, in.size()-2);
|
||||
else
|
||||
hostOut = in;
|
||||
}
|
||||
|
||||
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
|
||||
{
|
||||
vIP.clear();
|
||||
|
||||
{
|
||||
CNetAddr addr;
|
||||
if (addr.SetSpecial(std::string(pszName))) {
|
||||
vIP.push_back(addr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
struct addrinfo aiHint;
|
||||
memset(&aiHint, 0, sizeof(struct addrinfo));
|
||||
|
||||
@ -44,19 +74,17 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
|
||||
#ifdef WIN32
|
||||
# ifdef USE_IPV6
|
||||
aiHint.ai_family = AF_UNSPEC;
|
||||
aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
|
||||
# else
|
||||
aiHint.ai_family = AF_INET;
|
||||
aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
|
||||
# endif
|
||||
aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
|
||||
#else
|
||||
# ifdef USE_IPV6
|
||||
aiHint.ai_family = AF_UNSPEC;
|
||||
aiHint.ai_flags = AI_ADDRCONFIG | (fAllowLookup ? 0 : AI_NUMERICHOST);
|
||||
# else
|
||||
aiHint.ai_family = AF_INET;
|
||||
aiHint.ai_flags = AI_ADDRCONFIG | (fAllowLookup ? 0 : AI_NUMERICHOST);
|
||||
# endif
|
||||
aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
|
||||
#endif
|
||||
struct addrinfo *aiRes = NULL;
|
||||
int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
|
||||
@ -114,36 +142,11 @@ bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault,
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
int port = portDefault;
|
||||
char psz[256];
|
||||
char *pszHost = psz;
|
||||
strlcpy(psz, pszName, sizeof(psz));
|
||||
char* pszColon = strrchr(psz+1,':');
|
||||
char *pszPortEnd = NULL;
|
||||
int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
|
||||
if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
|
||||
{
|
||||
if (psz[0] == '[' && pszColon[-1] == ']')
|
||||
{
|
||||
pszHost = psz+1;
|
||||
pszColon[-1] = 0;
|
||||
}
|
||||
else
|
||||
pszColon[0] = 0;
|
||||
if (port >= 0 && port <= USHRT_MAX)
|
||||
port = portParsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (psz[0] == '[' && psz[strlen(psz)-1] == ']')
|
||||
{
|
||||
pszHost = psz+1;
|
||||
psz[strlen(psz)-1] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
std::string hostname = "";
|
||||
SplitHostPort(std::string(pszName), port, hostname);
|
||||
|
||||
std::vector<CNetAddr> vIP;
|
||||
bool fRet = LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
|
||||
bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
|
||||
if (!fRet)
|
||||
return false;
|
||||
vAddr.resize(vIP.size());
|
||||
@ -496,22 +499,9 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
|
||||
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout)
|
||||
{
|
||||
string strDest(pszDest);
|
||||
string strDest;
|
||||
int port = portDefault;
|
||||
|
||||
// split hostname and port
|
||||
size_t colon = strDest.find_last_of(':');
|
||||
if (colon != strDest.npos) {
|
||||
char *endp = NULL;
|
||||
int n = strtol(pszDest + colon + 1, &endp, 10);
|
||||
if (endp && *endp == 0 && n >= 0) {
|
||||
strDest = strDest.substr(0, colon);
|
||||
if (n > 0 && n < 0x10000)
|
||||
port = n;
|
||||
}
|
||||
}
|
||||
if (strDest[0] == '[' && strDest[strDest.size()-1] == ']')
|
||||
strDest = strDest.substr(1, strDest.size()-2);
|
||||
SplitHostPort(string(pszDest), port, strDest);
|
||||
|
||||
SOCKET hSocket = INVALID_SOCKET;
|
||||
CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxyInfo.second), port);
|
||||
@ -549,6 +539,32 @@ void CNetAddr::SetIP(const CNetAddr& ipIn)
|
||||
memcpy(ip, ipIn.ip, sizeof(ip));
|
||||
}
|
||||
|
||||
static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
|
||||
static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5};
|
||||
|
||||
bool CNetAddr::SetSpecial(const std::string &strName)
|
||||
{
|
||||
if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
|
||||
std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str());
|
||||
if (vchAddr.size() != 16-sizeof(pchOnionCat))
|
||||
return false;
|
||||
memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
|
||||
for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++)
|
||||
ip[i + sizeof(pchOnionCat)] = vchAddr[i];
|
||||
return true;
|
||||
}
|
||||
if (strName.size()>11 && strName.substr(strName.size() - 11, 11) == ".oc.b32.i2p") {
|
||||
std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 11).c_str());
|
||||
if (vchAddr.size() != 16-sizeof(pchGarliCat))
|
||||
return false;
|
||||
memcpy(ip, pchOnionCat, sizeof(pchGarliCat));
|
||||
for (unsigned int i=0; i<16-sizeof(pchGarliCat); i++)
|
||||
ip[i + sizeof(pchGarliCat)] = vchAddr[i];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr()
|
||||
{
|
||||
Init();
|
||||
@ -595,7 +611,7 @@ bool CNetAddr::IsIPv4() const
|
||||
|
||||
bool CNetAddr::IsIPv6() const
|
||||
{
|
||||
return (!IsIPv4());
|
||||
return (!IsIPv4() && !IsTor() && !IsI2P());
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC1918() const
|
||||
@ -654,15 +670,13 @@ bool CNetAddr::IsRFC4843() const
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsOnionCat() const
|
||||
bool CNetAddr::IsTor() const
|
||||
{
|
||||
static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
|
||||
return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsGarliCat() const
|
||||
bool CNetAddr::IsI2P() const
|
||||
{
|
||||
static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5};
|
||||
return (memcmp(ip, pchGarliCat, sizeof(pchGarliCat)) == 0);
|
||||
}
|
||||
|
||||
@ -724,7 +738,7 @@ bool CNetAddr::IsValid() const
|
||||
|
||||
bool CNetAddr::IsRoutable() const
|
||||
{
|
||||
return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || (IsRFC4193() && !IsOnionCat() && !IsGarliCat()) || IsRFC4843() || IsLocal());
|
||||
return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || (IsRFC4193() && !IsTor() && !IsI2P()) || IsRFC4843() || IsLocal());
|
||||
}
|
||||
|
||||
enum Network CNetAddr::GetNetwork() const
|
||||
@ -735,10 +749,10 @@ enum Network CNetAddr::GetNetwork() const
|
||||
if (IsIPv4())
|
||||
return NET_IPV4;
|
||||
|
||||
if (IsOnionCat())
|
||||
if (IsTor())
|
||||
return NET_TOR;
|
||||
|
||||
if (IsGarliCat())
|
||||
if (IsI2P())
|
||||
return NET_I2P;
|
||||
|
||||
return NET_IPV6;
|
||||
@ -746,6 +760,10 @@ enum Network CNetAddr::GetNetwork() const
|
||||
|
||||
std::string CNetAddr::ToStringIP() const
|
||||
{
|
||||
if (IsTor())
|
||||
return EncodeBase32(&ip[6], 10) + ".onion";
|
||||
if (IsI2P())
|
||||
return EncodeBase32(&ip[6], 10) + ".oc.b32.i2p";
|
||||
CService serv(*this, 0);
|
||||
#ifdef USE_IPV6
|
||||
struct sockaddr_storage sockaddr;
|
||||
@ -758,7 +776,7 @@ std::string CNetAddr::ToStringIP() const
|
||||
if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST))
|
||||
return std::string(name);
|
||||
}
|
||||
if (IsIPv4())
|
||||
if (IsIPv4())
|
||||
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
|
||||
else
|
||||
return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
@ -847,6 +865,18 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
|
||||
vchRet.push_back(GetByte(2) ^ 0xFF);
|
||||
return vchRet;
|
||||
}
|
||||
else if (IsTor())
|
||||
{
|
||||
nClass = NET_TOR;
|
||||
nStartByte = 6;
|
||||
nBits = 4;
|
||||
}
|
||||
else if (IsI2P())
|
||||
{
|
||||
nClass = NET_I2P;
|
||||
nStartByte = 6;
|
||||
nBits = 4;
|
||||
}
|
||||
// for he.net, use /36 groups
|
||||
else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
|
||||
nBits = 36;
|
||||
@ -867,10 +897,10 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
int64 CNetAddr::GetHash() const
|
||||
uint64 CNetAddr::GetHash() const
|
||||
{
|
||||
uint256 hash = Hash(&ip[0], &ip[16]);
|
||||
int64 nRet;
|
||||
uint64 nRet;
|
||||
memcpy(&nRet, &hash, sizeof(nRet));
|
||||
return nRet;
|
||||
}
|
||||
@ -880,27 +910,82 @@ void CNetAddr::print() const
|
||||
printf("CNetAddr(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
// for IPv6 partners: for unknown/Teredo partners: for IPv4 partners:
|
||||
// 0 - unroutable // 0 - unroutable // 0 - unroutable
|
||||
// 1 - teredo // 1 - teredo // 1 - ipv4
|
||||
// 2 - tunneled ipv6 // 2 - tunneled ipv6
|
||||
// 3 - ipv4 // 3 - ipv6
|
||||
// 4 - ipv6 // 4 - ipv4
|
||||
// private extensions to enum Network, only returned by GetExtNetwork,
|
||||
// and only used in GetReachabilityFrom
|
||||
static const int NET_UNKNOWN = NET_MAX + 0;
|
||||
static const int NET_TEREDO = NET_MAX + 1;
|
||||
int static GetExtNetwork(const CNetAddr *addr)
|
||||
{
|
||||
if (addr == NULL)
|
||||
return NET_UNKNOWN;
|
||||
if (addr->IsRFC4380())
|
||||
return NET_TEREDO;
|
||||
return addr->GetNetwork();
|
||||
}
|
||||
|
||||
/** Calculates a metric for how reachable (*this) is from a given partner */
|
||||
int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
|
||||
{
|
||||
if (!IsValid() || !IsRoutable())
|
||||
return 0;
|
||||
if (paddrPartner && paddrPartner->IsIPv4())
|
||||
return IsIPv4() ? 1 : 0;
|
||||
if (IsRFC4380())
|
||||
return 1;
|
||||
if (IsRFC3964() || IsRFC6052())
|
||||
return 2;
|
||||
bool fRealIPv6 = paddrPartner && !paddrPartner->IsRFC4380() && paddrPartner->IsValid() && paddrPartner->IsRoutable();
|
||||
if (fRealIPv6)
|
||||
return IsIPv4() ? 3 : 4;
|
||||
else
|
||||
return IsIPv4() ? 4 : 3;
|
||||
enum Reachability {
|
||||
REACH_UNREACHABLE,
|
||||
REACH_DEFAULT,
|
||||
REACH_TEREDO,
|
||||
REACH_IPV6_WEAK,
|
||||
REACH_IPV4,
|
||||
REACH_IPV6_STRONG,
|
||||
REACH_PRIVATE
|
||||
};
|
||||
|
||||
if (!IsRoutable())
|
||||
return REACH_UNREACHABLE;
|
||||
|
||||
int ourNet = GetExtNetwork(this);
|
||||
int theirNet = GetExtNetwork(paddrPartner);
|
||||
bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
|
||||
|
||||
switch(theirNet) {
|
||||
case NET_IPV4:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
}
|
||||
case NET_IPV6:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunneled
|
||||
}
|
||||
case NET_TOR:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well
|
||||
case NET_TOR: return REACH_PRIVATE;
|
||||
}
|
||||
case NET_I2P:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_I2P: return REACH_PRIVATE;
|
||||
}
|
||||
case NET_TEREDO:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV6: return REACH_IPV6_WEAK;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
}
|
||||
case NET_UNKNOWN:
|
||||
case NET_UNROUTABLE:
|
||||
default:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV6: return REACH_IPV6_WEAK;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
case NET_I2P: return REACH_PRIVATE; // assume connections from unroutable addresses are
|
||||
case NET_TOR: return REACH_PRIVATE; // either from Tor/I2P, or don't care about our address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CService::Init()
|
||||
@ -1055,7 +1140,7 @@ std::string CService::ToStringPort() const
|
||||
|
||||
std::string CService::ToStringIPPort() const
|
||||
{
|
||||
if (IsIPv4()) {
|
||||
if (IsIPv4() || IsTor() || IsI2P()) {
|
||||
return ToStringIP() + ":" + ToStringPort();
|
||||
} else {
|
||||
return "[" + ToStringIP() + "]:" + ToStringPort();
|
||||
|
@ -25,7 +25,7 @@ enum Network
|
||||
NET_TOR,
|
||||
NET_I2P,
|
||||
|
||||
NET_MAX
|
||||
NET_MAX,
|
||||
};
|
||||
|
||||
extern int nConnectTimeout;
|
||||
@ -44,8 +44,9 @@ class CNetAddr
|
||||
explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
|
||||
void Init();
|
||||
void SetIP(const CNetAddr& ip);
|
||||
bool SetSpecial(const std::string &strName); // for Tor and I2P addresses
|
||||
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
||||
bool IsIPv6() const; // IPv6 address (not IPv4)
|
||||
bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor/I2P)
|
||||
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
||||
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
|
||||
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
|
||||
@ -56,8 +57,8 @@ class CNetAddr
|
||||
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
|
||||
bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
|
||||
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
|
||||
bool IsOnionCat() const;
|
||||
bool IsGarliCat() const;
|
||||
bool IsTor() const;
|
||||
bool IsI2P() const;
|
||||
bool IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsValid() const;
|
||||
@ -66,7 +67,7 @@ class CNetAddr
|
||||
std::string ToString() const;
|
||||
std::string ToStringIP() const;
|
||||
int GetByte(int n) const;
|
||||
int64 GetHash() const;
|
||||
uint64 GetHash() const;
|
||||
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
||||
std::vector<unsigned char> GetGroup() const;
|
||||
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
|
||||
@ -133,6 +134,7 @@ class CService : public CNetAddr
|
||||
};
|
||||
|
||||
enum Network ParseNetwork(std::string net);
|
||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
|
||||
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
|
||||
bool GetProxy(enum Network net, CService &addrProxy);
|
||||
bool IsProxy(const CNetAddr &addr);
|
||||
|
@ -212,7 +212,7 @@ int main(int argc, char *argv[])
|
||||
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
||||
{
|
||||
GUIUtil::HelpMessageBox help;
|
||||
help.exec();
|
||||
help.showOrPrint();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,9 @@
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
<normaloff>:/icons/add</normaloff>:/icons/add</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -93,6 +96,9 @@
|
||||
<property name="autoRepeatDelay">
|
||||
<number>300</number>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -109,6 +115,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelBalance">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>123.456 BTC</string>
|
||||
</property>
|
||||
|
@ -441,15 +441,21 @@ HelpMessageBox::HelpMessageBox(QWidget *parent) :
|
||||
setDetailedText(coreOptions + "\n" + uiOptions);
|
||||
}
|
||||
|
||||
void HelpMessageBox::exec()
|
||||
void HelpMessageBox::printToConsole()
|
||||
{
|
||||
#if defined(WIN32)
|
||||
// On windows, show a message box, as there is no stderr in windowed applications
|
||||
QMessageBox::exec();
|
||||
#else
|
||||
// On other operating systems, the expected action is to print the message to the console.
|
||||
QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions;
|
||||
fprintf(stderr, "%s", strUsage.toStdString().c_str());
|
||||
}
|
||||
|
||||
void HelpMessageBox::showOrPrint()
|
||||
{
|
||||
#if defined(WIN32)
|
||||
// On windows, show a message box, as there is no stderr/stdout in windowed applications
|
||||
exec();
|
||||
#else
|
||||
// On other operating systems, print help text to console
|
||||
printToConsole();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,11 @@ namespace GUIUtil
|
||||
public:
|
||||
HelpMessageBox(QWidget *parent = 0);
|
||||
|
||||
void exec();
|
||||
/** Show message box or print help message to standard output, based on operating system. */
|
||||
void showOrPrint();
|
||||
|
||||
/** Print help message to console */
|
||||
void printToConsole();
|
||||
|
||||
private:
|
||||
QString header;
|
||||
|
@ -152,7 +152,7 @@ void OverviewPage::setNumTransactions(int count)
|
||||
void OverviewPage::setModel(WalletModel *model)
|
||||
{
|
||||
this->model = model;
|
||||
if(model)
|
||||
if(model && model->getOptionsModel())
|
||||
{
|
||||
// Set up transaction list
|
||||
filter = new TransactionFilterProxy();
|
||||
@ -172,19 +172,25 @@ void OverviewPage::setModel(WalletModel *model)
|
||||
setNumTransactions(model->getNumTransactions());
|
||||
connect(model, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int)));
|
||||
|
||||
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(displayUnitChanged()));
|
||||
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
}
|
||||
|
||||
// update the display unit, to not use the default ("BTC")
|
||||
updateDisplayUnit();
|
||||
}
|
||||
|
||||
void OverviewPage::displayUnitChanged()
|
||||
void OverviewPage::updateDisplayUnit()
|
||||
{
|
||||
if(!model || !model->getOptionsModel())
|
||||
return;
|
||||
if(currentBalance != -1)
|
||||
setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance);
|
||||
if(model && model->getOptionsModel())
|
||||
{
|
||||
if(currentBalance != -1)
|
||||
setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance);
|
||||
|
||||
txdelegate->unit = model->getOptionsModel()->getDisplayUnit();
|
||||
ui->listTransactions->update();
|
||||
// Update txdelegate->unit with the current unit
|
||||
txdelegate->unit = model->getOptionsModel()->getDisplayUnit();
|
||||
|
||||
ui->listTransactions->update();
|
||||
}
|
||||
}
|
||||
|
||||
void OverviewPage::showOutOfSyncWarning(bool fShow)
|
||||
|
@ -44,7 +44,7 @@ private:
|
||||
TransactionFilterProxy *filter;
|
||||
|
||||
private slots:
|
||||
void displayUnitChanged();
|
||||
void updateDisplayUnit();
|
||||
void handleTransactionClicked(const QModelIndex &index);
|
||||
};
|
||||
|
||||
|
@ -46,10 +46,11 @@ void SendCoinsDialog::setModel(WalletModel *model)
|
||||
entry->setModel(model);
|
||||
}
|
||||
}
|
||||
if(model)
|
||||
if(model && model->getOptionsModel())
|
||||
{
|
||||
setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance());
|
||||
connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64)));
|
||||
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,7 +203,7 @@ SendCoinsEntry *SendCoinsDialog::addEntry()
|
||||
ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
|
||||
QCoreApplication::instance()->processEvents();
|
||||
QScrollBar* bar = ui->scrollArea->verticalScrollBar();
|
||||
if (bar)
|
||||
if(bar)
|
||||
bar->setSliderPosition(bar->maximum());
|
||||
return entry;
|
||||
}
|
||||
@ -245,7 +246,7 @@ QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
|
||||
|
||||
void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
|
||||
{
|
||||
if (!fNewRecipientAllowed)
|
||||
if(!fNewRecipientAllowed)
|
||||
return;
|
||||
|
||||
SendCoinsEntry *entry = 0;
|
||||
@ -289,3 +290,12 @@ void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint
|
||||
int unit = model->getOptionsModel()->getDisplayUnit();
|
||||
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
|
||||
}
|
||||
|
||||
void SendCoinsDialog::updateDisplayUnit()
|
||||
{
|
||||
if(model && model->getOptionsModel())
|
||||
{
|
||||
// Update labelBalance with the current balance and the current unit
|
||||
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->getBalance()));
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ private:
|
||||
|
||||
private slots:
|
||||
void on_sendButton_clicked();
|
||||
|
||||
void removeEntry(SendCoinsEntry* entry);
|
||||
void updateDisplayUnit();
|
||||
};
|
||||
|
||||
#endif // SENDCOINSDIALOG_H
|
||||
|
@ -68,6 +68,10 @@ void SendCoinsEntry::on_payTo_textChanged(const QString &address)
|
||||
void SendCoinsEntry::setModel(WalletModel *model)
|
||||
{
|
||||
this->model = model;
|
||||
|
||||
if(model && model->getOptionsModel())
|
||||
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
@ -82,10 +86,8 @@ void SendCoinsEntry::clear()
|
||||
ui->addAsLabel->clear();
|
||||
ui->payAmount->clear();
|
||||
ui->payTo->setFocus();
|
||||
if(model && model->getOptionsModel())
|
||||
{
|
||||
ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
|
||||
}
|
||||
// update the display unit, to not use the default ("BTC")
|
||||
updateDisplayUnit();
|
||||
}
|
||||
|
||||
void SendCoinsEntry::on_deleteButton_clicked()
|
||||
@ -160,3 +162,11 @@ void SendCoinsEntry::setFocus()
|
||||
ui->payTo->setFocus();
|
||||
}
|
||||
|
||||
void SendCoinsEntry::updateDisplayUnit()
|
||||
{
|
||||
if(model && model->getOptionsModel())
|
||||
{
|
||||
// Update payAmount with the current unit
|
||||
ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ private slots:
|
||||
void on_payTo_textChanged(const QString &address);
|
||||
void on_addressBookButton_clicked();
|
||||
void on_pasteButton_clicked();
|
||||
void updateDisplayUnit();
|
||||
|
||||
private:
|
||||
Ui::SendCoinsEntry *ui;
|
||||
|
@ -230,6 +230,8 @@ TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *paren
|
||||
QTimer *timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(updateConfirmations()));
|
||||
timer->start(MODEL_UPDATE_DELAY);
|
||||
|
||||
connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
}
|
||||
|
||||
TransactionTableModel::~TransactionTableModel()
|
||||
@ -624,3 +626,8 @@ QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex
|
||||
}
|
||||
}
|
||||
|
||||
void TransactionTableModel::updateDisplayUnit()
|
||||
{
|
||||
// emit dataChanged to update Amount column with the current unit
|
||||
emit dataChanged(index(0, Amount), index(priv->size()-1, Amount));
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ private:
|
||||
public slots:
|
||||
void updateTransaction(const QString &hash, int status);
|
||||
void updateConfirmations();
|
||||
void updateDisplayUnit();
|
||||
|
||||
friend class TransactionTablePriv;
|
||||
};
|
||||
|
20
src/test/base32_tests.cpp
Normal file
20
src/test/base32_tests.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(base32_tests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(base32_testvectors)
|
||||
{
|
||||
static const std::string vstrIn[] = {"","f","fo","foo","foob","fooba","foobar"};
|
||||
static const std::string vstrOut[] = {"","my======","mzxq====","mzxw6===","mzxw6yq=","mzxw6ytb","mzxw6ytboi======"};
|
||||
for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
|
||||
{
|
||||
std::string strEnc = EncodeBase32(vstrIn[i]);
|
||||
BOOST_CHECK(strEnc == vstrOut[i]);
|
||||
std::string strDec = DecodeBase32(vstrOut[i]);
|
||||
BOOST_CHECK(strDec == vstrIn[i]);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
125
src/test/bignum_tests.cpp
Normal file
125
src/test/bignum_tests.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <limits>
|
||||
|
||||
#include "bignum.h"
|
||||
#include "util.h"
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(bignum_tests)
|
||||
|
||||
// Unfortunately there's no standard way of preventing a function from being
|
||||
// inlined, so we define a macro for it.
|
||||
//
|
||||
// You should use it like this:
|
||||
// NOINLINE void function() {...}
|
||||
#if defined(__GNUC__)
|
||||
// This also works and will be defined for any compiler implementing gcc
|
||||
// extensions, such as clang and icc.
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define NOINLINE __declspec(noinline)
|
||||
#else
|
||||
// We give out a warning because it impacts the correctness of one bignum test.
|
||||
#warning You should define NOINLINE for your compiler.
|
||||
#define NOINLINE
|
||||
#endif
|
||||
|
||||
// For the following test case, it is useful to use additional tools.
|
||||
//
|
||||
// The simplest one to use is the compiler flag -ftrapv, which detects integer
|
||||
// overflows and similar errors. However, due to optimizations and compilers
|
||||
// taking advantage of undefined behavior sometimes it may not actually detect
|
||||
// anything.
|
||||
//
|
||||
// You can also use compiler-based stack protection to possibly detect possible
|
||||
// stack buffer overruns.
|
||||
//
|
||||
// For more accurate diagnostics, you can use an undefined arithmetic operation
|
||||
// detector such as the clang-based tool:
|
||||
//
|
||||
// "IOC: An Integer Overflow Checker for C/C++"
|
||||
//
|
||||
// Available at: http://embed.cs.utah.edu/ioc/
|
||||
//
|
||||
// It might also be useful to use Google's AddressSanitizer to detect
|
||||
// stack buffer overruns, which valgrind can't currently detect.
|
||||
|
||||
// Let's force this code not to be inlined, in order to actually
|
||||
// test a generic version of the function. This increases the chance
|
||||
// that -ftrapv will detect overflows.
|
||||
NOINLINE void mysetint64(CBigNum& num, int64 n)
|
||||
{
|
||||
num.setint64(n);
|
||||
}
|
||||
|
||||
// For each number, we do 2 tests: one with inline code, then we reset the
|
||||
// value to 0, then the second one with a non-inlined function.
|
||||
BOOST_AUTO_TEST_CASE(bignum_setint64)
|
||||
{
|
||||
int64 n;
|
||||
|
||||
{
|
||||
n = 0;
|
||||
CBigNum num(n);
|
||||
BOOST_CHECK(num.ToString() == "0");
|
||||
num.setulong(0);
|
||||
BOOST_CHECK(num.ToString() == "0");
|
||||
mysetint64(num, n);
|
||||
BOOST_CHECK(num.ToString() == "0");
|
||||
}
|
||||
{
|
||||
n = 1;
|
||||
CBigNum num(n);
|
||||
BOOST_CHECK(num.ToString() == "1");
|
||||
num.setulong(0);
|
||||
BOOST_CHECK(num.ToString() == "0");
|
||||
mysetint64(num, n);
|
||||
BOOST_CHECK(num.ToString() == "1");
|
||||
}
|
||||
{
|
||||
n = -1;
|
||||
CBigNum num(n);
|
||||
BOOST_CHECK(num.ToString() == "-1");
|
||||
num.setulong(0);
|
||||
BOOST_CHECK(num.ToString() == "0");
|
||||
mysetint64(num, n);
|
||||
BOOST_CHECK(num.ToString() == "-1");
|
||||
}
|
||||
{
|
||||
n = 5;
|
||||
CBigNum num(n);
|
||||
BOOST_CHECK(num.ToString() == "5");
|
||||
num.setulong(0);
|
||||
BOOST_CHECK(num.ToString() == "0");
|
||||
mysetint64(num, n);
|
||||
BOOST_CHECK(num.ToString() == "5");
|
||||
}
|
||||
{
|
||||
n = -5;
|
||||
CBigNum num(n);
|
||||
BOOST_CHECK(num.ToString() == "-5");
|
||||
num.setulong(0);
|
||||
BOOST_CHECK(num.ToString() == "0");
|
||||
mysetint64(num, n);
|
||||
BOOST_CHECK(num.ToString() == "-5");
|
||||
}
|
||||
{
|
||||
n = std::numeric_limits<int64>::min();
|
||||
CBigNum num(n);
|
||||
BOOST_CHECK(num.ToString() == "-9223372036854775808");
|
||||
num.setulong(0);
|
||||
BOOST_CHECK(num.ToString() == "0");
|
||||
mysetint64(num, n);
|
||||
BOOST_CHECK(num.ToString() == "-9223372036854775808");
|
||||
}
|
||||
{
|
||||
n = std::numeric_limits<int64>::max();
|
||||
CBigNum num(n);
|
||||
BOOST_CHECK(num.ToString() == "9223372036854775807");
|
||||
num.setulong(0);
|
||||
BOOST_CHECK(num.ToString() == "0");
|
||||
mysetint64(num, n);
|
||||
BOOST_CHECK(num.ToString() == "9223372036854775807");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
@ -235,7 +235,7 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
||||
BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired));
|
||||
BOOST_CHECK(addrs[0] == keyaddr[0]);
|
||||
BOOST_CHECK(addrs[1] == keyaddr[1]);
|
||||
BOOST_CHECK(nRequired = 1);
|
||||
BOOST_CHECK(nRequired == 1);
|
||||
BOOST_CHECK(IsMine(keystore, s));
|
||||
BOOST_CHECK(!IsMine(emptykeystore, s));
|
||||
BOOST_CHECK(!IsMine(partialkeystore, s));
|
||||
|
102
src/test/netbase_tests.cpp
Normal file
102
src/test/netbase_tests.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "netbase.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(netbase_tests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(netbase_networks)
|
||||
{
|
||||
BOOST_CHECK(CNetAddr("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
|
||||
BOOST_CHECK(CNetAddr("::1").GetNetwork() == NET_UNROUTABLE);
|
||||
BOOST_CHECK(CNetAddr("8.8.8.8").GetNetwork() == NET_IPV4);
|
||||
BOOST_CHECK(CNetAddr("2001::8888").GetNetwork() == NET_IPV6);
|
||||
BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(netbase_properties)
|
||||
{
|
||||
BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4());
|
||||
BOOST_CHECK(CNetAddr("::FFFF:192.168.1.1").IsIPv4());
|
||||
BOOST_CHECK(CNetAddr("::1").IsIPv6());
|
||||
BOOST_CHECK(CNetAddr("10.0.0.1").IsRFC1918());
|
||||
BOOST_CHECK(CNetAddr("192.168.1.1").IsRFC1918());
|
||||
BOOST_CHECK(CNetAddr("172.31.255.255").IsRFC1918());
|
||||
BOOST_CHECK(CNetAddr("2001:0DB8::").IsRFC3849());
|
||||
BOOST_CHECK(CNetAddr("169.254.1.1").IsRFC3927());
|
||||
BOOST_CHECK(CNetAddr("2002::1").IsRFC3964());
|
||||
BOOST_CHECK(CNetAddr("FC00::").IsRFC4193());
|
||||
BOOST_CHECK(CNetAddr("2001::2").IsRFC4380());
|
||||
BOOST_CHECK(CNetAddr("2001:10::").IsRFC4843());
|
||||
BOOST_CHECK(CNetAddr("FE80::").IsRFC4862());
|
||||
BOOST_CHECK(CNetAddr("64:FF9B::").IsRFC6052());
|
||||
BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
|
||||
BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal());
|
||||
BOOST_CHECK(CNetAddr("::1").IsLocal());
|
||||
BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable());
|
||||
BOOST_CHECK(CNetAddr("2001::1").IsRoutable());
|
||||
BOOST_CHECK(CNetAddr("127.0.0.1").IsValid());
|
||||
}
|
||||
|
||||
bool static TestSplitHost(string test, string host, int port)
|
||||
{
|
||||
string hostOut;
|
||||
int portOut = -1;
|
||||
SplitHostPort(test, portOut, hostOut);
|
||||
return hostOut == host && port == portOut;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(netbase_splithost)
|
||||
{
|
||||
BOOST_CHECK(TestSplitHost("www.bitcoin.org", "www.bitcoin.org", -1));
|
||||
BOOST_CHECK(TestSplitHost("[www.bitcoin.org]", "www.bitcoin.org", -1));
|
||||
BOOST_CHECK(TestSplitHost("www.bitcoin.org:80", "www.bitcoin.org", 80));
|
||||
BOOST_CHECK(TestSplitHost("[www.bitcoin.org]:80", "www.bitcoin.org", 80));
|
||||
BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1));
|
||||
BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333));
|
||||
BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1));
|
||||
BOOST_CHECK(TestSplitHost("[127.0.0.1]:8333", "127.0.0.1", 8333));
|
||||
BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1));
|
||||
BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:8333", "::ffff:127.0.0.1", 8333));
|
||||
BOOST_CHECK(TestSplitHost("[::]:8333", "::", 8333));
|
||||
BOOST_CHECK(TestSplitHost("::8333", "::8333", -1));
|
||||
BOOST_CHECK(TestSplitHost(":8333", "", 8333));
|
||||
BOOST_CHECK(TestSplitHost("[]:8333", "", 8333));
|
||||
BOOST_CHECK(TestSplitHost("", "", -1));
|
||||
}
|
||||
|
||||
bool static TestParse(string src, string canon)
|
||||
{
|
||||
CService addr;
|
||||
if (!LookupNumeric(src.c_str(), addr, 65535))
|
||||
return canon == "";
|
||||
return canon == addr.ToString();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
|
||||
{
|
||||
BOOST_CHECK(TestParse("127.0.0.1", "127.0.0.1:65535"));
|
||||
BOOST_CHECK(TestParse("127.0.0.1:8333", "127.0.0.1:8333"));
|
||||
BOOST_CHECK(TestParse("::ffff:127.0.0.1", "127.0.0.1:65535"));
|
||||
BOOST_CHECK(TestParse("::", "[::]:65535"));
|
||||
BOOST_CHECK(TestParse("[::]:8333", "[::]:8333"));
|
||||
BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535"));
|
||||
BOOST_CHECK(TestParse(":::", ""));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(onioncat_test)
|
||||
{
|
||||
// values from http://www.cypherpunk.at/onioncat/wiki/OnionCat
|
||||
CNetAddr addr1("5wyqrzbvrdsumnok.onion");
|
||||
CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca");
|
||||
BOOST_CHECK(addr1 == addr2);
|
||||
BOOST_CHECK(addr1.IsTor());
|
||||
BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion");
|
||||
BOOST_CHECK(addr1.IsRoutable());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
188
src/util.cpp
188
src/util.cpp
@ -58,6 +58,7 @@ using namespace std;
|
||||
map<string, string> mapArgs;
|
||||
map<string, vector<string> > mapMultiArgs;
|
||||
bool fDebug = false;
|
||||
bool fDebugNet = false;
|
||||
bool fPrintToConsole = false;
|
||||
bool fPrintToDebugger = false;
|
||||
bool fRequestShutdown = false;
|
||||
@ -702,6 +703,193 @@ string DecodeBase64(const string& str)
|
||||
return string((const char*)&vchRet[0], vchRet.size());
|
||||
}
|
||||
|
||||
string EncodeBase32(const unsigned char* pch, size_t len)
|
||||
{
|
||||
static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
|
||||
|
||||
string strRet="";
|
||||
strRet.reserve((len+4)/5*8);
|
||||
|
||||
int mode=0, left=0;
|
||||
const unsigned char *pchEnd = pch+len;
|
||||
|
||||
while (pch<pchEnd)
|
||||
{
|
||||
int enc = *(pch++);
|
||||
switch (mode)
|
||||
{
|
||||
case 0: // we have no bits
|
||||
strRet += pbase32[enc >> 3];
|
||||
left = (enc & 7) << 2;
|
||||
mode = 1;
|
||||
break;
|
||||
|
||||
case 1: // we have three bits
|
||||
strRet += pbase32[left | (enc >> 6)];
|
||||
strRet += pbase32[(enc >> 1) & 31];
|
||||
left = (enc & 1) << 4;
|
||||
mode = 2;
|
||||
break;
|
||||
|
||||
case 2: // we have one bit
|
||||
strRet += pbase32[left | (enc >> 4)];
|
||||
left = (enc & 15) << 1;
|
||||
mode = 3;
|
||||
break;
|
||||
|
||||
case 3: // we have four bits
|
||||
strRet += pbase32[left | (enc >> 7)];
|
||||
strRet += pbase32[(enc >> 2) & 31];
|
||||
left = (enc & 3) << 3;
|
||||
mode = 4;
|
||||
break;
|
||||
|
||||
case 4: // we have two bits
|
||||
strRet += pbase32[left | (enc >> 5)];
|
||||
strRet += pbase32[enc & 31];
|
||||
mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const int nPadding[5] = {0, 6, 4, 3, 1};
|
||||
if (mode)
|
||||
{
|
||||
strRet += pbase32[left];
|
||||
for (int n=0; n<nPadding[mode]; n++)
|
||||
strRet += '=';
|
||||
}
|
||||
|
||||
return strRet;
|
||||
}
|
||||
|
||||
string EncodeBase32(const string& str)
|
||||
{
|
||||
return EncodeBase32((const unsigned char*)str.c_str(), str.size());
|
||||
}
|
||||
|
||||
vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
|
||||
{
|
||||
static const int decode32_table[256] =
|
||||
{
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||
23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
if (pfInvalid)
|
||||
*pfInvalid = false;
|
||||
|
||||
vector<unsigned char> vchRet;
|
||||
vchRet.reserve((strlen(p))*5/8);
|
||||
|
||||
int mode = 0;
|
||||
int left = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int dec = decode32_table[(unsigned char)*p];
|
||||
if (dec == -1) break;
|
||||
p++;
|
||||
switch (mode)
|
||||
{
|
||||
case 0: // we have no bits and get 5
|
||||
left = dec;
|
||||
mode = 1;
|
||||
break;
|
||||
|
||||
case 1: // we have 5 bits and keep 2
|
||||
vchRet.push_back((left<<3) | (dec>>2));
|
||||
left = dec & 3;
|
||||
mode = 2;
|
||||
break;
|
||||
|
||||
case 2: // we have 2 bits and keep 7
|
||||
left = left << 5 | dec;
|
||||
mode = 3;
|
||||
break;
|
||||
|
||||
case 3: // we have 7 bits and keep 4
|
||||
vchRet.push_back((left<<1) | (dec>>4));
|
||||
left = dec & 15;
|
||||
mode = 4;
|
||||
break;
|
||||
|
||||
case 4: // we have 4 bits, and keep 1
|
||||
vchRet.push_back((left<<4) | (dec>>1));
|
||||
left = dec & 1;
|
||||
mode = 5;
|
||||
break;
|
||||
|
||||
case 5: // we have 1 bit, and keep 6
|
||||
left = left << 5 | dec;
|
||||
mode = 6;
|
||||
break;
|
||||
|
||||
case 6: // we have 6 bits, and keep 3
|
||||
vchRet.push_back((left<<2) | (dec>>3));
|
||||
left = dec & 7;
|
||||
mode = 7;
|
||||
break;
|
||||
|
||||
case 7: // we have 3 bits, and keep 0
|
||||
vchRet.push_back((left<<5) | dec);
|
||||
mode = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pfInvalid)
|
||||
switch (mode)
|
||||
{
|
||||
case 0: // 8n base32 characters processed: ok
|
||||
break;
|
||||
|
||||
case 1: // 8n+1 base32 characters processed: impossible
|
||||
case 3: // +3
|
||||
case 6: // +6
|
||||
*pfInvalid = true;
|
||||
break;
|
||||
|
||||
case 2: // 8n+2 base32 characters processed: require '======'
|
||||
if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(unsigned char)p[6]] != -1)
|
||||
*pfInvalid = true;
|
||||
break;
|
||||
|
||||
case 4: // 8n+4 base32 characters processed: require '===='
|
||||
if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(unsigned char)p[4]] != -1)
|
||||
*pfInvalid = true;
|
||||
break;
|
||||
|
||||
case 5: // 8n+5 base32 characters processed: require '==='
|
||||
if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(unsigned char)p[3]] != -1)
|
||||
*pfInvalid = true;
|
||||
break;
|
||||
|
||||
case 7: // 8n+7 base32 characters processed: require '='
|
||||
if (left || p[0] != '=' || decode32_table[(unsigned char)p[1]] != -1)
|
||||
*pfInvalid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
string DecodeBase32(const string& str)
|
||||
{
|
||||
vector<unsigned char> vchRet = DecodeBase32(str.c_str());
|
||||
return string((const char*)&vchRet[0], vchRet.size());
|
||||
}
|
||||
|
||||
|
||||
bool WildcardMatch(const char* psz, const char* mask)
|
||||
{
|
||||
|
@ -105,6 +105,7 @@ inline void Sleep(int64 n)
|
||||
extern std::map<std::string, std::string> mapArgs;
|
||||
extern std::map<std::string, std::vector<std::string> > mapMultiArgs;
|
||||
extern bool fDebug;
|
||||
extern bool fDebugNet;
|
||||
extern bool fPrintToConsole;
|
||||
extern bool fPrintToDebugger;
|
||||
extern bool fRequestShutdown;
|
||||
@ -146,6 +147,10 @@ std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL);
|
||||
std::string DecodeBase64(const std::string& str);
|
||||
std::string EncodeBase64(const unsigned char* pch, size_t len);
|
||||
std::string EncodeBase64(const std::string& str);
|
||||
std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = NULL);
|
||||
std::string DecodeBase32(const std::string& str);
|
||||
std::string EncodeBase32(const unsigned char* pch, size_t len);
|
||||
std::string EncodeBase32(const std::string& str);
|
||||
void ParseParameters(int argc, const char*const argv[]);
|
||||
bool WildcardMatch(const char* psz, const char* mask);
|
||||
bool WildcardMatch(const std::string& str, const std::string& mask);
|
||||
@ -272,7 +277,7 @@ inline int64 GetPerformanceCounter()
|
||||
#else
|
||||
timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
nCounter = t.tv_sec * 1000000 + t.tv_usec;
|
||||
nCounter = (int64) t.tv_sec * 1000000 + t.tv_usec;
|
||||
#endif
|
||||
return nCounter;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user