Litecoin: Protocol and default settings

0) Adjust BIP30 enforcement values

1) Reduce amount that peers can adjust our time to eliminate an attack vector. Thanks to
coblee for this fix.

2) Zeitgeist2 patch - thanks to Lolcust and ArtForz. This fixes an issue where a
51% attack can change difficulty at will. Go back the full period unless it's the
first retarget after genesis.

3) Avoid overflow in CalculateNextWorkRequired(). Thanks to pooler for the overflow fix.

4) Zeitgeist2 bool fshift bnNew.bits(). Thanks to romanornr for this path.

5) SegWit ContextualCheckBlockHeader adjustment and extra coverage.

6) Reject peer proto version below 70002. Thanks to wtogami for this patch.

7) Send final alert message to nodes warning about removal of the alert system. Thanks to coblee for this patch.

8) Adjust default settings for Litecoin.

9) Adjust STALE_CHECK_INTERVAL value
This commit is contained in:
Adrian Gallagher 2017-01-29 07:00:00 -08:00
parent 073d829346
commit a66fc11fc4
No known key found for this signature in database
GPG Key ID: FE3348877809386C
20 changed files with 76 additions and 47 deletions

View File

@ -5,13 +5,13 @@ rpcpassword=somepassword
host=127.0.0.1
#mainnet default
port=8332
port=9332
#testnet default
#port=18332
#port=19332
#regtest default
#port=18443
#port=19443
#signet default
#port=38332

View File

@ -1,5 +1,5 @@
### QoS (Quality of service) ###
This is a Linux bash script that will set up tc to limit the outgoing bandwidth for connections to the Bitcoin network. It limits outbound TCP traffic with a source or destination port of 8333, but not if the destination IP is within a LAN.
This is a Linux bash script that will set up tc to limit the outgoing bandwidth for connections to the Litecoin network. It limits outbound TCP traffic with a source or destination port of 9333, but not if the destination IP is within a LAN (defined as 192.168.x.x).
This means one can have an always-on bitcoind instance running, and another local bitcoind/bitcoin-qt instance which connects to this node and receives blocks from it.
This means one can have an always-on litecoind instance running, and another local litecoind/litecoin-qt instance which connects to this node and receives blocks from it.

View File

@ -9,7 +9,7 @@ export LC_ALL=C
IF="eth0"
#limit of the network interface in question
LINKCEIL="1gbit"
#limit outbound Bitcoin protocol traffic to this rate
#limit outbound Litecoin protocol traffic to this rate
LIMIT="160kbit"
#defines the IPv4 address space for which you wish to disable rate limiting
LOCALNET_V4="192.168.0.0/16"
@ -47,16 +47,16 @@ fi
# ret=$?
#done
#limit outgoing traffic to and from port 8333. but not when dealing with a host on the local network
#limit outgoing traffic to and from port 9333. but not when dealing with a host on the local network
# (defined by $LOCALNET_V4 and $LOCALNET_V6)
# --set-mark marks packages matching these criteria with the number "2" (v4)
# --set-mark marks packages matching these criteria with the number "4" (v6)
# these packets are filtered by the tc filter with "handle 2"
# this filter sends the packages into the 1:11 class, and this class is limited to ${LIMIT}
iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET_V4} -j MARK --set-mark 0x2
iptables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET_V4} -j MARK --set-mark 0x2
iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 9333 ! -d ${LOCALNET_V4} -j MARK --set-mark 0x2
iptables -t mangle -A OUTPUT -p tcp -m tcp --sport 9333 ! -d ${LOCALNET_V4} -j MARK --set-mark 0x2
if [ -n "${LOCALNET_V6}" ] ; then
ip6tables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4
ip6tables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4
ip6tables -t mangle -A OUTPUT -p tcp -m tcp --dport 9333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4
ip6tables -t mangle -A OUTPUT -p tcp -m tcp --sport 9333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4
fi

View File

@ -128,10 +128,10 @@ def main():
g.write(' * IPv4 as well as onion addresses are wrapped inside an IPv6 address accordingly.\n')
g.write(' */\n')
with open(os.path.join(indir,'nodes_main.txt'), 'r', encoding="utf8") as f:
process_nodes(g, f, 'pnSeed6_main', 8333)
process_nodes(g, f, 'pnSeed6_main', 9333)
g.write('\n')
with open(os.path.join(indir,'nodes_test.txt'), 'r', encoding="utf8") as f:
process_nodes(g, f, 'pnSeed6_test', 18333)
process_nodes(g, f, 'pnSeed6_test', 19335)
g.write('#endif // BITCOIN_CHAINPARAMSSEEDS_H\n')
if __name__ == '__main__':

View File

@ -83,7 +83,7 @@ https://github.com/bitcoin/bips/blob/master/bip-0064.mediawiki
Example:
```
$ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff7627ff72e5e8b0f71210f92ea7a4000c5d75-0.json 2>/dev/null | json_pp
$ curl localhost:19332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff7627ff72e5e8b0f71210f92ea7a4000c5d75-0.json 2>/dev/null | json_pp
{
"chainHeight" : 325347,
"chaintipHash" : "00000000fb01a7f3745a717f8caebee056c484e6e0bfe4a9591c235bb70506fb",
@ -125,4 +125,4 @@ Only supports JSON as output format.
Risks
-------------
Running a web browser on the same node with a REST enabled bitcoind can be a risk. Accessing prepared XSS websites could read out tx/block data of your node by placing links like `<script src="http://127.0.0.1:8332/rest/tx/1234567890.json">` which might break the nodes privacy.
Running a web browser on the same node with a REST enabled bitcoind can be a risk. Accessing prepared XSS websites could read out tx/block data of your node by placing links like `<script src="http://127.0.0.1:9332/rest/tx/1234567890.json">` which might break the nodes privacy.

View File

@ -55,12 +55,12 @@ config file): *Needed for Tor version 0.2.7.0 and older versions of Tor only. Fo
versions of Tor see [Section 3](#3-automatically-listen-on-tor).*
HiddenServiceDir /var/lib/tor/bitcoin-service/
HiddenServicePort 8333 127.0.0.1:8334
HiddenServicePort 18333 127.0.0.1:18334
HiddenServicePort 9333 127.0.0.1:9334
HiddenServicePort 19333 127.0.0.1:19334
The directory can be different of course, but virtual port numbers should be equal to
your bitcoind's P2P listen port (8333 by default), and target addresses and ports
should be equal to binding address and port for inbound Tor connections (127.0.0.1:8334 by default).
your litecoind's P2P listen port (9333 by default), and target addresses and ports
should be equal to binding address and port for inbound Tor connections (127.0.0.1:9334 by default).
-externalip=X You can tell bitcoin about its publicly reachable addresses using
this option, and this can be an onion address. Given the above
@ -100,7 +100,7 @@ as well, use `discover` instead:
./bitcoind ... -discover
and open port 8333 on your firewall (or use -upnp).
and open port 9333 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:

View File

@ -51,11 +51,11 @@
# Use as many addnode= settings as you like to connect to specific peers
#addnode=69.164.218.197
#addnode=10.0.0.2:8333
#addnode=10.0.0.2:9333
# Alternatively use as many connect= settings as you like to connect ONLY to specific peers
#connect=69.164.218.197
#connect=10.0.0.1:8333
#connect=10.0.0.1:9333
# Listening mode, enabled by default except when 'connect' is being used
#listen=1
@ -117,7 +117,7 @@
#rpcallowip=2001:db8:85a3:0:0:8a2e:370:7334/96
# Listen for RPC connections on this TCP port:
#rpcport=8332
#rpcport=9332
# You can use Bitcoin or bitcoind to send commands to Bitcoin/bitcoind
# running on another host using this option:

View File

@ -22,7 +22,7 @@ static const CAmount COIN = 100000000;
* critical; in unusual circumstances like a(nother) overflow bug that allowed
* for the creation of coins out of thin air modification could lead to a fork.
* */
static const CAmount MAX_MONEY = 21000000 * COIN;
static const CAmount MAX_MONEY = 84000000 * COIN;
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
#endif // BITCOIN_AMOUNT_H

View File

@ -53,7 +53,7 @@ static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT = 4;
/** Timeout for (unprotected) outbound peers to sync to our chainwork, in seconds */
static constexpr int64_t CHAIN_SYNC_TIMEOUT = 20 * 60; // 20 minutes
/** How frequently to check for stale tips, in seconds */
static constexpr int64_t STALE_CHECK_INTERVAL = 10 * 60; // 10 minutes
static constexpr int64_t STALE_CHECK_INTERVAL = 2.5 * 60; // 2.5 minutes
/** How frequently to check for extra outbound peers and disconnect, in seconds */
static constexpr int64_t EXTRA_PEER_CHECK_INTERVAL = 45;
/** Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict, in seconds */
@ -2473,7 +2473,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// If the peer is old enough to have the old alert system, send it the final alert.
if (greatest_common_version <= 70012) {
CDataStream finalAlert(ParseHex("60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"), SER_NETWORK, PROTOCOL_VERSION);
CDataStream finalAlert(ParseHex("5c0100000015f7675900000000ffffff7f00000000ffffff7ffeffff7f0000000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220405f7e7572b176f3316d4e12deab75ad4ff978844f7a7bcd5ed06f6aa094eb6602207880fcc07d0a78e0f46f188d115e04ed4ad48980ea3572cb0e0cb97921048095"), SER_NETWORK, PROTOCOL_VERSION);
m_connman.PushMessage(&pfrom, CNetMsgMaker(greatest_common_version).Make("alert", finalAlert));
}

View File

@ -38,9 +38,17 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
}
// Go back by what we want to be 14 days worth of blocks
int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
assert(nHeightFirst >= 0);
const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
// Litecoin: This fixes an issue where a 51% attack can change difficulty at will.
// Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz
int blockstogoback = params.DifficultyAdjustmentInterval()-1;
if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval())
blockstogoback = params.DifficultyAdjustmentInterval();
// Go back by what we want to be 14 days worth of blocks
const CBlockIndex* pindexFirst = pindexLast;
for (int i = 0; pindexFirst && i < blockstogoback; i++)
pindexFirst = pindexFirst->pprev;
assert(pindexFirst);
return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
@ -59,11 +67,19 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
nActualTimespan = params.nPowTargetTimespan*4;
// Retarget
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
arith_uint256 bnNew;
arith_uint256 bnOld;
bnNew.SetCompact(pindexLast->nBits);
bnOld = bnNew;
// Litecoin: intermediate uint256 can overflow by 1 bit
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
bool fShift = bnNew.bits() > bnPowLimit.bits() - 1;
if (fShift)
bnNew >>= 1;
bnNew *= nActualTimespan;
bnNew /= params.nPowTargetTimespan;
if (fShift)
bnNew <<= 1;
if (bnNew > bnPowLimit)
bnNew = bnPowLimit;

View File

@ -284,8 +284,8 @@ static RPCHelpMan addnode()
},
RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
+ HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
HelpExampleCli("addnode", "\"192.168.0.6:9333\" \"onetry\"")
+ HelpExampleRpc("addnode", "\"192.168.0.6:9333\", \"onetry\"")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
@ -392,7 +392,7 @@ static RPCHelpMan getaddednodeinfo()
{
{RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::STR, "address", "The bitcoin server IP and port we're connected to"},
{RPCResult::Type::STR, "address", "The litecoin server IP and port we're connected to"},
{RPCResult::Type::STR, "connected", "connection, inbound or outbound"},
}},
}},

View File

@ -20,7 +20,7 @@
#define NUM_MULTIPLES_1BTC 10000
// amounts 50 .. 21000000
#define NUM_MULTIPLES_50BTC 420000
#define NUM_MULTIPLES_50BTC 1680000
BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup)
@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(compress_amounts)
BOOST_CHECK(TestPair( CENT, 0x7));
BOOST_CHECK(TestPair( COIN, 0x9));
BOOST_CHECK(TestPair( 50*COIN, 0x32));
BOOST_CHECK(TestPair(21000000*COIN, 0x1406f40));
BOOST_CHECK(TestPair(84000000*COIN, 0x501BD00));
for (uint64_t i = 1; i <= NUM_MULTIPLES_UNIT; i++)
BOOST_CHECK(TestEncode(i));

View File

@ -375,7 +375,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
}
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
// Extend to a 210000-long block chain.
while (::ChainActive().Tip()->nHeight < 210000) {
while (::ChainActive().Tip()->nHeight < 840000) {
CBlockIndex* prev = ::ChainActive().Tip();
CBlockIndex* next = new CBlockIndex();
next->phashBlock = new uint256(InsecureRand256());

View File

@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(netbase_properties)
BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable());
BOOST_CHECK(ResolveIP("2001::1").IsRoutable());
BOOST_CHECK(ResolveIP("127.0.0.1").IsValid());
BOOST_CHECK(CreateInternal("FD6B:88C0:8724:edb1:8e4:3588:e546:35ca").IsInternal());
BOOST_CHECK(CreateInternal("FD6C:E9FE:4549:edb1:8e4:3588:e546:35ca").IsInternal());
BOOST_CHECK(CreateInternal("bar.com").IsInternal());
}
@ -125,9 +125,9 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
BOOST_CHECK(TestParse(":::", "[::]:0"));
// verify that an internal address fails to resolve
BOOST_CHECK(TestParse("[fd6b:88c0:8724:1:2:3:4:5]", "[::]:0"));
BOOST_CHECK(TestParse("[fd6c:e9fe:4549:1:2:3:4:5]", "[::]:0"));
// and that a one-off resolves correctly
BOOST_CHECK(TestParse("[fd6c:88c0:8724:1:2:3:4:5]", "[fd6c:88c0:8724:1:2:3:4:5]:65535"));
BOOST_CHECK(TestParse("[fd6d:e9fe:4549:1:2:3:4:5]", "[fd6d:e9fe:4549:1:2:3:4:5]:65535"));
}
BOOST_AUTO_TEST_CASE(onioncat_test)

View File

@ -10,7 +10,7 @@
#include <stdint.h>
#include <vector>
static const int64_t DEFAULT_MAX_TIME_ADJUSTMENT = 70 * 60;
static const int64_t DEFAULT_MAX_TIME_ADJUSTMENT = 35 * 60;
class CNetAddr;

View File

@ -2021,8 +2021,10 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
// Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the
// two in the chain that violate it. This prevents exploiting the issue against nodes during their
// initial block download.
bool fEnforceBIP30 = !((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256S("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256S("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
bool fEnforceBIP30 = true;
//bool fEnforceBIP30 = !((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256S("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
// (pindex->nHeight==91880 && pindex->GetBlockHash() == uint256S("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
// Once BIP34 activated it was not possible to create new duplicate coinbases and thus other than starting
// with the 2 existing duplicate coinbase pairs, not possible to create overwriting txs. But by the
@ -3518,6 +3520,10 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, strprintf("bad-version(0x%08x)", block.nVersion),
strprintf("rejected nVersion=0x%08x block", block.nVersion));
if (block.nVersion < VERSIONBITS_TOP_BITS && IsWitnessEnabled(pindexPrev, consensusParams))
return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion),
strprintf("rejected nVersion=0x%08x block", block.nVersion));
return true;
}

View File

@ -82,7 +82,7 @@ static const bool DEFAULT_FEEFILTER = true;
static const int DEFAULT_STOPATHEIGHT = 0;
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ::ChainActive().Tip() will not be pruned. */
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
static const signed int DEFAULT_CHECKBLOCKS = 6;
static const signed int DEFAULT_CHECKBLOCKS = 6 * 4;
static const unsigned int DEFAULT_CHECKLEVEL = 3;
// Require that user allocate at least 550 MiB for block & undo files (blk???.dat and rev???.dat)
// At 1MB per block, 288 blocks = 288MB.

View File

@ -21,6 +21,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)"
VB_TOP_BITS = 0x20000000
def trueDummy(tx):
scriptSig = CScript(tx.vin[0].scriptSig)
@ -109,11 +110,12 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.nodes[0].sendrawtransaction(i.serialize_with_witness().hex(), 0)
self.block_submit(self.nodes[0], test6txs, True, True)
def block_submit(self, node, txs, witness=False, accept=False):
def block_submit(self, node, txs, witness=False, accept=False, version):
tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
assert_equal(tmpl['previousblockhash'], self.lastblockhash)
assert_equal(tmpl['height'], self.lastblockheight + 1)
block = create_block(tmpl=tmpl, ntime=self.lastblocktime + 1)
block.nVersion = version
for tx in txs:
tx.rehash()
block.vtx.append(tx)

View File

@ -149,7 +149,7 @@ class ProxyTest(BitcoinTestFramework):
assert isinstance(cmd, Socks5Command)
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
assert_equal(cmd.addr, b"bitcoinostk4e4re.onion")
assert_equal(cmd.port, 8333)
assert_equal(cmd.port, 9333)
if not auth:
assert_equal(cmd.username, None)
assert_equal(cmd.password, None)
@ -163,7 +163,7 @@ class ProxyTest(BitcoinTestFramework):
assert isinstance(cmd, Socks5Command)
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
assert_equal(cmd.addr, b"node.noumenon")
assert_equal(cmd.port, 8333)
assert_equal(cmd.port, 9333)
if not auth:
assert_equal(cmd.username, None)
assert_equal(cmd.password, None)

View File

@ -237,7 +237,7 @@ class SegWitTest(BitcoinTestFramework):
# Helper functions
def build_next_block(self, version=4):
def build_next_block(self, nVersion=VB_TOP_BITS):
"""Build a block on top of node0's tip."""
tip = self.nodes[0].getbestblockhash()
height = self.nodes[0].getblockcount() + 1
@ -1942,6 +1942,11 @@ class SegWitTest(BitcoinTestFramework):
def test_upgrade_after_activation(self):
"""Test the behavior of starting up a segwit-aware node after the softfork has activated."""
block = self.build_next_block(nVersion=4)
block.solve()
resp = self.nodes[0].submitblock(block.serialize().hex())
assert_equal(resp, 'bad-version(0x00000004)')
self.restart_node(2, extra_args=["-segwitheight={}".format(SEGWIT_HEIGHT)])
self.connect_nodes(0, 2)