From b2b361926215eadd6bf43ed1d7110b925fc7cae5 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Wed, 11 Mar 2015 16:48:53 -0700 Subject: [PATCH 0001/1283] Implement CTransaction::IsEquivalentTo(...) Define CTransaction::IsEquivalentTo(const CTransaction& tx) True if only scriptSigs are different. In other words, true if the two transactions are malleability clones. In other words, true if the two transactions have the same effect on the outside universe. In the wallet, only SyncMetaData for equivalent transactions. --- src/primitives/transaction.cpp | 9 +++++++++ src/primitives/transaction.h | 3 +++ src/wallet/wallet.cpp | 1 + 3 files changed, 13 insertions(+) diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 606dbea79..d864a9b6d 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -87,6 +87,15 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) { return *this; } +bool CTransaction::IsEquivalentTo(const CTransaction& tx) const +{ + CMutableTransaction tx1 = *this; + CMutableTransaction tx2 = tx; + for (unsigned int i = 0; i < tx1.vin.size(); i++) tx1.vin[i].scriptSig = CScript(); + for (unsigned int i = 0; i < tx2.vin.size(); i++) tx2.vin[i].scriptSig = CScript(); + return CTransaction(tx1) == CTransaction(tx2); +} + CAmount CTransaction::GetValueOut() const { CAmount nValueOut = 0; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 6cfd93a9a..0c9ebb7b8 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -222,6 +222,9 @@ public: return hash; } + // True if only scriptSigs are different + bool IsEquivalentTo(const CTransaction& tx) const; + // Return sum of txouts. CAmount GetValueOut() const; // GetValueIn() is a method on CCoinsViewCache, because diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 2566b2712..92bb972cf 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -417,6 +417,7 @@ void CWallet::SyncMetaData(pair range) const uint256& hash = it->second; CWalletTx* copyTo = &mapWallet[hash]; if (copyFrom == copyTo) continue; + if (!copyFrom->IsEquivalentTo(*copyTo)) continue; copyTo->mapValue = copyFrom->mapValue; copyTo->vOrderForm = copyFrom->vOrderForm; // fTimeReceivedIsTxTime not copied on purpose From defd2d55b789163be4a863d0887d5d309ff9cde3 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Wed, 11 Mar 2015 14:29:06 -0700 Subject: [PATCH 0002/1283] Better txn_doublespend.py test Remove reliance on accounting "move" ledger entries. Instead, create funding transactions (and deal with fee complexities). Do not rely on broken SyncMetaData. Instead expect double-spend amount to be debited from the default "" account. --- qa/rpc-tests/txn_doublespend.py | 77 ++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/qa/rpc-tests/txn_doublespend.py b/qa/rpc-tests/txn_doublespend.py index fe9168944..955108003 100755 --- a/qa/rpc-tests/txn_doublespend.py +++ b/qa/rpc-tests/txn_doublespend.py @@ -4,7 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # -# Test proper accounting with malleable transactions +# Test proper accounting with a double-spend conflict # from test_framework import BitcoinTestFramework @@ -32,28 +32,40 @@ class TxnMallTest(BitcoinTestFramework): self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! # Assign coins to foo and bar accounts: - self.nodes[0].move("", "foo", 1220) - self.nodes[0].move("", "bar", 30) - assert_equal(self.nodes[0].getbalance(""), 0) + node0_address_foo = self.nodes[0].getnewaddress("foo") + fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, 1219) + fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid) + + node0_address_bar = self.nodes[0].getnewaddress("bar") + fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, 29) + fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid) + + assert_equal(self.nodes[0].getbalance(""), + starting_balance - 1219 - 29 + fund_foo_tx["fee"] + fund_bar_tx["fee"]) # Coins are sent to node1_address node1_address = self.nodes[1].getnewaddress("from0") - # First: use raw transaction API to send 1210 BTC to node1_address, + # First: use raw transaction API to send 1240 BTC to node1_address, # but don't broadcast: - (total_in, inputs) = gather_inputs(self.nodes[0], 1210) - change_address = self.nodes[0].getnewaddress("foo") + doublespend_fee = Decimal('-.02') + rawtx_input_0 = {} + rawtx_input_0["txid"] = fund_foo_txid + rawtx_input_0["vout"] = find_output(self.nodes[0], fund_foo_txid, 1219) + rawtx_input_1 = {} + rawtx_input_1["txid"] = fund_bar_txid + rawtx_input_1["vout"] = find_output(self.nodes[0], fund_bar_txid, 29) + inputs = [rawtx_input_0, rawtx_input_1] + change_address = self.nodes[0].getnewaddress() outputs = {} - outputs[change_address] = 40 - outputs[node1_address] = 1210 + outputs[node1_address] = 1240 + outputs[change_address] = 1248 - 1240 + doublespend_fee rawtx = self.nodes[0].createrawtransaction(inputs, outputs) doublespend = self.nodes[0].signrawtransaction(rawtx) assert_equal(doublespend["complete"], True) - # Create two transaction from node[0] to node[1]; the - # second must spend change from the first because the first - # spends all mature inputs: - txid1 = self.nodes[0].sendfrom("foo", node1_address, 1210, 0) + # Create two spends using 1 50 BTC coin each + txid1 = self.nodes[0].sendfrom("foo", node1_address, 40, 0) txid2 = self.nodes[0].sendfrom("bar", node1_address, 20, 0) # Have node0 mine a block: @@ -65,16 +77,16 @@ class TxnMallTest(BitcoinTestFramework): tx2 = self.nodes[0].gettransaction(txid2) # Node0's balance should be starting balance, plus 50BTC for another - # matured block, minus 1210, minus 20, and minus transaction fees: - expected = starting_balance + # matured block, minus 40, minus 20, and minus transaction fees: + expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"] if self.options.mine_block: expected += 50 expected += tx1["amount"] + tx1["fee"] expected += tx2["amount"] + tx2["fee"] assert_equal(self.nodes[0].getbalance(), expected) # foo and bar accounts should be debited: - assert_equal(self.nodes[0].getbalance("foo"), 1220+tx1["amount"]+tx1["fee"]) - assert_equal(self.nodes[0].getbalance("bar"), 30+tx2["amount"]+tx2["fee"]) + assert_equal(self.nodes[0].getbalance("foo", 0), 1219+tx1["amount"]+tx1["fee"]) + assert_equal(self.nodes[0].getbalance("bar", 0), 29+tx2["amount"]+tx2["fee"]) if self.options.mine_block: assert_equal(tx1["confirmations"], 1) @@ -85,8 +97,10 @@ class TxnMallTest(BitcoinTestFramework): assert_equal(tx1["confirmations"], 0) assert_equal(tx2["confirmations"], 0) - # Now give doublespend to miner: - mutated_txid = self.nodes[2].sendrawtransaction(doublespend["hex"]) + # Now give doublespend and its parents to miner: + self.nodes[2].sendrawtransaction(fund_foo_tx["hex"]) + self.nodes[2].sendrawtransaction(fund_bar_tx["hex"]) + self.nodes[2].sendrawtransaction(doublespend["hex"]) # ... mine a block... self.nodes[2].generate(1) @@ -104,17 +118,28 @@ class TxnMallTest(BitcoinTestFramework): assert_equal(tx2["confirmations"], -1) # Node0's total balance should be starting balance, plus 100BTC for - # two more matured blocks, minus 1210 for the double-spend: - expected = starting_balance + 100 - 1210 + # two more matured blocks, minus 1240 for the double-spend, plus fees (which are + # negative): + expected = starting_balance + 100 - 1240 + fund_foo_tx["fee"] + fund_bar_tx["fee"] + doublespend_fee assert_equal(self.nodes[0].getbalance(), expected) assert_equal(self.nodes[0].getbalance("*"), expected) - # foo account should be debited, but bar account should not: - assert_equal(self.nodes[0].getbalance("foo"), 1220-1210) - assert_equal(self.nodes[0].getbalance("bar"), 30) + # Final "" balance is starting_balance - amount moved to accounts - doublespend + subsidies + + # fees (which are negative) + assert_equal(self.nodes[0].getbalance("foo"), 1219) + assert_equal(self.nodes[0].getbalance("bar"), 29) + assert_equal(self.nodes[0].getbalance(""), starting_balance + -1219 + - 29 + -1240 + + 100 + + fund_foo_tx["fee"] + + fund_bar_tx["fee"] + + doublespend_fee) - # Node1's "from" account balance should be just the mutated send: - assert_equal(self.nodes[1].getbalance("from0"), 1210) + # Node1's "from0" account balance should be just the doublespend: + assert_equal(self.nodes[1].getbalance("from0"), 1240) if __name__ == '__main__': TxnMallTest().main() + From 835c12291efc2ca03017622fe970218fdeb63727 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Wed, 18 Mar 2015 19:22:49 +0100 Subject: [PATCH 0003/1283] Clean up change computation in CreateTransaction. Compute the change directly as difference between the "requested" and the actual value returned by SelectCoins. This removes a duplication of the fee logic code. --- src/wallet/wallet.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index bb73038b9..75337d4a7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1757,9 +1757,9 @@ bool CWallet::CreateTransaction(const vector& vecSend, nChangePosRet = -1; bool fFirst = true; - CAmount nTotalValue = nValue; + CAmount nValueToSelect = nValue; if (nSubtractFeeFromAmount == 0) - nTotalValue += nFeeRet; + nValueToSelect += nFeeRet; double dPriority = 0; // vouts to the payees BOOST_FOREACH (const CRecipient& recipient, vecSend) @@ -1796,7 +1796,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, // Choose coins to use set > setCoins; CAmount nValueIn = 0; - if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl)) + if (!SelectCoins(nValueToSelect, setCoins, nValueIn, coinControl)) { strFailReason = _("Insufficient funds"); return false; @@ -1814,10 +1814,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, dPriority += (double)nCredit * age; } - CAmount nChange = nValueIn - nValue; - if (nSubtractFeeFromAmount == 0) - nChange -= nFeeRet; - + const CAmount nChange = nValueIn - nValueToSelect; if (nChange > 0) { // Fill a vout to ourself From 99088d60d8a7747c6d1a7fd5d8cd388be1b3e138 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 29 Sep 2014 01:00:01 -0400 Subject: [PATCH 0004/1283] Make CScriptNum() take nMaxNumSize as an argument While the existing numeric opcodes are all limited to 4-byte bignum arguments, new opcodes will need different limits. --- src/script/script.h | 7 ++++--- src/test/scriptnum_tests.cpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/script/script.h b/src/script/script.h index ed456f5c5..a4b9de304 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -195,7 +195,10 @@ public: m_value = n; } - explicit CScriptNum(const std::vector& vch, bool fRequireMinimal) + static const size_t nDefaultMaxNumSize = 4; + + explicit CScriptNum(const std::vector& vch, bool fRequireMinimal, + const size_t nMaxNumSize = nDefaultMaxNumSize) { if (vch.size() > nMaxNumSize) { throw scriptnum_error("script number overflow"); @@ -318,8 +321,6 @@ public: return result; } - static const size_t nMaxNumSize = 4; - private: static int64_t set_vch(const std::vector& vch) { diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp index 24c7dd3d5..d95724dbe 100644 --- a/src/test/scriptnum_tests.cpp +++ b/src/test/scriptnum_tests.cpp @@ -145,7 +145,7 @@ static void RunCreate(const int64_t& num) { CheckCreateInt(num); CScriptNum scriptnum(num); - if (scriptnum.getvch().size() <= CScriptNum::nMaxNumSize) + if (scriptnum.getvch().size() <= CScriptNum::nDefaultMaxNumSize) CheckCreateVch(num); else { From 48e9c57cf06352f890eac4285ae022d8746cf3fd Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 29 Sep 2014 01:02:59 -0400 Subject: [PATCH 0005/1283] Move LOCKTIME_THRESHOLD to src/script/script.h Will now be needed by CHECKLOCKTIMEVERIFY code. --- src/consensus/consensus.h | 2 -- src/script/script.h | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 9c5b7d4ff..f937844e9 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -12,7 +12,5 @@ static const unsigned int MAX_BLOCK_SIZE = 1000000; static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ static const int COINBASE_MATURITY = 100; -/** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */ -static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC #endif // BITCOIN_CONSENSUS_CONSENSUS_H diff --git a/src/script/script.h b/src/script/script.h index a4b9de304..45a06acc9 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -18,6 +18,10 @@ static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes +// Threshold for nLockTime: below this value it is interpreted as block number, +// otherwise as UNIX timestamp. +static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC + template std::vector ToByteVector(const T& in) { From 5d34e16d3a1e6ef37d5e6d254063c342b0e5fe39 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Mon, 23 Mar 2015 20:56:53 -0700 Subject: [PATCH 0006/1283] Add txn_clone.py test Does what the old txnmall.sh test did. Creates an equivalent malleated clone and tests that SyncMetaData syncs the accounting effects from the original transaction to the confirmed clone. --- qa/pull-tester/rpc-tests.sh | 2 + qa/rpc-tests/txn_clone.py | 167 ++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100755 qa/rpc-tests/txn_clone.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index efeee4553..ffddfa306 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -21,6 +21,8 @@ testScripts=( 'mempool_resurrect_test.py' 'txn_doublespend.py' 'txn_doublespend.py --mineblock' + 'txn_clone.py' + 'txn_clone.py --mineblock' 'getchaintips.py' 'rest.py' 'mempool_spendcoinbase.py' diff --git a/qa/rpc-tests/txn_clone.py b/qa/rpc-tests/txn_clone.py new file mode 100755 index 000000000..19bc34e3f --- /dev/null +++ b/qa/rpc-tests/txn_clone.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test proper accounting with an equivalent malleability clone +# + +from test_framework import BitcoinTestFramework +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from decimal import Decimal +from util import * +import os +import shutil + +class TxnMallTest(BitcoinTestFramework): + + def add_options(self, parser): + parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", + help="Test double-spend of 1-confirmed transaction") + + def setup_network(self): + # Start with split network: + return super(TxnMallTest, self).setup_network(True) + + def run_test(self): + # All nodes should start with 1,250 BTC: + starting_balance = 1250 + for i in range(4): + assert_equal(self.nodes[i].getbalance(), starting_balance) + self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! + + # Assign coins to foo and bar accounts: + self.nodes[0].settxfee(.001) + + node0_address_foo = self.nodes[0].getnewaddress("foo") + fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, 1219) + fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid) + + node0_address_bar = self.nodes[0].getnewaddress("bar") + fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, 29) + fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid) + + assert_equal(self.nodes[0].getbalance(""), + starting_balance - 1219 - 29 + fund_foo_tx["fee"] + fund_bar_tx["fee"]) + + # Coins are sent to node1_address + node1_address = self.nodes[1].getnewaddress("from0") + + # Send tx1, and another transaction tx2 that won't be cloned + txid1 = self.nodes[0].sendfrom("foo", node1_address, 40, 0) + txid2 = self.nodes[0].sendfrom("bar", node1_address, 20, 0) + + # Construct a clone of tx1, to be malleated + rawtx1 = self.nodes[0].getrawtransaction(txid1,1) + clone_inputs = [{"txid":rawtx1["vin"][0]["txid"],"vout":rawtx1["vin"][0]["vout"]}] + clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]:rawtx1["vout"][0]["value"], + rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]:rawtx1["vout"][1]["value"]} + clone_raw = self.nodes[0].createrawtransaction(clone_inputs, clone_outputs) + + # 3 hex manipulations on the clone are required + + # manipulation 1. sequence is at version+#inputs+input+sigstub + posseq = 2*(4+1+36+1) + seqbe = '%08x' % rawtx1["vin"][0]["sequence"] + clone_raw = clone_raw[:posseq] + seqbe[6:8] + seqbe[4:6] + seqbe[2:4] + seqbe[0:2] + clone_raw[posseq + 8:] + + # manipulation 2. createrawtransaction randomizes the order of its outputs, so swap them if necessary. + # output 0 is at version+#inputs+input+sigstub+sequence+#outputs + # 40 BTC serialized is 00286bee00000000 + pos0 = 2*(4+1+36+1+4+1) + hex40 = "00286bee00000000" + output_len = 16 + 2 + 2 * int("0x" + clone_raw[pos0 + 16 : pos0 + 16 + 2], 0) + if (rawtx1["vout"][0]["value"] == 40 and clone_raw[pos0 : pos0 + 16] != hex40 or + rawtx1["vout"][0]["value"] != 40 and clone_raw[pos0 : pos0 + 16] == hex40): + output0 = clone_raw[pos0 : pos0 + output_len] + output1 = clone_raw[pos0 + output_len : pos0 + 2 * output_len] + clone_raw = clone_raw[:pos0] + output1 + output0 + clone_raw[pos0 + 2 * output_len:] + + # manipulation 3. locktime is after outputs + poslt = pos0 + 2 * output_len + ltbe = '%08x' % rawtx1["locktime"] + clone_raw = clone_raw[:poslt] + ltbe[6:8] + ltbe[4:6] + ltbe[2:4] + ltbe[0:2] + clone_raw[poslt + 8:] + + # Use a different signature hash type to sign. This creates an equivalent but malleated clone. + # Don't send the clone anywhere yet + tx1_clone = self.nodes[0].signrawtransaction(clone_raw, None, None, "ALL|ANYONECANPAY") + assert_equal(tx1_clone["complete"], True) + + # Have node0 mine a block, if requested: + if (self.options.mine_block): + self.nodes[0].generate(1) + sync_blocks(self.nodes[0:2]) + + tx1 = self.nodes[0].gettransaction(txid1) + tx2 = self.nodes[0].gettransaction(txid2) + + # Node0's balance should be starting balance, plus 50BTC for another + # matured block, minus tx1 and tx2 amounts, and minus transaction fees: + expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"] + if self.options.mine_block: expected += 50 + expected += tx1["amount"] + tx1["fee"] + expected += tx2["amount"] + tx2["fee"] + assert_equal(self.nodes[0].getbalance(), expected) + + # foo and bar accounts should be debited: + assert_equal(self.nodes[0].getbalance("foo", 0), 1219 + tx1["amount"] + tx1["fee"]) + assert_equal(self.nodes[0].getbalance("bar", 0), 29 + tx2["amount"] + tx2["fee"]) + + if self.options.mine_block: + assert_equal(tx1["confirmations"], 1) + assert_equal(tx2["confirmations"], 1) + # Node1's "from0" balance should be both transaction amounts: + assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"] + tx2["amount"])) + else: + assert_equal(tx1["confirmations"], 0) + assert_equal(tx2["confirmations"], 0) + + # Send clone and its parent to miner + self.nodes[2].sendrawtransaction(fund_foo_tx["hex"]) + txid1_clone = self.nodes[2].sendrawtransaction(tx1_clone["hex"]) + # ... mine a block... + self.nodes[2].generate(1) + + # Reconnect the split network, and sync chain: + connect_nodes(self.nodes[1], 2) + self.nodes[2].generate(1) # Mine another block to make sure we sync + sync_blocks(self.nodes) + + # Re-fetch transaction info: + tx1 = self.nodes[0].gettransaction(txid1) + tx1_clone = self.nodes[0].gettransaction(txid1_clone) + tx2 = self.nodes[0].gettransaction(txid2) + + # Verify expected confirmations + assert_equal(tx1["confirmations"], -1) + assert_equal(tx1_clone["confirmations"], 2) + assert_equal(tx2["confirmations"], 0) + + # Check node0's total balance; should be same as before the clone, + 100 BTC for 2 matured, + # less possible orphaned matured subsidy + expected += 100 + if (self.options.mine_block): + expected -= 50 + assert_equal(self.nodes[0].getbalance(), expected) + assert_equal(self.nodes[0].getbalance("*", 0), expected) + + # Check node0's individual account balances. + # "foo" should have been debited by the equivalent clone of tx1 + assert_equal(self.nodes[0].getbalance("foo"), 1219 + tx1["amount"] + tx1["fee"]) + # "bar" should have been debited by (possibly unconfirmed) tx2 + assert_equal(self.nodes[0].getbalance("bar", 0), 29 + tx2["amount"] + tx2["fee"]) + # "" should have starting balance, less funding txes, plus subsidies + assert_equal(self.nodes[0].getbalance("", 0), starting_balance + - 1219 + + fund_foo_tx["fee"] + - 29 + + fund_bar_tx["fee"] + + 100) + + # Node1's "from0" account balance + assert_equal(self.nodes[1].getbalance("from0", 0), -(tx1["amount"] + tx2["amount"])) + +if __name__ == '__main__': + TxnMallTest().main() + From ef8dfe41d1eba0de6d6554e25e658169f97313b5 Mon Sep 17 00:00:00 2001 From: Mark Friedenbach Date: Fri, 22 May 2015 14:49:50 -0700 Subject: [PATCH 0007/1283] Prevent block.nTime from decreasing Under some circumstances it is possible for there to be a significant, discontinuous jump in a node's clock value. On mining nodes, this can result in block templates which are no longer valid due to time-based nLockTime constraints. UpdateTime() is modified so that it will never decrease a block's nLockTime, thereby preventing such invalidations. --- src/miner.cpp | 17 +++++++++++++---- src/miner.h | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 7a57b42e3..693e04dec 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -81,13 +81,19 @@ public: } }; -void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) +int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { - pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + int64_t nOldTime = pblock->nTime; + int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + + if (nOldTime < nNewTime) + pblock->nTime = nNewTime; // Updating time can change work required on testnet: if (consensusParams.fPowAllowMinDifficultyBlocks) pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); + + return nNewTime - nOldTime; } CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -138,6 +144,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) LOCK2(cs_main, mempool.cs); CBlockIndex* pindexPrev = chainActive.Tip(); const int nHeight = pindexPrev->nHeight + 1; + pblock->nTime = GetAdjustedTime(); CCoinsViewCache view(pcoinsTip); // Priority order to process transactions @@ -152,7 +159,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) mi != mempool.mapTx.end(); ++mi) { const CTransaction& tx = mi->second.GetTx(); - if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight)) + if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, pblock->nTime)) continue; COrphan* porphan = NULL; @@ -529,7 +536,9 @@ void static BitcoinMiner(CWallet *pwallet) break; // Update nTime every few seconds - UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); + if (UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev) < 0) + break; // Recreate the block if the clock has run backwards, + // so that we can use the correct time. if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) { // Changing pblock->nTime can change work required on testnet: diff --git a/src/miner.h b/src/miner.h index 96a6b70ec..d46f4b1f2 100644 --- a/src/miner.h +++ b/src/miner.h @@ -30,6 +30,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey); /** Modify the extranonce in a block */ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); -void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); +int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); #endif // BITCOIN_MINER_H From bfc30b34374d71928acee5ff41282f09cedfd5e4 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 2 Jun 2015 15:17:36 -0400 Subject: [PATCH 0008/1283] Ignore unrequested blocks too far ahead of tip --- qa/rpc-tests/p2p-acceptblock.py | 65 ++++++++++++++++++++++++++++----- src/main.cpp | 9 ++++- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py index fcdd1e1b9..6431f430a 100755 --- a/qa/rpc-tests/p2p-acceptblock.py +++ b/qa/rpc-tests/p2p-acceptblock.py @@ -40,6 +40,11 @@ The test: it's missing an intermediate block. Node1 should reorg to this longer chain. +4b.Send 288 more blocks on the longer chain. + Node0 should process all but the last block (too far ahead in height). + Send all headers to Node1, and then send the last block in that chain. + Node1 should accept the block because it's coming from a whitelisted peer. + 5. Send a duplicate of the block in #3 to Node0. Node0 should not process the block because it is unrequested, and stay on the shorter chain. @@ -126,13 +131,15 @@ class AcceptBlockTest(BitcoinTestFramework): # 2. Send one block that builds on each tip. # This should be accepted. blocks_h2 = [] # the height 2 blocks on each node's chain + block_time = time.time() + 1 for i in xrange(2): - blocks_h2.append(create_block(tips[i], create_coinbase(), time.time()+1)) + blocks_h2.append(create_block(tips[i], create_coinbase(), block_time)) blocks_h2[i].solve() + block_time += 1 test_node.send_message(msg_block(blocks_h2[0])) white_node.send_message(msg_block(blocks_h2[1])) - time.sleep(1) + time.sleep(0.5) assert_equal(self.nodes[0].getblockcount(), 2) assert_equal(self.nodes[1].getblockcount(), 2) print "First height 2 block accepted by both nodes" @@ -145,7 +152,7 @@ class AcceptBlockTest(BitcoinTestFramework): test_node.send_message(msg_block(blocks_h2f[0])) white_node.send_message(msg_block(blocks_h2f[1])) - time.sleep(1) # Give time to process the block + time.sleep(0.5) # Give time to process the block for x in self.nodes[0].getchaintips(): if x['hash'] == blocks_h2f[0].hash: assert_equal(x['status'], "headers-only") @@ -164,7 +171,7 @@ class AcceptBlockTest(BitcoinTestFramework): test_node.send_message(msg_block(blocks_h3[0])) white_node.send_message(msg_block(blocks_h3[1])) - time.sleep(1) + time.sleep(0.5) # Since the earlier block was not processed by node0, the new block # can't be fully validated. for x in self.nodes[0].getchaintips(): @@ -182,6 +189,45 @@ class AcceptBlockTest(BitcoinTestFramework): assert_equal(self.nodes[1].getblockcount(), 3) print "Successfully reorged to length 3 chain from whitelisted peer" + # 4b. Now mine 288 more blocks and deliver; all should be processed but + # the last (height-too-high) on node0. Node1 should process the tip if + # we give it the headers chain leading to the tip. + tips = blocks_h3 + headers_message = msg_headers() + all_blocks = [] # node0's blocks + for j in xrange(2): + for i in xrange(288): + next_block = create_block(tips[j].sha256, create_coinbase(), tips[j].nTime+1) + next_block.solve() + if j==0: + test_node.send_message(msg_block(next_block)) + all_blocks.append(next_block) + else: + headers_message.headers.append(CBlockHeader(next_block)) + tips[j] = next_block + + time.sleep(2) + for x in all_blocks: + try: + self.nodes[0].getblock(x.hash) + if x == all_blocks[287]: + raise AssertionError("Unrequested block too far-ahead should have been ignored") + except: + if x == all_blocks[287]: + print "Unrequested block too far-ahead not processed" + else: + raise AssertionError("Unrequested block with more work should have been accepted") + + headers_message.headers.pop() # Ensure the last block is unrequested + white_node.send_message(headers_message) # Send headers leading to tip + white_node.send_message(msg_block(tips[1])) # Now deliver the tip + try: + time.sleep(0.5) + self.nodes[1].getblock(tips[1].hash) + print "Unrequested block far ahead of tip accepted from whitelisted peer" + except: + raise AssertionError("Unrequested block from whitelisted peer not accepted") + # 5. Test handling of unrequested block on the node that didn't process # Should still not be processed (even though it has a child that has more # work). @@ -204,21 +250,20 @@ class AcceptBlockTest(BitcoinTestFramework): test_node.last_getdata = None test_node.send_message(msg_inv([CInv(2, blocks_h3[0].sha256)])) - time.sleep(1) + time.sleep(0.5) with mininode_lock: getdata = test_node.last_getdata - # Check that the getdata is for the right block - assert_equal(len(getdata.inv), 1) + # Check that the getdata includes the right block assert_equal(getdata.inv[0].hash, blocks_h2f[0].sha256) print "Inv at tip triggered getdata for unprocessed block" # 7. Send the missing block for the third time (now it is requested) test_node.send_message(msg_block(blocks_h2f[0])) - time.sleep(1) - assert_equal(self.nodes[0].getblockcount(), 3) - print "Successfully reorged to length 3 chain from non-whitelisted peer" + time.sleep(2) + assert_equal(self.nodes[0].getblockcount(), 290) + print "Successfully reorged to longer chain from non-whitelisted peer" [ c.disconnect_node() for c in connections ] diff --git a/src/main.cpp b/src/main.cpp index 760cda5de..e0997515b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2841,9 +2841,15 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, // Try to process all requested blocks that we don't have, but only // process an unrequested block if it's new and has enough work to - // advance our tip. + // advance our tip, and isn't too many blocks ahead. bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA; bool fHasMoreWork = (chainActive.Tip() ? pindex->nChainWork > chainActive.Tip()->nChainWork : true); + // Blocks that are too out-of-order needlessly limit the effectiveness of + // pruning, because pruning will not delete block files that contain any + // blocks which are too close in height to the tip. Apply this test + // regardless of whether pruning is enabled; it should generally be safe to + // not process unrequested blocks. + bool fTooFarAhead = (pindex->nHeight - chainActive.Height()) > MIN_BLOCKS_TO_KEEP; // TODO: deal better with return value and error conditions for duplicate // and unrequested blocks. @@ -2851,6 +2857,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, if (!fRequested) { // If we didn't ask for it: if (pindex->nTx != 0) return true; // This is a previously-processed block that was pruned if (!fHasMoreWork) return true; // Don't process less-work chains + if (fTooFarAhead) return true; // Block height is too high } if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) { From 3e9143386a90e508c8d41719294db11264f5f0a0 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Thu, 4 Jun 2015 13:00:26 -0400 Subject: [PATCH 0009/1283] Advance pindexLastCommonBlock for blocks in chainActive This prevents an edge case where a block downloaded and pruned in-between successive calls to FindNextBlocksToDownload could cause the block to be unnecessarily re-requested. --- src/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 760cda5de..dc9585b02 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -433,13 +433,14 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vectorIsValid(BLOCK_VALID_TREE)) { // We consider the chain that this peer is on invalid. return; } - if (pindex->nStatus & BLOCK_HAVE_DATA) { + if (pindex->nStatus & BLOCK_HAVE_DATA || chainActive.Contains(pindex)) { if (pindex->nChainTx) state->pindexLastCommonBlock = pindex; } else if (mapBlocksInFlight.count(pindex->GetBlockHash()) == 0) { From 076badb60f33f0c32b035de220ca14c52a423a2a Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 5 Jun 2015 17:07:17 -0230 Subject: [PATCH 0010/1283] Add getblockheader RPC call Alternative to getblock that works even when the block itself has been pruned, returning all available information. --- src/rpcblockchain.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++ src/rpcclient.cpp | 1 + src/rpcserver.cpp | 1 + src/rpcserver.h | 1 + 4 files changed, 85 insertions(+) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index e45368cb9..1baaaa7e1 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -51,6 +51,32 @@ double GetDifficulty(const CBlockIndex* blockindex) return dDiff; } +UniValue blockheaderToJSON(const CBlockIndex* blockindex) +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); + int confirmations = -1; + // Only report confirmations if the block is on the main chain + if (chainActive.Contains(blockindex)) + confirmations = chainActive.Height() - blockindex->nHeight + 1; + result.push_back(Pair("confirmations", confirmations)); + result.push_back(Pair("height", blockindex->nHeight)); + result.push_back(Pair("version", blockindex->nVersion)); + result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex())); + result.push_back(Pair("time", (int64_t)blockindex->nTime)); + result.push_back(Pair("nonce", (uint64_t)blockindex->nNonce)); + result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); + result.push_back(Pair("difficulty", GetDifficulty(blockindex))); + result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + + if (blockindex->pprev) + result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); + CBlockIndex *pnext = chainActive.Next(blockindex); + if (pnext) + result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); + return result; +} + UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) { @@ -255,6 +281,62 @@ UniValue getblockhash(const UniValue& params, bool fHelp) return pblockindex->GetBlockHash().GetHex(); } +UniValue getblockheader(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getblockheader \"hash\" ( verbose )\n" + "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" + "If verbose is true, returns an Object with information about blockheader .\n" + "\nArguments:\n" + "1. \"hash\" (string, required) The block hash\n" + "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" + "\nResult (for verbose = true):\n" + "{\n" + " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" + " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" + " \"height\" : n, (numeric) The block height or index\n" + " \"version\" : n, (numeric) The block version\n" + " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" + " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"nonce\" : n, (numeric) The nonce\n" + " \"bits\" : \"1d00ffff\", (string) The bits\n" + " \"difficulty\" : x.xxx, (numeric) The difficulty\n" + " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" + " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" + "}\n" + "\nResult (for verbose=false):\n" + "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" + "\nExamples:\n" + + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + ); + + LOCK(cs_main); + + std::string strHash = params[0].get_str(); + uint256 hash(uint256S(strHash)); + + bool fVerbose = true; + if (params.size() > 1) + fVerbose = params[1].get_bool(); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (!fVerbose) + { + CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); + ssBlock << pblockindex->GetBlockHeader(); + std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); + return strHex; + } + + return blockheaderToJSON(pblockindex); +} + UniValue getblock(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index f254da5de..b15df6a9b 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -71,6 +71,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listunspent", 1 }, { "listunspent", 2 }, { "getblock", 1 }, + { "getblockheader", 1 }, { "gettransaction", 1 }, { "getrawtransaction", 1 }, { "createrawtransaction", 0 }, diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index e6bf00861..aba016be7 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -288,6 +288,7 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "getblockcount", &getblockcount, true }, { "blockchain", "getblock", &getblock, true }, { "blockchain", "getblockhash", &getblockhash, true }, + { "blockchain", "getblockheader", &getblockheader, true }, { "blockchain", "getchaintips", &getchaintips, true }, { "blockchain", "getdifficulty", &getdifficulty, true }, { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 7b462a8b7..2830d9c10 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -229,6 +229,7 @@ extern UniValue settxfee(const UniValue& params, bool fHelp); extern UniValue getmempoolinfo(const UniValue& params, bool fHelp); extern UniValue getrawmempool(const UniValue& params, bool fHelp); extern UniValue getblockhash(const UniValue& params, bool fHelp); +extern UniValue getblockheader(const UniValue& params, bool fHelp); extern UniValue getblock(const UniValue& params, bool fHelp); extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp); extern UniValue gettxout(const UniValue& params, bool fHelp); From 65b94545036ae6e38e79e9c7166a3ba1ddb83f66 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Mon, 8 Jun 2015 16:34:58 -0400 Subject: [PATCH 0011/1283] Use best header chain timestamps to detect partitioning The partition checking code was using chainActive timestamps to detect partitioning; with headers-first syncing, it should use (and with this pull request, does use) pIndexBestHeader timestamps. Fixes issue #6251 --- src/init.cpp | 2 +- src/main.cpp | 16 ++++++++++------ src/main.h | 2 +- src/test/alert_tests.cpp | 10 ++++------ 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 02dca5703..ac1b68de8 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1396,7 +1396,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Monitor the chain, and alert if we get blocks much quicker or slower than expected int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing; CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload, - boost::ref(cs_main), boost::cref(chainActive), nPowTargetSpacing); + boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing); scheduler.scheduleEvery(f, nPowTargetSpacing); #ifdef ENABLE_WALLET diff --git a/src/main.cpp b/src/main.cpp index e9a5f7efd..d74db2b92 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1711,9 +1711,10 @@ void ThreadScriptCheck() { // we're being fed a bad chain (blocks being generated much // too slowly or too quickly). // -void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CChain& chain, int64_t nPowTargetSpacing) +void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, + int64_t nPowTargetSpacing) { - if (initialDownloadCheck()) return; + if (bestHeader == NULL || initialDownloadCheck()) return; static int64_t lastAlertTime = 0; int64_t now = GetAdjustedTime(); @@ -1729,10 +1730,13 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const int64_t startTime = GetAdjustedTime()-SPAN_SECONDS; LOCK(cs); - int h = chain.Height(); - while (h > 0 && chain[h]->GetBlockTime() >= startTime) - --h; - int nBlocks = chain.Height()-h; + const CBlockIndex* i = bestHeader; + int nBlocks = 0; + while (i->GetBlockTime() >= startTime) { + ++nBlocks; + i = i->pprev; + if (i == NULL) return; // Ran out of chain, we must not be fully sync'ed + } // How likely is it to find that many by chance? double p = boost::math::pdf(poisson, nBlocks); diff --git a/src/main.h b/src/main.h index abaedae20..2d39367fc 100644 --- a/src/main.h +++ b/src/main.h @@ -186,7 +186,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); /** Try to detect Partition (network isolation) attacks against us */ -void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CChain& chain, int64_t nPowTargetSpacing); +void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(); /** Format a string that describes several potential problems detected by the core */ diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 22cb475e0..38dcc6023 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -201,7 +201,6 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) { // Test PartitionCheck CCriticalSection csDummy; - CChain chainDummy; CBlockIndex indexDummy[100]; CChainParams& params = Params(CBaseChainParams::MAIN); int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; @@ -220,17 +219,16 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) // Other members don't matter, the partition check code doesn't // use them } - chainDummy.SetTip(&indexDummy[99]); // Test 1: chain with blocks every nPowTargetSpacing seconds, // as normal, no worries: - PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); BOOST_CHECK(strMiscWarning.empty()); // Test 2: go 3.5 hours without a block, expect a warning: now += 3*60*60+30*60; SetMockTime(now); - PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); BOOST_CHECK(!strMiscWarning.empty()); BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); strMiscWarning = ""; @@ -239,7 +237,7 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) // code: now += 60*10; SetMockTime(now); - PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); BOOST_CHECK(strMiscWarning.empty()); // Test 4: get 2.5 times as many blocks as expected: @@ -248,7 +246,7 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) int64_t quickSpacing = nPowTargetSpacing*2/5; for (int i = 0; i < 100; i++) // Tweak chain timestamps: indexDummy[i].nTime = now - (100-i)*quickSpacing; - PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); BOOST_CHECK(!strMiscWarning.empty()); BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); strMiscWarning = ""; From 506bae3ac94ae9d5edfa794d9b80a7c9921ace17 Mon Sep 17 00:00:00 2001 From: dexX7 Date: Tue, 9 Jun 2015 17:11:13 +0200 Subject: [PATCH 0012/1283] Return all available information via validateaddress `"validateaddress"` omits some information, even in cases where is it available. The primary motivation is to be able to retrieve redeemScripts, after using `"addmultisigaddress"`, when not all keys are available in the keystore, but the redeemScript actually is. The output of `"validateaddress"` with this commit: Keys not available: ```js validateaddress "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3" { "isvalid": true, "address": "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3", "scriptPubKey": "76a914fa20d564550b105787f7ce3a9ad7fd9a45cd407088ac", "ismine": false, "iswatchonly": false, "isscript": false } ``` ```js validateaddress "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK" { "isvalid": true, "address": "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK", "scriptPubKey": "a9146769c19a16c9400b908756e19a4d2afb9e9760e187", "ismine": false, "iswatchonly": false, "isscript": true } ``` After adding the redeemScript: ```js addmultisigaddress 2 '["02537357B156A33306A7A014A3748631C59DF405B56F11BA4AA4A3CE81501AF095","02F1FB200390E7864EF4450C07B15988179A57C3CF3A878F668E1070CB615749FE"]' 2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK validateaddress "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK" { "isvalid": true, "address": "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK", "scriptPubKey": "a9146769c19a16c9400b908756e19a4d2afb9e9760e187", "ismine": false, "iswatchonly": false, "isscript": true, "script": "multisig", "hex": "522102537357b156a33306a7a014a3748631c59df405b56f11ba4aa4a3ce81501af0952102f1fb200390e7864ef4450c07b15988179a57c3cf3a878f668e1070cb615749fe52ae", "addresses": [ "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3", "mmSKNtbYYHRrhTLKiok5TuYrGEs4Y2A4k6" ], "sigsrequired": 2, "account": "" } ``` All keys available: ```js validateaddress "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3" { "isvalid": true, "address": "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3", "scriptPubKey": "76a914fa20d564550b105787f7ce3a9ad7fd9a45cd407088ac", "ismine": true, "iswatchonly": false, "isscript": false, "pubkey": "02537357b156a33306a7a014a3748631c59df405b56f11ba4aa4a3ce81501af095", "iscompressed": true, "account": "" } ``` ```js validateaddress "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK" { "isvalid": true, "address": "2N2g2H7gjA8a11g1yKBgh5VTqndyvbnWpBK", "scriptPubKey": "a9146769c19a16c9400b908756e19a4d2afb9e9760e187", "ismine": true, "iswatchonly": false, "isscript": true, "script": "multisig", "hex": "522102537357b156a33306a7a014a3748631c59df405b56f11ba4aa4a3ce81501af0952102f1fb200390e7864ef4450c07b15988179a57c3cf3a878f668e1070cb615749fe52ae", "addresses": [ "n4KWZKx349gdMQGgTnZ8W6WfgSwybkGSK3", "mmSKNtbYYHRrhTLKiok5TuYrGEs4Y2A4k6" ], "sigsrequired": 2, "account": "" } ``` --- src/rpcmisc.cpp | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index fe6eb81b8..1d47bc06a 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -109,20 +109,14 @@ UniValue getinfo(const UniValue& params, bool fHelp) #ifdef ENABLE_WALLET class DescribeAddressVisitor : public boost::static_visitor { -private: - isminetype mine; - public: - DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {} - UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); } UniValue operator()(const CKeyID &keyID) const { UniValue obj(UniValue::VOBJ); CPubKey vchPubKey; obj.push_back(Pair("isscript", false)); - if (mine == ISMINE_SPENDABLE) { - pwalletMain->GetPubKey(keyID, vchPubKey); + if (pwalletMain->GetPubKey(keyID, vchPubKey)) { obj.push_back(Pair("pubkey", HexStr(vchPubKey))); obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); } @@ -131,10 +125,9 @@ public: UniValue operator()(const CScriptID &scriptID) const { UniValue obj(UniValue::VOBJ); + CScript subscript; obj.push_back(Pair("isscript", true)); - if (mine != ISMINE_NO) { - CScript subscript; - pwalletMain->GetCScript(scriptID, subscript); + if (pwalletMain->GetCScript(scriptID, subscript)) { std::vector addresses; txnouttype whichType; int nRequired; @@ -200,11 +193,9 @@ UniValue validateaddress(const UniValue& params, bool fHelp) #ifdef ENABLE_WALLET isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO; ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false)); - if (mine != ISMINE_NO) { - ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false)); - UniValue detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); - ret.pushKVs(detail); - } + ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false)); + UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest); + ret.pushKVs(detail); if (pwalletMain && pwalletMain->mapAddressBook.count(dest)) ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name)); #endif From c110575a92ebe2e9a58b53d56aafa1f1ae37dbb2 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 10 Jun 2015 13:59:41 -0400 Subject: [PATCH 0013/1283] gitian: Use the new bitcoin-detached-sigs git repo for OSX signatures Rather than fetching a signature.tar.gz from somewhere on the net, instruct Gitian to use a signature from a tag in the bitcoin-detached-sigs repository which corresponds to the tag of the release being built. This changes detached-sig-apply.sh to take a dirname rather than a tarball as an argument, though detached-sig-create.sh still outputs a tarball for convenience. --- contrib/gitian-descriptors/gitian-osx-signer.yml | 7 ++++--- contrib/macdeploy/detached-sig-apply.sh | 2 +- contrib/macdeploy/detached-sig-create.sh | 5 +++-- doc/release-process.md | 8 +++----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml index c0c0b0c98..36d7b0126 100644 --- a/contrib/gitian-descriptors/gitian-osx-signer.yml +++ b/contrib/gitian-descriptors/gitian-osx-signer.yml @@ -8,10 +8,11 @@ packages: - "libc6:i386" - "faketime" reference_datetime: "2015-06-01 00:00:00" -remotes: [] +remotes: +- "url": "https://github.com/bitcoin/bitcoin-detached-sigs.git" + "dir": "signature" files: - "bitcoin-osx-unsigned.tar.gz" -- "signature.tar.gz" script: | WRAP_DIR=$HOME/wrapped mkdir -p ${WRAP_DIR} @@ -32,6 +33,6 @@ script: | SIGNED=bitcoin-osx-signed.dmg tar -xf ${UNSIGNED} - ./detached-sig-apply.sh ${UNSIGNED} signature.tar.gz + ./detached-sig-apply.sh ${UNSIGNED} signature/osx ${WRAP_DIR}/genisoimage -no-cache-inodes -D -l -probe -V "Bitcoin-Core" -no-pad -r -apple -o uncompressed.dmg signed-app ${WRAP_DIR}/dmg dmg uncompressed.dmg ${OUTDIR}/${SIGNED} diff --git a/contrib/macdeploy/detached-sig-apply.sh b/contrib/macdeploy/detached-sig-apply.sh index 169f69043..781fe315e 100755 --- a/contrib/macdeploy/detached-sig-apply.sh +++ b/contrib/macdeploy/detached-sig-apply.sh @@ -20,7 +20,7 @@ fi rm -rf ${TEMPDIR} && mkdir -p ${TEMPDIR} tar -C ${TEMPDIR} -xf ${UNSIGNED} -tar -C ${TEMPDIR} -xf ${SIGNATURE} +cp -rf "${SIGNATURE}"/* ${TEMPDIR} if [ -z "${PAGESTUFF}" ]; then PAGESTUFF=${TEMPDIR}/pagestuff diff --git a/contrib/macdeploy/detached-sig-create.sh b/contrib/macdeploy/detached-sig-create.sh index 18f8661ce..89a2da32f 100755 --- a/contrib/macdeploy/detached-sig-create.sh +++ b/contrib/macdeploy/detached-sig-create.sh @@ -7,6 +7,7 @@ CODESIGN=codesign TEMPDIR=sign.temp TEMPLIST=${TEMPDIR}/signatures.txt OUT=signature.tar.gz +OUTROOT=osx if [ ! -n "$1" ]; then echo "usage: $0 " @@ -23,7 +24,7 @@ grep -v CodeResources < "${TEMPLIST}" | while read i; do TARGETFILE="${BUNDLE}/`echo "${i}" | sed "s|.*${BUNDLE}/||"`" SIZE=`pagestuff "$i" -p | tail -2 | grep size | sed 's/[^0-9]*//g'` OFFSET=`pagestuff "$i" -p | tail -2 | grep offset | sed 's/[^0-9]*//g'` - SIGNFILE="${TEMPDIR}/${TARGETFILE}.sign" + SIGNFILE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}.sign" DIRNAME="`dirname "${SIGNFILE}"`" mkdir -p "${DIRNAME}" echo "Adding detached signature for: ${TARGETFILE}. Size: ${SIZE}. Offset: ${OFFSET}" @@ -32,7 +33,7 @@ done grep CodeResources < "${TEMPLIST}" | while read i; do TARGETFILE="${BUNDLE}/`echo "${i}" | sed "s|.*${BUNDLE}/||"`" - RESOURCE="${TEMPDIR}/${TARGETFILE}" + RESOURCE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}" DIRNAME="`dirname "${RESOURCE}"`" mkdir -p "${DIRNAME}" echo "Adding resource for: "${TARGETFILE}"" diff --git a/doc/release-process.md b/doc/release-process.md index d3109c6aa..45c44640c 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -92,15 +92,13 @@ Commit your signature to gitian.sigs: popd Wait for OSX detached signature: - Once the OSX build has 3 matching signatures, Gavin will sign it with the apple App-Store key. - He will then upload a detached signature to be combined with the unsigned app to create a signed binary. + Once the OSX build has 3 matching signatures, it will be signed with the Apple App-Store key. + A detached signature will then be committed to the bitcoin-detached-sigs repository, which can be combined with the unsigned app to create a signed binary. Create the signed OSX binary: pushd ./gitian-builder - # Fetch the signature as instructed by Gavin - cp signature.tar.gz inputs/ - ./bin/gbuild -i ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml + ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml mv build/out/bitcoin-osx-signed.dmg ../bitcoin-${VERSION}-osx.dmg popd From 1b0db7b984c49f40cf95c6f685c3c5c790f07606 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 1 Jun 2015 09:09:51 +0200 Subject: [PATCH 0014/1283] [Qt] extend rpc console peers tab - add node id, ping wait, whitelisted and common height - rephrase some labels to make them easier to understand for users --- src/qt/forms/rpcconsole.ui | 142 ++++++++++++++++++++++++++++--------- src/qt/peertablemodel.cpp | 1 + src/qt/rpcconsole.cpp | 18 +++-- 3 files changed, 120 insertions(+), 41 deletions(-) diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index c1eb18550..7ae823747 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -745,14 +745,14 @@ - + - Direction + Whitelisted - + IBeamCursor @@ -768,14 +768,14 @@ - + - Version + Direction - + IBeamCursor @@ -791,14 +791,14 @@ - + - User Agent + Version - + IBeamCursor @@ -814,13 +814,36 @@ + + + User Agent + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + Services - + IBeamCursor @@ -839,7 +862,7 @@ - Starting Height + Starting Block @@ -862,7 +885,7 @@ - Sync Height + Synced Headers @@ -883,14 +906,14 @@ - + - Ban Score + Synced Blocks - + IBeamCursor @@ -906,14 +929,14 @@ - + - Connection Time + Ban Score - + IBeamCursor @@ -929,14 +952,14 @@ - + - Last Send + Connection Time - + IBeamCursor @@ -952,14 +975,14 @@ - + - Last Receive + Last Send - + IBeamCursor @@ -975,14 +998,14 @@ - + - Bytes Sent + Last Receive - + IBeamCursor @@ -998,14 +1021,14 @@ - + - Bytes Received + Bytes Sent - + IBeamCursor @@ -1021,14 +1044,14 @@ - + - Ping Time + Bytes Received - + IBeamCursor @@ -1044,13 +1067,62 @@ + + + Ping Time + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + The duration of a currently outstanding ping. + + + Ping Wait + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + Time Offset - + IBeamCursor @@ -1066,7 +1138,7 @@ - + Qt::Vertical diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 220f273d0..06403734e 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -68,6 +68,7 @@ public: CNodeCombinedStats stats; stats.nodeStateStats.nMisbehavior = 0; stats.nodeStateStats.nSyncHeight = -1; + stats.nodeStateStats.nCommonHeight = -1; stats.fNodeStateStatsAvailable = false; pnode->copyStats(stats.nodeStats); cachedNodeStats.append(stats); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index e99972d49..73ee33cbd 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -611,7 +611,8 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats) cachedNodeid = stats->nodeStats.nodeid; // update the detail ui with latest node information - QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName)); + QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " "); + peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid)); if (!stats->nodeStats.addrLocal.empty()) peerAddrDetails += "
" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal)); ui->peerHeading->setText(peerAddrDetails); @@ -622,11 +623,13 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats) ui->peerBytesRecv->setText(FormatBytes(stats->nodeStats.nRecvBytes)); ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetTime() - stats->nodeStats.nTimeConnected)); ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingTime)); + ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingWait)); ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset)); - ui->peerVersion->setText(QString("%1").arg(stats->nodeStats.nVersion)); + ui->peerVersion->setText(QString("%1").arg(QString::number(stats->nodeStats.nVersion))); ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer)); ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound") : tr("Outbound")); - ui->peerHeight->setText(QString("%1").arg(stats->nodeStats.nStartingHeight)); + ui->peerHeight->setText(QString("%1").arg(QString::number(stats->nodeStats.nStartingHeight))); + ui->peerWhitelisted->setText(stats->nodeStats.fWhitelisted ? tr("Yes") : tr("No")); // This check fails for example if the lock was busy and // nodeStateStats couldn't be fetched. @@ -639,9 +642,12 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats) ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight)); else ui->peerSyncHeight->setText(tr("Unknown")); - } else { - ui->peerBanScore->setText(tr("Fetching...")); - ui->peerSyncHeight->setText(tr("Fetching...")); + + // Common height is init to -1 + if (stats->nodeStateStats.nCommonHeight > -1) + ui->peerCommonHeight->setText(QString("%1").arg(stats->nodeStateStats.nCommonHeight)); + else + ui->peerCommonHeight->setText(tr("Unknown")); } ui->detailWidget->show(); From 7211adad85275db24835bb877a29b28adcf06f62 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 1 Jun 2015 11:39:52 +0200 Subject: [PATCH 0015/1283] [Qt] replace Boost foreach with Qt version peertablemodel.cpp --- src/qt/peertablemodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 06403734e..f5904a4d8 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -63,7 +63,7 @@ public: #if QT_VERSION >= 0x040700 cachedNodeStats.reserve(vNodes.size()); #endif - BOOST_FOREACH(CNode* pnode, vNodes) + foreach (CNode* pnode, vNodes) { CNodeCombinedStats stats; stats.nodeStateStats.nMisbehavior = 0; @@ -92,7 +92,7 @@ public: // build index map mapNodeRows.clear(); int row = 0; - BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats) + foreach (const CNodeCombinedStats& stats, cachedNodeStats) mapNodeRows.insert(std::pair(stats.nodeStats.nodeid, row++)); } From e0597268116cf90d961abeba9d14aaad0ab682d2 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sat, 6 Jun 2015 10:38:15 +0200 Subject: [PATCH 0016/1283] [Qt] deselect peer when switching away from peers tab in RPC console --- src/qt/rpcconsole.cpp | 32 +++++++++++++++++--------------- src/qt/rpcconsole.h | 4 +++- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 73ee33cbd..681617bd8 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -485,10 +485,10 @@ void RPCConsole::startExecutor() void RPCConsole::on_tabWidget_currentChanged(int index) { - if(ui->tabWidget->widget(index) == ui->tab_console) - { + if (ui->tabWidget->widget(index) == ui->tab_console) ui->lineEdit->setFocus(); - } + else if (ui->tabWidget->widget(index) != ui->tab_peers) + clearSelectedNode(); } void RPCConsole::on_openDebugLogfileButton_clicked() @@ -558,12 +558,11 @@ void RPCConsole::peerLayoutChanged() return; // find the currently selected row - int selectedRow; + int selectedRow = -1; QModelIndexList selectedModelIndex = ui->peerWidget->selectionModel()->selectedIndexes(); - if (selectedModelIndex.isEmpty()) - selectedRow = -1; - else + if (!selectedModelIndex.isEmpty()) { selectedRow = selectedModelIndex.first().row(); + } // check if our detail node has a row in the table (it may not necessarily // be at selectedRow since its position can change after a layout change) @@ -573,9 +572,6 @@ void RPCConsole::peerLayoutChanged() { // detail node dissapeared from table (node disconnected) fUnselect = true; - cachedNodeid = -1; - ui->detailWidget->hide(); - ui->peerHeading->setText(tr("Select a peer to view detailed information.")); } else { @@ -590,10 +586,8 @@ void RPCConsole::peerLayoutChanged() stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow); } - if (fUnselect && selectedRow >= 0) - { - ui->peerWidget->selectionModel()->select(QItemSelection(selectedModelIndex.first(), selectedModelIndex.last()), - QItemSelectionModel::Deselect); + if (fUnselect && selectedRow >= 0) { + clearSelectedNode(); } if (fReselect) @@ -694,6 +688,14 @@ void RPCConsole::disconnectSelectedNode() // Find the node, disconnect it and clear the selected node if (CNode *bannedNode = FindNode(strNode.toStdString())) { bannedNode->CloseSocketDisconnect(); - ui->peerWidget->selectionModel()->clearSelection(); + clearSelectedNode(); } } + +void RPCConsole::clearSelectedNode() +{ + ui->peerWidget->selectionModel()->clearSelection(); + cachedNodeid = -1; + ui->detailWidget->hide(); + ui->peerHeading->setText(tr("Select a peer to view detailed information.")); +} diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 767e9aaee..a309df7ba 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -76,7 +76,7 @@ public slots: void peerSelected(const QItemSelection &selected, const QItemSelection &deselected); /** Handle updated peer information */ void peerLayoutChanged(); - /** Disconnect a selected node on the Peers tab */ + /** Disconnect a selected node on the Peers tab */ void disconnectSelectedNode(); signals: @@ -90,6 +90,8 @@ private: void setTrafficGraphRange(int mins); /** show detailed information on ui about selected node */ void updateNodeDetail(const CNodeCombinedStats *stats); + /** clear the selected node */ + void clearSelectedNode(); enum ColumnWidths { From 9b4e7d9a5ec0f69c175d23dc9c94ed723147cf45 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 1 May 2015 15:21:06 +0200 Subject: [PATCH 0017/1283] Add DummySignatureCreator which just creates zeroed sigs --- src/script/sign.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/script/sign.h | 8 ++++++++ 2 files changed, 44 insertions(+) diff --git a/src/script/sign.cpp b/src/script/sign.cpp index eab629cd9..4543ca303 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -275,3 +275,39 @@ CScript CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecke return CombineSignatures(scriptPubKey, checker, txType, vSolutions, stack1, stack2); } + +namespace { +/** Dummy signature checker which accepts all signatures. */ +class DummySignatureChecker : public BaseSignatureChecker +{ +public: + DummySignatureChecker() {} + + bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const + { + return true; + } +}; +const DummySignatureChecker dummyChecker; +} + +const BaseSignatureChecker& DummySignatureCreator::Checker() const +{ + return dummyChecker; +} + +bool DummySignatureCreator::CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode) const +{ + // Create a dummy signature that is a valid DER-encoding + vchSig.assign(72, '\000'); + vchSig[0] = 0x30; + vchSig[1] = 69; + vchSig[2] = 0x02; + vchSig[3] = 33; + vchSig[4] = 0x01; + vchSig[4 + 33] = 0x02; + vchSig[5 + 33] = 32; + vchSig[6 + 33] = 0x01; + vchSig[6 + 33 + 32] = SIGHASH_ALL; + return true; +} diff --git a/src/script/sign.h b/src/script/sign.h index 0c4cf61e5..13f45007d 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -43,6 +43,14 @@ public: bool CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode) const; }; +/** A signature creator that just produces 72-byte empty signatyres. */ +class DummySignatureCreator : public BaseSignatureCreator { +public: + DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {} + const BaseSignatureChecker& Checker() const; + bool CreateSig(std::vector& vchSig, const CKeyID& keyid, const CScript& scriptCode) const; +}; + /** Produce a script signature using a generic signature creator. */ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, CScript& scriptSig); From 2d84e22703594643c70dfa36dac2a83f8f0f713e Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 24 Apr 2015 18:27:00 -0700 Subject: [PATCH 0018/1283] Small tweaks to CCoinControl for fundrawtransaction --- src/coincontrol.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/coincontrol.h b/src/coincontrol.h index 92fae9847..3e8de83c3 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -12,6 +12,8 @@ class CCoinControl { public: CTxDestination destChange; + //! If false, allows unselected inputs, but requires all selected inputs be used + bool fAllowOtherInputs; CCoinControl() { @@ -21,6 +23,7 @@ public: void SetNull() { destChange = CNoDestination(); + fAllowOtherInputs = false; setSelected.clear(); } @@ -50,7 +53,7 @@ public: setSelected.clear(); } - void ListSelected(std::vector& vOutpoints) + void ListSelected(std::vector& vOutpoints) const { vOutpoints.assign(setSelected.begin(), setSelected.end()); } From 1e0d1a2ff02982d6ffe61e70b027c56f3bf22d0b Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 24 Apr 2015 18:29:00 -0700 Subject: [PATCH 0019/1283] Add FundTransaction method to wallet Some code stolen from Jonas Schnelli --- src/wallet/wallet.cpp | 125 ++++++++++++++++++++++++++++++++++++++---- src/wallet/wallet.h | 5 +- 2 files changed, 117 insertions(+), 13 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3f12d88e7..eee57900b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1509,7 +1509,7 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const isminetype mine = IsMine(pcoin->vout[i]); if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO && !IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) && - (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) + (!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected((*it).first, i))) vCoins.push_back(COutput(pcoin, i, nDepth, (mine & ISMINE_SPENDABLE) != ISMINE_NO)); } } @@ -1669,25 +1669,108 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set return all selected outputs (we want all selected to go into the transaction for sure) - if (coinControl && coinControl->HasSelected()) + if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs) { BOOST_FOREACH(const COutput& out, vCoins) { - if(!out.fSpendable) - continue; + if (!out.fSpendable) + continue; nValueRet += out.tx->vout[out.i].nValue; setCoinsRet.insert(make_pair(out.tx, out.i)); } return (nValueRet >= nTargetValue); } - return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) || - SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) || - (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet))); + // calculate value from preset inputs and store them + set > setPresetCoins; + CAmount nValueFromPresetInputs = 0; + + std::vector vPresetInputs; + if (coinControl) + coinControl->ListSelected(vPresetInputs); + BOOST_FOREACH(const COutPoint& outpoint, vPresetInputs) + { + map::const_iterator it = mapWallet.find(outpoint.hash); + if (it != mapWallet.end()) + { + const CWalletTx* pcoin = &it->second; + // Clearly invalid input, fail + if (pcoin->vout.size() <= outpoint.n) + return false; + nValueFromPresetInputs += pcoin->vout[outpoint.n].nValue; + setPresetCoins.insert(make_pair(pcoin, outpoint.n)); + } else + return false; // TODO: Allow non-wallet inputs + } + + // remove preset inputs from vCoins + for (vector::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();) + { + if (setPresetCoins.count(make_pair(it->tx, it->i))) + it = vCoins.erase(it); + else + ++it; + } + + bool res = nTargetValue <= nValueFromPresetInputs || + SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 6, vCoins, setCoinsRet, nValueRet) || + SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 1, vCoins, setCoinsRet, nValueRet) || + (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, vCoins, setCoinsRet, nValueRet)); + + // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset + setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end()); + + // add preset inputs to the total value selected + nValueRet += nValueFromPresetInputs; + + return res; } -bool CWallet::CreateTransaction(const vector& vecSend, - CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl) +bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosRet, std::string& strFailReason) +{ + vector vecSend; + + // Turn the txout set into a CRecipient vector + BOOST_FOREACH(const CTxOut& txOut, tx.vout) + { + CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, false}; + vecSend.push_back(recipient); + } + + CCoinControl coinControl; + coinControl.fAllowOtherInputs = true; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + coinControl.Select(txin.prevout); + + CReserveKey reservekey(this); + CWalletTx wtx; + if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false)) + return false; + + if (nChangePosRet != -1) + tx.vout.insert(tx.vout.begin() + nChangePosRet, wtx.vout[nChangePosRet]); + + // Add new txins (keeping original txin scriptSig/order) + BOOST_FOREACH(const CTxIn& txin, wtx.vin) + { + bool found = false; + BOOST_FOREACH(const CTxIn& origTxIn, tx.vin) + { + if (txin.prevout.hash == origTxIn.prevout.hash && txin.prevout.n == origTxIn.prevout.n) + { + found = true; + break; + } + } + if (!found) + tx.vin.push_back(txin); + } + + return true; +} + +bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, + int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign) { CAmount nValue = 0; unsigned int nSubtractFeeFromAmount = 0; @@ -1890,23 +1973,43 @@ bool CWallet::CreateTransaction(const vector& vecSend, // Sign int nIn = 0; + CTransaction txNewConst(txNew); BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) - if (!SignSignature(*this, *coin.first, txNew, nIn++)) + { + bool signSuccess; + const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey; + CScript& scriptSigRes = txNew.vin[nIn].scriptSig; + if (sign) + signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, SIGHASH_ALL), scriptPubKey, scriptSigRes); + else + signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, scriptSigRes); + + if (!signSuccess) { strFailReason = _("Signing transaction failed"); return false; } + nIn++; + } + + unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION); + + // Remove scriptSigs if we used dummy signatures for fee calculation + if (!sign) { + BOOST_FOREACH (CTxIn& vin, txNew.vin) + vin.scriptSig = CScript(); + } // Embed the constructed transaction data in wtxNew. *static_cast(&wtxNew) = CTransaction(txNew); // Limit size - unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION); if (nBytes >= MAX_STANDARD_TX_SIZE) { strFailReason = _("Transaction too large"); return false; } + dPriority = wtxNew.ComputePriority(dPriority, nBytes); // Can we complete this as a free transaction? diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 9f3f08d11..b6a8e8671 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -625,8 +625,9 @@ public: CAmount GetWatchOnlyBalance() const; CAmount GetUnconfirmedWatchOnlyBalance() const; CAmount GetImmatureWatchOnlyBalance() const; - bool CreateTransaction(const std::vector& vecSend, - CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); + bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason); + bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, + std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); static CFeeRate minTxFee; From 21bbd920e5cc02dae5e75795c1f0bbfba9a41b53 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 24 Apr 2015 18:27:30 -0700 Subject: [PATCH 0020/1283] Add fundrawtransaction RPC method --- src/rpcclient.cpp | 1 + src/rpcserver.cpp | 3 ++ src/rpcserver.h | 1 + src/test/rpc_wallet_tests.cpp | 6 ++++ src/wallet/rpcwallet.cpp | 54 +++++++++++++++++++++++++++++++++++ 5 files changed, 65 insertions(+) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index f254da5de..ca673aa52 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -78,6 +78,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "signrawtransaction", 1 }, { "signrawtransaction", 2 }, { "sendrawtransaction", 1 }, + { "fundrawtransaction", 1 }, { "gettxout", 1 }, { "gettxout", 2 }, { "gettxoutproof", 0 }, diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 3894dd08b..011cfcb34 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -316,6 +316,9 @@ static const CRPCCommand vRPCCommands[] = { "rawtransactions", "getrawtransaction", &getrawtransaction, true }, { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false }, { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */ +#ifdef ENABLE_WALLET + { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false }, +#endif /* Utility functions */ { "util", "createmultisig", &createmultisig, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 7b462a8b7..5fb4faa8f 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -217,6 +217,7 @@ extern UniValue listlockunspent(const UniValue& params, bool fHelp); extern UniValue createrawtransaction(const UniValue& params, bool fHelp); extern UniValue decoderawtransaction(const UniValue& params, bool fHelp); extern UniValue decodescript(const UniValue& params, bool fHelp); +extern UniValue fundrawtransaction(const UniValue& params, bool fHelp); extern UniValue signrawtransaction(const UniValue& params, bool fHelp); extern UniValue sendrawtransaction(const UniValue& params, bool fHelp); extern UniValue gettxoutproof(const UniValue& params, bool fHelp); diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index a72b65610..9368963ff 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -217,6 +217,12 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) UniValue arr = retValue.get_array(); BOOST_CHECK(arr.size() > 0); BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get()); + + /********************************* + * fundrawtransaction + *********************************/ + BOOST_CHECK_THROW(CallRPC("fundrawtransaction 28z"), runtime_error); + BOOST_CHECK_THROW(CallRPC("fundrawtransaction 01000000000180969800000000001976a91450ce0a4b0ee0ddeb633da85199728b940ac3fe9488ac00000000"), runtime_error); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d284fcf15..1ef2980e8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2359,3 +2359,57 @@ UniValue listunspent(const UniValue& params, bool fHelp) return results; } + +UniValue fundrawtransaction(const UniValue& params, bool fHelp) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() != 1) + throw runtime_error( + "fundrawtransaction \"hexstring\"\n" + "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n" + "This will not modify existing inputs, and will add one change output to the outputs.\n" + "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n" + "The inputs added will not be signed, use signrawtransaction for that.\n" + "\nArguments:\n" + "1. \"hexstring\" (string, required) The hex string of the raw transaction\n" + "\nResult:\n" + "{\n" + " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n" + " \"fee\": n, (numeric) The fee added to the transaction\n" + " \"changepos\": n (numeric) The position of the added change output, or -1\n" + "}\n" + "\"hex\" \n" + "\nExamples:\n" + "\nCreate a transaction with no inputs\n" + + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") + + "\nAdd sufficient unsigned inputs to meet the output value\n" + + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") + + "\nSign the transaction\n" + + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") + + "\nSend the transaction\n" + + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"") + ); + + RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)); + + // parse hex string from parameter + CTransaction origTx; + if (!DecodeHexTx(origTx, params[0].get_str())) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + + CMutableTransaction tx(origTx); + CAmount nFee; + string strFailReason; + int nChangePos = -1; + if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason)) + throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason); + + UniValue result(UniValue::VOBJ); + result.push_back(Pair("hex", EncodeHexTx(tx))); + result.push_back(Pair("changepos", nChangePos)); + result.push_back(Pair("fee", ValueFromAmount(nFee))); + + return result; +} From 208589514cdc344c2d33228dba7f00b305d0174b Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 24 Apr 2015 18:26:30 -0700 Subject: [PATCH 0021/1283] fundrawtransaction tests --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/fundrawtransaction.py | 556 +++++++++++++++++++++++++++++ 2 files changed, 557 insertions(+) create mode 100755 qa/rpc-tests/fundrawtransaction.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 9b318650e..f7f7b13cf 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -30,6 +30,7 @@ testScripts=( 'zapwallettxes.py' 'proxy_test.py' 'merkle_blocks.py' + 'fundrawtransaction.py' 'signrawtransactions.py' 'walletbackup.py' ); diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py new file mode 100755 index 000000000..e859b2643 --- /dev/null +++ b/qa/rpc-tests/fundrawtransaction.py @@ -0,0 +1,556 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +from pprint import pprint +from time import sleep + +# Create one-input, one-output, no-fee transaction: +class RawTransactionsTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 3) + + def setup_network(self, split=False): + self.nodes = start_nodes(3, self.options.tmpdir) + + connect_nodes_bi(self.nodes,0,1) + connect_nodes_bi(self.nodes,1,2) + connect_nodes_bi(self.nodes,0,2) + + self.is_network_split=False + self.sync_all() + + def run_test(self): + print "Mining blocks..." + feeTolerance = Decimal(0.00000002) #if the fee's positive delta is higher than this value tests will fail, neg. delta always fail the tests + + self.nodes[2].generate(1) + self.nodes[0].generate(101) + self.sync_all() + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5); + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0); + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0); + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + ############### + # simple test # + ############### + inputs = [ ] + outputs = { self.nodes[0].getnewaddress() : 1.0 } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + fee = rawtxfund['fee'] + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + totalOut = 0 + for out in dec_tx['vout']: + totalOut += out['value'] + + assert_equal(len(dec_tx['vin']), 1) #one vin coin + assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') + assert_equal(fee + totalOut, 1.5) #the 1.5BTC coin must be taken + + ############################## + # simple test with two coins # + ############################## + inputs = [ ] + outputs = { self.nodes[0].getnewaddress() : 2.2 } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + fee = rawtxfund['fee'] + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + totalOut = 0 + for out in dec_tx['vout']: + totalOut += out['value'] + + assert_equal(len(dec_tx['vin']), 2) #one vin coin + assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') + assert_equal(dec_tx['vin'][1]['scriptSig']['hex'], '') + assert_equal(fee + totalOut, 2.5) #the 1.5BTC+1.0BTC coins must have be taken + + ############################## + # simple test with two coins # + ############################## + inputs = [ ] + outputs = { self.nodes[0].getnewaddress() : 2.6 } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + fee = rawtxfund['fee'] + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + totalOut = 0 + for out in dec_tx['vout']: + totalOut += out['value'] + + assert_equal(len(dec_tx['vin']), 1) #one vin coin + assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') + assert_equal(fee + totalOut, 5.0) #the 5.0BTC coin must have be taken + + + ################################ + # simple test with two outputs # + ################################ + inputs = [ ] + outputs = { self.nodes[0].getnewaddress() : 2.6, self.nodes[1].getnewaddress() : 2.5 } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + fee = rawtxfund['fee'] + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + totalOut = 0 + for out in dec_tx['vout']: + totalOut += out['value'] + + assert_equal(len(dec_tx['vin']), 2) #one vin coin + assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') + assert_equal(dec_tx['vin'][1]['scriptSig']['hex'], '') + assert_equal(fee + totalOut, 6.0) #the 5.0BTC + 1.0BTC coins must have be taken + + + + ######################################################################### + # test a fundrawtransaction with a VIN greater than the required amount # + ######################################################################### + utx = False + listunspent = self.nodes[2].listunspent() + for aUtx in listunspent: + if aUtx['amount'] == 5.0: + utx = aUtx + break; + + assert_equal(utx!=False, True) + + inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] + outputs = { self.nodes[0].getnewaddress() : 1.0 } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) + + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + fee = rawtxfund['fee'] + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + totalOut = 0 + for out in dec_tx['vout']: + totalOut += out['value'] + + assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee + + + + ##################################################################### + # test a fundrawtransaction with which will not get a change output # + ##################################################################### + utx = False + listunspent = self.nodes[2].listunspent() + for aUtx in listunspent: + if aUtx['amount'] == 5.0: + utx = aUtx + break; + + assert_equal(utx!=False, True) + + inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] + outputs = { self.nodes[0].getnewaddress() : Decimal(5.0) - fee - feeTolerance } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) + + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + fee = rawtxfund['fee'] + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + totalOut = 0 + for out in dec_tx['vout']: + totalOut += out['value'] + + assert_equal(rawtxfund['changepos'], -1) + assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee + + + + ######################################################################### + # test a fundrawtransaction with a VIN smaller than the required amount # + ######################################################################### + utx = False + listunspent = self.nodes[2].listunspent() + for aUtx in listunspent: + if aUtx['amount'] == 1.0: + utx = aUtx + break; + + assert_equal(utx!=False, True) + + inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] + outputs = { self.nodes[0].getnewaddress() : 1.0 } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + + # 4-byte version + 1-byte vin count + 36-byte prevout then script_len + rawtx = rawtx[:82] + "0100" + rawtx[84:] + + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) + assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex']) + + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + fee = rawtxfund['fee'] + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + totalOut = 0 + matchingOuts = 0 + for i, out in enumerate(dec_tx['vout']): + totalOut += out['value'] + if outputs.has_key(out['scriptPubKey']['addresses'][0]): + matchingOuts+=1 + else: + assert_equal(i, rawtxfund['changepos']) + + assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) + assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex']) + + assert_equal(matchingOuts, 1) + assert_equal(len(dec_tx['vout']), 2) + + assert_equal(fee + totalOut, 2.5) #this tx must use the 1.0BTC and the 1.5BTC coin + + + ########################################### + # test a fundrawtransaction with two VINs # + ########################################### + utx = False + utx2 = False + listunspent = self.nodes[2].listunspent() + for aUtx in listunspent: + if aUtx['amount'] == 1.0: + utx = aUtx + if aUtx['amount'] == 5.0: + utx2 = aUtx + + + assert_equal(utx!=False, True) + + inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] + outputs = { self.nodes[0].getnewaddress() : 6.0 } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) + + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + fee = rawtxfund['fee'] + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + totalOut = 0 + matchingOuts = 0 + for out in dec_tx['vout']: + totalOut += out['value'] + if outputs.has_key(out['scriptPubKey']['addresses'][0]): + matchingOuts+=1 + + assert_equal(matchingOuts, 1) + assert_equal(len(dec_tx['vout']), 2) + + matchingIns = 0 + for vinOut in dec_tx['vin']: + for vinIn in inputs: + if vinIn['txid'] == vinOut['txid']: + matchingIns+=1 + + assert_equal(matchingIns, 2) #we now must see two vins identical to vins given as params + assert_equal(fee + totalOut, 7.5) #this tx must use the 1.0BTC and the 1.5BTC coin + + + ######################################################### + # test a fundrawtransaction with two VINs and two vOUTs # + ######################################################### + utx = False + utx2 = False + listunspent = self.nodes[2].listunspent() + for aUtx in listunspent: + if aUtx['amount'] == 1.0: + utx = aUtx + if aUtx['amount'] == 5.0: + utx2 = aUtx + + + assert_equal(utx!=False, True) + + inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] + outputs = { self.nodes[0].getnewaddress() : 6.0, self.nodes[0].getnewaddress() : 1.0 } + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) + + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + fee = rawtxfund['fee'] + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + totalOut = 0 + matchingOuts = 0 + for out in dec_tx['vout']: + totalOut += out['value'] + if outputs.has_key(out['scriptPubKey']['addresses'][0]): + matchingOuts+=1 + + assert_equal(matchingOuts, 2) + assert_equal(len(dec_tx['vout']), 3) + assert_equal(fee + totalOut, 7.5) #this tx must use the 1.0BTC and the 1.5BTC coin + + + ############################################## + # test a fundrawtransaction with invalid vin # + ############################################## + listunspent = self.nodes[2].listunspent() + inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin! + outputs = { self.nodes[0].getnewaddress() : 1.0} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) + + errorString = "" + try: + rawtxfund = self.nodes[2].fundrawtransaction(rawtx) + except JSONRPCException,e: + errorString = e.error['message'] + + assert_equal("Insufficient" in errorString, True); + + + + ############################################################ + #compare fee of a standard pubkeyhash transaction + inputs = [] + outputs = {self.nodes[1].getnewaddress():1.1} + rawTx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawTx) + + #create same transaction over sendtoaddress + txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1); + signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] + + #compare fee + feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee); + assert(feeDelta >= 0 and feeDelta <= feeTolerance) + ############################################################ + + ############################################################ + #compare fee of a standard pubkeyhash transaction with multiple outputs + inputs = [] + outputs = {self.nodes[1].getnewaddress():1.1,self.nodes[1].getnewaddress():1.2,self.nodes[1].getnewaddress():0.1,self.nodes[1].getnewaddress():1.3,self.nodes[1].getnewaddress():0.2,self.nodes[1].getnewaddress():0.3} + rawTx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawTx) + #create same transaction over sendtoaddress + txId = self.nodes[0].sendmany("", outputs); + signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] + + #compare fee + feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee); + assert(feeDelta >= 0 and feeDelta <= feeTolerance) + ############################################################ + + + ############################################################ + #compare fee of a 2of2 multisig p2sh transaction + + # create 2of2 addr + addr1 = self.nodes[1].getnewaddress() + addr2 = self.nodes[1].getnewaddress() + + addr1Obj = self.nodes[1].validateaddress(addr1) + addr2Obj = self.nodes[1].validateaddress(addr2) + + mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) + + inputs = [] + outputs = {mSigObj:1.1} + rawTx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawTx) + + #create same transaction over sendtoaddress + txId = self.nodes[0].sendtoaddress(mSigObj, 1.1); + signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] + + #compare fee + feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee); + assert(feeDelta >= 0 and feeDelta <= feeTolerance) + ############################################################ + + + ############################################################ + #compare fee of a standard pubkeyhash transaction + + # create 4of5 addr + addr1 = self.nodes[1].getnewaddress() + addr2 = self.nodes[1].getnewaddress() + addr3 = self.nodes[1].getnewaddress() + addr4 = self.nodes[1].getnewaddress() + addr5 = self.nodes[1].getnewaddress() + + addr1Obj = self.nodes[1].validateaddress(addr1) + addr2Obj = self.nodes[1].validateaddress(addr2) + addr3Obj = self.nodes[1].validateaddress(addr3) + addr4Obj = self.nodes[1].validateaddress(addr4) + addr5Obj = self.nodes[1].validateaddress(addr5) + + mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']]) + + inputs = [] + outputs = {mSigObj:1.1} + rawTx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawTx) + + #create same transaction over sendtoaddress + txId = self.nodes[0].sendtoaddress(mSigObj, 1.1); + signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] + + #compare fee + feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee); + assert(feeDelta >= 0 and feeDelta <= feeTolerance) + ############################################################ + + + ############################################################ + # spend a 2of2 multisig transaction over fundraw + + # create 2of2 addr + addr1 = self.nodes[2].getnewaddress() + addr2 = self.nodes[2].getnewaddress() + + addr1Obj = self.nodes[2].validateaddress(addr1) + addr2Obj = self.nodes[2].validateaddress(addr2) + + mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) + + + # send 1.2 BTC to msig addr + txId = self.nodes[0].sendtoaddress(mSigObj, 1.2); + self.sync_all() + self.nodes[1].generate(1) + self.sync_all() + + oldBalance = self.nodes[1].getbalance() + inputs = [] + outputs = {self.nodes[1].getnewaddress():1.1} + rawTx = self.nodes[2].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[2].fundrawtransaction(rawTx) + + signedTx = self.nodes[2].signrawtransaction(fundedTx['hex']) + txId = self.nodes[2].sendrawtransaction(signedTx['hex']) + self.sync_all() + self.nodes[1].generate(1) + self.sync_all() + + # make sure funds are received at node1 + assert_equal(oldBalance+Decimal('1.10000000'), self.nodes[1].getbalance()) + + ############################################################ + # locked wallet test + self.nodes[1].encryptwallet("test") + self.nodes.pop(1) + stop_nodes(self.nodes) + wait_bitcoinds() + + self.nodes = start_nodes(3, self.options.tmpdir) + + connect_nodes_bi(self.nodes,0,1) + connect_nodes_bi(self.nodes,1,2) + connect_nodes_bi(self.nodes,0,2) + self.is_network_split=False + self.sync_all() + + error = False + try: + self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2); + except: + error = True + assert(error) + + oldBalance = self.nodes[0].getbalance() + + inputs = [] + outputs = {self.nodes[0].getnewaddress():1.1} + rawTx = self.nodes[1].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[1].fundrawtransaction(rawTx) + + #now we need to unlock + self.nodes[1].walletpassphrase("test", 100) + signedTx = self.nodes[1].signrawtransaction(fundedTx['hex']) + txId = self.nodes[1].sendrawtransaction(signedTx['hex']) + self.sync_all() + self.nodes[1].generate(1) + self.sync_all() + + # make sure funds are received at node1 + assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance()) + + + + ############################################### + # multiple (~19) inputs tx test | Compare fee # + ############################################### + + #empty node1, send some small coins from node0 to node1 + self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True); + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + for i in range(0,20): + self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01); + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + #fund a tx with ~20 small inputs + inputs = [] + outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} + rawTx = self.nodes[1].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[1].fundrawtransaction(rawTx) + + #create same transaction over sendtoaddress + txId = self.nodes[1].sendmany("", outputs); + signedFee = self.nodes[1].getrawmempool(True)[txId]['fee'] + + #compare fee + feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee); + assert(feeDelta >= 0 and feeDelta <= feeTolerance*19) #~19 inputs + + + ############################################# + # multiple (~19) inputs tx test | sign/send # + ############################################# + + #again, empty node1, send some small coins from node0 to node1 + self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True); + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + for i in range(0,20): + self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01); + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + #fund a tx with ~20 small inputs + oldBalance = self.nodes[0].getbalance() + + inputs = [] + outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} + rawTx = self.nodes[1].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[1].fundrawtransaction(rawTx) + fundedAndSignedTx = self.nodes[1].signrawtransaction(fundedTx['hex']) + txId = self.nodes[1].sendrawtransaction(fundedAndSignedTx['hex']) + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + assert_equal(oldBalance+Decimal('50.19000000'), self.nodes[0].getbalance()) #0.19+block reward + + +if __name__ == '__main__': + RawTransactionsTest().main() From 0cc7b2352e749a7863d7b5ed680e3fb5f04f9511 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Wed, 10 Jun 2015 14:57:57 +0200 Subject: [PATCH 0022/1283] Fix univalue handling of \u0000 characters. Univalue's parsing of \u escape sequences did not handle NUL characters correctly. They were, effectively, dropped. The extended test-case fails with the old code, and is fixed with this patch. --- src/test/univalue_tests.cpp | 6 ++++-- src/univalue/univalue_read.cpp | 15 ++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp index de84faca2..2c1d303f6 100644 --- a/src/test/univalue_tests.cpp +++ b/src/test/univalue_tests.cpp @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(univalue_object) } static const char *json1 = -"[1.10000000,{\"key1\":\"str\",\"key2\":800,\"key3\":{\"name\":\"martian\"}}]"; +"[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian\"}}]"; BOOST_AUTO_TEST_CASE(univalue_readwrite) { @@ -306,7 +306,9 @@ BOOST_AUTO_TEST_CASE(univalue_readwrite) BOOST_CHECK_EQUAL(obj.size(), 3); BOOST_CHECK(obj["key1"].isStr()); - BOOST_CHECK_EQUAL(obj["key1"].getValStr(), "str"); + std::string correctValue("str"); + correctValue.push_back('\0'); + BOOST_CHECK_EQUAL(obj["key1"].getValStr(), correctValue); BOOST_CHECK(obj["key2"].isNum()); BOOST_CHECK_EQUAL(obj["key2"].getValStr(), "800"); BOOST_CHECK(obj["key3"].isObject()); diff --git a/src/univalue/univalue_read.cpp b/src/univalue/univalue_read.cpp index 5cea77899..261771811 100644 --- a/src/univalue/univalue_read.cpp +++ b/src/univalue/univalue_read.cpp @@ -188,25 +188,22 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, case 't': valStr += "\t"; break; case 'u': { - char buf[4] = {0,0,0,0}; - char *last = &buf[0]; unsigned int codepoint; if (hatoui(raw + 1, raw + 1 + 4, codepoint) != raw + 1 + 4) return JTOK_ERR; if (codepoint <= 0x7f) - *last = (char)codepoint; + valStr.push_back((char)codepoint); else if (codepoint <= 0x7FF) { - *last++ = (char)(0xC0 | (codepoint >> 6)); - *last = (char)(0x80 | (codepoint & 0x3F)); + valStr.push_back((char)(0xC0 | (codepoint >> 6))); + valStr.push_back((char)(0x80 | (codepoint & 0x3F))); } else if (codepoint <= 0xFFFF) { - *last++ = (char)(0xE0 | (codepoint >> 12)); - *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F)); - *last = (char)(0x80 | (codepoint & 0x3F)); + valStr.push_back((char)(0xE0 | (codepoint >> 12))); + valStr.push_back((char)(0x80 | ((codepoint >> 6) & 0x3F))); + valStr.push_back((char)(0x80 | (codepoint & 0x3F))); } - valStr += buf; raw += 4; break; } From ef2a3de25c882396e1776b554878d2784b6b7391 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 11 Jun 2015 16:12:34 -0400 Subject: [PATCH 0023/1283] Add paytxfee to getwalletinfo, warnings to getnetworkinfo --- qa/rpc-tests/README.md | 2 +- src/rpcnet.cpp | 2 ++ src/wallet/rpcwallet.cpp | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md index 6221c93d8..efc81e7a9 100644 --- a/qa/rpc-tests/README.md +++ b/qa/rpc-tests/README.md @@ -25,7 +25,7 @@ Run all possible tests with `qa/pull-tester/rpc-tests.sh -extended`. Possible options: -```` +``` -h, --help show this help message and exit --nocleanup Leave bitcoinds and test.* datadir on exit or error --noshutdown Don't stop bitcoinds after the test execution diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index a36831de2..c4e038eeb 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -408,6 +408,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) " }\n" " ,...\n" " ]\n" + " \"warnings\": \"...\" (string) any network warnings (such as alert messages) \n" "}\n" "\nExamples:\n" + HelpExampleCli("getnetworkinfo", "") @@ -439,5 +440,6 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) } } obj.push_back(Pair("localaddresses", localAddresses)); + obj.push_back(Pair("warnings", GetWarnings("statusbar"))); return obj; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e44940993..479b7d606 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2195,6 +2195,7 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n" " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" + " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in btc/kb\n" "}\n" "\nExamples:\n" + HelpExampleCli("getwalletinfo", "") @@ -2213,6 +2214,7 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); if (pwalletMain->IsCrypted()) obj.push_back(Pair("unlocked_until", nWalletUnlockTime)); + obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()))); return obj; } From baf05075fae2cc2625a2a74b35cc66902f3cbfa3 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 10 Jun 2015 09:19:13 +0200 Subject: [PATCH 0024/1283] Improve proxy initialization Simplify and make the code in AppInit2 more clear. This provides a straightforward flow, gets rid of .count() (which makes it possible to override an earlier provided proxy option to nothing), as well as comments the different cases. --- src/init.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 326cdf520..277a16ad0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -984,31 +984,36 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } - proxyType addrProxy; - bool fProxy = false; - if (mapArgs.count("-proxy")) { - addrProxy = proxyType(CService(mapArgs["-proxy"], 9050), GetBoolArg("-proxyrandomize", true)); + bool proxyRandomize = GetBoolArg("-proxyrandomize", true); + // -proxy sets a proxy for all outgoing network traffic + // -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default + std::string proxyArg = GetArg("-proxy", ""); + if (proxyArg != "" && proxyArg != "0") { + proxyType addrProxy = proxyType(CService(proxyArg, 9050), proxyRandomize); if (!addrProxy.IsValid()) - return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"])); + return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg)); SetProxy(NET_IPV4, addrProxy); SetProxy(NET_IPV6, addrProxy); + SetProxy(NET_TOR, addrProxy); SetNameProxy(addrProxy); - fProxy = true; + SetReachable(NET_TOR); // by default, -proxy sets onion as reachable, unless -noonion later } - // -onion can override normal proxy, -noonion disables connecting to .onion entirely - if (!(mapArgs.count("-onion") && mapArgs["-onion"] == "0") && - (fProxy || mapArgs.count("-onion"))) { - proxyType addrOnion; - if (!mapArgs.count("-onion")) - addrOnion = addrProxy; - else - addrOnion = proxyType(CService(mapArgs["-onion"], 9050), GetBoolArg("-proxyrandomize", true)); - if (!addrOnion.IsValid()) - return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"])); - SetProxy(NET_TOR, addrOnion); - SetReachable(NET_TOR); + // -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses + // -noonion (or -onion=0) disables connecting to .onion entirely + // An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none) + std::string onionArg = GetArg("-onion", ""); + if (onionArg != "") { + if (onionArg == "0") { // Handle -noonion/-onion=0 + SetReachable(NET_TOR, false); // set onions as unreachable + } else { + proxyType addrOnion = proxyType(CService(onionArg, 9050), proxyRandomize); + if (!addrOnion.IsValid()) + return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg)); + SetProxy(NET_TOR, addrOnion); + SetReachable(NET_TOR); + } } // see Step 2: parameter interactions for more information about these From 7d6a85ab5b1dc96e0f3f6f835f27bb81ba2af919 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Fri, 12 Jun 2015 14:07:43 -0700 Subject: [PATCH 0025/1283] Fix getbalance * Chance "getbalance *" not to use IsTrusted. The method and result now match the "getbalance " behavior. In particular, "getbalance * 0" now works. Also fixed a comment -- GetGalance has required 1 confirmation for many years, and the default "getbalance *" behavior matches that. --- src/wallet/rpcwallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d284fcf15..43fcc632f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -733,12 +733,12 @@ UniValue getbalance(const UniValue& params, bool fHelp) if (params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() // (GetBalance() sums up all unspent TxOuts) - // getbalance and getbalance '*' 0 should return the same number + // getbalance and "getbalance * 1 true" should return the same number CAmount nBalance = 0; for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0) + if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) continue; CAmount allFee; From b19a88b2a0e7bd9ef603055bc8e1ef058673025d Mon Sep 17 00:00:00 2001 From: Jacob Welsh Date: Fri, 12 Jun 2015 14:19:09 -0500 Subject: [PATCH 0026/1283] depends: fix Boost 1.55 build on GCC 5 Boost assumes variadic templates are always available in GCC 4.4+, but they aren't since we don't build with -std=c++11. This applies the patch that fixed the issue in boost 1.57: https://github.com/boostorg/config/commit/eec808554936ae068b23df07ab54d4dc6302a695 See also: https://svn.boost.org/trac/boost/ticket/10500 --- depends/packages/boost.mk | 3 +- depends/patches/boost/gcc_5_no_cxx11.patch | 37 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 depends/patches/boost/gcc_5_no_cxx11.patch diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index f50828c54..e7aa48ddf 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -3,7 +3,7 @@ $(package)_version=1_55_0 $(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.55.0 $(package)_file_name=$(package)_$($(package)_version).tar.bz2 $(package)_sha256_hash=fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 -$(package)_patches=darwin_boost_atomic-1.patch darwin_boost_atomic-2.patch +$(package)_patches=darwin_boost_atomic-1.patch darwin_boost_atomic-2.patch gcc_5_no_cxx11.patch define $(package)_set_vars $(package)_config_opts_release=variant=release @@ -28,6 +28,7 @@ endef define $(package)_preprocess_cmds patch -p2 < $($(package)_patch_dir)/darwin_boost_atomic-1.patch && \ patch -p2 < $($(package)_patch_dir)/darwin_boost_atomic-2.patch && \ + patch -p2 < $($(package)_patch_dir)/gcc_5_no_cxx11.patch && \ echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;" > user-config.jam endef diff --git a/depends/patches/boost/gcc_5_no_cxx11.patch b/depends/patches/boost/gcc_5_no_cxx11.patch new file mode 100644 index 000000000..04514c593 --- /dev/null +++ b/depends/patches/boost/gcc_5_no_cxx11.patch @@ -0,0 +1,37 @@ +From eec808554936ae068b23df07ab54d4dc6302a695 Mon Sep 17 00:00:00 2001 +From: jzmaddock +Date: Sat, 23 Aug 2014 09:38:02 +0100 +Subject: [PATCH] Fix BOOST_NO_CXX11_VARIADIC_TEMPLATES definition - the + feature was introduced in GCC 4.4. + +--- + include/boost/config/compiler/gcc.hpp | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/include/boost/config/compiler/gcc.hpp b/include/boost/config/compiler/gcc.hpp +index f37159d..97d8a18 100644 +--- a/include/boost/config/compiler/gcc.hpp ++++ b/include/boost/config/compiler/gcc.hpp +@@ -154,14 +154,6 @@ + # define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS + # define BOOST_NO_CXX11_RVALUE_REFERENCES + # define BOOST_NO_CXX11_STATIC_ASSERT +- +-// Variadic templates compiler: +-// http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html +-# if defined(__VARIADIC_TEMPLATES) || (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4) && defined(__GXX_EXPERIMENTAL_CXX0X__)) +-# define BOOST_HAS_VARIADIC_TMPL +-# else +-# define BOOST_NO_CXX11_VARIADIC_TEMPLATES +-# endif + #endif + + // C++0x features in 4.4.n and later +@@ -176,6 +168,7 @@ + # define BOOST_NO_CXX11_DELETED_FUNCTIONS + # define BOOST_NO_CXX11_TRAILING_RESULT_TYPES + # define BOOST_NO_CXX11_INLINE_NAMESPACES ++# define BOOST_NO_CXX11_VARIADIC_TEMPLATES + #endif + + #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) From e3cae525382520ddbef92bf86f43eaf0521f4325 Mon Sep 17 00:00:00 2001 From: Josh Lehan Date: Sun, 16 Nov 2014 03:19:23 -0800 Subject: [PATCH 0027/1283] Added -whiteconnections= option This sets aside a number of connection slots for whitelisted peers, useful for ensuring your local users and miners can always get in, even if your limit on inbound connections has already been reached. --- src/init.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++---------- src/net.cpp | 12 +++++++++++- src/net.h | 13 +++++++++++++ 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index b5f9a0310..9d140c8e2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -328,6 +328,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-whitebind=", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6")); strUsage += HelpMessageOpt("-whitelist=", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); + strUsage += HelpMessageOpt("-whiteconnections=", strprintf(_("Reserve this many inbound connections for whitelisted peers (default: %d)"), 0)); #ifdef ENABLE_WALLET strUsage += HelpMessageGroup(_("Wallet options:")); @@ -723,16 +724,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -rescan=1\n", __func__); } - // Make sure enough file descriptors are available - int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1); - nMaxConnections = GetArg("-maxconnections", 125); - nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0); - int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS); - if (nFD < MIN_CORE_FILEDESCRIPTORS) - return InitError(_("Not enough file descriptors available.")); - if (nFD - MIN_CORE_FILEDESCRIPTORS < nMaxConnections) - nMaxConnections = nFD - MIN_CORE_FILEDESCRIPTORS; - // if using block pruning, then disable txindex if (GetArg("-prune", 0)) { if (GetBoolArg("-txindex", false)) @@ -743,6 +734,47 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } #endif } + + // Make sure enough file descriptors are available + int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1); + int nUserMaxConnections = GetArg("-maxconnections", 125); + nMaxConnections = std::max(nUserMaxConnections, 0); + int nUserWhiteConnections = GetArg("-whiteconnections", 0); + nWhiteConnections = std::max(nUserWhiteConnections, 0); + + if ((mapArgs.count("-whitelist")) || (mapArgs.count("-whitebind"))) { + if (!(mapArgs.count("-maxconnections"))) { + // User is using whitelist feature, + // but did not specify -maxconnections parameter. + // Silently increase the default to compensate, + // so that the whitelist connection reservation feature + // does not inadvertently reduce the default + // inbound connection capacity of the network. + nMaxConnections += nWhiteConnections; + } + } else { + // User not using whitelist feature. + // Silently disable connection reservation, + // for the same reason as above. + nWhiteConnections = 0; + } + + // Trim requested connection counts, to fit into system limitations + nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0); + int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS); + if (nFD < MIN_CORE_FILEDESCRIPTORS) + return InitError(_("Not enough file descriptors available.")); + nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS, nMaxConnections); + + if (nMaxConnections < nUserMaxConnections) + InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections)); + + // Connection capacity is prioritized in this order: + // outbound connections (hardcoded to 8), + // then whitelisted connections, + // then non-whitelisted connections get whatever's left (if any). + if ((nWhiteConnections > 0) && (nWhiteConnections >= (nMaxConnections - 8))) + InitWarning(strprintf(_("All non-whitelisted incoming connections will be dropped, because -whiteconnections is %d and -maxconnections is only %d."), nWhiteConnections, nMaxConnections)); // ********************************************************* Step 3: parameter-to-internal-flags @@ -910,6 +942,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Using data directory %s\n", strDataDir); LogPrintf("Using config file %s\n", GetConfigFile().string()); LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); + if (nWhiteConnections > 0) + LogPrintf("Reserving %i of these connections for whitelisted inbound peers\n", nWhiteConnections); std::ostringstream strErrors; LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads); diff --git a/src/net.cpp b/src/net.cpp index 42ac0e50e..541318e74 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -79,6 +79,7 @@ uint64_t nLocalHostNonce = 0; static std::vector vhListenSocket; CAddrMan addrman; int nMaxConnections = 125; +int nWhiteConnections = 0; bool fAddressesInitialized = false; vector vNodes; @@ -827,6 +828,7 @@ void ThreadSocketHandler() SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len); CAddress addr; int nInbound = 0; + int nMaxInbound = nMaxConnections - MAX_OUTBOUND_CONNECTIONS; if (hSocket != INVALID_SOCKET) if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) @@ -846,8 +848,14 @@ void ThreadSocketHandler() if (nErr != WSAEWOULDBLOCK) LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr)); } - else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS) + else if (nInbound >= nMaxInbound) { + LogPrint("net", "connection from %s dropped (full)\n", addr.ToString()); + CloseSocket(hSocket); + } + else if (!whitelisted && (nInbound >= (nMaxInbound - nWhiteConnections))) + { + LogPrint("net", "connection from %s dropped (non-whitelisted)\n", addr.ToString()); CloseSocket(hSocket); } else if (CNode::IsBanned(addr) && !whitelisted) @@ -861,6 +869,8 @@ void ThreadSocketHandler() pnode->AddRef(); pnode->fWhitelisted = whitelisted; + LogPrint("net", "connection from %s accepted\n", addr.ToString()); + { LOCK(cs_vNodes); vNodes.push_back(pnode); diff --git a/src/net.h b/src/net.h index 938f2376f..bd360276a 100644 --- a/src/net.h +++ b/src/net.h @@ -140,7 +140,20 @@ extern bool fListen; extern uint64_t nLocalServices; extern uint64_t nLocalHostNonce; extern CAddrMan addrman; + +// The allocation of connections against the maximum allowed (nMaxConnections) +// is prioritized as follows: +// 1st: Outbound connections (MAX_OUTBOUND_CONNECTIONS) +// 2nd: Inbound connections from whitelisted peers (nWhiteConnections) +// 3rd: Inbound connections from non-whitelisted peers +// Thus, the number of connection slots for the general public to use is: +// nMaxConnections - (MAX_OUTBOUND_CONNECTIONS + nWhiteConnections) +// Any additional inbound connections beyond limits will be immediately closed + +/** Maximum number of connections to simultaneously allow (aka connection slots) */ extern int nMaxConnections; +/** Number of connection slots to reserve for inbound from whitelisted peers */ +extern int nWhiteConnections; extern std::vector vNodes; extern CCriticalSection cs_vNodes; From 06818f7145cac51529b07f9cade5e16dabc22d29 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 15 Jun 2015 08:40:15 +0200 Subject: [PATCH 0028/1283] doc: Add section on plurals to strings policy Thanks to @pryds for explaining this to me on Transifex. --- doc/translation_strings_policy.md | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/doc/translation_strings_policy.md b/doc/translation_strings_policy.md index 6824b1d8e..cf72a55b2 100644 --- a/doc/translation_strings_policy.md +++ b/doc/translation_strings_policy.md @@ -64,6 +64,44 @@ Avoid dividing up a message into fragments. Translators see every string separat There have been difficulties with use of HTML in translation strings; translators should not be able to accidentally affect the formatting of messages. This may sometimes be at conflict with the recommendation in the previous section. +### Plurals + +Plurals can be complex in some languages. A quote from the gettext documentation: + + In Polish we use e.g. plik (file) this way: + 1 plik, + 2,3,4 pliki, + 5-21 pliko'w, + 22-24 pliki, + 25-31 pliko'w + and so on + +In Qt code use tr's third argument for optional plurality. For example: + + tr("%n hour(s)","",secs/HOUR_IN_SECONDS); + tr("%n day(s)","",secs/DAY_IN_SECONDS); + tr("%n week(s)","",secs/WEEK_IN_SECONDS); + +This adds ``s to the respective `.ts` file, which can be translated separately depending on the language. In English, this is simply: + + + %n active connection(s) to Bitcoin network + + %n active connection to Bitcoin network + %n active connections to Bitcoin network + + + +Where it is possible try to avoid embedding numbers into the flow of the string at all. e.g. + + WARNING: check your network connection, %d blocks received in the last %d hours (%d expected) + +versus + + WARNING: check your network connection, less blocks (%d) were received in the last %n hours than expected (%d). + +The second example reduces the number of pluralized words that translators have to handle from three to one, at no cost to comprehensibility of the sentence. + ### String freezes During a string freeze (often before a major release), no translation strings are to be added, modified or removed. From 02a6702a82a5b00e0e0351041dd3267308b7f319 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 12 Jun 2015 12:00:39 +0200 Subject: [PATCH 0029/1283] Add option `-alerts` to opt out of alert system Make it possible to opt-out of the centralized alert system by providing an option `-noalerts` or `-alerts=0`. The default remains unchanged. This is a gentler form of #6260, in which I went a bit overboard by removing the alert system completely. I intend to add this to the GUI options in another pull after this. --- src/init.cpp | 3 +++ src/main.cpp | 3 ++- src/main.h | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 326cdf520..fc7a7fc7f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -266,6 +266,7 @@ std::string HelpMessage(HelpMessageMode mode) // Do not translate _(...) -help-debug options, Many technical terms, and only a very small audience, so is unnecessary stress to translators. string strUsage = HelpMessageGroup(_("Options:")); strUsage += HelpMessageOpt("-?", _("This help message")); + strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS)); strUsage += HelpMessageOpt("-alertnotify=", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)")); strUsage += HelpMessageOpt("-blocknotify=", _("Execute command when the best block changes (%s in cmd is replaced by block hash)")); strUsage += HelpMessageOpt("-checkblocks=", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288)); @@ -865,6 +866,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", true); nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes); + fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS); + // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log // Initialize elliptic curve code diff --git a/src/main.cpp b/src/main.cpp index 69c972a79..49263a13f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,6 +61,7 @@ bool fCheckBlockIndex = false; bool fCheckpointsEnabled = true; size_t nCoinCacheUsage = 5000 * 300; uint64_t nPruneTarget = 0; +bool fAlerts = DEFAULT_ALERTS; /** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */ CFeeRate minRelayTxFee = CFeeRate(1000); @@ -4622,7 +4623,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } - else if (strCommand == "alert") + else if (fAlerts && strCommand == "alert") { CAlert alert; vRecv >> alert; diff --git a/src/main.h b/src/main.h index 7eaf58d71..aceac2831 100644 --- a/src/main.h +++ b/src/main.h @@ -52,6 +52,8 @@ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000; +/** Default for accepting alerts from the P2P network. */ +static const bool DEFAULT_ALERTS = true; /** The maximum size for transactions we're willing to relay/mine */ static const unsigned int MAX_STANDARD_TX_SIZE = 100000; /** Maximum number of signature check operations in an IsStandard() P2SH script */ @@ -113,6 +115,7 @@ extern bool fCheckBlockIndex; extern bool fCheckpointsEnabled; extern size_t nCoinCacheUsage; extern CFeeRate minRelayTxFee; +extern bool fAlerts; /** Best header we've seen so far (used for getheaders queries' starting points). */ extern CBlockIndex *pindexBestHeader; From edbdf8855ded4142d78c0f9b5ef8c3233c61a5f0 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 15 Jun 2015 12:44:56 +0200 Subject: [PATCH 0030/1283] tests: Extend RPC proxy tests Also test -noonion --- qa/rpc-tests/proxy_test.py | 62 +++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index 9a9b2f530..3623c1616 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -68,10 +68,10 @@ class ProxyTest(BitcoinTestFramework): ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'], ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'], ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'], - ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0'] + ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] ]) - def node_test(self, node, proxies, auth): + def node_test(self, node, proxies, auth, test_onion=True): rv = [] # Test: outgoing IPv4 connection through node node.addnode("15.61.23.23:1234", "onetry") @@ -99,17 +99,18 @@ class ProxyTest(BitcoinTestFramework): assert_equal(cmd.password, None) rv.append(cmd) - # Test: outgoing onion connection through node - node.addnode("bitcoinostk4e4re.onion:8333", "onetry") - cmd = proxies[2].queue.get() - assert(isinstance(cmd, Socks5Command)) - assert_equal(cmd.atyp, AddressType.DOMAINNAME) - assert_equal(cmd.addr, "bitcoinostk4e4re.onion") - assert_equal(cmd.port, 8333) - if not auth: - assert_equal(cmd.username, None) - assert_equal(cmd.password, None) - rv.append(cmd) + if test_onion: + # Test: outgoing onion connection through node + node.addnode("bitcoinostk4e4re.onion:8333", "onetry") + cmd = proxies[2].queue.get() + assert(isinstance(cmd, Socks5Command)) + assert_equal(cmd.atyp, AddressType.DOMAINNAME) + assert_equal(cmd.addr, "bitcoinostk4e4re.onion") + assert_equal(cmd.port, 8333) + if not auth: + assert_equal(cmd.username, None) + assert_equal(cmd.password, None) + rv.append(cmd) # Test: outgoing DNS name connection through node node.addnode("node.noumenon:8333", "onetry") @@ -139,8 +140,41 @@ class ProxyTest(BitcoinTestFramework): assert_equal(len(credentials), 4) # proxy on IPv6 localhost - self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False) + self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False) + + def networks_dict(d): + r = {} + for x in d['networks']: + r[x['name']] = x + return r + + # test RPC getnetworkinfo + n0 = networks_dict(self.nodes[0].getnetworkinfo()) + for net in ['ipv4','ipv6','onion']: + assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr)) + assert_equal(n0[net]['proxy_randomize_credentials'], True) + assert_equal(n0['onion']['reachable'], True) + + n1 = networks_dict(self.nodes[1].getnetworkinfo()) + for net in ['ipv4','ipv6']: + assert_equal(n1[net]['proxy'], '%s:%i' % (self.conf1.addr)) + assert_equal(n1[net]['proxy_randomize_credentials'], False) + assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr)) + assert_equal(n1['onion']['proxy_randomize_credentials'], False) + assert_equal(n1['onion']['reachable'], True) + n2 = networks_dict(self.nodes[2].getnetworkinfo()) + for net in ['ipv4','ipv6','onion']: + assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr)) + assert_equal(n2[net]['proxy_randomize_credentials'], True) + assert_equal(n2['onion']['reachable'], True) + + n3 = networks_dict(self.nodes[3].getnetworkinfo()) + for net in ['ipv4','ipv6']: + assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr)) + assert_equal(n3[net]['proxy_randomize_credentials'], False) + assert_equal(n3['onion']['reachable'], False) + if __name__ == '__main__': ProxyTest().main() From 40c592aa2139cdab9ffe9ac837e106e79dd0ac1a Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 15 Jun 2015 14:43:31 +0200 Subject: [PATCH 0031/1283] make CAddrMan::size() return the correct type of size_t --- src/addrman.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addrman.h b/src/addrman.h index 373b0f39f..2623d8980 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -458,7 +458,7 @@ public: } //! Return the number of (unique) addresses in all tables. - int size() + size_t size() const { return vRandom.size(); } From 26a639e21fa94fbd3d7643608dd2a1d3307036d9 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 15 Jun 2015 14:45:19 +0200 Subject: [PATCH 0032/1283] remove using namespace std from addrman.cpp --- src/addrman.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/addrman.cpp b/src/addrman.cpp index c41ee3f9f..b605f4351 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -8,8 +8,6 @@ #include "serialize.h" #include "streams.h" -using namespace std; - int CAddrInfo::GetTriedBucket(const uint256& nKey) const { uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetHash().GetCheapHash(); @@ -68,7 +66,7 @@ double CAddrInfo::GetChance(int64_t nNow) const fChance *= 0.01; // deprioritize 66% after each failed attempt, but at most 1/28th to avoid the search taking forever or overly penalizing outages. - fChance *= pow(0.66, min(nAttempts, 8)); + fChance *= pow(0.66, std::min(nAttempts, 8)); return fChance; } @@ -258,7 +256,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60); int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60); if (addr.nTime && (!pinfo->nTime || pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty)) - pinfo->nTime = max((int64_t)0, addr.nTime - nTimePenalty); + pinfo->nTime = std::max((int64_t)0, addr.nTime - nTimePenalty); // add services pinfo->nServices |= addr.nServices; @@ -283,7 +281,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP return false; } else { pinfo = Create(addr, source, &nId); - pinfo->nTime = max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty); + pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty); nNew++; fNew = true; } From 72bf90d770ce5b2653fd482928646cd6a9f5f6d7 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 15 Jun 2015 15:46:02 -0400 Subject: [PATCH 0033/1283] Fix scheduler build with some boost versions. Some boost versions have a conflicting overload of wait_until that returns void. Explicitly use a template here to avoid hitting that overload. --- src/scheduler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scheduler.cpp b/src/scheduler.cpp index c42eb7244..d5bb588b7 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -50,8 +50,10 @@ void CScheduler::serviceQueue() // Keep waiting until timeout } #else + // Some boost versions have a conflicting overload of wait_until that returns void. + // Explicitly use a template here to avoid hitting that overload. while (!shouldStop() && !taskQueue.empty() && - newTaskScheduled.wait_until(lock, taskQueue.begin()->first) != boost::cv_status::timeout) { + newTaskScheduled.wait_until<>(lock, taskQueue.begin()->first) != boost::cv_status::timeout) { // Keep waiting until timeout } #endif From a3a80c253cdd0299f92b9e1ba9888f0f9421f245 Mon Sep 17 00:00:00 2001 From: rion Date: Mon, 15 Jun 2015 21:02:29 -0700 Subject: [PATCH 0034/1283] remove berkeley-db4 workaround "brew install berkeley-db4" appears to be working again. simplified instructions by removing the berkeley-db4 workaround. --- doc/build-osx.md | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/doc/build-osx.md b/doc/build-osx.md index 913e72519..dc319dd1c 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -32,33 +32,10 @@ Instructions: Homebrew #### Install dependencies using Homebrew - brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt5 + brew install autoconf automake berkeley-db4 libtool boost miniupnpc openssl pkg-config protobuf qt5 NOTE: Building with Qt4 is still supported, however, could result in a broken UI. As such, building with Qt5 is recommended. -#### Installing berkeley-db4 using Homebrew - -The homebrew package for berkeley-db4 has been broken for some time. It will install without Java though. - -Running this command takes you into brew's interactive mode, which allows you to configure, make, and install by hand: -``` -$ brew install https://raw.github.com/homebrew/homebrew/master/Library/Formula/berkeley-db4.rb -–without-java -``` - -The rest of these commands are run inside brew interactive mode: -``` -/private/tmp/berkeley-db4-UGpd0O/db-4.8.30 $ cd .. -/private/tmp/berkeley-db4-UGpd0O $ db-4.8.30/dist/configure --prefix=/usr/local/Cellar/berkeley-db4/4.8.30 --mandir=/usr/local/Cellar/berkeley-db4/4.8.30/share/man --enable-cxx -/private/tmp/berkeley-db4-UGpd0O $ make -/private/tmp/berkeley-db4-UGpd0O $ make install -/private/tmp/berkeley-db4-UGpd0O $ exit -``` - -After exiting, you'll get a warning that the install is keg-only, which means it wasn't symlinked to `/usr/local`. You don't need it to link it to build bitcoin, but if you want to, here's how: - - $ brew link --force berkeley-db4 - - ### Building `bitcoind` 1. Clone the github tree to get the source code and go into the directory. From cd27bba060d91995da706bc03cd2ef39b79b49b1 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 16 Jun 2015 03:46:36 -0400 Subject: [PATCH 0035/1283] locking: teach Clang's -Wthread-safety to cope with our scoped lock macros This allows us to use function/variable/class attributes to specify locking requisites, allowing problems to be detected during static analysis. This works perfectly with newer Clang versions (tested with 3.3-3.7). For older versions (tested 3.2), it compiles fine but spews lots of false-positives. --- src/sync.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sync.h b/src/sync.h index 78b904347..705647e4a 100644 --- a/src/sync.h +++ b/src/sync.h @@ -101,7 +101,7 @@ void PrintLockContention(const char* pszName, const char* pszFile, int nLine); /** Wrapper around boost::unique_lock */ template -class CMutexLock +class SCOPED_LOCKABLE CMutexLock { private: boost::unique_lock lock; @@ -129,7 +129,7 @@ private: } public: - CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock) + CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, boost::defer_lock) { if (fTry) TryEnter(pszName, pszFile, nLine); @@ -137,7 +137,7 @@ public: Enter(pszName, pszFile, nLine); } - CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) + CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn) { if (!pmutexIn) return; @@ -148,7 +148,7 @@ public: Enter(pszName, pszFile, nLine); } - ~CMutexLock() + ~CMutexLock() UNLOCK_FUNCTION() { if (lock.owns_lock()) LeaveCritical(); From 2b890dd424b32320be6fc0333e67e2d7c9616065 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 16 Jun 2015 04:02:25 -0400 Subject: [PATCH 0036/1283] locking: fix a few small issues uncovered by -Wthread-safety - rpcwallet: No need to lock twice here - openssl: Clang doesn't understand selective lock/unlock here. Ignore it. - CNode: Fix a legitimate (though very unlikely) locking bug. --- src/net.cpp | 4 +++- src/util.cpp | 2 +- src/wallet/rpcwallet.cpp | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 42ac0e50e..adf89554d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2032,8 +2032,10 @@ void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend) Fuzz(GetArg("-fuzzmessagestest", 10)); if (ssSend.size() == 0) + { + LEAVE_CRITICAL_SECTION(cs_vSend); return; - + } // Set the size unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE; WriteLE32((uint8_t*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], nSize); diff --git a/src/util.cpp b/src/util.cpp index da5821e53..1097878b2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -113,7 +113,7 @@ CTranslationInterface translationInterface; /** Init OpenSSL library multithreading support */ static CCriticalSection** ppmutexOpenSSL; -void locking_callback(int mode, int i, const char* file, int line) +void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS { if (mode & CRYPTO_LOCK) { ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5404dd4aa..b32f1f6b0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -476,7 +476,6 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp) addressInfo.push_back(CBitcoinAddress(address).ToString()); addressInfo.push_back(ValueFromAmount(balances[address])); { - LOCK(pwalletMain->cs_wallet); if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end()) addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name); } From a794284e61988a226ea39327449be9906a1b5abd Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 16 Jun 2015 04:08:26 -0400 Subject: [PATCH 0037/1283] locking: add a quick example of GUARDED_BY This was chosen not because it's necessarily helpful, but because its locking assumptions were already correct. --- src/main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0be54ebd4..f198edffe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -72,9 +72,9 @@ struct COrphanTx { CTransaction tx; NodeId fromPeer; }; -map mapOrphanTransactions; -map > mapOrphanTransactionsByPrev; -void EraseOrphansFor(NodeId peer); +map mapOrphanTransactions GUARDED_BY(cs_main);; +map > mapOrphanTransactionsByPrev GUARDED_BY(cs_main);; +void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** * Returns true if there are nRequired or more blocks of minVersion or above @@ -523,7 +523,7 @@ CBlockTreeDB *pblocktree = NULL; // mapOrphanTransactions // -bool AddOrphanTx(const CTransaction& tx, NodeId peer) +bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { uint256 hash = tx.GetHash(); if (mapOrphanTransactions.count(hash)) @@ -553,7 +553,7 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) return true; } -void static EraseOrphanTx(uint256 hash) +void static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { map::iterator it = mapOrphanTransactions.find(hash); if (it == mapOrphanTransactions.end()) @@ -587,7 +587,7 @@ void EraseOrphansFor(NodeId peer) } -unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) +unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { unsigned int nEvicted = 0; while (mapOrphanTransactions.size() > nMaxOrphans) @@ -3783,7 +3783,7 @@ std::string GetWarnings(const std::string& strFor) // -bool static AlreadyHave(const CInv& inv) +bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { switch (inv.type) { From 57092ed9e7edb3c60adc75823dd922ad67ddec62 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Oct 2014 09:25:08 +0200 Subject: [PATCH 0038/1283] rpc: make `gettxoutsettinfo` run lock-free For leveldb "An iterator operates on a snapshot of the database taken when the iterator is created". This means that it is unnecessary to lock out other threads while computing statistics, and neither to hold cs_main for the whole time. Let the thread run free. --- src/rpcblockchain.cpp | 2 -- src/txdb.cpp | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index e45368cb9..85229e985 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -345,8 +345,6 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) + HelpExampleRpc("gettxoutsetinfo", "") ); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); CCoinsStats stats; diff --git a/src/txdb.cpp b/src/txdb.cpp index df9ff8d8c..935b78467 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -147,7 +147,10 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { return error("%s: Deserialize or I/O error - %s", __func__, e.what()); } } - stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight; + { + LOCK(cs_main); + stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; + } stats.hashSerialized = ss.GetHash(); stats.nTotalAmount = nTotalAmount; return true; From 60dbe730164552128d9b79b5120b4b5e9d456bbb Mon Sep 17 00:00:00 2001 From: Alex van der Peet Date: Thu, 11 Jun 2015 20:20:54 -0700 Subject: [PATCH 0039/1283] New RPC command disconnectnode --- src/rpcnet.cpp | 22 ++++++++++++++++++++++ src/rpcprotocol.h | 1 + src/rpcserver.cpp | 1 + src/rpcserver.h | 1 + 4 files changed, 25 insertions(+) diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index c4e038eeb..aeaf54814 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -214,6 +214,28 @@ UniValue addnode(const UniValue& params, bool fHelp) return NullUniValue; } +UniValue disconnectnode(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "disconnectnode \"node\" \n" + "\nImmediately disconnects from the specified node.\n" + "\nArguments:\n" + "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n" + "\nExamples:\n" + + HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"") + + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"") + ); + + CNode* pNode = FindNode(params[0].get_str()); + if (pNode == NULL) + throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes"); + + pNode->CloseSocketDisconnect(); + + return NullUniValue; +} + UniValue getaddednodeinfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index b9fa09195..ecd7c1f7d 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -63,6 +63,7 @@ enum RPCErrorCode RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //! Still downloading initial blocks RPC_CLIENT_NODE_ALREADY_ADDED = -23, //! Node is already added RPC_CLIENT_NODE_NOT_ADDED = -24, //! Node has not been added before + RPC_CLIENT_NODE_NOT_CONNECTED = -29, //! Node to disconnect not found in connected nodes //! Wallet errors RPC_WALLET_ERROR = -4, //! Unspecified problem with wallet (key not found etc.) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 3894dd08b..c27bba519 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -273,6 +273,7 @@ static const CRPCCommand vRPCCommands[] = /* P2P networking */ { "network", "getnetworkinfo", &getnetworkinfo, true }, { "network", "addnode", &addnode, true }, + { "network", "disconnectnode", &disconnectnode, true }, { "network", "getaddednodeinfo", &getaddednodeinfo, true }, { "network", "getconnectioncount", &getconnectioncount, true }, { "network", "getnettotals", &getnettotals, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 7b462a8b7..fdd871d0b 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -151,6 +151,7 @@ extern UniValue getconnectioncount(const UniValue& params, bool fHelp); // in rp extern UniValue getpeerinfo(const UniValue& params, bool fHelp); extern UniValue ping(const UniValue& params, bool fHelp); extern UniValue addnode(const UniValue& params, bool fHelp); +extern UniValue disconnectnode(const UniValue& params, bool fHelp); extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp); extern UniValue getnettotals(const UniValue& params, bool fHelp); From 0ce30eaa36295447c6e7f8d16a05798c746fe28a Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 15 Jun 2015 07:46:51 +0200 Subject: [PATCH 0040/1283] fix crash on shutdown when e.g. changing -txindex and abort action - fixes #3136 - the problem is related to Boost path and a static initialized internal pointer - using a std::string in CDBEnv::EnvShutdown() prevents the problem - this removes the boost::filesystem::path path field from CDBEnv --- src/wallet/db.cpp | 12 ++++++------ src/wallet/db.h | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 53cfcf096..e5bc653c3 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -43,7 +43,7 @@ void CDBEnv::EnvShutdown() if (ret != 0) LogPrintf("CDBEnv::EnvShutdown: Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret)); if (!fMockDb) - DbEnv(0).remove(path.string().c_str(), 0); + DbEnv(0).remove(strPath.c_str(), 0); } void CDBEnv::Reset() @@ -78,10 +78,10 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) boost::this_thread::interruption_point(); - path = pathIn; - boost::filesystem::path pathLogDir = path / "database"; + strPath = pathIn.string(); + boost::filesystem::path pathLogDir = pathIn / "database"; TryCreateDirectory(pathLogDir); - boost::filesystem::path pathErrorFile = path / "db.log"; + boost::filesystem::path pathErrorFile = pathIn / "db.log"; LogPrintf("CDBEnv::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string()); unsigned int nEnvFlags = 0; @@ -98,7 +98,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) dbenv->set_flags(DB_AUTO_COMMIT, 1); dbenv->set_flags(DB_TXN_WRITE_NOSYNC, 1); dbenv->log_set_config(DB_LOG_AUTO_REMOVE, 1); - int ret = dbenv->open(path.string().c_str(), + int ret = dbenv->open(strPath.c_str(), DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | @@ -455,7 +455,7 @@ void CDBEnv::Flush(bool fShutdown) dbenv->log_archive(&listp, DB_ARCH_REMOVE); Close(); if (!fMockDb) - boost::filesystem::remove_all(path / "database"); + boost::filesystem::remove_all(boost::filesystem::path(strPath) / "database"); } } } diff --git a/src/wallet/db.h b/src/wallet/db.h index 2df6f6e5a..64071caa3 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -27,7 +27,9 @@ class CDBEnv private: bool fDbEnvInit; bool fMockDb; - boost::filesystem::path path; + // Don't change into boost::filesystem::path, as that can result in + // shutdown problems/crashes caused by a static initialized internal pointer. + std::string strPath; void EnvShutdown(); From 0da6ae2dc312ad180dd5118a41810d2ee95f01d4 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 12 May 2015 20:56:50 -0400 Subject: [PATCH 0041/1283] Do not inv old or missing blocks when pruning When responding to a getblocks message, only return inv's as long as we HAVE_DATA for blocks in the chain, and only for blocks that we aren't likely to delete in the near future. --- src/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 4f4926eb4..49bcce5ce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4153,6 +4153,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrint("net", " getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); break; } + // If pruning, don't inv blocks unless we have on disk and are likely to still have + // for some reasonable time window (1 hour) that block relay might require. + const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / chainparams.GetConsensus().nPowTargetSpacing; + if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= chainActive.Tip()->nHeight - nPrunedBlocksLikelyToHave)) + { + LogPrint("net", " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); + break; + } pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash())); if (--nLimit <= 0) { From ae6f957a628efeeae47b8a2deee595c2ac5e7640 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Fri, 15 May 2015 17:07:11 -0400 Subject: [PATCH 0042/1283] Enable block relay when pruning --- src/main.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 49bcce5ce..0791e3ed0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2281,9 +2281,7 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { int nBlockEstimate = 0; if (fCheckpointsEnabled) nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints()); - // Don't relay blocks if pruning -- could cause a peer to try to download, resulting - // in a stalled download if the block file is pruned before the request. - if (nLocalServices & NODE_NETWORK) { + { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) From 2252fb91cd19832c8baa63a10aaf7ce32bb400f8 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 May 2015 10:07:23 +0200 Subject: [PATCH 0043/1283] [net] extend core functionallity for ban/unban/listban --- src/net.cpp | 27 +++++++++++++++++++++------ src/net.h | 5 ++++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 42ac0e50e..51d1c5333 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -458,16 +458,31 @@ bool CNode::IsBanned(CNetAddr ip) return fResult; } -bool CNode::Ban(const CNetAddr &addr) { +bool CNode::Ban(const CNetAddr &addr, int64_t bantimeoffset) { int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban - { - LOCK(cs_setBanned); - if (setBanned[addr] < banTime) - setBanned[addr] = banTime; - } + if (bantimeoffset > 0) + banTime = GetTime()+bantimeoffset; + + LOCK(cs_setBanned); + if (setBanned[addr] < banTime) + setBanned[addr] = banTime; + return true; } +bool CNode::Unban(const CNetAddr &addr) { + LOCK(cs_setBanned); + if (setBanned.erase(addr)) + return true; + return false; +} + +void CNode::GetBanned(std::map &banMap) +{ + LOCK(cs_setBanned); + banMap = setBanned; //create a thread safe copy +} + std::vector CNode::vWhitelistedRange; CCriticalSection CNode::cs_vWhitelistedRange; diff --git a/src/net.h b/src/net.h index 938f2376f..dd6fca396 100644 --- a/src/net.h +++ b/src/net.h @@ -606,7 +606,10 @@ public: // new code. static void ClearBanned(); // needed for unit testing static bool IsBanned(CNetAddr ip); - static bool Ban(const CNetAddr &ip); + static bool Ban(const CNetAddr &ip, int64_t bantimeoffset = 0); + static bool Unban(const CNetAddr &ip); + static void GetBanned(std::map &banmap); + void copyStats(CNodeStats &stats); static bool IsWhitelistedRange(const CNetAddr &ip); From d930b26a264ed7eae6ce239f3bfb4ff023df8195 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 May 2015 10:07:46 +0200 Subject: [PATCH 0044/1283] [RPC] add setban/listbanned/clearbanned RPC commands --- src/rpcclient.cpp | 1 + src/rpcnet.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++ src/rpcserver.cpp | 3 ++ src/rpcserver.h | 3 ++ 4 files changed, 96 insertions(+) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index f254da5de..1cc516e7b 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -93,6 +93,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "estimatepriority", 0 }, { "prioritisetransaction", 1 }, { "prioritisetransaction", 2 }, + { "setban", 2 }, }; class CRPCConvertTable diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index aeaf54814..6157a2d0a 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -465,3 +465,92 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) obj.push_back(Pair("warnings", GetWarnings("statusbar"))); return obj; } + +Value setban(const Array& params, bool fHelp) +{ + string strCommand; + if (params.size() >= 2) + strCommand = params[1].get_str(); + if (fHelp || params.size() < 2 || + (strCommand != "add" && strCommand != "remove")) + throw runtime_error( + "setban \"node\" \"add|remove\" (bantime)\n" + "\nAttempts add or remove a IP from the banned list.\n" + "\nArguments:\n" + "1. \"ip\" (string, required) The IP (see getpeerinfo for nodes ip)\n" + "2. \"command\" (string, required) 'add' to add a IP to the list, 'remove' to remove a IP from the list\n" + "1. \"bantime\" (numeric, optional) time in seconds how long the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" + "\nExamples:\n" + + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400") + ); + + CNetAddr netAddr(params[0].get_str()); + if (!netAddr.IsValid()) + throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP Address"); + + if (strCommand == "add") + { + if (CNode::IsBanned(netAddr)) + throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP already banned"); + + int64_t banTime = 0; //use standard bantime if not specified + if (params.size() == 3 && !params[2].is_null()) + banTime = params[2].get_int64(); + + CNode::Ban(netAddr, banTime); + + //disconnect possible nodes + while(CNode *bannedNode = FindNode(netAddr)) + bannedNode->CloseSocketDisconnect(); + } + else if(strCommand == "remove") + { + if (!CNode::Unban(netAddr)) + throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Unban failed"); + } + + return Value::null; +} + +Value listbanned(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "listbanned\n" + "\nList all banned IPs.\n" + "\nExamples:\n" + + HelpExampleCli("listbanned", "") + + HelpExampleRpc("listbanned", "") + ); + + std::map banMap; + CNode::GetBanned(banMap); + + Array bannedAddresses; + for (std::map::iterator it = banMap.begin(); it != banMap.end(); it++) + { + Object rec; + rec.push_back(Pair("address", (*it).first.ToString())); + rec.push_back(Pair("bannedtill", (*it).second)); + bannedAddresses.push_back(rec); + } + + return bannedAddresses; +} + +Value clearbanned(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "clearbanned\n" + "\nClear all banned IPs.\n" + "\nExamples:\n" + + HelpExampleCli("clearbanned", "") + + HelpExampleRpc("clearbanned", "") + ); + + CNode::ClearBanned(); + + return Value::null; +} diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index c27bba519..6d089c673 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -279,6 +279,9 @@ static const CRPCCommand vRPCCommands[] = { "network", "getnettotals", &getnettotals, true }, { "network", "getpeerinfo", &getpeerinfo, true }, { "network", "ping", &ping, true }, + { "network", "setban", &setban, true }, + { "network", "listbanned", &listbanned, true }, + { "network", "clearbanned", &clearbanned, true }, /* Block chain and UTXO */ { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index fdd871d0b..2b3a59a7b 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -154,6 +154,9 @@ extern UniValue addnode(const UniValue& params, bool fHelp); extern UniValue disconnectnode(const UniValue& params, bool fHelp); extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp); extern UniValue getnettotals(const UniValue& params, bool fHelp); +extern UniValue setban(const json_spirit::Array& params, bool fHelp); +extern UniValue listbanned(const json_spirit::Array& params, bool fHelp); +extern UniValue clearbanned(const json_spirit::Array& params, bool fHelp); extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp extern UniValue importprivkey(const UniValue& params, bool fHelp); From 1086ffba2639098558422935eba1cae9983dd913 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 May 2015 10:20:31 +0200 Subject: [PATCH 0045/1283] [QA] add setban/listbanned/clearbanned tests --- qa/rpc-tests/httpbasics.py | 43 ++++++++++++++++++++++++-------------- src/test/rpc_tests.cpp | 9 ++++++++ 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index 64ba49df6..f35fe27dd 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -20,83 +20,94 @@ try: except ImportError: import urlparse -class HTTPBasicsTest (BitcoinTestFramework): +class HTTPBasicsTest (BitcoinTestFramework): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, extra_args=[['-rpckeepalive=1'], ['-rpckeepalive=0'], [], []]) - def run_test(self): - + def run_test(self): + ################################################# # lowlevel check for http persistent connection # ################################################# url = urlparse.urlparse(self.nodes[0].url) authpair = url.username + ':' + url.password headers = {"Authorization": "Basic " + base64.b64encode(authpair)} - + conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read(); assert_equal('"error":null' in out1, True) assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! - + #send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) out2 = conn.getresponse().read(); assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! conn.close() - + #same should be if we add keep-alive because this should be the std. behaviour headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection": "keep-alive"} - + conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read(); assert_equal('"error":null' in out1, True) assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! - + #send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) out2 = conn.getresponse().read(); assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! conn.close() - + #now do the same with "Connection: close" headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection":"close"} - + conn = httplib.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read(); assert_equal('"error":null' in out1, True) - assert_equal(conn.sock!=None, False) #now the connection must be closed after the response - + assert_equal(conn.sock!=None, False) #now the connection must be closed after the response + #node1 (2nd node) is running with disabled keep-alive option urlNode1 = urlparse.urlparse(self.nodes[1].url) authpair = urlNode1.username + ':' + urlNode1.password headers = {"Authorization": "Basic " + base64.b64encode(authpair)} - + conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read(); assert_equal('"error":null' in out1, True) assert_equal(conn.sock!=None, False) #connection must be closed because keep-alive was set to false - + #node2 (third node) is running with standard keep-alive parameters which means keep-alive is off urlNode2 = urlparse.urlparse(self.nodes[2].url) authpair = urlNode2.username + ':' + urlNode2.password headers = {"Authorization": "Basic " + base64.b64encode(authpair)} - + conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read(); assert_equal('"error":null' in out1, True) assert_equal(conn.sock!=None, True) #connection must be closed because bitcoind should use keep-alive by default - + + ########################### + # setban/listbanned tests # + ########################### + assert_equal(len(self.nodes[2].getpeerinfo()), 4); #we should have 4 nodes at this point + self.nodes[2].setban("127.0.0.1", "add") + time.sleep(3) #wait till the nodes are disconected + assert_equal(len(self.nodes[2].getpeerinfo()), 0); #all nodes must be disconnected at this point + assert_equal(len(self.nodes[2].listbanned()), 1); + self.nodes[2].clearbanned() + assert_equal(len(self.nodes[2].listbanned()), 0); + if __name__ == '__main__': HTTPBasicsTest ().main () diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 08f988fdb..3cec4b76d 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -177,4 +177,13 @@ BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr) BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::ffff:127.0.0.1")).ToString(), "127.0.0.1"); } +BOOST_AUTO_TEST_CASE(rpc_ban) +{ + BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.1 add"))); + BOOST_CHECK_THROW(CallRPC(string("setban 127.0.0.1:8334")), runtime_error); //portnumber for setban not allowed + BOOST_CHECK_NO_THROW(CallRPC(string("listbanned"))); + BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.1 remove"))); + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); +} + BOOST_AUTO_TEST_SUITE_END() From e8b93473f12ec901f965cd244a7437646ee66c43 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 19 May 2015 17:15:25 +0200 Subject: [PATCH 0046/1283] [net] remove unused return type bool from CNode::Ban() --- src/net.cpp | 4 +--- src/net.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 51d1c5333..a065bb29b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -458,7 +458,7 @@ bool CNode::IsBanned(CNetAddr ip) return fResult; } -bool CNode::Ban(const CNetAddr &addr, int64_t bantimeoffset) { +void CNode::Ban(const CNetAddr &addr, int64_t bantimeoffset) { int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban if (bantimeoffset > 0) banTime = GetTime()+bantimeoffset; @@ -466,8 +466,6 @@ bool CNode::Ban(const CNetAddr &addr, int64_t bantimeoffset) { LOCK(cs_setBanned); if (setBanned[addr] < banTime) setBanned[addr] = banTime; - - return true; } bool CNode::Unban(const CNetAddr &addr) { diff --git a/src/net.h b/src/net.h index dd6fca396..ee3da16aa 100644 --- a/src/net.h +++ b/src/net.h @@ -606,7 +606,7 @@ public: // new code. static void ClearBanned(); // needed for unit testing static bool IsBanned(CNetAddr ip); - static bool Ban(const CNetAddr &ip, int64_t bantimeoffset = 0); + static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0); static bool Unban(const CNetAddr &ip); static void GetBanned(std::map &banmap); From 433fb1a95d7a96a033d7454e198d274e92108865 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 25 May 2015 20:03:51 +0200 Subject: [PATCH 0047/1283] [RPC] extend setban to allow subnets --- qa/rpc-tests/httpbasics.py | 25 +++++++++++++++---- src/net.cpp | 50 ++++++++++++++++++++++++++++++++------ src/net.h | 8 ++++-- src/netbase.cpp | 5 ++++ src/netbase.h | 1 + src/rpcnet.cpp | 44 +++++++++++++++++++++------------ src/test/rpc_tests.cpp | 40 +++++++++++++++++++++++++++--- 7 files changed, 139 insertions(+), 34 deletions(-) diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index f35fe27dd..6d6ef9df7 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -101,13 +101,28 @@ class HTTPBasicsTest (BitcoinTestFramework): ########################### # setban/listbanned tests # ########################### - assert_equal(len(self.nodes[2].getpeerinfo()), 4); #we should have 4 nodes at this point + assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point self.nodes[2].setban("127.0.0.1", "add") time.sleep(3) #wait till the nodes are disconected - assert_equal(len(self.nodes[2].getpeerinfo()), 0); #all nodes must be disconnected at this point - assert_equal(len(self.nodes[2].listbanned()), 1); + assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point + assert_equal(len(self.nodes[2].listbanned()), 1) self.nodes[2].clearbanned() - assert_equal(len(self.nodes[2].listbanned()), 0); - + assert_equal(len(self.nodes[2].listbanned()), 0) + self.nodes[2].setban("127.0.0.0/24", "add") + assert_equal(len(self.nodes[2].listbanned()), 1) + try: + self.nodes[2].setban("127.0.0.1", "add") #throws exception because 127.0.0.1 is within range 127.0.0.0/24 + except: + pass + assert_equal(len(self.nodes[2].listbanned()), 1) #still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24 + try: + self.nodes[2].setban("127.0.0.1", "remove") + except: + pass + assert_equal(len(self.nodes[2].listbanned()), 1) + self.nodes[2].setban("127.0.0.0/24", "remove") + assert_equal(len(self.nodes[2].listbanned()), 0) + self.nodes[2].clearbanned() + assert_equal(len(self.nodes[2].listbanned()), 0) if __name__ == '__main__': HTTPBasicsTest ().main () diff --git a/src/net.cpp b/src/net.cpp index a065bb29b..3ba2379ea 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -332,6 +332,15 @@ CNode* FindNode(const CNetAddr& ip) return NULL; } +CNode* FindNode(const CSubNet& subNet) +{ + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if (subNet.Match((CNetAddr)pnode->addr)) + return (pnode); + return NULL; +} + CNode* FindNode(const std::string& addrName) { LOCK(cs_vNodes); @@ -434,7 +443,7 @@ void CNode::PushVersion() -std::map CNode::setBanned; +std::map CNode::setBanned; CCriticalSection CNode::cs_setBanned; void CNode::ClearBanned() @@ -447,7 +456,24 @@ bool CNode::IsBanned(CNetAddr ip) bool fResult = false; { LOCK(cs_setBanned); - std::map::iterator i = setBanned.find(ip); + for (std::map::iterator it = setBanned.begin(); it != setBanned.end(); it++) + { + CSubNet subNet = (*it).first; + int64_t t = (*it).second; + + if(subNet.Match(ip) && GetTime() < t) + fResult = true; + } + } + return fResult; +} + +bool CNode::IsBanned(CSubNet subnet) +{ + bool fResult = false; + { + LOCK(cs_setBanned); + std::map::iterator i = setBanned.find(subnet); if (i != setBanned.end()) { int64_t t = (*i).second; @@ -458,24 +484,34 @@ bool CNode::IsBanned(CNetAddr ip) return fResult; } -void CNode::Ban(const CNetAddr &addr, int64_t bantimeoffset) { +void CNode::Ban(const CNetAddr& addr, int64_t bantimeoffset) { + CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128")); + Ban(subNet, bantimeoffset); +} + +void CNode::Ban(const CSubNet& subNet, int64_t bantimeoffset) { int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban if (bantimeoffset > 0) banTime = GetTime()+bantimeoffset; LOCK(cs_setBanned); - if (setBanned[addr] < banTime) - setBanned[addr] = banTime; + if (setBanned[subNet] < banTime) + setBanned[subNet] = banTime; } bool CNode::Unban(const CNetAddr &addr) { + CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128")); + return Unban(subNet); +} + +bool CNode::Unban(const CSubNet &subNet) { LOCK(cs_setBanned); - if (setBanned.erase(addr)) + if (setBanned.erase(subNet)) return true; return false; } -void CNode::GetBanned(std::map &banMap) +void CNode::GetBanned(std::map &banMap) { LOCK(cs_setBanned); banMap = setBanned; //create a thread safe copy diff --git a/src/net.h b/src/net.h index ee3da16aa..d800aa22c 100644 --- a/src/net.h +++ b/src/net.h @@ -66,6 +66,7 @@ unsigned int SendBufferSize(); void AddOneShot(const std::string& strDest); void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); +CNode* FindNode(const CSubNet& subNet); CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL); @@ -284,7 +285,7 @@ protected: // Denial-of-service detection/prevention // Key is IP address, value is banned-until-time - static std::map setBanned; + static std::map setBanned; static CCriticalSection cs_setBanned; // Whitelisted ranges. Any node connecting from these is automatically @@ -606,9 +607,12 @@ public: // new code. static void ClearBanned(); // needed for unit testing static bool IsBanned(CNetAddr ip); + static bool IsBanned(CSubNet subnet); static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0); + static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0); static bool Unban(const CNetAddr &ip); - static void GetBanned(std::map &banmap); + static bool Unban(const CSubNet &ip); + static void GetBanned(std::map &banmap); void copyStats(CNodeStats &stats); diff --git a/src/netbase.cpp b/src/netbase.cpp index e3cb4e706..b7c77fda6 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1330,6 +1330,11 @@ bool operator!=(const CSubNet& a, const CSubNet& b) return !(a==b); } +bool operator<(const CSubNet& a, const CSubNet& b) +{ + return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16))); +} + #ifdef WIN32 std::string NetworkErrorString(int err) { diff --git a/src/netbase.h b/src/netbase.h index 1f2957116..27f0eac2a 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -125,6 +125,7 @@ class CSubNet friend bool operator==(const CSubNet& a, const CSubNet& b); friend bool operator!=(const CSubNet& a, const CSubNet& b); + friend bool operator<(const CSubNet& a, const CSubNet& b); }; /** A combination of a network address (CNetAddr) and a (TCP) port */ diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 6157a2d0a..e6c33e1d0 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -474,39 +474,51 @@ Value setban(const Array& params, bool fHelp) if (fHelp || params.size() < 2 || (strCommand != "add" && strCommand != "remove")) throw runtime_error( - "setban \"node\" \"add|remove\" (bantime)\n" - "\nAttempts add or remove a IP from the banned list.\n" + "setban \"ip(/netmask)\" \"add|remove\" (bantime)\n" + "\nAttempts add or remove a IP/Subnet from the banned list.\n" "\nArguments:\n" - "1. \"ip\" (string, required) The IP (see getpeerinfo for nodes ip)\n" - "2. \"command\" (string, required) 'add' to add a IP to the list, 'remove' to remove a IP from the list\n" - "1. \"bantime\" (numeric, optional) time in seconds how long the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" + "1. \"ip(/netmask)\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n" + "2. \"command\" (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n" + "1. \"bantime\" (numeric, optional) time in seconds how long the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" "\nExamples:\n" + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400") ); - CNetAddr netAddr(params[0].get_str()); - if (!netAddr.IsValid()) - throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP Address"); + CSubNet subNet; + CNetAddr netAddr; + bool isSubnet = false; + + if (params[0].get_str().find("/") != string::npos) + isSubnet = true; + + if (!isSubnet) + netAddr = CNetAddr(params[0].get_str()); + else + subNet = CSubNet(params[0].get_str()); + + if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) + throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet"); if (strCommand == "add") { - if (CNode::IsBanned(netAddr)) - throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP already banned"); + if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr)) + throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); int64_t banTime = 0; //use standard bantime if not specified if (params.size() == 3 && !params[2].is_null()) banTime = params[2].get_int64(); - CNode::Ban(netAddr, banTime); + isSubnet ? CNode::Ban(subNet, banTime) : CNode::Ban(netAddr, banTime); //disconnect possible nodes - while(CNode *bannedNode = FindNode(netAddr)) + while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr))) bannedNode->CloseSocketDisconnect(); } else if(strCommand == "remove") { - if (!CNode::Unban(netAddr)) + if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) )) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Unban failed"); } @@ -518,17 +530,17 @@ Value listbanned(const Array& params, bool fHelp) if (fHelp || params.size() != 0) throw runtime_error( "listbanned\n" - "\nList all banned IPs.\n" + "\nList all banned IPs/Subnets.\n" "\nExamples:\n" + HelpExampleCli("listbanned", "") + HelpExampleRpc("listbanned", "") ); - std::map banMap; + std::map banMap; CNode::GetBanned(banMap); Array bannedAddresses; - for (std::map::iterator it = banMap.begin(); it != banMap.end(); it++) + for (std::map::iterator it = banMap.begin(); it != banMap.end(); it++) { Object rec; rec.push_back(Pair("address", (*it).first.ToString())); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 3cec4b76d..26588a43e 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -179,11 +179,43 @@ BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr) BOOST_AUTO_TEST_CASE(rpc_ban) { - BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.1 add"))); - BOOST_CHECK_THROW(CallRPC(string("setban 127.0.0.1:8334")), runtime_error); //portnumber for setban not allowed - BOOST_CHECK_NO_THROW(CallRPC(string("listbanned"))); - BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.1 remove"))); BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + + Value r; + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0 add"))); + BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.0:8334")), runtime_error); //portnumber for setban not allowed + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + Array ar = r.get_array(); + Object o1 = ar[0].get_obj(); + Value adr = find_value(o1, "address"); + BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.255"); + BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0 remove")));; + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + BOOST_CHECK_EQUAL(ar.size(), 0); + + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + o1 = ar[0].get_obj(); + adr = find_value(o1, "address"); + BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0"); + + // must throw an exception because 127.0.0.1 is in already banned suubnet range + BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.1 add")), runtime_error); + + BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0/24 remove")));; + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + BOOST_CHECK_EQUAL(ar.size(), 0); + + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/255.255.0.0 add"))); + BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.1.1 add")), runtime_error); + + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + BOOST_CHECK_EQUAL(ar.size(), 0); } BOOST_AUTO_TEST_SUITE_END() From 3de24d7647db2b9167cee25549c3c603582e19e6 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 12 Jun 2015 17:42:32 +0200 Subject: [PATCH 0048/1283] rename json field "bannedtill" to "banned_until" --- src/rpcnet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index e6c33e1d0..35ef92ecf 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -544,7 +544,7 @@ Value listbanned(const Array& params, bool fHelp) { Object rec; rec.push_back(Pair("address", (*it).first.ToString())); - rec.push_back(Pair("bannedtill", (*it).second)); + rec.push_back(Pair("banned_untill", (*it).second)); bannedAddresses.push_back(rec); } From 4e36e9bcc7d071bba4c45fd89c0cfd2e2361ffe3 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 12 Jun 2015 18:31:47 +0200 Subject: [PATCH 0049/1283] setban: rewrite to UniValue, allow absolute bantime --- src/net.cpp | 8 ++++---- src/net.h | 4 ++-- src/rpcclient.cpp | 1 + src/rpcnet.cpp | 27 ++++++++++++++++----------- src/rpcserver.h | 6 +++--- src/test/rpc_tests.cpp | 25 ++++++++++++++++++++----- 6 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 3ba2379ea..6b8a0a2b1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -484,15 +484,15 @@ bool CNode::IsBanned(CSubNet subnet) return fResult; } -void CNode::Ban(const CNetAddr& addr, int64_t bantimeoffset) { +void CNode::Ban(const CNetAddr& addr, int64_t bantimeoffset, bool sinceUnixEpoch) { CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128")); - Ban(subNet, bantimeoffset); + Ban(subNet, bantimeoffset, sinceUnixEpoch); } -void CNode::Ban(const CSubNet& subNet, int64_t bantimeoffset) { +void CNode::Ban(const CSubNet& subNet, int64_t bantimeoffset, bool sinceUnixEpoch) { int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban if (bantimeoffset > 0) - banTime = GetTime()+bantimeoffset; + banTime = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset; LOCK(cs_setBanned); if (setBanned[subNet] < banTime) diff --git a/src/net.h b/src/net.h index d800aa22c..69e4c592a 100644 --- a/src/net.h +++ b/src/net.h @@ -608,8 +608,8 @@ public: static void ClearBanned(); // needed for unit testing static bool IsBanned(CNetAddr ip); static bool IsBanned(CSubNet subnet); - static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0); - static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0); + static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); + static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); static bool Unban(const CNetAddr &ip); static bool Unban(const CSubNet &ip); static void GetBanned(std::map &banmap); diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 1cc516e7b..1d94e4f61 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -94,6 +94,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "prioritisetransaction", 1 }, { "prioritisetransaction", 2 }, { "setban", 2 }, + { "setban", 3 }, }; class CRPCConvertTable diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 35ef92ecf..97d5ccbff 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -466,7 +466,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp) return obj; } -Value setban(const Array& params, bool fHelp) +UniValue setban(const UniValue& params, bool fHelp) { string strCommand; if (params.size() >= 2) @@ -474,12 +474,13 @@ Value setban(const Array& params, bool fHelp) if (fHelp || params.size() < 2 || (strCommand != "add" && strCommand != "remove")) throw runtime_error( - "setban \"ip(/netmask)\" \"add|remove\" (bantime)\n" + "setban \"ip(/netmask)\" \"add|remove\" (bantime) (absolute)\n" "\nAttempts add or remove a IP/Subnet from the banned list.\n" "\nArguments:\n" "1. \"ip(/netmask)\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n" "2. \"command\" (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n" - "1. \"bantime\" (numeric, optional) time in seconds how long the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" + "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" + "4. \"absolute\" (boolean, optional) If set, the bantime must be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n" "\nExamples:\n" + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") @@ -507,10 +508,14 @@ Value setban(const Array& params, bool fHelp) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); int64_t banTime = 0; //use standard bantime if not specified - if (params.size() == 3 && !params[2].is_null()) + if (params.size() >= 3 && !params[2].isNull()) banTime = params[2].get_int64(); - isSubnet ? CNode::Ban(subNet, banTime) : CNode::Ban(netAddr, banTime); + bool absolute = false; + if (params.size() == 4 && params[3].isTrue()) + absolute = true; + + isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute); //disconnect possible nodes while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr))) @@ -522,10 +527,10 @@ Value setban(const Array& params, bool fHelp) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Unban failed"); } - return Value::null; + return NullUniValue; } -Value listbanned(const Array& params, bool fHelp) +UniValue listbanned(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -539,10 +544,10 @@ Value listbanned(const Array& params, bool fHelp) std::map banMap; CNode::GetBanned(banMap); - Array bannedAddresses; + UniValue bannedAddresses(UniValue::VARR); for (std::map::iterator it = banMap.begin(); it != banMap.end(); it++) { - Object rec; + UniValue rec(UniValue::VOBJ); rec.push_back(Pair("address", (*it).first.ToString())); rec.push_back(Pair("banned_untill", (*it).second)); bannedAddresses.push_back(rec); @@ -551,7 +556,7 @@ Value listbanned(const Array& params, bool fHelp) return bannedAddresses; } -Value clearbanned(const Array& params, bool fHelp) +UniValue clearbanned(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -564,5 +569,5 @@ Value clearbanned(const Array& params, bool fHelp) CNode::ClearBanned(); - return Value::null; + return NullUniValue; } diff --git a/src/rpcserver.h b/src/rpcserver.h index 2b3a59a7b..d08ae72f5 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -154,9 +154,9 @@ extern UniValue addnode(const UniValue& params, bool fHelp); extern UniValue disconnectnode(const UniValue& params, bool fHelp); extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp); extern UniValue getnettotals(const UniValue& params, bool fHelp); -extern UniValue setban(const json_spirit::Array& params, bool fHelp); -extern UniValue listbanned(const json_spirit::Array& params, bool fHelp); -extern UniValue clearbanned(const json_spirit::Array& params, bool fHelp); +extern UniValue setban(const UniValue& params, bool fHelp); +extern UniValue listbanned(const UniValue& params, bool fHelp); +extern UniValue clearbanned(const UniValue& params, bool fHelp); extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp extern UniValue importprivkey(const UniValue& params, bool fHelp); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 26588a43e..e60281949 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -181,25 +181,40 @@ BOOST_AUTO_TEST_CASE(rpc_ban) { BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); - Value r; + UniValue r; BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0 add"))); BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.0:8334")), runtime_error); //portnumber for setban not allowed BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); - Array ar = r.get_array(); - Object o1 = ar[0].get_obj(); - Value adr = find_value(o1, "address"); + UniValue ar = r.get_array(); + UniValue o1 = ar[0].get_obj(); + UniValue adr = find_value(o1, "address"); BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.255"); BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0 remove")));; BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); ar = r.get_array(); BOOST_CHECK_EQUAL(ar.size(), 0); - BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add 1607731200 true"))); BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); ar = r.get_array(); o1 = ar[0].get_obj(); adr = find_value(o1, "address"); + UniValue banned_until = find_value(o1, "banned_untill"); BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0"); + BOOST_CHECK_EQUAL(banned_until.get_int64(), 1607731200); // absolute time check + + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add 200"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + o1 = ar[0].get_obj(); + adr = find_value(o1, "address"); + banned_until = find_value(o1, "banned_untill"); + BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0"); + int64_t now = GetTime(); + BOOST_CHECK(banned_until.get_int64() > now); + BOOST_CHECK(banned_until.get_int64()-now <= 200); // must throw an exception because 127.0.0.1 is in already banned suubnet range BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.1 add")), runtime_error); From d624167387a658c9b2c25ad13492262ccd2592bf Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 12 Jun 2015 19:51:50 +0200 Subject: [PATCH 0050/1283] fix CSubNet comparison operator --- src/netbase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index b7c77fda6..adac5c2d0 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1332,7 +1332,7 @@ bool operator!=(const CSubNet& a, const CSubNet& b) bool operator<(const CSubNet& a, const CSubNet& b) { - return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16))); + return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0)); } #ifdef WIN32 From 1f02b802538ff16313c27f1539860ee06b907c7c Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 12 Jun 2015 22:27:03 +0200 Subject: [PATCH 0051/1283] setban: add RPCErrorCode --- src/rpcnet.cpp | 2 +- src/rpcprotocol.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 97d5ccbff..5a26c7c3a 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -524,7 +524,7 @@ UniValue setban(const UniValue& params, bool fHelp) else if(strCommand == "remove") { if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) )) - throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Unban failed"); + throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed"); } return NullUniValue; diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index ecd7c1f7d..ccd2439c9 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -64,6 +64,7 @@ enum RPCErrorCode RPC_CLIENT_NODE_ALREADY_ADDED = -23, //! Node is already added RPC_CLIENT_NODE_NOT_ADDED = -24, //! Node has not been added before RPC_CLIENT_NODE_NOT_CONNECTED = -29, //! Node to disconnect not found in connected nodes + RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //! Invalid IP/Subnet //! Wallet errors RPC_WALLET_ERROR = -4, //! Unspecified problem with wallet (key not found etc.) From 9d79afe9a925c4aaed5d922ee432e9b3aa4d877a Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 16 Jun 2015 18:21:03 +0200 Subject: [PATCH 0052/1283] add RPC tests for setban & disconnectnode --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/httpbasics.py | 28 +-------------- qa/rpc-tests/nodehandling.py | 69 ++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 27 deletions(-) create mode 100755 qa/rpc-tests/nodehandling.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 9b318650e..426d81fa9 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -32,6 +32,7 @@ testScripts=( 'merkle_blocks.py' 'signrawtransactions.py' 'walletbackup.py' + 'nodehandling.py' ); testScriptsExt=( 'bipdersig-p2p.py' diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index 6d6ef9df7..8ccb82128 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -4,7 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # -# Test REST interface +# Test rpc http basics # from test_framework.test_framework import BitcoinTestFramework @@ -98,31 +98,5 @@ class HTTPBasicsTest (BitcoinTestFramework): assert_equal('"error":null' in out1, True) assert_equal(conn.sock!=None, True) #connection must be closed because bitcoind should use keep-alive by default - ########################### - # setban/listbanned tests # - ########################### - assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point - self.nodes[2].setban("127.0.0.1", "add") - time.sleep(3) #wait till the nodes are disconected - assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point - assert_equal(len(self.nodes[2].listbanned()), 1) - self.nodes[2].clearbanned() - assert_equal(len(self.nodes[2].listbanned()), 0) - self.nodes[2].setban("127.0.0.0/24", "add") - assert_equal(len(self.nodes[2].listbanned()), 1) - try: - self.nodes[2].setban("127.0.0.1", "add") #throws exception because 127.0.0.1 is within range 127.0.0.0/24 - except: - pass - assert_equal(len(self.nodes[2].listbanned()), 1) #still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24 - try: - self.nodes[2].setban("127.0.0.1", "remove") - except: - pass - assert_equal(len(self.nodes[2].listbanned()), 1) - self.nodes[2].setban("127.0.0.0/24", "remove") - assert_equal(len(self.nodes[2].listbanned()), 0) - self.nodes[2].clearbanned() - assert_equal(len(self.nodes[2].listbanned()), 0) if __name__ == '__main__': HTTPBasicsTest ().main () diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py new file mode 100755 index 000000000..9a77bd97e --- /dev/null +++ b/qa/rpc-tests/nodehandling.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test node handling +# + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import base64 + +try: + import http.client as httplib +except ImportError: + import httplib +try: + import urllib.parse as urlparse +except ImportError: + import urlparse + +class NodeHandlingTest (BitcoinTestFramework): + def run_test(self): + ########################### + # setban/listbanned tests # + ########################### + assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point + self.nodes[2].setban("127.0.0.1", "add") + time.sleep(3) #wait till the nodes are disconected + assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point + assert_equal(len(self.nodes[2].listbanned()), 1) + self.nodes[2].clearbanned() + assert_equal(len(self.nodes[2].listbanned()), 0) + self.nodes[2].setban("127.0.0.0/24", "add") + assert_equal(len(self.nodes[2].listbanned()), 1) + try: + self.nodes[2].setban("127.0.0.1", "add") #throws exception because 127.0.0.1 is within range 127.0.0.0/24 + except: + pass + assert_equal(len(self.nodes[2].listbanned()), 1) #still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24 + try: + self.nodes[2].setban("127.0.0.1", "remove") + except: + pass + assert_equal(len(self.nodes[2].listbanned()), 1) + self.nodes[2].setban("127.0.0.0/24", "remove") + assert_equal(len(self.nodes[2].listbanned()), 0) + self.nodes[2].clearbanned() + assert_equal(len(self.nodes[2].listbanned()), 0) + + ########################### + # RPC disconnectnode test # + ########################### + url = urlparse.urlparse(self.nodes[1].url) + self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1))) + time.sleep(2) #disconnecting a node needs a little bit of time + for node in self.nodes[0].getpeerinfo(): + assert(node['addr'] != url.hostname+":"+str(p2p_port(1))) + + connect_nodes_bi(self.nodes,0,1) #reconnect the node + found = False + for node in self.nodes[0].getpeerinfo(): + if node['addr'] == url.hostname+":"+str(p2p_port(1)): + found = True + assert(found) + +if __name__ == '__main__': + NodeHandlingTest ().main () From 82e6487af865ca65ffbee397fa3f388bfe77f423 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 18 Jun 2015 17:56:37 +0200 Subject: [PATCH 0053/1283] Adding pgp public key for cdecker as requested by @jonasschnelli in bitcoin/gitian.sigs#182 --- contrib/gitian-downloader/cdecker-key.pgp | Bin 0 -> 2230 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 contrib/gitian-downloader/cdecker-key.pgp diff --git a/contrib/gitian-downloader/cdecker-key.pgp b/contrib/gitian-downloader/cdecker-key.pgp new file mode 100644 index 0000000000000000000000000000000000000000..928a74b3155da22877d1b6ad32fa2a7cb745e0ba GIT binary patch literal 2230 zcmV;n2ub&u0u2OJad_te5CGcA$X6^vk`c1?pseb{~J$|@`l@Q|q<3T7-%PAwUe)Euk)_aMR#FWm(B5Be2!Oo=Wtu8P)xljzO$51+Qo)2q#JnRF4BS?3VBc^*b_IYas86K#@ehX`$WR{ZCpIaoi!bud%C9}kQ%82Y5A2tsDp`iC> zb@4$}Mqb#V(MlkvG<(~$31`-;bK!cs%a&56Ma!zU4rhB{4hZ-HXiNQs8)oM_lgMe> z6}`-BQRcv}n+3+b&|0AyLE={&o&V?YP(;2l0XuyF?eTNAN57Thv3738aa08D7mg`@ z5%Q7f54g;ycZ7Ejk?l)uJVm1?)XGVQwHqWn*h)av&&UWMyM(WpXJXJY;2KYh`jS zV`y?|b98B8Za`;kVQFkGV{dIfi2^tT69EDMA_W3fad_tf8v_Ol2?z%R0tOWb0tpHW z1Qr4V0RkQY0vCV)3JDPQLkCn64#M;c7Z3kx-Pw581T7xW@g#1KQEnw3E_{|`?3|VH zCUs0L`8XFlAbKALe*D14Qr4dZZ&t-R9GIdGBM8tk%epxx!vI2wGth+Q z=#p{WPr^cWf&;utQo)%Gok=z3f(mm0a|hkVF9ne4>5PQ1u5?NZ zHa4SJx7Q}F2`1oIvGZ9mUMjwmp@d5%?6S7SJ{=BoEfo|?-Wz!tVsWo-V;PTqGfnyZ zaOWp;La>x%(R3)4lz5ElXABaWNr^359~0-X1N;Irs(VW_EE=psd(3HIFvUWaBGwV_G7szr@U9|!ESX3NzsLKUI(keDDhlJHE=31U zC#VfBXqT7iV)=e2{1X`U@oF>X;VmdTefGB}M}Qu2xC*VKfh9{j=E-IpoU~^j^P5S+ z@-|e^y}Va`V#)*?9fMqV`n4EwBq_URg+Jk*gk9B(Tz=7nP*e`fIjVnay17-W9KeMs_E(tzi^)hMPj!I>-O3I9zg+ z#y68noBJdmL^Rz0SND^JeBD5vI^uMN&znN>?OIU0ZA*>*Vt^9ut}A6#u%l+2WQZ~ z+0xLtzJxu82{QH-AO+u{?~H4e%69Mc=zDJT%Lifcy!Kr{P3;f|YrPFDI4mH3gI>@k zu+mEOLpcm_hgIbqB`Uju^XZI&z#r?Qtakm-{`;U)zGZ!;&l#&~fU;=6xf^iSoc6!G zaNHq?Jq9+DA&$RX7h%?f5f0r7(c9eVdjBXybX*-D0duR|i|?M@nh6BsUxBcM{w)L_ zGX|8JniDyiUg7MixWAb6Xe?TcaUyNS${SEoNGHJAkvbI(?UrTNoGRffujC^}E~ymrhPt;SlGJn+;&7*pf2t+Wm^cz= Euvy_F$p8QV literal 0 HcmV?d00001 From d08cfc2bd752fdb1e8547f957f1c38275540df7a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 18 Jun 2015 18:17:36 -0400 Subject: [PATCH 0054/1283] gitian: add a gitian-win-signer descriptor This is exactly like the current OSX signing process. osslsigncode has been patched to detach and re-attach Windows signatures. The changes can be seen here: https://github.com/theuni/osslsigncode/commits/attach-signature There's a pull-request open upstream for the changes: https://sourceforge.net/p/osslsigncode/osslsigncode/merge-requests/3/ This work has been back-ported to the stable 1.7.1 release of osslsigncode, so that a smaller patch can be reviewed. --- .../gitian-descriptors/gitian-win-signer.yml | 34 +++++++++++++++++++ doc/release-process.md | 32 ++++++++++------- 2 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 contrib/gitian-descriptors/gitian-win-signer.yml diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml new file mode 100644 index 000000000..0bf2ac9b2 --- /dev/null +++ b/contrib/gitian-descriptors/gitian-win-signer.yml @@ -0,0 +1,34 @@ +--- +name: "bitcoin-win-signer" +suites: +- "precise" +architectures: +- "amd64" +packages: +- "libssl-dev" +- "autoconf" +reference_datetime: "2015-06-01 00:00:00" +remotes: +- "url": "https://github.com/bitcoin/bitcoin-detached-sigs.git" + "dir": "signature" +files: +- "osslsigncode-1.7.1.tar.gz" +- "osslsigncode-Backports-to-1.7.1.patch" +- "bitcoin-win32-setup.exe" +- "bitcoin-win64-setup.exe" +script: | + BUILD_DIR=`pwd` + SIGDIR=${BUILD_DIR}/signature/win + + echo "f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 osslsigncode-1.7.1.tar.gz" | sha256sum -c + echo "a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 osslsigncode-Backports-to-1.7.1.patch" | sha256sum -c + + tar xf osslsigncode-1.7.1.tar.gz + cd osslsigncode-1.7.1 + patch -p1 < ${BUILD_DIR}/osslsigncode-Backports-to-1.7.1.patch + + ./configure --without-gsf --without-curl --disable-dependency-tracking + make + + ./osslsigncode attach-signature -in ${BUILD_DIR}/bitcoin-win32-setup.exe -out ${OUTDIR}/bitcoin-win32-setup-signed.exe -sigin ${SIGDIR}/bitcoin-win32-setup.exe.pem + ./osslsigncode attach-signature -in ${BUILD_DIR}/bitcoin-win64-setup.exe -out ${OUTDIR}/bitcoin-win64-setup-signed.exe -sigin ${SIGDIR}/bitcoin-win64-setup.exe.pem diff --git a/doc/release-process.md b/doc/release-process.md index 45c44640c..07005bfbb 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -41,6 +41,8 @@ Release Process ###fetch and build inputs: (first time, or when dependency versions change) mkdir -p inputs + wget -P inputs https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch + wget -P inputs http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz Register and download the Apple SDK: (see OSX Readme for details) @@ -65,7 +67,9 @@ Release Process mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../ ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-win --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml - mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../ + mv build/out/bitcoin-*.zip ../ + mv build/out/bitcoin-*-win64-setup.exe inputs/bitcoin-win64-setup.exe + mv build/out/bitcoin-*-win32-setup.exe inputs/bitcoin-win32-setup.exe ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml mv build/out/bitcoin-*-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz @@ -75,7 +79,7 @@ Release Process 1. source tarball (bitcoin-${VERSION}.tar.gz) 2. linux 32-bit and 64-bit binaries dist tarballs (bitcoin-${VERSION}-linux[32|64].tar.gz) - 3. windows 32-bit and 64-bit installers and dist zips (bitcoin-${VERSION}-win[32|64]-setup.exe, bitcoin-${VERSION}-win[32|64].zip) + 3. windows 32-bit and 64-bit unsigned installers and dist zips (bitcoin-${VERSION}-win[32|64]-setup.exe, bitcoin-${VERSION}-win[32|64].zip) 4. OSX unsigned installer (bitcoin-${VERSION}-osx-unsigned.dmg) 5. Gitian signatures (in gitian.sigs/${VERSION}-/(your gitian key)/ @@ -91,9 +95,9 @@ Commit your signature to gitian.sigs: git push # Assuming you can push to the gitian.sigs tree popd - Wait for OSX detached signature: - Once the OSX build has 3 matching signatures, it will be signed with the Apple App-Store key. - A detached signature will then be committed to the bitcoin-detached-sigs repository, which can be combined with the unsigned app to create a signed binary. + Wait for Windows/OSX detached signatures: + Once the Windows/OSX builds each have 3 matching signatures, they will be signed with their respective release keys. + Detached signatures will then be committed to the bitcoin-detached-sigs repository, which can be combined with the unsigned apps to create signed binaries. Create the signed OSX binary: @@ -103,10 +107,20 @@ Commit your signature to gitian.sigs: mv build/out/bitcoin-osx-signed.dmg ../bitcoin-${VERSION}-osx.dmg popd -Commit your signature for the signed OSX binary: + Create the signed Windows binaries: + + pushd ./gitian-builder + ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml + mv build/out/bitcoin-win64-setup-signed.exe ../bitcoin-${VERSION}-win64-setup.exe + mv build/out/bitcoin-win32-setup-signed.exe ../bitcoin-${VERSION}-win32-setup.exe + popd + +Commit your signature for the signed OSX/Windows binaries: pushd gitian.sigs git add ${VERSION}-osx-signed/${SIGNER} + git add ${VERSION}-win-signed/${SIGNER} git commit -a git push # Assuming you can push to the gitian.sigs tree popd @@ -115,12 +129,6 @@ Commit your signature for the signed OSX binary: ### After 3 or more people have gitian-built and their results match: -- Perform code-signing. - - - Code-sign Windows -setup.exe (in a Windows virtual machine using signtool) - - Note: only Gavin has the code-signing keys currently. - - Create `SHA256SUMS.asc` for the builds, and GPG-sign it: ```bash sha256sum * > SHA256SUMS From a4d9f95653d7196a4eea9e3b1452d4c617b5bd2e Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 18 Jun 2015 23:24:37 -0400 Subject: [PATCH 0055/1283] build: comparison tool swap This should be functionally identical to what's in place now. It was built from https://github.com/theuni/bitcoinj/commit/be0eef774462409df277b2a83d71c30451f107c5 That commit is the same as this pruned commit in TheBlueMatt's repo: https://github.com/TheBlueMatt/bitcoinj/commit/0f7b5d8 Now we'll be able to trust the line numbers in the stack traces. --- depends/packages/native_comparisontool.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/packages/native_comparisontool.mk b/depends/packages/native_comparisontool.mk index d1b86dc2d..2a8a19b0a 100644 --- a/depends/packages/native_comparisontool.mk +++ b/depends/packages/native_comparisontool.mk @@ -1,8 +1,8 @@ package=native_comparisontool -$(package)_version=0f7b5d8 -$(package)_download_path=https://github.com/TheBlueMatt/test-scripts/raw/38b490a2599d422b12d5ce8f165792f63fd8f54f +$(package)_version=be0eef7 +$(package)_download_path=https://github.com/theuni/bitcoind-comparisontool/raw/master $(package)_file_name=pull-tests-$($(package)_version).jar -$(package)_sha256_hash=ecd43b988a8b673b483e4f69f931596360a5e90fc415c75c4c259faa690df198 +$(package)_sha256_hash=46c2efa25e717751e1ef380d428761b1e37b43d6d1e92ac761b15ee92703e560 $(package)_install_dirname=BitcoindComparisonTool_jar $(package)_install_filename=BitcoindComparisonTool.jar From 62909f68a087e85475b7fbad6d9a3a8873d0c811 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 19 Jun 2015 13:31:33 +0200 Subject: [PATCH 0056/1283] fix missing lock in CNode::ClearBanned() --- src/net.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net.cpp b/src/net.cpp index 6b8a0a2b1..0511256e5 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -448,6 +448,7 @@ CCriticalSection CNode::cs_setBanned; void CNode::ClearBanned() { + LOCK(cs_setBanned); setBanned.clear(); } From 932687bc105904e27ee120be95d2c9f1660ecdfa Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 19 Jun 2015 13:51:42 +0200 Subject: [PATCH 0057/1283] setban: add IPv6 tests --- src/test/rpc_tests.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index e60281949..c38df0ecf 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -231,6 +231,33 @@ BOOST_AUTO_TEST_CASE(rpc_ban) BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); ar = r.get_array(); BOOST_CHECK_EQUAL(ar.size(), 0); + + + BOOST_CHECK_THROW(r = CallRPC(string("setban test add")), runtime_error); //invalid IP + + //IPv6 tests + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban FE80:0000:0000:0000:0202:B3FF:FE1E:8329 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + o1 = ar[0].get_obj(); + adr = find_value(o1, "address"); + BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:db8::/30 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + o1 = ar[0].get_obj(); + adr = find_value(o1, "address"); + BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/ffff:fffc:0:0:0:0:0:0"); + + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + o1 = ar[0].get_obj(); + adr = find_value(o1, "address"); + BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); } BOOST_AUTO_TEST_SUITE_END() From 1c043d567230d639fa86afb96575689bfc8abdcd Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 19 Jun 2015 16:32:22 +0200 Subject: [PATCH 0058/1283] fix lock issue for QT node diconnect and RPC disconnectnode --- src/qt/rpcconsole.cpp | 2 +- src/rpcnet.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 681617bd8..f828ce253 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -687,7 +687,7 @@ void RPCConsole::disconnectSelectedNode() QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address); // Find the node, disconnect it and clear the selected node if (CNode *bannedNode = FindNode(strNode.toStdString())) { - bannedNode->CloseSocketDisconnect(); + bannedNode->fDisconnect = true; clearSelectedNode(); } } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 5a26c7c3a..1572b1668 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -231,7 +231,7 @@ UniValue disconnectnode(const UniValue& params, bool fHelp) if (pNode == NULL) throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes"); - pNode->CloseSocketDisconnect(); + pNode->fDisconnect = true; return NullUniValue; } @@ -519,7 +519,7 @@ UniValue setban(const UniValue& params, bool fHelp) //disconnect possible nodes while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr))) - bannedNode->CloseSocketDisconnect(); + bannedNode->fDisconnect = true; } else if(strCommand == "remove") { From 36c97b4e5dbf233734bd1882f8b6822a3bdcee97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Wed, 17 Jun 2015 21:23:53 +0200 Subject: [PATCH 0059/1283] Bugfix: Don't check the genesis block header before accepting it This fixes an error triggered when running with -reindex after #5975 --- src/main.cpp | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0be54ebd4..a4cbe43d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2809,36 +2809,37 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc uint256 hash = block.GetHash(); BlockMap::iterator miSelf = mapBlockIndex.find(hash); CBlockIndex *pindex = NULL; - if (miSelf != mapBlockIndex.end()) { - // Block header is already known. - pindex = miSelf->second; - if (ppindex) - *ppindex = pindex; - if (pindex->nStatus & BLOCK_FAILED_MASK) - return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate"); - return true; - } - - if (!CheckBlockHeader(block, state)) - return false; - - // Get prev block index - CBlockIndex* pindexPrev = NULL; if (hash != chainparams.GetConsensus().hashGenesisBlock) { + + if (miSelf != mapBlockIndex.end()) { + // Block header is already known. + pindex = miSelf->second; + if (ppindex) + *ppindex = pindex; + if (pindex->nStatus & BLOCK_FAILED_MASK) + return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate"); + return true; + } + + if (!CheckBlockHeader(block, state)) + return false; + + // Get prev block index + CBlockIndex* pindexPrev = NULL; BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); if (mi == mapBlockIndex.end()) return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk"); pindexPrev = (*mi).second; if (pindexPrev->nStatus & BLOCK_FAILED_MASK) return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); + + assert(pindexPrev); + if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, hash)) + return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, state.GetRejectReason().c_str()); + + if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + return false; } - assert(pindexPrev); - if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, hash)) - return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, state.GetRejectReason().c_str()); - - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) - return false; - if (pindex == NULL) pindex = AddToBlockIndex(block); From 4f40716dcb61f492f93a781751bfa25f712cba8b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 17 Jun 2015 18:06:39 +0200 Subject: [PATCH 0060/1283] test: Move reindex test to standard tests This test finishes very quickly, so it should be part of the default set of tests in rpc-tests. --- qa/pull-tester/rpc-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 426d81fa9..0f394094c 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -33,6 +33,7 @@ testScripts=( 'signrawtransactions.py' 'walletbackup.py' 'nodehandling.py' + 'reindex.py' ); testScriptsExt=( 'bipdersig-p2p.py' @@ -44,7 +45,6 @@ testScriptsExt=( 'invalidateblock.py' 'keypool.py' 'receivedby.py' - 'reindex.py' 'rpcbind_test.py' # 'script_test.py' 'smartfees.py' From b6668209aadb7357404057985e1779d8faec52ed Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 21 Jun 2015 08:22:31 +0200 Subject: [PATCH 0061/1283] build: Remove -DBOOST_SPIRIT_THREADSAFE Now that boost spirit is no longer used, `-DBOOST_SPIRIT_THREADSAFE` doesn't need to be passed to the compiler anymore. --- configure.ac | 2 +- src/rpcprotocol.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 61b6a314a..8a54c2f76 100644 --- a/configure.ac +++ b/configure.ac @@ -162,7 +162,7 @@ fi if test "x$CXXFLAGS_overridden" = "xno"; then CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter" fi -CPPFLAGS="$CPPFLAGS -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" +CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" AC_ARG_WITH([utils], [AS_HELP_STRING([--with-utils], diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 090e5ea7f..89dec2977 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -251,7 +251,6 @@ int ReadHTTPMessage(std::basic_istream& stream, map Date: Sun, 21 Jun 2015 12:08:48 -0400 Subject: [PATCH 0062/1283] build: comparison tool NPE fix This should fix the spurious comparison tool failures. See discussion here: https://github.com/bitcoin/bitcoin/pull/6305 The race fix was cherry-picked on top of the version we're currently using, so it should be functionally identical otherwise. --- depends/packages/native_comparisontool.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/native_comparisontool.mk b/depends/packages/native_comparisontool.mk index 2a8a19b0a..e0ae0cec7 100644 --- a/depends/packages/native_comparisontool.mk +++ b/depends/packages/native_comparisontool.mk @@ -1,8 +1,8 @@ package=native_comparisontool -$(package)_version=be0eef7 +$(package)_version=8c6666f $(package)_download_path=https://github.com/theuni/bitcoind-comparisontool/raw/master $(package)_file_name=pull-tests-$($(package)_version).jar -$(package)_sha256_hash=46c2efa25e717751e1ef380d428761b1e37b43d6d1e92ac761b15ee92703e560 +$(package)_sha256_hash=a865332b3827abcde684ab79f5f43c083b0b6a4c97ff5508c79f29fee24f11cd $(package)_install_dirname=BitcoindComparisonTool_jar $(package)_install_filename=BitcoindComparisonTool.jar From db6047d61b742be07442f891e70570b791c585e3 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 1 Jun 2015 21:03:51 +0200 Subject: [PATCH 0063/1283] Take the training wheels off anti-fee-sniping Now that the off-by-one error w/nLockTime txs issue has been fixed by 87550eef (75a4d512 in the 0.11 branch) we can make the anti-fee-sniping protection create transactions with nLockTime set such that they're only valid in the next block, rather than an earlier block. There was also a concern about poor propagation, however testing with transactions with nLockTime = GetAdjustedTime()+1 as a proxy for nLockTime propagation, as well as a few transactions sent the moment blocks were received, has turned up no detectable issues with propagation. If you have a block at a given height you certainly have at least one peer with that block who will accept the transaction. That peer will certainly have other peers who will accept it, and soon essentially the whole network has the transaction. In particular, if a node recives a transaction that it rejects due to the tx being non-final, it will be accepted again later as it winds its way around the network. --- src/wallet/wallet.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3f12d88e7..50d20485d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1715,15 +1715,25 @@ bool CWallet::CreateTransaction(const vector& vecSend, // Discourage fee sniping. // - // However because of a off-by-one-error in previous versions we need to - // neuter it by setting nLockTime to at least one less than nBestHeight. - // Secondly currently propagation of transactions created for block heights - // corresponding to blocks that were just mined may be iffy - transactions - // aren't re-accepted into the mempool - we additionally neuter the code by - // going ten blocks back. Doesn't yet do anything for sniping, but does act - // to shake out wallet bugs like not showing nLockTime'd transactions at - // all. - txNew.nLockTime = std::max(0, chainActive.Height() - 10); + // For a large miner the value of the transactions in the best block and + // the mempool can exceed the cost of delibrately attempting to mine two + // blocks to orphan the current best block. By setting nLockTime such that + // only the next block can include the transaction, we discourage this + // practice as the height restricted and limited blocksize gives miners + // considering fee sniping fewer options for pulling off this attack. + // + // A simple way to think about this is from the wallet's point of view we + // always want the blockchain to move forward. By setting nLockTime this + // way we're basically making the statement that we only want this + // transaction to appear in the next block; we don't want to potentially + // encourage reorgs by allowing transactions to appear at lower heights + // than the next block in forks of the best chain. + // + // Of course, the subsidy is high enough, and transaction volume low + // enough, that fee sniping isn't a problem yet, but by implementing a fix + // now we ensure code won't be written that makes assumptions about + // nLockTime that preclude a fix later. + txNew.nLockTime = chainActive.Height(); // Secondly occasionally randomly pick a nLockTime even further back, so // that transactions that are delayed after signing for whatever reason, From bc60b2b4b401f0adff5b8b9678903ff8feb5867b Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 29 Sep 2014 03:44:25 -0400 Subject: [PATCH 0064/1283] Replace NOP2 with CHECKLOCKTIMEVERIFY (BIP65) CHECKLOCKTIMEVERIFY -> Fails if tx.nLockTime < nLockTime, allowing the funds in a txout to be locked until some block height or block time in the future is reached. Only the logic and unittests are implemented; this commit does not have any actual soft-fork logic in it. Thanks to Pieter Wuille for rebase. Credit goes to Gregory Maxwell for the suggestion of comparing the argument against the transaction nLockTime rather than the current time/blockheight directly. --- src/script/interpreter.cpp | 83 +++++++++++++++++++++++++++++++++- src/script/interpreter.h | 11 +++++ src/script/script.h | 1 + src/script/script_error.cpp | 4 ++ src/script/script_error.h | 4 ++ src/test/data/tx_invalid.json | 64 ++++++++++++++++++++++++++ src/test/data/tx_valid.json | 42 +++++++++++++++++ src/test/transaction_tests.cpp | 3 +- 8 files changed, 209 insertions(+), 3 deletions(-) diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 84a7432fd..0b78fdf5a 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -335,9 +335,51 @@ bool EvalScript(vector >& stack, const CScript& script, un // Control // case OP_NOP: - break; + break; - case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: + case OP_CHECKLOCKTIMEVERIFY: + { + if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) { + // not enabled; treat as a NOP2 + if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { + return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); + } + break; + } + + if (stack.size() < 1) + return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); + + // Note that elsewhere numeric opcodes are limited to + // operands in the range -2**31+1 to 2**31-1, however it is + // legal for opcodes to produce results exceeding that + // range. This limitation is implemented by CScriptNum's + // default 4-byte limit. + // + // If we kept to that limit we'd have a year 2038 problem, + // even though the nLockTime field in transactions + // themselves is uint32 which only becomes meaningless + // after the year 2106. + // + // Thus as a special case we tell CScriptNum to accept up + // to 5-byte bignums, which are good until 2**39-1, well + // beyond the 2**32-1 limit of the nLockTime field itself. + const CScriptNum nLockTime(stacktop(-1), fRequireMinimal, 5); + + // In the rare event that the argument may be < 0 due to + // some arithmetic being done first, you can always use + // 0 MAX CHECKLOCKTIMEVERIFY. + if (nLockTime < 0) + return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME); + + // Actually compare the specified lock time with the transaction. + if (!checker.CheckLockTime(nLockTime)) + return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME); + + break; + } + + case OP_NOP1: case OP_NOP3: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: { if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) @@ -1084,6 +1126,43 @@ bool TransactionSignatureChecker::CheckSig(const vector& vchSigIn return true; } +bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const +{ + // There are two times of nLockTime: lock-by-blockheight + // and lock-by-blocktime, distinguished by whether + // nLockTime < LOCKTIME_THRESHOLD. + // + // We want to compare apples to apples, so fail the script + // unless the type of nLockTime being tested is the same as + // the nLockTime in the transaction. + if (!( + (txTo->nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) || + (txTo->nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD) + )) + return false; + + // Now that we know we're comparing apples-to-apples, the + // comparison is a simple numeric one. + if (nLockTime > (int64_t)txTo->nLockTime) + return false; + + // Finally the nLockTime feature can be disabled and thus + // CHECKLOCKTIMEVERIFY bypassed if every txin has been + // finalized by setting nSequence to maxint. The + // transaction would be allowed into the blockchain, making + // the opcode ineffective. + // + // Testing if this vin is not final is sufficient to + // prevent this condition. Alternatively we could test all + // inputs, but testing just this input minimizes the data + // required to prove correct CHECKLOCKTIMEVERIFY execution. + if (txTo->vin[nIn].IsFinal()) + return false; + + return true; +} + + bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) { set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); diff --git a/src/script/interpreter.h b/src/script/interpreter.h index fc64438f6..35d572f0a 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -76,6 +76,11 @@ enum // (softfork safe, BIP62 rule 6) // Note: CLEANSTACK should never be used without P2SH. SCRIPT_VERIFY_CLEANSTACK = (1U << 8), + + // Verify CHECKLOCKTIMEVERIFY + // + // See BIP65 for details. + SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), }; uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); @@ -88,6 +93,11 @@ public: return false; } + virtual bool CheckLockTime(const CScriptNum& nLockTime) const + { + return false; + } + virtual ~BaseSignatureChecker() {} }; @@ -103,6 +113,7 @@ protected: public: TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {} bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const; + bool CheckLockTime(const CScriptNum& nLockTime) const; }; class MutableTransactionSignatureChecker : public TransactionSignatureChecker diff --git a/src/script/script.h b/src/script/script.h index 45a06acc9..be2a57c3b 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -154,6 +154,7 @@ enum opcodetype // expansion OP_NOP1 = 0xb0, OP_NOP2 = 0xb1, + OP_CHECKLOCKTIMEVERIFY = OP_NOP2, OP_NOP3 = 0xb2, OP_NOP4 = 0xb3, OP_NOP5 = 0xb4, diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index d8ecfde1d..f1aa1fb40 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -47,6 +47,10 @@ const char* ScriptErrorString(const ScriptError serror) return "OP_RETURN was encountered"; case SCRIPT_ERR_UNBALANCED_CONDITIONAL: return "Invalid OP_IF construction"; + case SCRIPT_ERR_NEGATIVE_LOCKTIME: + return "Negative locktime"; + case SCRIPT_ERR_UNSATISFIED_LOCKTIME: + return "Locktime requirement not satisfied"; case SCRIPT_ERR_SIG_HASHTYPE: return "Signature hash type missing or not understood"; case SCRIPT_ERR_SIG_DER: diff --git a/src/script/script_error.h b/src/script/script_error.h index 6365680b2..bb10b8a29 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -35,6 +35,10 @@ typedef enum ScriptError_t SCRIPT_ERR_INVALID_ALTSTACK_OPERATION, SCRIPT_ERR_UNBALANCED_CONDITIONAL, + /* OP_CHECKLOCKTIMEVERIFY */ + SCRIPT_ERR_NEGATIVE_LOCKTIME, + SCRIPT_ERR_UNSATISFIED_LOCKTIME, + /* BIP62 */ SCRIPT_ERR_SIG_HASHTYPE, SCRIPT_ERR_SIG_DER, diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index 31d33c63f..9def4042d 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -120,6 +120,70 @@ [[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510100ffffffff010000000000000000016a00000000", "P2SH"], +["CHECKLOCKTIMEVERIFY tests"], + +["By-height locks, with argument just beyond tx nLockTime"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000fe64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], + +["By-time locks, with argument just beyond tx nLockTime (but within numerical boundries)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000001 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument missing"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument negative with by-blockheight nLockTime=0"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument negative with by-blocktime nLockTime=500,000,000"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Input locked"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Another input being unlocked isn't sufficient; the CHECKLOCKTIMEVERIFY-using input must be unlocked"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"] , + ["0000000000000000000000000000000000000000000000000000000000000200", 1, "1"]], +"010000000200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00020000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument/tx height/time mismatch, both versions"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument 2^32 with nLockTime=2^32-1"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967296 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Same, but with nLockTime=2^31-1"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffff7f", "P2SH,CHECKLOCKTIMEVERIFY"], + +["6 byte non-minimally-encoded arguments are invalid even in their contents are valid"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Failure due to failing CHECKLOCKTIMEVERIFY in scriptSig"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Failure due to failing CHECKLOCKTIMEVERIFY in redeemScript"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index 182b88ef6..24fff575c 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -187,5 +187,47 @@ "0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"], +["CHECKLOCKTIMEVERIFY tests"], + +["By-height locks, with argument == 0 and == tx nLockTime"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], + +["By-time locks, with argument just beyond tx nLockTime (but within numerical boundries)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Any non-maxint nSequence is fine"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["The argument can be calculated rather than created directly by a PUSHDATA"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 1ADD NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Perhaps even by an ADD producing a 5-byte result that is out of bounds for other opcodes"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 2147483647 ADD NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"], + +["5 byte non-minimally-encoded arguments are valid"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Valid CHECKLOCKTIMEVERIFY in scriptSig"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Valid CHECKLOCKTIMEVERIFY in redeemScript"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"], + ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 2a3083316..fe7f00a8b 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -39,7 +39,8 @@ static std::map mapFlagNames = boost::assign::map_list_of (string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA) (string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY) (string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) - (string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK); + (string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK) + (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY); unsigned int ParseScriptFlags(string strFlags) { From ffd75adce01a78b3461b3ff05bcc2b530a9ce994 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Wed, 17 Dec 2014 00:31:44 -0500 Subject: [PATCH 0065/1283] Enable CHECKLOCKTIMEVERIFY as a standard script verify flag Transactions that fail CLTV verification will be rejected from the mempool, making it easy to test the feature. However blocks containing "invalid" CLTV-using transactions will still be accepted; this is *not* the soft-fork required to actually enable CLTV for production use. --- src/script/standard.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/script/standard.h b/src/script/standard.h index a8b0acc98..3b401dfe4 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -50,7 +50,8 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY SCRIPT_VERIFY_MINIMALDATA | SCRIPT_VERIFY_NULLDUMMY | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | - SCRIPT_VERIFY_CLEANSTACK; + SCRIPT_VERIFY_CLEANSTACK | + SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; /** For convenience, standard but not mandatory verify flags. */ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; From 88d8525ca2ff2afc171cd0f625a098371f3a6af5 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 22 Jun 2015 08:52:11 +0200 Subject: [PATCH 0066/1283] doc: update mailing list address Move from sourceforge to linux foundation. Also get rid of some other stale mentions of sourceforge. --- README.md | 2 +- contrib/debian/copyright | 3 +-- contrib/gitian-downloader/linux-download-config | 2 +- contrib/gitian-downloader/win32-download-config | 2 +- doc/dnsseed-policy.md | 3 ++- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 67c5ed5b4..4fe6a8749 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ development team members simply pulls it. If it is a *more complicated or potentially controversial* change, then the patch submitter will be asked to start a discussion (if they haven't already) on the -[mailing list](http://sourceforge.net/mailarchive/forum.php?forum_name=bitcoin-development). +[mailing list](https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev) The patch will be accepted if there is broad consensus that it is a good thing. Developers should expect to rework and resubmit patches if the code doesn't diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 3741031f9..55ebcaab4 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -2,8 +2,7 @@ Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?rev=174 Upstream-Name: Bitcoin Upstream-Contact: Satoshi Nakamoto irc://#bitcoin@freenode.net -Source: http://sourceforge.net/projects/bitcoin/files/ - https://github.com/bitcoin/bitcoin +Source: https://github.com/bitcoin/bitcoin Files: * Copyright: 2009-2012, Bitcoin Core Developers diff --git a/contrib/gitian-downloader/linux-download-config b/contrib/gitian-downloader/linux-download-config index 367d4c421..c0048d336 100644 --- a/contrib/gitian-downloader/linux-download-config +++ b/contrib/gitian-downloader/linux-download-config @@ -3,7 +3,7 @@ name: bitcoin urls: - http://bitcoin.org/bitcoin-latest-linux-gitian.zip rss: -- url: http://sourceforge.net/api/file/index/project-id/244765/mtime/desc/limit/100/rss +- url: xpath: //item/link/text() pattern: bitcoin-\d+.\d+.\d+-linux-gitian.zip signers: diff --git a/contrib/gitian-downloader/win32-download-config b/contrib/gitian-downloader/win32-download-config index ef47918a1..0ad3bdd4f 100644 --- a/contrib/gitian-downloader/win32-download-config +++ b/contrib/gitian-downloader/win32-download-config @@ -3,7 +3,7 @@ name: bitcoin urls: - http://bitcoin.org/bitcoin-latest-win32-gitian.zip rss: -- url: http://sourceforge.net/api/file/index/project-id/244765/mtime/desc/limit/100/rss +- url: xpath: //item/link/text() pattern: bitcoin-\d+.\d+.\d+-win32-gitian.zip signers: diff --git a/doc/dnsseed-policy.md b/doc/dnsseed-policy.md index 506e17115..814ae3876 100644 --- a/doc/dnsseed-policy.md +++ b/doc/dnsseed-policy.md @@ -43,7 +43,8 @@ related to the DNS seed operation. If these expectations cannot be satisfied the operator should discontinue providing services and contact the active Bitcoin -Core development team as well as posting on bitcoin-development. +Core development team as well as posting on +[bitcoin-dev](https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev). Behavior outside of these expectations may be reasonable in some situations but should be discussed in public in advance. From e617fe25785bfba30bcb0a8d8af6797b44ba07f5 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 13 May 2015 20:04:39 +0000 Subject: [PATCH 0067/1283] Fix various warnings Found while building on Debian 7 --- src/main.h | 4 ++-- src/rest.cpp | 2 +- src/txmempool.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.h b/src/main.h index 9bf7bbb2f..734f36ecf 100644 --- a/src/main.h +++ b/src/main.h @@ -128,7 +128,7 @@ extern bool fPruneMode; /** Number of MiB of block files that we're trying to stay below. */ extern uint64_t nPruneTarget; /** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */ -static const signed int MIN_BLOCKS_TO_KEEP = 288; +static const unsigned int MIN_BLOCKS_TO_KEEP = 288; // Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat) // At 1MB per block, 288 blocks = 288MB. @@ -138,7 +138,7 @@ static const signed int MIN_BLOCKS_TO_KEEP = 288; // full block file chunks, we need the high water mark which triggers the prune to be // one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB // Setting the target to > than 550MB will make it likely we can respect the target. -static const signed int MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024; +static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024; /** Register with a network node to receive its signals */ void RegisterNodeSignals(CNodeSignals& nodeSignals); diff --git a/src/rest.cpp b/src/rest.cpp index 7c238d506..5af9d5c79 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -19,7 +19,7 @@ using namespace std; using namespace json_spirit; -static const int MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once +static const size_t MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once enum RetFormat { RF_UNDEF, diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 1c16e2092..2292191be 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -166,7 +166,7 @@ void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned in continue; const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash); if (fSanityCheck) assert(coins); - if (!coins || (coins->IsCoinBase() && nMemPoolHeight - coins->nHeight < COINBASE_MATURITY)) { + if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) { transactionsToRemove.push_back(tx); break; } From 6a4b97e8633c64593d7d0c9bd18079e52bc03e82 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Fri, 19 Jun 2015 10:42:39 -0400 Subject: [PATCH 0068/1283] Testing infrastructure: mocktime fixes New, undocumented-on-purpose -mocktime=timestamp command-line argument to startup with mocktime set. Needed because time-related blockchain sanity checks are done on startup, before a test has a chance to make a setmocktime RPC call. And changed the setmocktime RPC call so calling it will not result in currently connected peers being disconnected due to inactivity timeouts. --- src/init.cpp | 3 +++ src/rpcmisc.cpp | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index bcdd1f2f3..c4e3573de 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -868,6 +868,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS); + // Option to startup with mocktime set (used for regression testing): + SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op + // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log // Initialize elliptic curve code diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 1d47bc06a..cab57d702 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -378,10 +378,19 @@ UniValue setmocktime(const UniValue& params, bool fHelp) if (!Params().MineBlocksOnDemand()) throw runtime_error("setmocktime for regression testing (-regtest mode) only"); - LOCK(cs_main); + // cs_vNodes is locked and node send/receive times are updated + // atomically with the time change to prevent peers from being + // disconnected because we think we haven't communicated with them + // in a long time. + LOCK2(cs_main, cs_vNodes); RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); SetMockTime(params[0].get_int64()); + uint64_t t = GetTime(); + BOOST_FOREACH(CNode* pnode, vNodes) { + pnode->nLastSend = pnode->nLastRecv = t; + } + return NullUniValue; } From ccd4369a23ca78cc348bc66a7a8c69a971ffcbf7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 23 Jun 2015 21:31:47 +0200 Subject: [PATCH 0069/1283] contrib: Improvements to hardcoded seeds scripts - Moved all seed related scripts to contrib/seeds for consistency - Updated `makeseeds.py` to handle IPv6 and onions, fix regular expression for recent Bitcoin Core versions - Fixed a bug in `generate-seeds.py` with regard to IPv6 parsing --- contrib/seeds/README.md | 2 +- {share => contrib}/seeds/generate-seeds.py | 5 +- contrib/seeds/makeseeds.py | 58 +++++++++++++++++----- {share => contrib}/seeds/nodes_main.txt | 0 contrib/seeds/nodes_test.txt | 11 ++++ share/seeds/nodes_test.txt | 5 -- 6 files changed, 61 insertions(+), 20 deletions(-) rename {share => contrib}/seeds/generate-seeds.py (96%) rename {share => contrib}/seeds/nodes_main.txt (100%) create mode 100644 contrib/seeds/nodes_test.txt delete mode 100644 share/seeds/nodes_test.txt diff --git a/contrib/seeds/README.md b/contrib/seeds/README.md index bc88201f0..63647fa11 100644 --- a/contrib/seeds/README.md +++ b/contrib/seeds/README.md @@ -1,7 +1,7 @@ ### Seeds ### Utility to generate the seeds.txt list that is compiled into the client -(see [src/chainparamsseeds.h](/src/chainparamsseeds.h) and [share/seeds](/share/seeds)). +(see [src/chainparamsseeds.h](/src/chainparamsseeds.h) and other utilities in [contrib/seeds](/contrib/seeds)). The 512 seeds compiled into the 0.10 release were created from sipa's DNS seed data, like this: diff --git a/share/seeds/generate-seeds.py b/contrib/seeds/generate-seeds.py similarity index 96% rename from share/seeds/generate-seeds.py rename to contrib/seeds/generate-seeds.py index cdd683121..167c219c6 100755 --- a/share/seeds/generate-seeds.py +++ b/contrib/seeds/generate-seeds.py @@ -77,6 +77,9 @@ def parse_spec(s, defaultport): if match: # ipv6 host = match.group(1) port = match.group(2) + elif s.count(':') > 1: # ipv6, no port + host = s + port = '' else: (host,_,port) = s.partition(':') @@ -118,7 +121,7 @@ def main(): g.write('#define BITCOIN_CHAINPARAMSSEEDS_H\n') g.write('/**\n') g.write(' * List of fixed seed nodes for the bitcoin network\n') - g.write(' * AUTOGENERATED by share/seeds/generate-seeds.py\n') + g.write(' * AUTOGENERATED by contrib/seeds/generate-seeds.py\n') g.write(' *\n') g.write(' * Each line contains a 16-byte IPv6 address and a port.\n') g.write(' * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly.\n') diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index b831395f2..0bd91b8a7 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -24,24 +24,42 @@ import sys import dns.resolver PATTERN_IPV4 = re.compile(r"^((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})):8333$") -PATTERN_AGENT = re.compile(r"^(\/Satoshi:0.8.6\/|\/Satoshi:0.9.(2|3)\/|\/Satoshi:0.10.\d{1,2}\/)$") +PATTERN_IPV6 = re.compile(r"^\[([0-9a-z:]+)\]:8333$") +PATTERN_ONION = re.compile(r"^([abcdefghijklmnopqrstuvwxyz234567]{16}\.onion):8333$") +PATTERN_AGENT = re.compile(r"^(\/Satoshi:0\.8\.6\/|\/Satoshi:0\.9\.(2|3|4|5)\/|\/Satoshi:0\.10\.\d{1,2}\/|\/Satoshi:0\.11\.\d{1,2}\/)$") def parseline(line): sline = line.split() if len(sline) < 11: return None - # Match only IPv4 m = PATTERN_IPV4.match(sline[0]) + sortkey = None + ip = None if m is None: - return None - # Do IPv4 sanity check - ip = 0 - for i in range(0,4): - if int(m.group(i+2)) < 0 or int(m.group(i+2)) > 255: + m = PATTERN_IPV6.match(sline[0]) + if m is None: + m = PATTERN_ONION.match(sline[0]) + if m is None: + return None + else: + net = 'onion' + sortkey = m.group(1) + else: + net = 'ipv6' + if m.group(1) in ['::']: # Not interested in localhost + return None + sortkey = m.group(1) # XXX parse IPv6 into number, could use name_to_ipv6 from generate-seeds + else: + # Do IPv4 sanity check + ip = 0 + for i in range(0,4): + if int(m.group(i+2)) < 0 or int(m.group(i+2)) > 255: + return None + ip = ip + (int(m.group(i+2)) << (8*(3-i))) + if ip == 0: return None - ip = ip + (int(m.group(i+2)) << (8*(3-i))) - if ip == 0: - return None + net = 'ipv4' + sortkey = ip # Skip bad results. if sline[1] == 0: return None @@ -59,6 +77,7 @@ def parseline(line): blocks = int(sline[8]) # Construct result. return { + 'net': net, 'ip': m.group(1), 'ipnum': ip, 'uptime': uptime30, @@ -67,13 +86,20 @@ def parseline(line): 'agent': agent, 'service': service, 'blocks': blocks, + 'sortkey': sortkey, } # Based on Greg Maxwell's seed_filter.py def filterbyasn(ips, max_per_asn, max_total): + # Sift out ips by type + ips_ipv4 = [ip for ip in ips if ip['net'] == 'ipv4'] + ips_ipv6 = [ip for ip in ips if ip['net'] == 'ipv6'] + ips_onion = [ip for ip in ips if ip['net'] == 'onion'] + + # Filter IPv4 by ASN result = [] asn_count = {} - for ip in ips: + for ip in ips_ipv4: if len(result) == max_total: break try: @@ -86,13 +112,19 @@ def filterbyasn(ips, max_per_asn, max_total): result.append(ip) except: sys.stderr.write('ERR: Could not resolve ASN for "' + ip['ip'] + '"\n') + + # TODO: filter IPv6 by ASN + + # Add back non-IPv4 + result.extend(ips_ipv6) + result.extend(ips_onion) return result def main(): lines = sys.stdin.readlines() ips = [parseline(line) for line in lines] - # Skip entries with valid IPv4 address. + # Skip entries with valid address. ips = [ip for ip in ips if ip is not None] # Skip entries from suspicious hosts. ips = [ip for ip in ips if ip['ip'] not in SUSPICIOUS_HOSTS] @@ -109,7 +141,7 @@ def main(): # Look up ASNs and limit results, both per ASN and globally. ips = filterbyasn(ips, MAX_SEEDS_PER_ASN, NSEEDS) # Sort the results by IP address (for deterministic output). - ips.sort(key=lambda x: (x['ipnum'])) + ips.sort(key=lambda x: (x['net'], x['sortkey'])) for ip in ips: print ip['ip'] diff --git a/share/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt similarity index 100% rename from share/seeds/nodes_main.txt rename to contrib/seeds/nodes_main.txt diff --git a/contrib/seeds/nodes_test.txt b/contrib/seeds/nodes_test.txt new file mode 100644 index 000000000..98365ee50 --- /dev/null +++ b/contrib/seeds/nodes_test.txt @@ -0,0 +1,11 @@ +# List of fixed seed nodes for testnet + +# Onion nodes +thfsmmn2jbitcoin.onion +it2pj4f7657g3rhi.onion +nkf5e6b7pl4jfd4a.onion +4zhkir2ofl7orfom.onion +t6xj6wilh4ytvcs7.onion +i6y6ivorwakd7nw3.onion +ubqj4rsu3nqtxmtp.onion + diff --git a/share/seeds/nodes_test.txt b/share/seeds/nodes_test.txt deleted file mode 100644 index 71782836f..000000000 --- a/share/seeds/nodes_test.txt +++ /dev/null @@ -1,5 +0,0 @@ -# List of fixed seed nodes for testnet - -# Onion nodes -thfsmmn2jbitcoin.onion -it2pj4f7657g3rhi.onion From 884454aebe9e20964643b70ff8c41f47709380bc Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 25 Jun 2015 07:53:15 +0200 Subject: [PATCH 0070/1283] contrib: Add port parsing to makeseeds.py Allow for non-8333 nodes to appear in the internal seeds. This will allow bitcoind to bypas a filter on 8333. This also makes it possible to use the same tool for e.g. testnet. As hosts with multiple nodes per IP are likely abusive, add a filter to remove these (the ASN check will take care of them for IPv4, but not IPv6 or onion). --- contrib/seeds/makeseeds.py | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index 0bd91b8a7..4072405ef 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -22,10 +22,11 @@ SUSPICIOUS_HOSTS = set([ import re import sys import dns.resolver +import collections -PATTERN_IPV4 = re.compile(r"^((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})):8333$") -PATTERN_IPV6 = re.compile(r"^\[([0-9a-z:]+)\]:8333$") -PATTERN_ONION = re.compile(r"^([abcdefghijklmnopqrstuvwxyz234567]{16}\.onion):8333$") +PATTERN_IPV4 = re.compile(r"^((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})):(\d+)$") +PATTERN_IPV6 = re.compile(r"^\[([0-9a-z:]+)\]:(\d+)$") +PATTERN_ONION = re.compile(r"^([abcdefghijklmnopqrstuvwxyz234567]{16}\.onion):(\d+)$") PATTERN_AGENT = re.compile(r"^(\/Satoshi:0\.8\.6\/|\/Satoshi:0\.9\.(2|3|4|5)\/|\/Satoshi:0\.10\.\d{1,2}\/|\/Satoshi:0\.11\.\d{1,2}\/)$") def parseline(line): @@ -43,12 +44,15 @@ def parseline(line): return None else: net = 'onion' - sortkey = m.group(1) + ipstr = sortkey = m.group(1) + port = int(m.group(2)) else: net = 'ipv6' if m.group(1) in ['::']: # Not interested in localhost return None - sortkey = m.group(1) # XXX parse IPv6 into number, could use name_to_ipv6 from generate-seeds + ipstr = m.group(1) + sortkey = ipstr # XXX parse IPv6 into number, could use name_to_ipv6 from generate-seeds + port = int(m.group(2)) else: # Do IPv4 sanity check ip = 0 @@ -60,6 +64,8 @@ def parseline(line): return None net = 'ipv4' sortkey = ip + ipstr = m.group(1) + port = int(m.group(6)) # Skip bad results. if sline[1] == 0: return None @@ -78,7 +84,8 @@ def parseline(line): # Construct result. return { 'net': net, - 'ip': m.group(1), + 'ip': ipstr, + 'port': port, 'ipnum': ip, 'uptime': uptime30, 'lastsuccess': lastsuccess, @@ -89,6 +96,13 @@ def parseline(line): 'sortkey': sortkey, } +def filtermultiport(ips): + '''Filter out hosts with more nodes per IP''' + hist = collections.defaultdict(list) + for ip in ips: + hist[ip['sortkey']].append(ip) + return [value[0] for (key,value) in hist.items() if len(value)==1] + # Based on Greg Maxwell's seed_filter.py def filterbyasn(ips, max_per_asn, max_total): # Sift out ips by type @@ -138,13 +152,18 @@ def main(): ips = [ip for ip in ips if PATTERN_AGENT.match(ip['agent'])] # Sort by availability (and use last success as tie breaker) ips.sort(key=lambda x: (x['uptime'], x['lastsuccess'], x['ip']), reverse=True) + # Filter out hosts with multiple bitcoin ports, these are likely abusive + ips = filtermultiport(ips) # Look up ASNs and limit results, both per ASN and globally. ips = filterbyasn(ips, MAX_SEEDS_PER_ASN, NSEEDS) # Sort the results by IP address (for deterministic output). ips.sort(key=lambda x: (x['net'], x['sortkey'])) for ip in ips: - print ip['ip'] + if ip['net'] == 'ipv6': + print '[%s]:%i' % (ip['ip'], ip['port']) + else: + print '%s:%i' % (ip['ip'], ip['port']) if __name__ == '__main__': main() From b9329536cd8a6c152b41c9276f1def14b4d2442d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 25 Jun 2015 08:04:03 +0200 Subject: [PATCH 0071/1283] Hardcoded seeds update June 2015 --- contrib/seeds/nodes_main.txt | 1417 +++++++++++++++++++++------------- src/chainparamsseeds.h | 1273 +++++++++++++++++++----------- 2 files changed, 1689 insertions(+), 1001 deletions(-) diff --git a/contrib/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt index 3dba6d8a6..17339d514 100644 --- a/contrib/seeds/nodes_main.txt +++ b/contrib/seeds/nodes_main.txt @@ -1,540 +1,879 @@ -# List of fixed seed nodes for main network - -# IPv4 nodes (generated using contrib/seeds/makeseeds.py) -1.33.197.110 -1.34.180.245 -1.202.128.218 -2.35.195.25 -5.100.123.19 -5.175.145.169 -5.199.133.193 -5.199.151.10 -5.228.1.230 -14.200.200.145 -18.228.0.188 -18.228.0.200 -23.30.243.153 -23.88.232.49 -23.99.105.9 -23.226.137.208 -23.227.177.161 -23.227.191.50 -23.229.45.32 -23.236.144.69 -23.253.148.113 -23.253.241.22 -23.255.227.231 -24.20.205.222 -24.23.120.252 -24.94.98.96 -24.98.95.201 -24.111.90.55 -24.119.119.105 -24.138.25.149 -31.3.214.45 -31.186.87.46 -31.186.101.98 -31.186.250.186 -31.204.153.107 -37.44.16.231 -37.44.44.11 -37.120.168.204 -37.143.86.26 -37.187.75.24 -37.188.68.169 -37.192.95.150 -37.201.246.116 -37.205.10.140 -46.10.210.17 -46.19.138.154 -46.28.204.123 -46.28.205.67 -46.38.235.229 -46.163.76.230 -46.166.162.91 -46.173.190.50 -46.227.66.132 -46.229.238.187 -46.236.116.209 -47.55.14.65 -50.7.252.229 -50.46.159.91 -50.78.49.181 -50.78.231.57 -50.79.153.65 -50.116.34.44 -50.126.86.253 -50.142.41.23 -50.199.113.193 -50.200.78.107 -50.206.138.177 -50.252.52.49 -54.165.25.75 -54.169.107.40 -54.179.190.56 -54.187.82.121 -54.246.85.246 -58.74.7.205 -58.96.183.121 -61.62.58.38 -61.63.91.72 -61.63.91.112 -61.72.211.228 -62.43.40.154 -62.43.130.178 -62.80.185.213 -62.109.49.26 -62.173.139.58 -62.181.238.186 -62.210.114.127 -63.141.228.138 -63.153.213.78 -63.223.84.145 -63.251.88.112 -64.31.110.50 -64.34.121.45 -64.114.6.42 -64.140.125.98 -64.156.193.100 -65.30.47.116 -65.35.132.177 -65.96.193.165 -65.111.189.26 -66.68.10.30 -66.114.33.250 -66.130.46.63 -66.175.215.135 -66.190.253.165 -66.194.38.254 -66.244.98.111 -67.162.238.30 -67.169.255.17 -67.183.173.25 -67.219.233.140 -67.227.240.115 -67.247.222.71 -68.43.114.66 -68.52.33.36 -68.198.245.241 -69.12.226.165 -69.13.198.188 -69.15.179.62 -69.39.239.47 -69.47.45.87 -69.62.217.206 -69.64.42.31 -69.64.81.61 -69.67.219.200 -69.90.132.157 -69.94.30.177 -69.136.175.241 -70.61.97.228 -70.123.118.132 -71.59.152.182 -71.198.248.151 -71.200.242.89 -71.225.179.157 -72.14.187.51 -72.38.34.180 -72.52.72.187 -72.91.144.182 -72.167.49.217 -72.201.243.55 -72.223.60.249 -72.228.153.102 -73.26.101.228 -73.50.158.200 -73.181.204.170 -74.57.199.180 -74.63.222.226 -74.81.231.21 -74.193.126.82 -74.207.235.164 -75.83.197.114 -75.144.114.9 -76.112.5.247 -76.174.20.247 -77.37.240.142 -77.57.202.107 -77.172.123.53 -77.221.91.253 -77.235.48.48 -77.245.78.2 -78.8.58.249 -78.27.191.182 -78.129.236.141 -78.131.88.47 -78.157.205.6 -79.132.230.144 -79.143.188.155 -79.160.221.140 -79.161.111.114 -80.100.189.3 -80.147.140.121 -80.203.75.133 -80.220.99.227 -80.222.20.169 -80.241.1.7 -81.23.191.243 -81.38.11.202 -81.80.9.71 -81.110.213.165 -81.133.155.237 -81.171.34.37 -81.181.155.180 -82.39.156.137 -82.73.161.95 -82.130.45.40 -82.165.153.47 -82.168.128.133 -82.179.225.118 -82.194.245.158 -82.199.102.10 -82.211.30.243 -82.217.133.145 -82.221.128.35 -82.221.131.177 -82.233.225.205 -83.0.249.146 -83.89.31.249 -83.128.29.231 -83.128.253.142 -83.143.130.56 -83.150.2.99 -83.150.9.196 -83.161.64.45 -83.212.103.212 -83.212.111.114 -83.246.75.8 -83.254.81.31 -83.254.150.54 -84.2.34.104 -84.15.61.60 -84.17.25.135 -84.42.144.19 -84.212.210.135 -84.215.165.231 -84.238.140.176 -84.240.31.184 -85.25.214.137 -85.139.163.132 -85.199.4.228 -85.214.61.209 -85.214.108.77 -86.123.16.17 -87.48.42.199 -87.104.168.104 -87.229.73.171 -87.236.196.77 -88.97.56.98 -88.134.178.89 -88.150.233.19 -88.168.133.3 -88.208.18.246 -88.208.33.202 -89.18.28.21 -89.85.220.84 -89.163.227.28 -89.184.83.60 -89.231.96.83 -89.236.49.117 -91.90.66.209 -91.106.194.97 -91.134.75.115 -91.152.193.36 -91.152.219.35 -91.197.10.234 -91.209.77.101 -91.210.106.147 -91.214.200.205 -91.223.115.38 -91.234.48.232 -91.250.86.18 -92.27.7.209 -92.255.207.73 -93.74.163.234 -93.84.114.106 -93.152.166.29 -93.171.216.221 -93.185.177.71 -94.19.12.244 -94.42.115.50 -94.79.177.206 -94.136.147.119 -94.143.245.5 -94.188.50.39 -94.190.227.112 -94.198.135.29 -94.226.107.86 -94.242.219.90 -94.242.229.168 -94.244.160.84 -95.31.10.209 -95.85.25.41 -95.105.161.136 -95.154.165.45 -95.154.200.216 -95.167.109.125 -95.211.125.231 -95.211.216.235 -96.33.25.17 -96.43.130.178 -97.118.8.236 -98.102.6.125 -98.202.20.45 -98.217.125.225 -98.234.210.111 -98.237.20.123 -98.255.144.176 -99.113.64.43 -99.229.22.8 -103.1.212.19 -103.30.42.189 -103.224.165.48 -103.243.94.140 -104.131.107.107 -104.131.116.184 -104.143.0.156 -104.219.184.9 -106.185.38.174 -107.6.4.145 -107.150.8.27 -107.150.33.20 -107.170.228.129 -107.170.240.173 -108.51.20.86 -108.61.149.222 -108.61.151.172 -108.161.129.247 -108.170.140.21 -109.60.211.216 -109.73.42.36 -109.73.172.138 -109.163.235.239 -109.190.196.220 -109.201.135.216 -109.228.152.2 -109.228.154.81 -109.230.220.125 -109.234.156.218 -109.235.49.27 -109.235.69.84 -112.124.71.0 -113.146.68.251 -115.29.17.82 -115.70.176.17 -117.41.162.184 -118.27.8.170 -119.230.7.211 -119.246.71.52 -121.172.8.100 -122.128.109.148 -123.231.224.63 -128.175.195.31 -128.199.164.96 -128.199.254.244 -129.97.69.76 -129.123.7.7 -129.123.7.39 -129.186.17.17 -131.247.169.190 -133.242.209.63 -134.102.94.38 -134.119.17.145 -137.116.160.176 -137.226.34.42 -138.210.217.170 -141.255.166.194 -143.215.129.126 -144.76.244.19 -146.148.52.162 -146.148.80.57 -146.185.19.30 -146.185.142.86 -146.185.253.51 -148.251.6.214 -149.154.155.235 -149.210.133.244 -151.224.248.252 -153.121.75.229 -153.127.251.67 -154.20.2.139 -157.13.61.5 -158.58.173.48 -159.253.23.132 -162.209.110.218 -162.213.254.205 -162.239.254.100 -162.242.150.39 -162.243.81.138 -162.243.235.56 -162.244.79.16 -162.245.217.119 -162.248.102.117 -162.251.108.53 -162.254.149.139 -162.255.116.78 -166.70.94.106 -167.88.45.124 -167.88.120.210 -173.26.49.43 -173.30.14.6 -173.80.114.197 -173.167.214.243 -173.208.219.108 -173.220.67.156 -173.236.101.34 -173.246.107.34 -173.255.237.241 -174.2.213.209 -174.51.23.224 -174.51.123.159 -174.57.212.121 -174.109.33.28 -175.126.124.91 -175.126.124.92 -176.10.116.242 -176.36.35.126 -176.36.99.222 -176.124.110.47 -176.194.33.44 -176.223.201.198 -178.62.26.83 -178.62.36.48 -178.62.212.141 -178.62.254.59 -178.78.250.3 -178.155.86.226 -178.175.134.35 -178.248.111.4 -178.254.1.170 -178.254.34.161 -179.43.114.14 -182.213.208.28 -184.68.2.46 -184.72.238.42 -184.94.226.34 -184.94.227.58 -184.107.139.58 -184.107.206.45 -185.10.48.117 -185.21.216.156 -185.38.47.224 -185.45.192.129 -185.53.129.230 -185.53.131.114 -185.55.53.61 -185.55.53.63 -185.61.119.2 -185.61.148.203 -186.2.167.23 -188.92.75.178 -188.122.92.134 -188.138.9.208 -188.165.209.148 -188.226.206.239 -190.10.8.124 -190.10.10.147 -192.0.130.142 -192.3.89.159 -192.73.234.138 -192.75.95.107 -192.95.100.102 -192.155.84.181 -192.169.233.206 -192.198.93.86 -192.227.135.216 -193.0.109.3 -193.77.50.208 -193.109.68.62 -193.150.121.37 -193.224.69.98 -194.79.8.37 -194.141.86.10 -195.12.180.94 -195.56.63.10 -195.116.93.93 -195.154.174.226 -195.159.111.98 -195.169.138.2 -195.189.126.35 -195.197.175.190 -197.242.93.82 -198.11.214.147 -198.49.41.21 -199.33.124.186 -199.204.186.146 -199.233.238.115 -199.241.189.66 -202.60.68.242 -202.60.69.232 -203.183.151.39 -203.219.14.204 -204.44.123.109 -204.44.123.162 -204.45.120.178 -206.190.134.44 -206.248.184.127 -207.244.73.8 -208.66.30.27 -209.81.9.223 -209.105.243.229 -209.126.70.159 -209.140.30.169 -209.165.128.235 -209.190.2.242 -210.66.254.236 -210.73.27.33 -211.72.66.229 -212.25.37.124 -212.71.235.114 -212.71.252.109 -212.114.48.31 -212.174.151.118 -213.66.205.194 -213.129.248.139 -213.136.87.34 -213.165.82.133 -213.167.17.6 -213.179.158.253 -213.189.53.125 -213.222.208.93 -216.49.158.161 -216.55.143.154 -216.131.91.100 -216.245.206.181 -216.250.138.230 -217.11.225.189 -217.23.6.133 -217.75.88.178 -217.172.143.140 -217.195.169.209 -217.196.248.106 -219.138.161.162 -222.167.248.90 -223.18.254.55 - -# Onion nodes +1.34.168.128:8333 +1.202.128.218:8333 +2.30.0.210:8333 +5.9.96.203:8333 +5.45.71.130:8333 +5.45.98.141:8333 +5.102.145.68:8333 +5.135.160.77:8333 +5.189.134.246:8333 +5.199.164.132:8333 +5.249.135.102:8333 +8.19.44.110:8333 +8.22.230.8:8333 +14.200.200.145:8333 +18.228.0.188:8333 +18.228.0.200:8333 +23.24.168.97:8333 +23.28.35.227:8333 +23.92.76.170:8333 +23.99.64.119:8333 +23.228.166.128:8333 +23.229.45.32:8333 +24.8.105.128:8333 +24.16.69.137:8333 +24.94.98.96:8333 +24.102.118.7:8333 +24.118.166.228:8333 +24.122.133.49:8333 +24.166.97.162:8333 +24.213.235.242:8333 +24.226.107.64:8333 +24.228.192.171:8333 +27.140.133.18:8333 +31.41.40.25:8333 +31.43.101.59:8333 +31.184.195.181:8333 +31.193.139.66:8333 +37.200.70.102:8333 +37.205.10.151:8333 +42.3.106.227:8333 +42.60.133.106:8333 +45.56.85.231:8333 +45.56.102.228:8333 +45.79.130.235:8333 +46.28.204.61:11101 +46.38.235.229:8333 +46.59.2.74:8333 +46.101.132.37:8333 +46.101.168.50:8333 +46.163.76.230:8333 +46.166.161.103:8333 +46.182.132.100:8333 +46.223.36.94:8333 +46.227.66.132:8333 +46.227.66.138:8333 +46.239.107.74:8333 +46.249.39.100:8333 +46.250.98.108:8333 +50.7.37.114:8333 +50.81.53.151:8333 +50.115.43.253:8333 +50.116.20.87:8333 +50.116.33.92:8333 +50.125.167.245:8333 +50.143.9.51:8333 +50.188.192.133:8333 +54.77.162.76:8333 +54.153.97.109:8333 +54.165.192.125:8333 +58.96.105.85:8333 +59.167.196.135:8333 +60.29.227.163:8333 +61.35.225.19:8333 +62.43.130.178:8333 +62.109.49.26:8333 +62.202.0.97:8333 +62.210.66.227:8333 +62.210.192.169:8333 +64.74.98.205:8333 +64.156.193.100:8333 +64.203.102.86:8333 +64.229.142.48:8333 +65.96.193.165:8333 +66.30.3.7:8333 +66.114.33.49:8333 +66.118.133.194:8333 +66.135.10.126:8333 +66.172.10.4:8333 +66.194.38.250:8333 +66.194.38.253:8333 +66.215.192.104:8333 +67.60.98.115:8333 +67.164.35.36:8333 +67.191.162.244:8333 +67.207.195.77:8333 +67.219.233.140:8333 +67.221.193.55:8333 +67.228.162.228:8333 +68.50.67.199:8333 +68.62.3.203:8333 +68.65.205.226:9000 +68.106.42.191:8333 +68.150.181.198:8333 +68.196.196.106:8333 +68.224.194.81:8333 +69.46.5.194:8333 +69.50.171.238:8333 +69.64.43.152:8333 +69.65.41.13:8333 +69.90.132.200:8333 +69.143.1.243:8333 +69.146.98.216:8333 +69.165.246.38:8333 +69.207.6.135:8333 +69.251.208.26:8333 +70.38.1.101:8333 +70.38.9.66:8333 +70.90.2.18:8333 +71.58.228.226:8333 +71.199.11.189:8333 +71.199.193.202:8333 +71.205.232.181:8333 +71.236.200.162:8333 +72.24.73.186:8333 +72.52.130.110:8333 +72.53.111.37:8333 +72.235.38.70:8333 +73.31.171.149:8333 +73.32.137.72:8333 +73.137.133.238:8333 +73.181.192.103:8333 +73.190.2.60:8333 +73.195.192.137:8333 +73.222.35.117:8333 +74.57.199.180:8333 +74.82.233.205:8333 +74.85.66.82:8333 +74.101.224.127:8333 +74.113.69.16:8333 +74.122.235.68:8333 +74.193.68.141:8333 +74.208.164.219:8333 +75.100.37.122:8333 +75.145.149.169:8333 +75.168.34.20:8333 +76.20.44.240:8333 +76.100.70.17:8333 +76.168.3.239:8333 +76.186.140.103:8333 +77.92.68.221:8333 +77.109.101.142:8333 +77.110.11.86:8333 +77.242.108.18:8333 +78.46.96.150:9020 +78.84.100.95:8333 +79.132.230.144:8333 +79.133.43.63:8333 +79.160.76.153:8333 +79.169.34.24:8333 +79.188.7.78:8333 +80.217.226.25:8333 +80.223.100.179:8333 +80.240.129.221:8333 +81.1.173.243:8333 +81.7.11.50:8333 +81.7.16.17:8333 +81.66.111.3:8333 +81.80.9.71:8333 +81.140.43.138:8333 +81.171.34.37:8333 +81.174.247.50:8333 +81.181.155.53:8333 +81.184.5.253:8333 +81.187.69.130:8333 +81.230.3.84:8333 +82.42.128.51:8333 +82.74.226.21:8333 +82.142.75.50:8333 +82.199.102.10:8333 +82.200.205.30:8333 +82.221.108.21:8333 +82.221.128.35:8333 +82.238.124.41:8333 +82.242.0.245:8333 +83.76.123.110:8333 +83.150.9.196:8333 +83.162.196.192:8333 +83.162.234.224:8333 +83.170.104.91:8333 +83.255.66.118:8334 +84.2.34.104:8333 +84.45.98.91:8333 +84.47.161.150:8333 +84.212.192.131:8333 +84.215.169.101:8333 +84.238.140.176:8333 +84.245.71.31:8333 +85.17.4.212:8333 +85.114.128.134:8333 +85.159.237.191:8333 +85.166.130.189:8333 +85.199.4.228:8333 +85.214.66.168:8333 +85.214.195.210:8333 +85.229.0.73:8333 +86.21.96.45:8333 +87.48.42.199:8333 +87.81.143.82:8333 +87.81.251.72:8333 +87.104.24.185:8333 +87.104.168.104:8333 +87.117.234.71:8333 +87.118.96.197:8333 +87.145.12.57:8333 +87.159.170.190:8333 +88.150.168.160:8333 +88.208.0.79:8333 +88.208.0.149:8333 +88.214.194.226:8343 +89.1.11.32:8333 +89.36.235.108:8333 +89.67.96.2:15321 +89.98.16.41:8333 +89.108.72.195:8333 +89.156.35.157:8333 +89.163.227.28:8333 +89.212.33.237:8333 +89.212.160.165:8333 +89.231.96.83:8333 +89.248.164.64:8333 +90.149.193.199:8333 +91.77.239.245:8333 +91.106.194.97:8333 +91.126.77.77:8333 +91.134.38.195:8333 +91.156.97.181:8333 +91.207.68.144:8333 +91.209.77.101:8333 +91.214.200.205:8333 +91.220.131.242:8333 +91.220.163.18:8333 +91.233.23.35:8333 +92.13.96.93:8333 +92.14.74.114:8333 +92.27.7.209:8333 +92.221.228.13:8333 +92.255.207.73:8333 +93.72.167.148:8333 +93.74.163.234:8333 +93.123.174.66:8333 +93.152.166.29:8333 +93.181.45.188:8333 +94.19.12.244:8333 +94.190.227.112:8333 +94.198.135.29:8333 +94.224.162.65:8333 +94.226.107.86:8333 +94.242.198.161:8333 +95.31.10.209:8333 +95.65.72.244:8333 +95.84.162.95:8333 +95.90.139.46:8333 +95.183.49.27:8005 +95.215.47.133:8333 +96.23.67.85:8333 +96.44.166.190:8333 +97.93.225.74:8333 +98.26.0.34:8333 +98.27.225.102:8333 +98.229.117.229:8333 +98.249.68.125:8333 +98.255.5.155:8333 +99.101.240.114:8333 +101.100.174.138:8333 +101.251.203.6:8333 +103.3.60.61:8333 +103.30.42.189:8333 +103.224.165.48:8333 +104.36.83.233:8333 +104.37.129.22:8333 +104.54.192.251:8333 +104.128.228.252:8333 +104.128.230.185:8334 +104.130.161.47:8333 +104.131.33.60:8333 +104.143.0.156:8333 +104.156.111.72:8333 +104.167.111.84:8333 +104.193.40.248:8333 +104.197.7.174:8333 +104.197.8.250:8333 +104.223.1.133:8333 +104.236.97.140:8333 +104.238.128.214:8333 +104.238.130.182:8333 +106.38.234.84:8333 +106.185.36.204:8333 +107.6.4.145:8333 +107.150.2.6:8333 +107.150.40.234:8333 +107.155.108.130:8333 +107.161.182.115:8333 +107.170.66.231:8333 +107.190.128.226:8333 +107.191.106.115:8333 +108.16.2.61:8333 +109.70.4.168:8333 +109.162.35.196:8333 +109.163.235.239:8333 +109.190.196.220:8333 +109.191.39.60:8333 +109.234.106.191:8333 +109.238.81.82:8333 +114.76.147.27:8333 +115.28.224.127:8333 +115.68.110.82:18333 +118.97.79.218:8333 +118.189.207.197:8333 +119.228.96.233:8333 +120.147.178.81:8333 +121.41.123.5:8333 +121.67.5.230:8333 +122.107.143.110:8333 +123.2.170.98:8333 +123.110.65.94:8333 +123.193.139.19:8333 +125.239.160.41:8333 +128.101.162.193:8333 +128.111.73.10:8333 +128.140.229.73:8333 +128.175.195.31:8333 +128.199.107.63:8333 +128.199.192.153:8333 +128.253.3.193:20020 +129.123.7.7:8333 +130.89.160.234:8333 +131.72.139.164:8333 +131.191.112.98:8333 +133.1.134.162:8333 +134.19.132.53:8333 +137.226.34.42:8333 +141.41.2.172:8333 +141.255.128.204:8333 +142.217.12.106:8333 +143.215.129.126:8333 +146.0.32.101:8337 +147.229.13.199:8333 +149.210.133.244:8333 +149.210.162.187:8333 +150.101.163.241:8333 +151.236.11.189:8333 +153.121.66.211:8333 +154.20.2.139:8333 +159.253.23.132:8333 +162.209.106.123:8333 +162.210.198.184:8333 +162.218.65.121:8333 +162.222.161.49:8333 +162.243.132.6:8333 +162.243.132.58:8333 +162.248.99.164:53011 +162.248.102.117:8333 +163.158.35.110:8333 +164.15.10.189:8333 +164.40.134.171:8333 +166.230.71.67:8333 +167.160.161.199:8333 +168.103.195.250:8333 +168.144.27.112:8333 +168.158.129.29:8333 +170.75.162.86:8333 +172.90.99.174:8333 +172.245.5.156:8333 +173.23.166.47:8333 +173.32.11.194:8333 +173.34.203.76:8333 +173.171.1.52:8333 +173.175.136.13:8333 +173.230.228.139:8333 +173.247.193.70:8333 +174.49.132.28:8333 +174.52.202.72:8333 +174.53.76.87:8333 +174.109.33.28:8333 +176.28.12.169:8333 +176.35.182.214:8333 +176.36.33.113:8333 +176.36.33.121:8333 +176.58.96.173:8333 +176.121.76.84:8333 +178.62.70.16:8333 +178.62.111.26:8333 +178.76.169.59:8333 +178.79.131.32:8333 +178.162.199.216:8333 +178.175.134.35:8333 +178.248.111.4:8333 +178.254.1.170:8333 +178.254.34.161:8333 +179.43.143.120:8333 +179.208.156.198:8333 +180.200.128.58:8333 +183.78.169.108:8333 +183.96.96.152:8333 +184.68.2.46:8333 +184.73.160.160:8333 +184.94.227.58:8333 +184.152.68.163:8333 +185.7.35.114:8333 +185.28.76.179:8333 +185.31.160.202:8333 +185.45.192.129:8333 +185.66.140.15:8333 +186.2.167.23:8333 +186.220.101.142:8333 +188.26.5.33:8333 +188.75.136.146:8333 +188.120.194.140:8333 +188.121.5.150:8333 +188.138.0.114:8333 +188.138.33.239:8333 +188.166.0.82:8333 +188.182.108.129:8333 +188.191.97.208:8333 +188.226.198.102:8001 +190.10.9.217:8333 +190.75.143.144:8333 +190.139.102.146:8333 +191.237.64.28:8333 +192.3.131.61:8333 +192.99.225.3:8333 +192.110.160.122:8333 +192.146.137.1:8333 +192.183.198.204:8333 +192.203.228.71:8333 +193.0.109.3:8333 +193.12.238.204:8333 +193.91.200.85:8333 +193.234.225.156:8333 +194.6.233.38:8333 +194.63.143.136:8333 +194.126.100.246:8333 +195.134.99.195:8333 +195.159.111.98:8333 +195.159.226.139:8333 +195.197.175.190:8333 +198.48.199.108:8333 +198.57.208.134:8333 +198.57.210.27:8333 +198.62.109.223:8333 +198.167.140.8:8333 +198.167.140.18:8333 +199.91.173.234:8333 +199.127.226.245:8333 +199.180.134.116:8333 +200.7.96.99:8333 +201.160.106.86:8333 +202.55.87.45:8333 +202.60.68.242:8333 +202.60.69.232:8333 +202.124.109.103:8333 +203.30.197.77:8333 +203.88.160.43:8333 +203.151.140.14:8333 +203.219.14.204:8333 +205.147.40.62:8333 +207.235.39.214:8333 +207.244.73.8:8333 +208.12.64.225:8333 +208.76.200.200:8333 +209.40.96.121:8333 +209.126.107.176:8333 +209.141.40.149:8333 +209.190.75.59:8333 +209.208.111.142:8333 +210.54.34.164:8333 +211.72.66.229:8333 +212.51.144.42:8333 +212.112.33.157:8333 +212.116.72.63:8333 +212.126.14.122:8333 +213.66.205.194:8333 +213.111.196.21:8333 +213.122.107.102:8333 +213.136.75.175:8333 +213.155.7.24:8333 +213.163.64.31:8333 +213.163.64.208:8333 +213.165.86.136:8333 +213.184.8.22:8333 +216.15.78.182:8333 +216.55.143.154:8333 +216.115.235.32:8333 +216.126.226.166:8333 +216.145.67.87:8333 +216.169.141.169:8333 +216.249.92.230:8333 +216.250.138.230:8333 +217.20.171.43:8333 +217.23.2.71:8333 +217.23.2.242:8333 +217.25.9.76:8333 +217.40.226.169:8333 +217.123.98.9:8333 +217.155.36.62:8333 +217.172.32.18:20993 +218.61.196.202:8333 +218.231.205.41:8333 +220.233.77.200:8333 +223.18.226.85:8333 +223.197.203.82:8333 +223.255.166.142:8333 +[2001:1291:2bf:1::100]:8333 +[2001:1418:100:5c2::2]:8333 +[2001:16d8:dd24:0:86c9:681e:f931:256]:8333 +[2001:19f0:1624:e6::579d:9428]:8333 +[2001:19f0:300:1340:225:90ff:fec9:2b6d]:8333 +[2001:19f0:4009:1405::64]:8333 +[2001:1b40:5000:2e::3fb0:6571]:8333 +[2001:410:a000:4050:8463:90b0:fffb:4e58]:8333 +[2001:410:a002:cafe:8463:90b0:fffb:4e58]:8333 +[2001:41d0:1:541e::1]:8333 +[2001:41d0:1:6a34::3]:8333 +[2001:41d0:1:6cd3::]:8333 +[2001:41d0:1:8b26::1]:8333 +[2001:41d0:1:a33d::1]:8333 +[2001:41d0:1:b855::1]:8333 +[2001:41d0:1:c139::1]:8333 +[2001:41d0:1:c8d7::1]:8333 +[2001:41d0:1:dd3f::1]:8333 +[2001:41d0:1:e29d::1]:8333 +[2001:41d0:1:f59f::33]:8333 +[2001:41d0:1:f7cc::1]:8333 +[2001:41d0:1:ff87::1]:8333 +[2001:41d0:2:2f05::1]:8333 +[2001:41d0:2:37c3::]:8200 +[2001:41d0:2:3e13::1]:8333 +[2001:41d0:2:8619::]:8333 +[2001:41d0:2:9c94::1]:8333 +[2001:41d0:2:a24f::]:8333 +[2001:41d0:2:adbf::]:8333 +[2001:41d0:2:b721::1]:8333 +[2001:41d0:2:ee52::1]:8333 +[2001:41d0:2:f1a5::]:8333 +[2001:41d0:2:fa54::1]:8333 +[2001:41d0:51:1::2036]:8333 +[2001:41d0:52:a00::1a1]:8333 +[2001:41d0:52:cff::6f5]:8333 +[2001:41d0:52:d00::2c0]:8333 +[2001:41d0:52:d00::cf2]:8333 +[2001:41d0:8:1087::1]:8333 +[2001:41d0:8:4a3c::b7c]:8333 +[2001:41d0:8:6728::]:8333 +[2001:41d0:8:b779::1]:8333 +[2001:41d0:8:c30f::1]:8333 +[2001:41d0:8:d2b2::1]:8333 +[2001:41d0:8:d5c3::1]:8333 +[2001:41d0:8:eb8b::]:8333 +[2001:41d0:a:16d0::1]:8333 +[2001:41d0:a:2b18::1]:8333 +[2001:41d0:a:3a9c::1]:8333 +[2001:41d0:a:4903::]:8333 +[2001:41d0:a:57b::1]:8333 +[2001:41d0:a:5c7a::]:8333 +[2001:41d0:a:6c29::1]:8333 +[2001:41d0:a:f482::1]:8333 +[2001:41d0:b:854:b7c:b7c:b7c:b7c]:8333 +[2001:41d0:d:111c::]:8333 +[2001:44b8:4116:7801:4216:7eff:fe78:3fe4]:8333 +[2001:470:1f08:837::2]:8333 +[2001:470:1f08:c33::2]:8333 +[2001:470:1f09:bca:218:7dff:fe10:be33]:8333 +[2001:470:1f0f:22d::212:26]:8333 +[2001:470:1f11:12d5::ae1:5611]:8333 +[2001:470:1f14:57a::2]:8333 +[2001:470:1f14:7d::2]:8333 +[2001:470:1f15:57c::1]:8333 +[2001:470:1f15:dda:3d9a:3f11:9a56:ed64]:8333 +[2001:470:25:482::2]:8333 +[2001:470:25:e4::2]:8333 +[2001:470:4:26b::2]:8333 +[2001:470:5f:5f::232]:8333 +[2001:470:66:119::2]:8333 +[2001:470:67:39d::71]:8333 +[2001:470:6c4f::cafe]:8333 +[2001:470:8:2e1::43]:8333 +[2001:470:90a7:96::afe:6021]:8333 +[2001:470:95c1::2]:8333 +[2001:470:b1d0:ffff::1000]:8333 +[2001:470:c1f2:3::201]:8333 +[2001:470:d00d:0:3664:a9ff:fe9a:5150]:8333 +[2001:470:e250:0:211:11ff:feb9:924c]:8333 +[2001:4800:7817:101:be76:4eff:fe04:dc52]:8333 +[2001:4800:7819:104:be76:4eff:fe04:7809]:8333 +[2001:4800:7819:104:be76:4eff:fe05:c828]:8333 +[2001:4802:7800:2:30d7:1775:ff20:1858]:8333 +[2001:4802:7802:101:be76:4eff:fe20:256]:8333 +[2001:4802:7802:103:be76:4eff:fe20:2de8]:8333 +[2001:4830:1100:2e8::2]:8333 +[2001:4ba0:fff7:181:dead::1]:8333 +[2001:4ba0:fffa:5d::93]:8333 +[2001:4ba0:ffff:1be:1:1005:0:1]:8335 +[2001:4c48:110:101:216:3eff:fe24:1162]:8333 +[2001:4dd0:f101::32]:8333 +[2001:4dd0:ff00:867f::3]:8333 +[2001:4dd0:ff00:9a67::9]:8333 +[2001:4dd0:ff00:9c55:c23f:d5ff:fe6c:7ee9]:8333 +[2001:5c0:1400:b::3cc7]:8333 +[2001:5c0:1400:b::3d01]:8333 +[2001:5c0:1400:b::8df]:8333 +[2001:5c0:1501:300::3]:8333 +[2001:610:1b19::3]:8333 +[2001:620:500:fff0:f21f:afff:fecf:91cc]:8333 +[2001:67c:1220:80c:ad:8de2:f7e2:c784]:8333 +[2001:67c:21ec:1000::b]:8333 +[2001:6f8:1296:0:76d4:35ff:feba:1d26]:8333 +[2001:840:f000:4250:3e4a:92ff:fe6d:145f]:8333 +[2001:8d8:840:500::39:1ae]:8333 +[2001:980:efd8:0:21:de4a:2709:912]:8333 +[2001:981:46:1::3]:8333 +[2001:981:9319:2:c0:a8:c8:8]:8333 +[2001:9d8:cafe:3::91]:8333 +[2001:ad0:1:1:26be:5ff:fe25:959d]:8333 +[2001:ba8:1f1:f34c::2]:8333 +[2001:bc8:381c:100::1]:8333 +[2002:175c:4caa::175c:4caa]:8333 +[2002:4404:82f1:0:8d55:8fbb:15fa:f4e0]:8333 +[2002:4475:2233:0:21f:5bff:fe33:9f70]:8333 +[2002:596c:48c3::596c:48c3]:8333 +[2002:8c6d:6521:9617:12bf:48ff:fed8:1724]:8333 +[2002:a646:5e6a::1:2]:8333 +[2002:b009:20c5::b009:20c5]:8333 +[2400:8900::f03c:91ff:fe6e:823e]:8333 +[2400:8900::f03c:91ff:fe70:d164]:8333 +[2400:8901::f03c:91ff:fe37:9761]:8333 +[2403:4200:403:2::ff]:8333 +[2403:b800:1000:64:40a:e9ff:fe5f:94c1]:8333 +[2403:b800:1000:64:9879:17ff:fe6a:a59f]:8333 +[2600:3c00::f03c:91ff:fe18:59b2]:8333 +[2600:3c00::f03c:91ff:fe37:a4b1]:8333 +[2600:3c00::f03c:91ff:fe56:2973]:8333 +[2600:3c00::f03c:91ff:fe6e:7297]:8333 +[2600:3c00::f03c:91ff:fe84:8a6e]:8333 +[2600:3c01::f03c:91ff:fe18:6adf]:8333 +[2600:3c01::f03c:91ff:fe18:e217]:8333 +[2600:3c01::f03c:91ff:fe33:1b31]:8333 +[2600:3c01::f03c:91ff:fe33:2fe1]:8333 +[2600:3c01::f03c:91ff:fe33:a03f]:8333 +[2600:3c01::f03c:91ff:fe50:5e06]:8333 +[2600:3c01::f03c:91ff:fe56:d645]:8333 +[2600:3c01::f03c:91ff:fe6e:a3dc]:8333 +[2600:3c01::f03c:91ff:fe89:a659]:8333 +[2600:3c02::f03c:91ff:fe6e:6f0b]:8333 +[2600:3c03::f03c:91ff:fe33:f6fb]:8333 +[2600:3c03::f03c:91ff:fe50:5fa7]:8333 +[2600:3c03::f03c:91ff:fe6e:1803]:8333 +[2600:3c03::f03c:91ff:fe6e:4ac0]:8333 +[2601:6:4800:47f:1e4e:1f4d:332c:3bf6]:8333 +[2601:d:5400:fed:8d54:c1e8:7ed7:d45e]:8333 +[2602:100:4b8f:6d2a:20c:29ff:feaf:c4c2]:8333 +[2602:ffc5:1f::1f:2d61]:8333 +[2602:ffc5:1f::1f:9211]:8333 +[2602:ffc5::ffc5:b844]:8333 +[2602:ffe8:100:2::457:936b]:8333 +[2602:ffea:1001:125::2ad4]:8333 +[2602:ffea:1001:6ff::837d]:8333 +[2602:ffea:1001:72b::578b]:8333 +[2602:ffea:1001:77a::9cae]:8333 +[2602:ffea:1:2fe::6bc8]:8333 +[2602:ffea:1:701::7968]:8333 +[2602:ffea:1:70d::82ec]:8333 +[2602:ffea:1:9ff::e957]:8333 +[2602:ffea:1:a5d::4acb]:8333 +[2602:ffea:a::24c4:d9fd]:8333 +[2602:ffea:a::c06:ae32]:8333 +[2604:0:c1:100:1ec1:deff:fe54:2235]:8333 +[2604:180:1:1af::42a9]:8333 +[2604:180::b208:398]:8333 +[2604:2880::6072:aed]:8333 +[2604:4080:1114:0:3285:a9ff:fe93:850c]:8333 +[2604:7c00:17:3d0::5a4d]:8333 +[2604:9a00:2100:a009:2::]:8333 +[2604:a880:1:20::22a:4001]:8333 +[2604:a880:800:10::752:f001]:8333 +[2604:c00:88:32:216:3eff:fee4:fcca]:8333 +[2604:c00:88:32:216:3eff:fef5:bc21]:8333 +[2605:7980:1:2::1761:3d4e]:8333 +[2605:e000:1417:4068:223:32ff:fe96:e2d]:8333 +[2606:6000:a441:9903:5054:ff:fe78:66ff]:8333 +[2606:df00:2::ae85:8fc6]:8333 +[2607:5300:100:200::e7f]:8333 +[2607:5300:10::a1]:8333 +[2607:5300:60:116e::1]:8333 +[2607:5300:60:1535::]:8333 +[2607:5300:60:1b32::1]:8333 +[2607:5300:60:2337::1]:8333 +[2607:5300:60:2b90::1]:8333 +[2607:5300:60:2d99::1]:8333 +[2607:5300:60:3cb::1]:8333 +[2607:5300:60:4a85::]:8333 +[2607:5300:60:5112:0:2:4af5:63fe]:8333 +[2607:5300:60:6dd5::]:8333 +[2607:5300:60:a91::1]:8333 +[2607:f1c0:820:1500::7f:3f44]:8333 +[2607:f1c0:848:1000::48:943c]:8333 +[2607:f948:0:1::7]:8333 +[2607:fcd0:100:2300::4ad:e594]:8333 +[2607:fcd0:100:2300::659e:9cb3]:8333 +[2607:fcd0:100:2300::c74b:a8ae]:8333 +[2607:fcd0:100:2300::d82:d8c2]:8333 +[2607:fcd0:100:4300::8795:2fa8]:8333 +[2607:fcd0:daaa:901::9561:e043]:8333 +[2a00:1178:2:43:5054:ff:fee7:2eb6]:8333 +[2a00:1328:e100:cc42:230:48ff:fe92:55d]:8333 +[2a00:14f0:e000:80d2:cd1a::1]:8333 +[2a00:16d8:c::5b6a:c261]:8333 +[2a00:61e0:4083:6d01:6852:1376:e972:2091]:8333 +[2a00:c98:2030:a02f:2::2]:8333 +[2a01:1b0:7999:402::131]:8333 +[2a01:1e8:e100:811c:700f:65f0:f72a:1084]:8333 +[2a01:238:42da:c500:6546:1293:5422:ab40]:8333 +[2a01:348:6:473::2]:8333 +[2a01:368:e010:2::2]:8333 +[2a01:430:17:1::ffff:549]:8333 +[2a01:430:17:1::ffff:830]:8333 +[2a01:488:66:1000:53a9:d04:0:1]:8333 +[2a01:488:66:1000:57e6:578c:0:1]:8333 +[2a01:488:66:1000:b01c:178d:0:1]:8333 +[2a01:488:67:1000:523:fdce:0:1]:8333 +[2a01:488:67:1000:b01c:30ab:0:1]:8333 +[2a01:4f8:100:24aa::2]:8333 +[2a01:4f8:100:44e7::2]:8333 +[2a01:4f8:100:5128::2]:8333 +[2a01:4f8:100:84a7::1:1]:8333 +[2a01:4f8:110:516c::2]:8333 +[2a01:4f8:110:536e::2]:8333 +[2a01:4f8:120:62e6::2]:8333 +[2a01:4f8:120:702e::2]:8333 +[2a01:4f8:120:8005::2]:8333 +[2a01:4f8:120:8203::2]:8333 +[2a01:4f8:120:8422::2]:8333 +[2a01:4f8:121:11eb::2]:8333 +[2a01:4f8:121:261::2]:8333 +[2a01:4f8:130:242b::10]:8333 +[2a01:4f8:130:242b::5]:8333 +[2a01:4f8:130:2468::3]:8333 +[2a01:4f8:130:632c::2]:8333 +[2a01:4f8:130:6366::2]:8333 +[2a01:4f8:130:6426::2]:8333 +[2a01:4f8:130:934f::2]:8333 +[2a01:4f8:131:2070::2]:8333 +[2a01:4f8:131:54a2::2]:8333 +[2a01:4f8:140:80ad::2]:8333 +[2a01:4f8:141:186::2]:8333 +[2a01:4f8:150:210b::2]:8333 +[2a01:4f8:150:2263::5]:8333 +[2a01:4f8:150:2349::2]:8333 +[2a01:4f8:150:61ee::2]:8333 +[2a01:4f8:150:7088:5054:ff:fe45:bff2]:8333 +[2a01:4f8:150:8324::2]:9001 +[2a01:4f8:151:1d8::2]:8333 +[2a01:4f8:151:5128::2]:8333 +[2a01:4f8:151:6347::2]:9001 +[2a01:4f8:161:526d::2]:8333 +[2a01:4f8:161:9349::2]:8333 +[2a01:4f8:162:23c6::2]:8333 +[2a01:4f8:162:4348::2]:8333 +[2a01:4f8:162:7345::2]:8333 +[2a01:4f8:162:7383::2]:8333 +[2a01:4f8:162:74e3::2]:8333 +[2a01:4f8:190:6065::2]:8333 +[2a01:4f8:190:6349::2]:8333 +[2a01:4f8:190:64c9::2]:8333 +[2a01:4f8:190:91ce::2]:8333 +[2a01:4f8:191:2194::83]:8333 +[2a01:4f8:191:40a1::2]:8333 +[2a01:4f8:191:4a7::2]:8333 +[2a01:4f8:191:63b4:5000::1]:8333 +[2a01:4f8:191:7121::2]:8333 +[2a01:4f8:191:83a2::2]:8333 +[2a01:4f8:191:93c4::2]:8333 +[2a01:4f8:192:60a9:0:1:5:2]:8333 +[2a01:4f8:192:73b2::2]:8333 +[2a01:4f8:192:8098::2]:8333 +[2a01:4f8:192:db::2]:8333 +[2a01:4f8:200:1012::2]:8333 +[2a01:4f8:200:22e3::2]:8333 +[2a01:4f8:200:414e::2]:8333 +[2a01:4f8:200:63af::222]:8333 +[2a01:4f8:200:71e3:78b4:f3ff:fead:e8cf]:8333 +[2a01:4f8:201:5164::2]:8333 +[2a01:4f8:201:6011::4]:8333 +[2a01:4f8:201:60d5::2]:8333 +[2a01:4f8:202:53c3::2]:8333 +[2a01:4f8:210:24aa::2]:8333 +[2a01:4f8:210:502f::2]:8333 +[2a01:4f8:211:14cf::2]:8333 +[2a01:4f8:211:1a59::2]:8333 +[2a01:4f8:211:2ac1::2]:8333 +[2a01:4f8:211:cca::2]:8333 +[2a01:4f8:a0:22a5::2]:8333 +[2a01:4f8:a0:5023::2]:8333 +[2a01:4f8:a0:5243::2]:8333 +[2a01:4f8:a0:74c8::2]:8333 +[2a01:4f8:a0:8227::2]:8333 +[2a01:4f8:a0:822d::2]:8333 +[2a01:4f8:d13:2183::2]:8333 +[2a01:608:ffff:a009:8bf5:879d:e51a:f837]:8333 +[2a01:79d:469e:ed94:c23f:d5ff:fe65:20c5]:8333 +[2a01:7c8:aab5:3e6:5054:ff:fed7:4e54]:8333 +[2a01:7e00::f03c:91ff:fe18:301e]:8333 +[2a01:7e00::f03c:91ff:fe18:7749]:8333 +[2a01:7e00::f03c:91ff:fe33:2d67]:8333 +[2a01:7e00::f03c:91ff:fe33:347c]:8333 +[2a01:7e00::f03c:91ff:fe33:ae50]:8333 +[2a01:7e00::f03c:91ff:fe56:6b5c]:8333 +[2a01:7e00::f03c:91ff:fe56:bee6]:8333 +[2a01:7e00::f03c:91ff:fe69:4895]:8333 +[2a01:7e00::f03c:91ff:fe69:9912]:8333 +[2a01:7e00::f03c:91ff:fe6e:26ee]:8333 +[2a01:7e00::f03c:91ff:fe73:42f1]:8333 +[2a01:7e00::f03c:91ff:fe84:434f]:8333 +[2a01:7e00::f03c:91ff:fe84:b36b]:8333 +[2a01:7e00::f03c:91ff:fe89:1faa]:8333 +[2a01:7e00::f03c:91ff:fe98:816]:8333 +[2a01:7e00::f03c:91ff:fedb:352e]:8333 +[2a01:7e00::f03c:91ff:fedb:4a1d]:8333 +[2a01:e34:edbb:6750:224:1dff:fe89:3897]:8333 +[2a01:e35:2f1d:3fb0:7187:c7ba:bcfc:80ce]:8333 +[2a01:e35:8787:96f0:9032:9297:39ae:496d]:8333 +[2a01:e35:8a3f:47c0:c617:feff:fe3c:9fbd]:8333 +[2a01:e35:8b66:6a0:4900:9dfd:d841:d025]:8333 +[2a02:168:4a01::39]:8333 +[2a02:168:5404:2:c23f:d5ff:fe6a:512e]:8333 +[2a02:180:1:1::5b8f:538c]:8333 +[2a02:2028:1016::2]:8333 +[2a02:2528:503:2::14]:8333 +[2a02:2528:503:2::15]:8333 +[2a02:2528:ff00:81a6:21e:c5ff:fe8d:f9a5]:8333 +[2a02:2770:5:0:21a:4aff:fee4:c7db]:8333 +[2a02:2770:8:0:21a:4aff:fe7b:3dcd]:8333 +[2a02:348:5e:5a29::1]:8333 +[2a02:7aa0:1619::202f:c06a]:8333 +[2a02:8109:8e40:35fc:ba27:ebff:feae:cf16]:8333 +[2a02:af8:6:1500::1:130]:8333 +[2a02:c200:0:10:1:0:6314:2222]:8333 +[2a02:c200:0:10:2:3:3295:1]:8332 +[2a02:c200:0:10:3:0:5449:1]:8333 +[2a02:c200:1:10:2:3:5899:1]:8333 +[2a02:c200:1:10::2705:1]:8333 +[2a02:ce80:0:20::1]:8333 +[2a02:fe0:c321:27e0:6ef0:49ff:fe11:a61d]:8333 +[2a03:4000:2:496::8]:8333 +[2a03:b0c0:0:1010::62:f001]:8333 +[2a03:f80:ed16:ca7:ea75:b12d:2af:9e2a]:8333 +3ffk7iumtx3cegbi.onion:8333 +3hshaantu6ot4upz.onion:8333 +45c5lc77qgpikafy.onion:8333 +77mx2jsxaoyesz2p.onion:8333 +7g7j54btiaxhtsiy.onion:8333 +b6fr7dlbu2kpiysf.onion:8333 +bitcoincfqcssig5.onion:8333 bitcoinostk4e4re.onion:8333 -5k4vwyy5stro33fb.onion:8333 -zy3kdqowmrb7xm7h.onion:8333 -e3tn727fywnioxrc.onion:8333 -kjy2eqzk4zwi5zd3.onion:8333 -pt2awtcs2ulm75ig.onion:8333 -td7tgof3imei3fm6.onion:8333 -czsbwh4pq4mh3izl.onion:8333 -xdnigz4qn5dbbw2t.onion:8333 -ymnsfdejmc74vcfb.onion:7033 -jxrvw5iqizppbgml.onion:8333 -bk5ejfe56xakvtkk.onion:8333 -szsm43ou7otwwyfv.onion:8333 -5ghqw4wj6hpgfvdg.onion:8333 -evolynhit7shzeet.onion:8333 -4crhf372poejlc44.onion:8333 -tfu4kqfhsw5slqp2.onion:8333 -i2r5tbaizb75h26f.onion:8333 -btcnet3utgzyz2bf.onion:8333 -vso3r6cmjoomhhgg.onion:8333 -pqosrh6wfaucet32.onion:8333 -zy3kdqowmrb7xm7h.onion:8333 -r4de4zf4lyniu4mx.onion:8444 +bmutjfrj5btseddb.onion:8333 +drp4pvejybx2ejdr.onion:8333 +gixnv56d63buypan.onion:8333 +h2vlpudzphzqxutd.onion:8333 +hhiv5pnxenvbf4am.onion:8333 +lzxpkn6ptp3ohh63.onion:8333 +msphsgfiqfq5stne.onion:8333 +ncwk3lutemffcpc4.onion:8333 +okdzjarwekbshnof.onion:8333 +sjdomi4yb2dwkjbc.onion:8333 +uvwozwxlihntigbb.onion:8333 +v6ylz45dn5ybpk4d.onion:8333 +vk3qjdehyy4dwcxw.onion:8333 +vqpye2k5rcqvj5mq.onion:8333 +xudkoztdfrsuyyou.onion:8333 +z55v4ostefnwfy32.onion:8333 diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index 6b6e5103f..423362859 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -2,551 +2,900 @@ #define BITCOIN_CHAINPARAMSSEEDS_H /** * List of fixed seed nodes for the bitcoin network - * AUTOGENERATED by share/seeds/generate-seeds.py + * AUTOGENERATED by contrib/seeds/generate-seeds.py * * Each line contains a 16-byte IPv6 address and a port. * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly. */ static SeedSpec6 pnSeed6_main[] = { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x21,0xc5,0x6e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x22,0xb4,0xf5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x22,0xa8,0x80}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0xca,0x80,0xda}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x23,0xc3,0x19}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x64,0x7b,0x13}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xaf,0x91,0xa9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xc7,0x85,0xc1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xc7,0x97,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xe4,0x01,0xe6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x1e,0x00,0xd2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x60,0xcb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x47,0x82}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x62,0x8d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x66,0x91,0x44}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x87,0xa0,0x4d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbd,0x86,0xf6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xc7,0xa4,0x84}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xf9,0x87,0x66}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x08,0x13,0x2c,0x6e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x08,0x16,0xe6,0x08}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0e,0xc8,0xc8,0x91}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x12,0xe4,0x00,0xbc}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x12,0xe4,0x00,0xc8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x1e,0xf3,0x99}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x58,0xe8,0x31}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x63,0x69,0x09}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe2,0x89,0xd0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe3,0xb1,0xa1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe3,0xbf,0x32}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x18,0xa8,0x61}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x1c,0x23,0xe3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x5c,0x4c,0xaa}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x63,0x40,0x77}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe4,0xa6,0x80}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe5,0x2d,0x20}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xec,0x90,0x45}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xfd,0x94,0x71}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xfd,0xf1,0x16}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xff,0xe3,0xe7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x14,0xcd,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x17,0x78,0xfc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x08,0x69,0x80}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x10,0x45,0x89}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x5e,0x62,0x60}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x62,0x5f,0xc9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x6f,0x5a,0x37}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x77,0x77,0x69}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x8a,0x19,0x95}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x03,0xd6,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xba,0x57,0x2e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xba,0x65,0x62}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xba,0xfa,0xba}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xcc,0x99,0x6b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x2c,0x10,0xe7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x2c,0x2c,0x0b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x78,0xa8,0xcc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x8f,0x56,0x1a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbb,0x4b,0x18}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbc,0x44,0xa9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc0,0x5f,0x96}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc9,0xf6,0x74}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xcd,0x0a,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x0a,0xd2,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x13,0x8a,0x9a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcc,0x7b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcd,0x43}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x66,0x76,0x07}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x76,0xa6,0xe4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x7a,0x85,0x31}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xa6,0x61,0xa2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xd5,0xeb,0xf2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe2,0x6b,0x40}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe4,0xc0,0xab}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1b,0x8c,0x85,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x29,0x28,0x19}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x2b,0x65,0x3b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xb8,0xc3,0xb5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xc1,0x8b,0x42}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc8,0x46,0x66}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xcd,0x0a,0x97}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2a,0x03,0x6a,0xe3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2a,0x3c,0x85,0x6a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x38,0x55,0xe7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x38,0x66,0xe4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x4f,0x82,0xeb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcc,0x3d}, 11101}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x26,0xeb,0xe5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x3b,0x02,0x4a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x65,0x84,0x25}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x65,0xa8,0x32}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa3,0x4c,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xa2,0x5b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xad,0xbe,0x32}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xa1,0x67}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xb6,0x84,0x64}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xdf,0x24,0x5e}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe3,0x42,0x84}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xee,0xbb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xec,0x74,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x37,0x0e,0x41}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x07,0xfc,0xe5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x2e,0x9f,0x5b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x4e,0x31,0xb5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x4e,0xe7,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x4f,0x99,0x41}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x74,0x22,0x2c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x7e,0x56,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x8e,0x29,0x17}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xc7,0x71,0xc1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xc8,0x4e,0x6b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xce,0x8a,0xb1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xfc,0x34,0x31}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xa5,0x19,0x4b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xa9,0x6b,0x28}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xb3,0xbe,0x38}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xbb,0x52,0x79}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xf6,0x55,0xf6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0x4a,0x07,0xcd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0x60,0xb7,0x79}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x3e,0x3a,0x26}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x3f,0x5b,0x48}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x3f,0x5b,0x70}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x48,0xd3,0xe4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2b,0x28,0x9a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe3,0x42,0x8a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xef,0x6b,0x4a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xf9,0x27,0x64}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xfa,0x62,0x6c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x07,0x25,0x72}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x51,0x35,0x97}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x73,0x2b,0xfd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x74,0x14,0x57}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x74,0x21,0x5c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x7d,0xa7,0xf5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x8f,0x09,0x33}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xbc,0xc0,0x85}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x4d,0xa2,0x4c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x99,0x61,0x6d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xa5,0xc0,0x7d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0x60,0x69,0x55}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3b,0xa7,0xc4,0x87}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3c,0x1d,0xe3,0xa3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x23,0xe1,0x13}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2b,0x82,0xb2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x50,0xb9,0xd5}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x6d,0x31,0x1a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xad,0x8b,0x3a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xb5,0xee,0xba}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd2,0x72,0x7f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x8d,0xe4,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x99,0xd5,0x4e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0xdf,0x54,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0xfb,0x58,0x70}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x1f,0x6e,0x32}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x22,0x79,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x72,0x06,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x8c,0x7d,0x62}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xca,0x00,0x61}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd2,0x42,0xe3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd2,0xc0,0xa9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x4a,0x62,0xcd}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x9c,0xc1,0x64}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x1e,0x2f,0x74}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x23,0x84,0xb1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0xcb,0x66,0x56}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0xe5,0x8e,0x30}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x60,0xc1,0xa5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x6f,0xbd,0x1a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x44,0x0a,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x72,0x21,0xfa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x82,0x2e,0x3f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xaf,0xd7,0x87}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xbe,0xfd,0xa5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xc2,0x26,0xfe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xf4,0x62,0x6f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xa2,0xee,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xa9,0xff,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xb7,0xad,0x19}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x1e,0x03,0x07}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x72,0x21,0x31}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x76,0x85,0xc2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x87,0x0a,0x7e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xac,0x0a,0x04}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xc2,0x26,0xfa}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xc2,0x26,0xfd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xd7,0xc0,0x68}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x3c,0x62,0x73}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xa4,0x23,0x24}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xbf,0xa2,0xf4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xcf,0xc3,0x4d}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xdb,0xe9,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xe3,0xf0,0x73}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xf7,0xde,0x47}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x2b,0x72,0x42}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x34,0x21,0x24}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc6,0xf5,0xf1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x0c,0xe2,0xa5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x0d,0xc6,0xbc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x0f,0xb3,0x3e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x27,0xef,0x2f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x2f,0x2d,0x57}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x3e,0xd9,0xce}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x2a,0x1f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x51,0x3d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x43,0xdb,0xc8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x5a,0x84,0x9d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x5e,0x1e,0xb1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x88,0xaf,0xf1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x3d,0x61,0xe4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x7b,0x76,0x84}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x3b,0x98,0xb6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc6,0xf8,0x97}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc8,0xf2,0x59}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xe1,0xb3,0x9d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x0e,0xbb,0x33}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x26,0x22,0xb4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x34,0x48,0xbb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x5b,0x90,0xb6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xa7,0x31,0xd9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xc9,0xf3,0x37}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xdf,0x3c,0xf9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xe4,0x99,0x66}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x1a,0x65,0xe4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x32,0x9e,0xc8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0xb5,0xcc,0xaa}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xdd,0xc1,0x37}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xe4,0xa2,0xe4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x32,0x43,0xc7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x3e,0x03,0xcb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x41,0xcd,0xe2}, 9000}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x6a,0x2a,0xbf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x96,0xb5,0xc6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc4,0xc4,0x6a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xe0,0xc2,0x51}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x2e,0x05,0xc2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x32,0xab,0xee}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x2b,0x98}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x41,0x29,0x0d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x5a,0x84,0xc8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x8f,0x01,0xf3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x92,0x62,0xd8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xa5,0xf6,0x26}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xcf,0x06,0x87}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xfb,0xd0,0x1a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x26,0x01,0x65}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x26,0x09,0x42}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x5a,0x02,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x3a,0xe4,0xe2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc7,0x0b,0xbd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc7,0xc1,0xca}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xcd,0xe8,0xb5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xec,0xc8,0xa2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x18,0x49,0xba}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x34,0x82,0x6e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x35,0x6f,0x25}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xeb,0x26,0x46}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x1f,0xab,0x95}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x20,0x89,0x48}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x89,0x85,0xee}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0xb5,0xc0,0x67}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0xbe,0x02,0x3c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0xc3,0xc0,0x89}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0xde,0x23,0x75}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x39,0xc7,0xb4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x3f,0xde,0xe2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x51,0xe7,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xc1,0x7e,0x52}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xcf,0xeb,0xa4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x53,0xc5,0x72}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x90,0x72,0x09}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x70,0x05,0xf7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xae,0x14,0xf7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x25,0xf0,0x8e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x39,0xca,0x6b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xac,0x7b,0x35}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xdd,0x5b,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xeb,0x30,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xf5,0x4e,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x08,0x3a,0xf9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x1b,0xbf,0xb6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x81,0xec,0x8d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x83,0x58,0x2f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x9d,0xcd,0x06}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x52,0xe9,0xcd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x55,0x42,0x52}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x65,0xe0,0x7f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x71,0x45,0x10}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x7a,0xeb,0x44}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xc1,0x44,0x8d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xd0,0xa4,0xdb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x64,0x25,0x7a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x91,0x95,0xa9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0xa8,0x22,0x14}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x14,0x2c,0xf0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x64,0x46,0x11}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xa8,0x03,0xef}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xba,0x8c,0x67}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x5c,0x44,0xdd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x6d,0x65,0x8e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x6e,0x0b,0x56}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xf2,0x6c,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x2e,0x60,0x96}, 9020}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x54,0x64,0x5f}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x84,0xe6,0x90}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x8f,0xbc,0x9b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa0,0xdd,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa1,0x6f,0x72}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x64,0xbd,0x03}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x93,0x8c,0x79}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xcb,0x4b,0x85}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xdc,0x63,0xe3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xde,0x14,0xa9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xf1,0x01,0x07}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x17,0xbf,0xf3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x26,0x0b,0xca}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x85,0x2b,0x3f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa0,0x4c,0x99}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa9,0x22,0x18}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xbc,0x07,0x4e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd9,0xe2,0x19}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xdf,0x64,0xb3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xf0,0x81,0xdd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x01,0xad,0xf3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x0b,0x32}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x10,0x11}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x42,0x6f,0x03}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x50,0x09,0x47}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x6e,0xd5,0xa5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x85,0x9b,0xed}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x8c,0x2b,0x8a}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xab,0x22,0x25}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xb5,0x9b,0xb4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x27,0x9c,0x89}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x49,0xa1,0x5f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x82,0x2d,0x28}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa5,0x99,0x2f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa8,0x80,0x85}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xb3,0xe1,0x76}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc2,0xf5,0x9e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xae,0xf7,0x32}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xb5,0x9b,0x35}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xb8,0x05,0xfd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xbb,0x45,0x82}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xe6,0x03,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x2a,0x80,0x33}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x4a,0xe2,0x15}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x8e,0x4b,0x32}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc7,0x66,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd3,0x1e,0xf3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd9,0x85,0x91}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc8,0xcd,0x1e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x6c,0x15}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x80,0x23}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x83,0xb1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xe9,0xe1,0xcd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x00,0xf9,0x92}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x59,0x1f,0xf9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x80,0x1d,0xe7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x80,0xfd,0x8e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x8f,0x82,0x38}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x96,0x02,0x63}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xee,0x7c,0x29}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xf2,0x00,0xf5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x4c,0x7b,0x6e}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x96,0x09,0xc4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa1,0x40,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xd4,0x67,0xd4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xd4,0x6f,0x72}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf6,0x4b,0x08}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xfe,0x51,0x1f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xfe,0x96,0x36}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa2,0xc4,0xc0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa2,0xea,0xe0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xaa,0x68,0x5b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xff,0x42,0x76}, 8334}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x02,0x22,0x68}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x0f,0x3d,0x3c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x11,0x19,0x87}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x2a,0x90,0x13}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd4,0xd2,0x87}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd7,0xa5,0xe7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x2d,0x62,0x5b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x2f,0xa1,0x96}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd4,0xc0,0x83}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd7,0xa9,0x65}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xee,0x8c,0xb0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf0,0x1f,0xb8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x19,0xd6,0x89}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x8b,0xa3,0x84}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf5,0x47,0x1f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x11,0x04,0xd4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x72,0x80,0x86}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x9f,0xed,0xbf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xa6,0x82,0xbd}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xc7,0x04,0xe4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x3d,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x6c,0x4d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x7b,0x10,0x11}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x42,0xa8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0xc3,0xd2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xe5,0x00,0x49}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x15,0x60,0x2d}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x30,0x2a,0xc7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x51,0x8f,0x52}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x51,0xfb,0x48}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x68,0x18,0xb9}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x68,0xa8,0x68}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xe5,0x49,0xab}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xec,0xc4,0x4d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x61,0x38,0x62}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x86,0xb2,0x59}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x96,0xe9,0x13}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xa8,0x85,0x03}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x12,0xf6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x21,0xca}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x12,0x1c,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x55,0xdc,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x75,0xea,0x47}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x76,0x60,0xc5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x91,0x0c,0x39}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x9f,0xaa,0xbe}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x96,0xa8,0xa0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x00,0x4f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x00,0x95}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd6,0xc2,0xe2}, 8343}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x01,0x0b,0x20}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x24,0xeb,0x6c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x43,0x60,0x02}, 15321}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x62,0x10,0x29}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x6c,0x48,0xc3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x9c,0x23,0x9d}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xa3,0xe3,0x1c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xb8,0x53,0x3c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xd4,0x21,0xed}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xd4,0xa0,0xa5}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xe7,0x60,0x53}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xec,0x31,0x75}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x5a,0x42,0xd1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xf8,0xa4,0x40}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x95,0xc1,0xc7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x4d,0xef,0xf5}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x6a,0xc2,0x61}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x86,0x4b,0x73}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x98,0xc1,0x24}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x98,0xdb,0x23}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xc5,0x0a,0xea}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x7e,0x4d,0x4d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x86,0x26,0xc3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x9c,0x61,0xb5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xcf,0x44,0x90}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd1,0x4d,0x65}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd2,0x6a,0x93}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd6,0xc8,0xcd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xdf,0x73,0x26}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xea,0x30,0xe8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xfa,0x56,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xdc,0x83,0xf2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xdc,0xa3,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe9,0x17,0x23}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x0d,0x60,0x5d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x0e,0x4a,0x72}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x1b,0x07,0xd1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xdd,0xe4,0x0d}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xff,0xcf,0x49}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x48,0xa7,0x94}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x4a,0xa3,0xea}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x54,0x72,0x6a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x7b,0xae,0x42}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x98,0xa6,0x1d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xab,0xd8,0xdd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xb9,0xb1,0x47}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xb5,0x2d,0xbc}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x13,0x0c,0xf4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x2a,0x73,0x32}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x4f,0xb1,0xce}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x88,0x93,0x77}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x8f,0xf5,0x05}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xbc,0x32,0x27}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xbe,0xe3,0x70}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xc6,0x87,0x1d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xe0,0xa2,0x41}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xe2,0x6b,0x56}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf2,0xdb,0x5a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf2,0xe5,0xa8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf4,0xa0,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf2,0xc6,0xa1}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x1f,0x0a,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x55,0x19,0x29}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x69,0xa1,0x88}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9a,0xa5,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9a,0xc8,0xd8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xa7,0x6d,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd3,0x7d,0xe7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd3,0xd8,0xeb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x21,0x19,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x2b,0x82,0xb2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x76,0x08,0xec}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x66,0x06,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xca,0x14,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xd9,0x7d,0xe1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xea,0xd2,0x6f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xed,0x14,0x7b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xff,0x90,0xb0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0x71,0x40,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xe5,0x16,0x08}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x01,0xd4,0x13}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x41,0x48,0xf4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x54,0xa2,0x5f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x5a,0x8b,0x2e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xb7,0x31,0x1b}, 8005}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd7,0x2f,0x85}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x17,0x43,0x55}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x2c,0xa6,0xbe}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x5d,0xe1,0x4a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x1a,0x00,0x22}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x1b,0xe1,0x66}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xe5,0x75,0xe5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xf9,0x44,0x7d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xff,0x05,0x9b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0x65,0xf0,0x72}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0x64,0xae,0x8a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0xfb,0xcb,0x06}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x03,0x3c,0x3d}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x1e,0x2a,0xbd}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xe0,0xa5,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xf3,0x5e,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x83,0x6b,0x6b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x83,0x74,0xb8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x24,0x53,0xe9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x25,0x81,0x16}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x36,0xc0,0xfb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x80,0xe4,0xfc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x80,0xe6,0xb9}, 8334}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x82,0xa1,0x2f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x83,0x21,0x3c}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x8f,0x00,0x9c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xdb,0xb8,0x09}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6a,0xb9,0x26,0xae}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0x9c,0x6f,0x48}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xa7,0x6f,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc1,0x28,0xf8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc5,0x07,0xae}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc5,0x08,0xfa}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xdf,0x01,0x85}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xec,0x61,0x8c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xee,0x80,0xd6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xee,0x82,0xb6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6a,0x26,0xea,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6a,0xb9,0x24,0xcc}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x06,0x04,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x96,0x08,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x96,0x21,0x14}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xaa,0xe4,0x81}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xaa,0xf0,0xad}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x33,0x14,0x56}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3d,0x95,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3d,0x97,0xac}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xa1,0x81,0xf7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xaa,0x8c,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x3c,0xd3,0xd8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x49,0x2a,0x24}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x49,0xac,0x8a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x96,0x02,0x06}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x96,0x28,0xea}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x9b,0x6c,0x82}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xa1,0xb6,0x73}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xaa,0x42,0xe7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xbe,0x80,0xe2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xbf,0x6a,0x73}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x10,0x02,0x3d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x46,0x04,0xa8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xa2,0x23,0xc4}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xa3,0xeb,0xef}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xbe,0xc4,0xdc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xc9,0x87,0xd8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe4,0x98,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe4,0x9a,0x51}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe6,0xdc,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xea,0x9c,0xda}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xeb,0x31,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xeb,0x45,0x54}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x70,0x7c,0x47,0x00}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x71,0x92,0x44,0xfb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x1d,0x11,0x52}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x46,0xb0,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x75,0x29,0xa2,0xb8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x1b,0x08,0xaa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0xe6,0x07,0xd3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0xf6,0x47,0x34}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xac,0x08,0x64}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7a,0x80,0x6d,0x94}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0xe7,0xe0,0x3f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xbf,0x27,0x3c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xea,0x6a,0xbf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xee,0x51,0x52}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x72,0x4c,0x93,0x1b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x1c,0xe0,0x7f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x44,0x6e,0x52}, 18333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x61,0x4f,0xda}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0xbd,0xcf,0xc5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0xe4,0x60,0xe9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0x93,0xb2,0x51}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0x29,0x7b,0x05}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0x43,0x05,0xe6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7a,0x6b,0x8f,0x6e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0x02,0xaa,0x62}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0x6e,0x41,0x5e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0xc1,0x8b,0x13}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7d,0xef,0xa0,0x29}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x65,0xa2,0xc1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x6f,0x49,0x0a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x8c,0xe5,0x49}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xaf,0xc3,0x1f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xa4,0x60}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xfe,0xf4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x61,0x45,0x4c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0x6b,0x3f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xc7,0xc0,0x99}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0xfd,0x03,0xc1}, 20020}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x7b,0x07,0x07}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x7b,0x07,0x27}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0xba,0x11,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xf7,0xa9,0xbe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x85,0xf2,0xd1,0x3f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x66,0x5e,0x26}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x77,0x11,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0x74,0xa0,0xb0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x82,0x59,0xa0,0xea}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x48,0x8b,0xa4}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xbf,0x70,0x62}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x85,0x01,0x86,0xa2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x13,0x84,0x35}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0xe2,0x22,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0xd2,0xd9,0xaa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0xff,0xa6,0xc2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x29,0x02,0xac}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0xff,0x80,0xcc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8e,0xd9,0x0c,0x6a}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8f,0xd7,0x81,0x7e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0xf4,0x13}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0x94,0x34,0xa2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0x94,0x50,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0x13,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0x8e,0x56}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0xfd,0x33}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0xfb,0x06,0xd6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0x9a,0x9b,0xeb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0x00,0x20,0x65}, 8337}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x93,0xe5,0x0d,0xc7}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0xd2,0x85,0xf4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x97,0xe0,0xf8,0xfc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x79,0x4b,0xe5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x7f,0xfb,0x43}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0xd2,0xa2,0xbb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0x65,0xa3,0xf1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x97,0xec,0x0b,0xbd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x79,0x42,0xd3}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0x14,0x02,0x8b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x0d,0x3d,0x05}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x3a,0xad,0x30}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xfd,0x17,0x84}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd1,0x6e,0xda}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd5,0xfe,0xcd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xef,0xfe,0x64}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf2,0x96,0x27}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0x51,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0xeb,0x38}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf4,0x4f,0x10}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf5,0xd9,0x77}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd1,0x6a,0x7b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd2,0xc6,0xb8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xda,0x41,0x79}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xde,0xa1,0x31}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0x84,0x06}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0x84,0x3a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf8,0x63,0xa4}, 53011}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf8,0x66,0x75}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xfb,0x6c,0x35}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xfe,0x95,0x8b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xff,0x74,0x4e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa6,0x46,0x5e,0x6a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa7,0x58,0x2d,0x7c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa7,0x58,0x78,0xd2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x1a,0x31,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x1e,0x0e,0x06}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x50,0x72,0xc5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xa7,0xd6,0xf3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd0,0xdb,0x6c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xdc,0x43,0x9c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xec,0x65,0x22}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xf6,0x6b,0x22}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xff,0xed,0xf1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x02,0xd5,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x33,0x17,0xe0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x33,0x7b,0x9f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x39,0xd4,0x79}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa3,0x9e,0x23,0x6e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa4,0x0f,0x0a,0xbd}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa4,0x28,0x86,0xab}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa6,0xe6,0x47,0x43}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa7,0xa0,0xa1,0xc7}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa8,0x67,0xc3,0xfa}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa8,0x90,0x1b,0x70}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa8,0x9e,0x81,0x1d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaa,0x4b,0xa2,0x56}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x5a,0x63,0xae}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0xf5,0x05,0x9c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x17,0xa6,0x2f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x20,0x0b,0xc2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x22,0xcb,0x4c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xab,0x01,0x34}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xaf,0x88,0x0d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xe6,0xe4,0x8b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xf7,0xc1,0x46}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x31,0x84,0x1c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x34,0xca,0x48}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x35,0x4c,0x57}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x6d,0x21,0x1c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaf,0x7e,0x7c,0x5b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaf,0x7e,0x7c,0x5c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x0a,0x74,0xf2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x24,0x23,0x7e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x24,0x63,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7c,0x6e,0x2f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xc2,0x21,0x2c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xdf,0xc9,0xc6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0x1a,0x53}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0x24,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0xd4,0x8d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0xfe,0x3b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x4e,0xfa,0x03}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x9b,0x56,0xe2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x1c,0x0c,0xa9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x23,0xb6,0xd6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x24,0x21,0x71}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x24,0x21,0x79}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x3a,0x60,0xad}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x79,0x4c,0x54}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0x46,0x10}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3e,0x6f,0x1a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x4c,0xa9,0x3b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x4f,0x83,0x20}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xa2,0xc7,0xd8}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xaf,0x86,0x23}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xf8,0x6f,0x04}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x01,0xaa}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x22,0xa1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb3,0x2b,0x72,0x0e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb6,0xd5,0xd0,0x1c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb3,0x2b,0x8f,0x78}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb3,0xd0,0x9c,0xc6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb4,0xc8,0x80,0x3a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x4e,0xa9,0x6c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x60,0x60,0x98}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x44,0x02,0x2e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x48,0xee,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x5e,0xe2,0x22}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x49,0xa0,0xa0}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x5e,0xe3,0x3a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x6b,0x8b,0x3a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x6b,0xce,0x2d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0a,0x30,0x75}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x15,0xd8,0x9c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x26,0x2f,0xe0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x98,0x44,0xa3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x07,0x23,0x72}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x1c,0x4c,0xb3}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x1f,0xa0,0xca}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x2d,0xc0,0x81}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x35,0x81,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x35,0x83,0x72}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x37,0x35,0x3d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x37,0x35,0x3f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3d,0x77,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3d,0x94,0xcb}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x42,0x8c,0x0f}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0x02,0xa7,0x17}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x5c,0x4b,0xb2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x7a,0x5c,0x86}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x09,0xd0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xa5,0xd1,0x94}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xe2,0xce,0xef}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x0a,0x08,0x7c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x0a,0x0a,0x93}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x00,0x82,0x8e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x03,0x59,0x9f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x49,0xea,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x4b,0x5f,0x6b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x5f,0x64,0x66}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x9b,0x54,0xb5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa9,0xe9,0xce}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xc6,0x5d,0x56}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xe3,0x87,0xd8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0xdc,0x65,0x8e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x1a,0x05,0x21}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x4b,0x88,0x92}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x78,0xc2,0x8c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x79,0x05,0x96}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x00,0x72}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x21,0xef}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xa6,0x00,0x52}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xb6,0x6c,0x81}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xbf,0x61,0xd0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xe2,0xc6,0x66}, 8001}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x0a,0x09,0xd9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x4b,0x8f,0x90}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x8b,0x66,0x92}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbf,0xed,0x40,0x1c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x03,0x83,0x3d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x63,0xe1,0x03}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x6e,0xa0,0x7a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x92,0x89,0x01}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xb7,0xc6,0xcc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xcb,0xe4,0x47}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x00,0x6d,0x03}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x4d,0x32,0xd0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x6d,0x44,0x3e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x96,0x79,0x25}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xe0,0x45,0x62}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x4f,0x08,0x25}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x8d,0x56,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x0c,0xb4,0x5e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x38,0x3f,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x74,0x5d,0x5d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x9a,0xae,0xe2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x0c,0xee,0xcc}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x5b,0xc8,0x55}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xea,0xe1,0x9c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x06,0xe9,0x26}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x3f,0x8f,0x88}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x7e,0x64,0xf6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x86,0x63,0xc3}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x9f,0x6f,0x62}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xa9,0x8a,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xbd,0x7e,0x23}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x9f,0xe2,0x8b}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xc5,0xaf,0xbe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc5,0xf2,0x5d,0x52}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x0b,0xd6,0x93}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x31,0x29,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x21,0x7c,0xba}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xcc,0xba,0x92}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xe9,0xee,0x73}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf1,0xbd,0x42}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x30,0xc7,0x6c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x39,0xd0,0x86}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x39,0xd2,0x1b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x3e,0x6d,0xdf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xa7,0x8c,0x08}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xa7,0x8c,0x12}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x5b,0xad,0xea}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x7f,0xe2,0xf5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xb4,0x86,0x74}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x07,0x60,0x63}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc9,0xa0,0x6a,0x56}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x37,0x57,0x2d}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x3c,0x44,0xf2}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x3c,0x45,0xe8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0xb7,0x97,0x27}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x7c,0x6d,0x67}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x1e,0xc5,0x4d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x58,0xa0,0x2b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x97,0x8c,0x0e}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0xdb,0x0e,0xcc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x2c,0x7b,0x6d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x2c,0x7b,0xa2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x2d,0x78,0xb2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xbe,0x86,0x2c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xf8,0xb8,0x7f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcd,0x93,0x28,0x3e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xeb,0x27,0xd6}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xf4,0x49,0x08}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x42,0x1e,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x51,0x09,0xdf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x69,0xf3,0xe5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x7e,0x46,0x9f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x8c,0x1e,0xa9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xa5,0x80,0xeb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xbe,0x02,0xf2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0x42,0xfe,0xec}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0x49,0x1b,0x21}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x0c,0x40,0xe1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x4c,0xc8,0xc8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x28,0x60,0x79}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x7e,0x6b,0xb0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x8d,0x28,0x95}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xbe,0x4b,0x3b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xd0,0x6f,0x8e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0x36,0x22,0xa4}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd3,0x48,0x42,0xe5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x19,0x25,0x7c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x47,0xeb,0x72}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x47,0xfc,0x6d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x72,0x30,0x1f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xae,0x97,0x76}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x33,0x90,0x2a}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x70,0x21,0x9d}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x74,0x48,0x3f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x7e,0x0e,0x7a}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x42,0xcd,0xc2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x81,0xf8,0x8b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x88,0x57,0x22}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xa5,0x52,0x85}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xa7,0x11,0x06}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xb3,0x9e,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xbd,0x35,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xde,0xd0,0x5d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x31,0x9e,0xa1}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x6f,0xc4,0x15}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x7a,0x6b,0x66}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x88,0x4b,0xaf}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x9b,0x07,0x18}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xa3,0x40,0x1f}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xa3,0x40,0xd0}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xa5,0x56,0x88}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xb8,0x08,0x16}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x0f,0x4e,0xb6}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x37,0x8f,0x9a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x83,0x5b,0x64}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xf5,0xce,0xb5}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x73,0xeb,0x20}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x7e,0xe2,0xa6}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x91,0x43,0x57}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xa9,0x8d,0xa9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xf9,0x5c,0xe6}, 8333}, {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xfa,0x8a,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x0b,0xe1,0xbd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x06,0x85}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x4b,0x58,0xb2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xac,0x8f,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xc3,0xa9,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xc4,0xf8,0x6a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdb,0x8a,0xa1,0xa2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xa7,0xf8,0x5a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdf,0x12,0xfe,0x37}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x14,0xab,0x2b}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x02,0x47}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x02,0xf2}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x19,0x09,0x4c}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x28,0xe2,0xa9}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x7b,0x62,0x09}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x9b,0x24,0x3e}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xac,0x20,0x12}, 20993}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xda,0x3d,0xc4,0xca}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xda,0xe7,0xcd,0x29}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0xe9,0x4d,0xc8}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdf,0x12,0xe2,0x55}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdf,0xc5,0xcb,0x52}, 8333}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdf,0xff,0xa6,0x8e}, 8333}, + {{0x20,0x01,0x12,0x91,0x02,0xbf,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00}, 8333}, + {{0x20,0x01,0x14,0x18,0x01,0x00,0x05,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x16,0xd8,0xdd,0x24,0x00,0x00,0x86,0xc9,0x68,0x1e,0xf9,0x31,0x02,0x56}, 8333}, + {{0x20,0x01,0x19,0xf0,0x16,0x24,0x00,0xe6,0x00,0x00,0x00,0x00,0x57,0x9d,0x94,0x28}, 8333}, + {{0x20,0x01,0x19,0xf0,0x03,0x00,0x13,0x40,0x02,0x25,0x90,0xff,0xfe,0xc9,0x2b,0x6d}, 8333}, + {{0x20,0x01,0x19,0xf0,0x40,0x09,0x14,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64}, 8333}, + {{0x20,0x01,0x1b,0x40,0x50,0x00,0x00,0x2e,0x00,0x00,0x00,0x00,0x3f,0xb0,0x65,0x71}, 8333}, + {{0x20,0x01,0x04,0x10,0xa0,0x00,0x40,0x50,0x84,0x63,0x90,0xb0,0xff,0xfb,0x4e,0x58}, 8333}, + {{0x20,0x01,0x04,0x10,0xa0,0x02,0xca,0xfe,0x84,0x63,0x90,0xb0,0xff,0xfb,0x4e,0x58}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0x54,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0x6a,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0x6c,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0x8b,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xa3,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xb8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xc1,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xc8,0xd7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xdd,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xe2,0x9d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xf5,0x9f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xf7,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x01,0xff,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0x2f,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0x37,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8200}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0x3e,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0x86,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0x9c,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0xa2,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0xad,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0xb7,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0xee,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0xf1,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x02,0xfa,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x51,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x36}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x52,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xa1}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x52,0x0c,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xf5}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x52,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xc0}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x52,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0xf2}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0x10,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0x4a,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x7c}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0x67,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0xb7,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0xc3,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0xd2,0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0xd5,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x08,0xeb,0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x16,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x2b,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x3a,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x49,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x05,0x7b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x5c,0x7a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6c,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xf4,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0b,0x08,0x54,0x0b,0x7c,0x0b,0x7c,0x0b,0x7c,0x0b,0x7c}, 8333}, + {{0x20,0x01,0x41,0xd0,0x00,0x0d,0x11,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x20,0x01,0x44,0xb8,0x41,0x16,0x78,0x01,0x42,0x16,0x7e,0xff,0xfe,0x78,0x3f,0xe4}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x08,0x08,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x08,0x0c,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x09,0x0b,0xca,0x02,0x18,0x7d,0xff,0xfe,0x10,0xbe,0x33}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x0f,0x02,0x2d,0x00,0x00,0x00,0x00,0x02,0x12,0x00,0x26}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x11,0x12,0xd5,0x00,0x00,0x00,0x00,0x0a,0xe1,0x56,0x11}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x14,0x05,0x7a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x14,0x00,0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x15,0x05,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x04,0x70,0x1f,0x15,0x0d,0xda,0x3d,0x9a,0x3f,0x11,0x9a,0x56,0xed,0x64}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x25,0x04,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x25,0x00,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x04,0x02,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x5f,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x32}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x66,0x01,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x67,0x03,0x9d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x71}, 8333}, + {{0x20,0x01,0x04,0x70,0x6c,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xca,0xfe}, 8333}, + {{0x20,0x01,0x04,0x70,0x00,0x08,0x02,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43}, 8333}, + {{0x20,0x01,0x04,0x70,0x90,0xa7,0x00,0x96,0x00,0x00,0x00,0x00,0x0a,0xfe,0x60,0x21}, 8333}, + {{0x20,0x01,0x04,0x70,0x95,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x04,0x70,0xb1,0xd0,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00}, 8333}, + {{0x20,0x01,0x04,0x70,0xc1,0xf2,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01}, 8333}, + {{0x20,0x01,0x04,0x70,0xd0,0x0d,0x00,0x00,0x36,0x64,0xa9,0xff,0xfe,0x9a,0x51,0x50}, 8333}, + {{0x20,0x01,0x04,0x70,0xe2,0x50,0x00,0x00,0x02,0x11,0x11,0xff,0xfe,0xb9,0x92,0x4c}, 8333}, + {{0x20,0x01,0x48,0x00,0x78,0x17,0x01,0x01,0xbe,0x76,0x4e,0xff,0xfe,0x04,0xdc,0x52}, 8333}, + {{0x20,0x01,0x48,0x00,0x78,0x19,0x01,0x04,0xbe,0x76,0x4e,0xff,0xfe,0x04,0x78,0x09}, 8333}, + {{0x20,0x01,0x48,0x00,0x78,0x19,0x01,0x04,0xbe,0x76,0x4e,0xff,0xfe,0x05,0xc8,0x28}, 8333}, + {{0x20,0x01,0x48,0x02,0x78,0x00,0x00,0x02,0x30,0xd7,0x17,0x75,0xff,0x20,0x18,0x58}, 8333}, + {{0x20,0x01,0x48,0x02,0x78,0x02,0x01,0x01,0xbe,0x76,0x4e,0xff,0xfe,0x20,0x02,0x56}, 8333}, + {{0x20,0x01,0x48,0x02,0x78,0x02,0x01,0x03,0xbe,0x76,0x4e,0xff,0xfe,0x20,0x2d,0xe8}, 8333}, + {{0x20,0x01,0x48,0x30,0x11,0x00,0x02,0xe8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x4b,0xa0,0xff,0xf7,0x01,0x81,0xde,0xad,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x01,0x4b,0xa0,0xff,0xfa,0x00,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93}, 8333}, + {{0x20,0x01,0x4b,0xa0,0xff,0xff,0x01,0xbe,0x00,0x01,0x10,0x05,0x00,0x00,0x00,0x01}, 8335}, + {{0x20,0x01,0x4c,0x48,0x01,0x10,0x01,0x01,0x02,0x16,0x3e,0xff,0xfe,0x24,0x11,0x62}, 8333}, + {{0x20,0x01,0x4d,0xd0,0xf1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32}, 8333}, + {{0x20,0x01,0x4d,0xd0,0xff,0x00,0x86,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, + {{0x20,0x01,0x4d,0xd0,0xff,0x00,0x9a,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09}, 8333}, + {{0x20,0x01,0x4d,0xd0,0xff,0x00,0x9c,0x55,0xc2,0x3f,0xd5,0xff,0xfe,0x6c,0x7e,0xe9}, 8333}, + {{0x20,0x01,0x05,0xc0,0x14,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0xc7}, 8333}, + {{0x20,0x01,0x05,0xc0,0x14,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x01}, 8333}, + {{0x20,0x01,0x05,0xc0,0x14,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xdf}, 8333}, + {{0x20,0x01,0x05,0xc0,0x15,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, + {{0x20,0x01,0x06,0x10,0x1b,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, + {{0x20,0x01,0x06,0x20,0x05,0x00,0xff,0xf0,0xf2,0x1f,0xaf,0xff,0xfe,0xcf,0x91,0xcc}, 8333}, + {{0x20,0x01,0x06,0x7c,0x12,0x20,0x08,0x0c,0x00,0xad,0x8d,0xe2,0xf7,0xe2,0xc7,0x84}, 8333}, + {{0x20,0x01,0x06,0x7c,0x21,0xec,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b}, 8333}, + {{0x20,0x01,0x06,0xf8,0x12,0x96,0x00,0x00,0x76,0xd4,0x35,0xff,0xfe,0xba,0x1d,0x26}, 8333}, + {{0x20,0x01,0x08,0x40,0xf0,0x00,0x42,0x50,0x3e,0x4a,0x92,0xff,0xfe,0x6d,0x14,0x5f}, 8333}, + {{0x20,0x01,0x08,0xd8,0x08,0x40,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x01,0xae}, 8333}, + {{0x20,0x01,0x09,0x80,0xef,0xd8,0x00,0x00,0x00,0x21,0xde,0x4a,0x27,0x09,0x09,0x12}, 8333}, + {{0x20,0x01,0x09,0x81,0x00,0x46,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, + {{0x20,0x01,0x09,0x81,0x93,0x19,0x00,0x02,0x00,0xc0,0x00,0xa8,0x00,0xc8,0x00,0x08}, 8333}, + {{0x20,0x01,0x09,0xd8,0xca,0xfe,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91}, 8333}, + {{0x20,0x01,0x0a,0xd0,0x00,0x01,0x00,0x01,0x26,0xbe,0x05,0xff,0xfe,0x25,0x95,0x9d}, 8333}, + {{0x20,0x01,0x0b,0xa8,0x01,0xf1,0xf3,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x20,0x01,0x0b,0xc8,0x38,0x1c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x20,0x02,0x17,0x5c,0x4c,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x5c,0x4c,0xaa}, 8333}, + {{0x20,0x02,0x44,0x04,0x82,0xf1,0x00,0x00,0x8d,0x55,0x8f,0xbb,0x15,0xfa,0xf4,0xe0}, 8333}, + {{0x20,0x02,0x44,0x75,0x22,0x33,0x00,0x00,0x02,0x1f,0x5b,0xff,0xfe,0x33,0x9f,0x70}, 8333}, + {{0x20,0x02,0x59,0x6c,0x48,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x6c,0x48,0xc3}, 8333}, + {{0x20,0x02,0x8c,0x6d,0x65,0x21,0x96,0x17,0x12,0xbf,0x48,0xff,0xfe,0xd8,0x17,0x24}, 8333}, + {{0x20,0x02,0xa6,0x46,0x5e,0x6a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02}, 8333}, + {{0x20,0x02,0xb0,0x09,0x20,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x09,0x20,0xc5}, 8333}, + {{0x24,0x00,0x89,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x6e,0x82,0x3e}, 8333}, + {{0x24,0x00,0x89,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x70,0xd1,0x64}, 8333}, + {{0x24,0x00,0x89,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x37,0x97,0x61}, 8333}, + {{0x24,0x03,0x42,0x00,0x04,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, 8333}, + {{0x24,0x03,0xb8,0x00,0x10,0x00,0x00,0x64,0x04,0x0a,0xe9,0xff,0xfe,0x5f,0x94,0xc1}, 8333}, + {{0x24,0x03,0xb8,0x00,0x10,0x00,0x00,0x64,0x98,0x79,0x17,0xff,0xfe,0x6a,0xa5,0x9f}, 8333}, + {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x18,0x59,0xb2}, 8333}, + {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x37,0xa4,0xb1}, 8333}, + {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x56,0x29,0x73}, 8333}, + {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x6e,0x72,0x97}, 8333}, + {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x84,0x8a,0x6e}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x18,0x6a,0xdf}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x18,0xe2,0x17}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x33,0x1b,0x31}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x33,0x2f,0xe1}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x33,0xa0,0x3f}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x50,0x5e,0x06}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x56,0xd6,0x45}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x6e,0xa3,0xdc}, 8333}, + {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x89,0xa6,0x59}, 8333}, + {{0x26,0x00,0x3c,0x02,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x6e,0x6f,0x0b}, 8333}, + {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x33,0xf6,0xfb}, 8333}, + {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x50,0x5f,0xa7}, 8333}, + {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x6e,0x18,0x03}, 8333}, + {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x6e,0x4a,0xc0}, 8333}, + {{0x26,0x01,0x00,0x06,0x48,0x00,0x04,0x7f,0x1e,0x4e,0x1f,0x4d,0x33,0x2c,0x3b,0xf6}, 8333}, + {{0x26,0x01,0x00,0x0d,0x54,0x00,0x0f,0xed,0x8d,0x54,0xc1,0xe8,0x7e,0xd7,0xd4,0x5e}, 8333}, + {{0x26,0x02,0x01,0x00,0x4b,0x8f,0x6d,0x2a,0x02,0x0c,0x29,0xff,0xfe,0xaf,0xc4,0xc2}, 8333}, + {{0x26,0x02,0xff,0xc5,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x2d,0x61}, 8333}, + {{0x26,0x02,0xff,0xc5,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x92,0x11}, 8333}, + {{0x26,0x02,0xff,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc5,0xb8,0x44}, 8333}, + {{0x26,0x02,0xff,0xe8,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x04,0x57,0x93,0x6b}, 8333}, + {{0x26,0x02,0xff,0xea,0x10,0x01,0x01,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x2a,0xd4}, 8333}, + {{0x26,0x02,0xff,0xea,0x10,0x01,0x06,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x7d}, 8333}, + {{0x26,0x02,0xff,0xea,0x10,0x01,0x07,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x57,0x8b}, 8333}, + {{0x26,0x02,0xff,0xea,0x10,0x01,0x07,0x7a,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0xae}, 8333}, + {{0x26,0x02,0xff,0xea,0x00,0x01,0x02,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0xc8}, 8333}, + {{0x26,0x02,0xff,0xea,0x00,0x01,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0x68}, 8333}, + {{0x26,0x02,0xff,0xea,0x00,0x01,0x07,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xec}, 8333}, + {{0x26,0x02,0xff,0xea,0x00,0x01,0x09,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe9,0x57}, 8333}, + {{0x26,0x02,0xff,0xea,0x00,0x01,0x0a,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0xcb}, 8333}, + {{0x26,0x02,0xff,0xea,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xc4,0xd9,0xfd}, 8333}, + {{0x26,0x02,0xff,0xea,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x06,0xae,0x32}, 8333}, + {{0x26,0x04,0x00,0x00,0x00,0xc1,0x01,0x00,0x1e,0xc1,0xde,0xff,0xfe,0x54,0x22,0x35}, 8333}, + {{0x26,0x04,0x01,0x80,0x00,0x01,0x01,0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0xa9}, 8333}, + {{0x26,0x04,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb2,0x08,0x03,0x98}, 8333}, + {{0x26,0x04,0x28,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x72,0x0a,0xed}, 8333}, + {{0x26,0x04,0x40,0x80,0x11,0x14,0x00,0x00,0x32,0x85,0xa9,0xff,0xfe,0x93,0x85,0x0c}, 8333}, + {{0x26,0x04,0x7c,0x00,0x00,0x17,0x03,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x5a,0x4d}, 8333}, + {{0x26,0x04,0x9a,0x00,0x21,0x00,0xa0,0x09,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x04,0xa8,0x80,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x2a,0x40,0x01}, 8333}, + {{0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x07,0x52,0xf0,0x01}, 8333}, + {{0x26,0x04,0x0c,0x00,0x00,0x88,0x00,0x32,0x02,0x16,0x3e,0xff,0xfe,0xe4,0xfc,0xca}, 8333}, + {{0x26,0x04,0x0c,0x00,0x00,0x88,0x00,0x32,0x02,0x16,0x3e,0xff,0xfe,0xf5,0xbc,0x21}, 8333}, + {{0x26,0x05,0x79,0x80,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x17,0x61,0x3d,0x4e}, 8333}, + {{0x26,0x05,0xe0,0x00,0x14,0x17,0x40,0x68,0x02,0x23,0x32,0xff,0xfe,0x96,0x0e,0x2d}, 8333}, + {{0x26,0x06,0x60,0x00,0xa4,0x41,0x99,0x03,0x50,0x54,0x00,0xff,0xfe,0x78,0x66,0xff}, 8333}, + {{0x26,0x06,0xdf,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0xae,0x85,0x8f,0xc6}, 8333}, + {{0x26,0x07,0x53,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x7f}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa1}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x11,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x15,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x1b,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x23,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x2b,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x2d,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x03,0xcb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x4a,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x51,0x12,0x00,0x00,0x00,0x02,0x4a,0xf5,0x63,0xfe}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x6d,0xd5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, + {{0x26,0x07,0x53,0x00,0x00,0x60,0x0a,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x26,0x07,0xf1,0xc0,0x08,0x20,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x3f,0x44}, 8333}, + {{0x26,0x07,0xf1,0xc0,0x08,0x48,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x94,0x3c}, 8333}, + {{0x26,0x07,0xf9,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333}, + {{0x26,0x07,0xfc,0xd0,0x01,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x04,0xad,0xe5,0x94}, 8333}, + {{0x26,0x07,0xfc,0xd0,0x01,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x65,0x9e,0x9c,0xb3}, 8333}, + {{0x26,0x07,0xfc,0xd0,0x01,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0xc7,0x4b,0xa8,0xae}, 8333}, + {{0x26,0x07,0xfc,0xd0,0x01,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x0d,0x82,0xd8,0xc2}, 8333}, + {{0x26,0x07,0xfc,0xd0,0x01,0x00,0x43,0x00,0x00,0x00,0x00,0x00,0x87,0x95,0x2f,0xa8}, 8333}, + {{0x26,0x07,0xfc,0xd0,0xda,0xaa,0x09,0x01,0x00,0x00,0x00,0x00,0x95,0x61,0xe0,0x43}, 8333}, + {{0x2a,0x00,0x11,0x78,0x00,0x02,0x00,0x43,0x50,0x54,0x00,0xff,0xfe,0xe7,0x2e,0xb6}, 8333}, + {{0x2a,0x00,0x13,0x28,0xe1,0x00,0xcc,0x42,0x02,0x30,0x48,0xff,0xfe,0x92,0x05,0x5d}, 8333}, + {{0x2a,0x00,0x14,0xf0,0xe0,0x00,0x80,0xd2,0xcd,0x1a,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x00,0x16,0xd8,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0x6a,0xc2,0x61}, 8333}, + {{0x2a,0x00,0x61,0xe0,0x40,0x83,0x6d,0x01,0x68,0x52,0x13,0x76,0xe9,0x72,0x20,0x91}, 8333}, + {{0x2a,0x00,0x0c,0x98,0x20,0x30,0xa0,0x2f,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x01,0xb0,0x79,0x99,0x04,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x31}, 8333}, + {{0x2a,0x01,0x01,0xe8,0xe1,0x00,0x81,0x1c,0x70,0x0f,0x65,0xf0,0xf7,0x2a,0x10,0x84}, 8333}, + {{0x2a,0x01,0x02,0x38,0x42,0xda,0xc5,0x00,0x65,0x46,0x12,0x93,0x54,0x22,0xab,0x40}, 8333}, + {{0x2a,0x01,0x03,0x48,0x00,0x06,0x04,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x03,0x68,0xe0,0x10,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0x30,0x00,0x17,0x00,0x01,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x49}, 8333}, + {{0x2a,0x01,0x04,0x30,0x00,0x17,0x00,0x01,0x00,0x00,0x00,0x00,0xff,0xff,0x08,0x30}, 8333}, + {{0x2a,0x01,0x04,0x88,0x00,0x66,0x10,0x00,0x53,0xa9,0x0d,0x04,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x01,0x04,0x88,0x00,0x66,0x10,0x00,0x57,0xe6,0x57,0x8c,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x01,0x04,0x88,0x00,0x66,0x10,0x00,0xb0,0x1c,0x17,0x8d,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x01,0x04,0x88,0x00,0x67,0x10,0x00,0x05,0x23,0xfd,0xce,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x01,0x04,0x88,0x00,0x67,0x10,0x00,0xb0,0x1c,0x30,0xab,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x00,0x24,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x00,0x44,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x00,0x51,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x00,0x84,0xa7,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x10,0x51,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x10,0x53,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x62,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x70,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x80,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x82,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x84,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x21,0x11,0xeb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x21,0x02,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x24,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x24,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x24,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x63,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x63,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x64,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x93,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x31,0x20,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x31,0x54,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x80,0xad,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x21,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x22,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x23,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x61,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x70,0x88,0x50,0x54,0x00,0xff,0xfe,0x45,0xbf,0xf2}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x83,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 9001}, + {{0x2a,0x01,0x04,0xf8,0x01,0x51,0x01,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x51,0x51,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x51,0x63,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 9001}, + {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x52,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x93,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x23,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x43,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x73,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x73,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x74,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x60,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x63,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x64,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x91,0xce,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x21,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x40,0xa1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x04,0xa7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x63,0xb4,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x71,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x83,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x93,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x60,0xa9,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x73,0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x80,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x00,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x10,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x22,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x41,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x63,0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x22}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x71,0xe3,0x78,0xb4,0xf3,0xff,0xfe,0xad,0xe8,0xcf}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x51,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x60,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x60,0xd5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x53,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x10,0x24,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x10,0x50,0x2f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x14,0xcf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x1a,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x2a,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x0c,0xca,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x22,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x50,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x52,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x74,0xc8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x82,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x82,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x04,0xf8,0x0d,0x13,0x21,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x01,0x06,0x08,0xff,0xff,0xa0,0x09,0x8b,0xf5,0x87,0x9d,0xe5,0x1a,0xf8,0x37}, 8333}, + {{0x2a,0x01,0x07,0x9d,0x46,0x9e,0xed,0x94,0xc2,0x3f,0xd5,0xff,0xfe,0x65,0x20,0xc5}, 8333}, + {{0x2a,0x01,0x07,0xc8,0xaa,0xb5,0x03,0xe6,0x50,0x54,0x00,0xff,0xfe,0xd7,0x4e,0x54}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x18,0x30,0x1e}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x18,0x77,0x49}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x33,0x2d,0x67}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x33,0x34,0x7c}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x33,0xae,0x50}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x56,0x6b,0x5c}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x56,0xbe,0xe6}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x69,0x48,0x95}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x69,0x99,0x12}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x6e,0x26,0xee}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x73,0x42,0xf1}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x84,0x43,0x4f}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x84,0xb3,0x6b}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x89,0x1f,0xaa}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x98,0x08,0x16}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xdb,0x35,0x2e}, 8333}, + {{0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xdb,0x4a,0x1d}, 8333}, + {{0x2a,0x01,0x0e,0x34,0xed,0xbb,0x67,0x50,0x02,0x24,0x1d,0xff,0xfe,0x89,0x38,0x97}, 8333}, + {{0x2a,0x01,0x0e,0x35,0x2f,0x1d,0x3f,0xb0,0x71,0x87,0xc7,0xba,0xbc,0xfc,0x80,0xce}, 8333}, + {{0x2a,0x01,0x0e,0x35,0x87,0x87,0x96,0xf0,0x90,0x32,0x92,0x97,0x39,0xae,0x49,0x6d}, 8333}, + {{0x2a,0x01,0x0e,0x35,0x8a,0x3f,0x47,0xc0,0xc6,0x17,0xfe,0xff,0xfe,0x3c,0x9f,0xbd}, 8333}, + {{0x2a,0x01,0x0e,0x35,0x8b,0x66,0x06,0xa0,0x49,0x00,0x9d,0xfd,0xd8,0x41,0xd0,0x25}, 8333}, + {{0x2a,0x02,0x01,0x68,0x4a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39}, 8333}, + {{0x2a,0x02,0x01,0x68,0x54,0x04,0x00,0x02,0xc2,0x3f,0xd5,0xff,0xfe,0x6a,0x51,0x2e}, 8333}, + {{0x2a,0x02,0x01,0x80,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x5b,0x8f,0x53,0x8c}, 8333}, + {{0x2a,0x02,0x20,0x28,0x10,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, + {{0x2a,0x02,0x25,0x28,0x05,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14}, 8333}, + {{0x2a,0x02,0x25,0x28,0x05,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15}, 8333}, + {{0x2a,0x02,0x25,0x28,0xff,0x00,0x81,0xa6,0x02,0x1e,0xc5,0xff,0xfe,0x8d,0xf9,0xa5}, 8333}, + {{0x2a,0x02,0x27,0x70,0x00,0x05,0x00,0x00,0x02,0x1a,0x4a,0xff,0xfe,0xe4,0xc7,0xdb}, 8333}, + {{0x2a,0x02,0x27,0x70,0x00,0x08,0x00,0x00,0x02,0x1a,0x4a,0xff,0xfe,0x7b,0x3d,0xcd}, 8333}, + {{0x2a,0x02,0x03,0x48,0x00,0x5e,0x5a,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0x7a,0xa0,0x16,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x2f,0xc0,0x6a}, 8333}, + {{0x2a,0x02,0x81,0x09,0x8e,0x40,0x35,0xfc,0xba,0x27,0xeb,0xff,0xfe,0xae,0xcf,0x16}, 8333}, + {{0x2a,0x02,0x0a,0xf8,0x00,0x06,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x30}, 8333}, + {{0x2a,0x02,0xc2,0x00,0x00,0x00,0x00,0x10,0x00,0x01,0x00,0x00,0x63,0x14,0x22,0x22}, 8333}, + {{0x2a,0x02,0xc2,0x00,0x00,0x00,0x00,0x10,0x00,0x02,0x00,0x03,0x32,0x95,0x00,0x01}, 8332}, + {{0x2a,0x02,0xc2,0x00,0x00,0x00,0x00,0x10,0x00,0x03,0x00,0x00,0x54,0x49,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x00,0x00,0x01,0x00,0x10,0x00,0x02,0x00,0x03,0x58,0x99,0x00,0x01}, 8333}, + {{0x2a,0x02,0xc2,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x00,0x27,0x05,0x00,0x01}, 8333}, + {{0x2a,0x02,0xce,0x80,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, + {{0x2a,0x02,0x0f,0xe0,0xc3,0x21,0x27,0xe0,0x6e,0xf0,0x49,0xff,0xfe,0x11,0xa6,0x1d}, 8333}, + {{0x2a,0x03,0x40,0x00,0x00,0x02,0x04,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333}, + {{0x2a,0x03,0xb0,0xc0,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x62,0xf0,0x01}, 8333}, + {{0x2a,0x03,0x0f,0x80,0xed,0x16,0x0c,0xa7,0xea,0x75,0xb1,0x2d,0x02,0xaf,0x9e,0x2a}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd9,0x4a,0xaf,0xa2,0x8c,0x9d,0xf6,0x22,0x18,0x28}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd9,0xe4,0x70,0x01,0xb3,0xa7,0x9d,0x3e,0x51,0xf9}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe7,0x45,0xd5,0x8b,0xff,0x81,0x9e,0x85,0x00,0xb8}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xff,0xd9,0x7d,0x26,0x57,0x03,0xb0,0x49,0x67,0x4f}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf9,0xbe,0x9e,0xf0,0x33,0x40,0x2e,0x79,0xc9,0x18}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0f,0x8b,0x1f,0x8d,0x61,0xa6,0x94,0xf4,0x62,0x45}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0x26,0x27,0x21,0xa2,0x2c,0x05,0x29,0x20,0xdd}, 8333}, {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0x26,0x27,0x21,0xae,0x94,0xd5,0xc2,0x72,0x24}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xea,0xb9,0x5b,0x63,0x1d,0x94,0xe2,0xed,0xec,0xa1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0x36,0xa1,0xc1,0xd6,0x64,0x43,0xfb,0xb3,0xe7}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0xe6,0xdf,0xeb,0xe5,0xc5,0x9a,0x87,0x5e,0x22}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x52,0x71,0xa2,0x43,0x2a,0xe6,0x6c,0x8e,0xe4,0x7b}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0xf4,0x0b,0x4c,0x52,0xd5,0x16,0xcf,0xf5,0x06}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0xff,0x33,0x38,0xbb,0x43,0x08,0x8d,0x95,0x9e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0x64,0x1b,0x1f,0x8f,0x87,0x18,0x7d,0xa3,0x2b}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb8,0xda,0x83,0x67,0x90,0x6f,0x46,0x10,0xdb,0x53}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc3,0x1b,0x22,0x8c,0x89,0x60,0xbf,0xca,0x88,0xa1}, 7033}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0xe3,0x5b,0x75,0x10,0x46,0x5e,0xf0,0x99,0x8b}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0xba,0x44,0x94,0x9d,0xf5,0xc0,0xaa,0xcd,0x4a}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x96,0x64,0xce,0x6d,0xd4,0xfb,0xa7,0x6b,0x60,0xb5}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x8f,0x0b,0x72,0xc9,0xf1,0xde,0x62,0xd4,0x66}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x25,0x5c,0xbc,0x34,0xe8,0x9f,0xe4,0x7c,0x90,0x93}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe0,0xa2,0x72,0xef,0xfa,0x7b,0x88,0x95,0x8b,0x9c}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0x69,0xc5,0x40,0xa7,0x95,0xbb,0x25,0xc1,0xfa}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x46,0xa3,0xd9,0x84,0x08,0xc8,0x7f,0xd3,0xeb,0xc5}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0c,0xc4,0xd2,0x4f,0x74,0x99,0xb3,0x8c,0xe8,0x25}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xac,0x9d,0xb8,0xf8,0x4c,0x4b,0x9c,0xc3,0x9c,0xc6}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0x1d,0x28,0x9f,0xd6,0x28,0x28,0x22,0x4f,0x7a}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0x36,0xa1,0xc1,0xd6,0x64,0x43,0xfb,0xb3,0xe7}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8f,0x06,0x4e,0x64,0xbc,0x5e,0x1a,0x8a,0x71,0x97}, 8444} + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0b,0x29,0x34,0x96,0x29,0xe8,0x67,0x22,0x0c,0x61}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0x5f,0xc7,0xd4,0x89,0xc0,0x6f,0xa2,0x24,0x71}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x32,0x2e,0xda,0xf7,0xc3,0xf6,0xc3,0x4c,0x3c,0x0d}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3e,0xaa,0xb7,0xd0,0x79,0x79,0xf3,0x0b,0xd2,0x63}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x39,0xd1,0x5e,0xbd,0xb7,0x23,0x6a,0x12,0xf0,0x0c}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5e,0x6e,0xf5,0x37,0xcf,0x9b,0xf6,0xe3,0x9f,0xdb}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x64,0x9e,0x79,0x18,0xa8,0x81,0x61,0xd9,0x4d,0xa4}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x68,0xac,0xad,0xae,0x93,0x23,0x0a,0x51,0x3c,0x5c}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x72,0x87,0x94,0x82,0x36,0x22,0x83,0x23,0xb5,0xc5}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x92,0x46,0xe6,0x23,0x98,0x0e,0x87,0x65,0x24,0x22}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa5,0x6c,0xec,0xda,0xeb,0x41,0xdb,0x34,0x18,0x21}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaf,0xb0,0xbc,0xf3,0xa3,0x6f,0x70,0x17,0xab,0x83}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaa,0xb7,0x04,0x8c,0x87,0xc6,0x38,0x3b,0x0a,0xf6}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xac,0x1f,0x82,0x69,0x5d,0x88,0xa1,0x54,0xf5,0x90}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbd,0x06,0xa7,0x66,0x63,0x2c,0x65,0x4c,0x61,0xd4}, 8333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcf,0x7b,0x5e,0x3a,0x53,0x21,0x5b,0x62,0xe3,0x7a}, 8333} }; static SeedSpec6 pnSeed6_test[] = { {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xcb,0x26,0x31,0xba,0x48,0x51,0x31,0x39,0x0d}, 18333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x44,0xf4,0xf4,0xf0,0xbf,0xf7,0x7e,0x6d,0xc4,0xe8}, 18333} + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x44,0xf4,0xf4,0xf0,0xbf,0xf7,0x7e,0x6d,0xc4,0xe8}, 18333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0x8b,0xd2,0x78,0x3f,0x7a,0xf8,0x92,0x8f,0x80}, 18333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe6,0x4e,0xa4,0x47,0x4e,0x2a,0xfe,0xe8,0x95,0xcc}, 18333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9f,0xae,0x9f,0x59,0x0b,0x3f,0x31,0x3a,0x8a,0x5f}, 18333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x47,0xb1,0xe4,0x55,0xd1,0xb0,0x14,0x3f,0xb6,0xdb}, 18333}, + {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa0,0x60,0x9e,0x46,0x54,0xdb,0x61,0x3b,0xb2,0x6f}, 18333} }; #endif // BITCOIN_CHAINPARAMSSEEDS_H From 77aeb7c964b66075aeddeb6542b53bdc0f96538c Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 24 Jun 2015 22:31:10 +0200 Subject: [PATCH 0072/1283] UniValue: don't escape solidus, keep espacing of reverse solidus --- src/test/univalue_tests.cpp | 2 +- src/univalue/gen.cpp | 1 - src/univalue/univalue_escapes.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp index 2c1d303f6..16bc8d30f 100644 --- a/src/test/univalue_tests.cpp +++ b/src/test/univalue_tests.cpp @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(univalue_object) } static const char *json1 = -"[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian\"}}]"; +"[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian http://test.com\"}}]"; BOOST_AUTO_TEST_CASE(univalue_readwrite) { diff --git a/src/univalue/gen.cpp b/src/univalue/gen.cpp index abebe8863..5e5a4d4ae 100644 --- a/src/univalue/gen.cpp +++ b/src/univalue/gen.cpp @@ -22,7 +22,6 @@ static void initJsonEscape() { escapes[(int)'"'] = "\\\""; escapes[(int)'\\'] = "\\\\"; - escapes[(int)'/'] = "\\/"; escapes[(int)'\b'] = "\\b"; escapes[(int)'\f'] = "\\f"; escapes[(int)'\n'] = "\\n"; diff --git a/src/univalue/univalue_escapes.h b/src/univalue/univalue_escapes.h index 051411828..4133b24ca 100644 --- a/src/univalue/univalue_escapes.h +++ b/src/univalue/univalue_escapes.h @@ -49,7 +49,7 @@ static const char *escapes[256] = { NULL, NULL, NULL, - "\\/", + NULL, NULL, NULL, NULL, From 627b9deff4e8e18fc6d001b6eb9818c13c648820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Wed, 24 Jun 2015 07:25:30 +0200 Subject: [PATCH 0073/1283] Policy: MOVEONLY: Create policy/policy.h with some constants --- src/Makefile.am | 1 + src/bitcoin-tx.cpp | 1 + src/init.cpp | 1 + src/main.cpp | 2 ++ src/main.h | 12 ---------- src/miner.cpp | 1 + src/policy/policy.h | 41 ++++++++++++++++++++++++++++++++++ src/rpcrawtransaction.cpp | 1 + src/script/sign.cpp | 3 ++- src/script/standard.h | 17 -------------- src/test/script_P2SH_tests.cpp | 1 + src/wallet/wallet.cpp | 1 + 12 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 src/policy/policy.h diff --git a/src/Makefile.am b/src/Makefile.am index 59618c494..5515b2f18 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -111,6 +111,7 @@ BITCOIN_CORE_H = \ netbase.h \ noui.h \ policy/fees.h \ + policy/policy.h \ pow.h \ primitives/block.h \ primitives/transaction.h \ diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 45990f6bd..9ad57d5c6 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -8,6 +8,7 @@ #include "consensus/consensus.h" #include "core_io.h" #include "keystore.h" +#include "policy/policy.h" #include "primitives/transaction.h" #include "script/script.h" #include "script/sign.h" diff --git a/src/init.cpp b/src/init.cpp index bcdd1f2f3..9478b8b55 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -18,6 +18,7 @@ #include "main.h" #include "miner.h" #include "net.h" +#include "policy/policy.h" #include "rpcserver.h" #include "script/standard.h" #include "scheduler.h" diff --git a/src/main.cpp b/src/main.cpp index 6c4cfe75a..05130f308 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,10 +11,12 @@ #include "chainparams.h" #include "checkpoints.h" #include "checkqueue.h" +#include "consensus/consensus.h" #include "consensus/validation.h" #include "init.h" #include "merkleblock.h" #include "net.h" +#include "policy/policy.h" #include "pow.h" #include "txdb.h" #include "txmempool.h" diff --git a/src/main.h b/src/main.h index 4e2efaada..85a144642 100644 --- a/src/main.h +++ b/src/main.h @@ -14,7 +14,6 @@ #include "chain.h" #include "chainparams.h" #include "coins.h" -#include "consensus/consensus.h" #include "net.h" #include "primitives/block.h" #include "primitives/transaction.h" @@ -47,19 +46,8 @@ class CValidationState; struct CNodeStateStats; -/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ -static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; -static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; -/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ -static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000; /** Default for accepting alerts from the P2P network. */ static const bool DEFAULT_ALERTS = true; -/** The maximum size for transactions we're willing to relay/mine */ -static const unsigned int MAX_STANDARD_TX_SIZE = 100000; -/** Maximum number of signature check operations in an IsStandard() P2SH script */ -static const unsigned int MAX_P2SH_SIGOPS = 15; -/** The maximum number of sigops we're willing to relay/mine in a single tx */ -static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; /** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; /** The maximum size of a blk?????.dat file (since 0.8) */ diff --git a/src/miner.cpp b/src/miner.cpp index f5919ca3a..fb859ca2b 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -12,6 +12,7 @@ #include "hash.h" #include "main.h" #include "net.h" +#include "policy/policy.h" #include "pow.h" #include "primitives/transaction.h" #include "timedata.h" diff --git a/src/policy/policy.h b/src/policy/policy.h new file mode 100644 index 000000000..48e192d55 --- /dev/null +++ b/src/policy/policy.h @@ -0,0 +1,41 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_POLICY_H +#define BITCOIN_POLICY_H + +#include "consensus/consensus.h" +#include "script/interpreter.h" +#include "script/standard.h" + +/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ +static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; +static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; +/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ +static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000; +/** The maximum size for transactions we're willing to relay/mine */ +static const unsigned int MAX_STANDARD_TX_SIZE = 100000; +/** Maximum number of signature check operations in an IsStandard() P2SH script */ +static const unsigned int MAX_P2SH_SIGOPS = 15; +/** The maximum number of sigops we're willing to relay/mine in a single tx */ +static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; +/** + * Standard script verification flags that standard transactions will comply + * with. However scripts violating these flags may still be present in valid + * blocks and we must accept those blocks. + */ +static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | + SCRIPT_VERIFY_DERSIG | + SCRIPT_VERIFY_STRICTENC | + SCRIPT_VERIFY_MINIMALDATA | + SCRIPT_VERIFY_NULLDUMMY | + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | + SCRIPT_VERIFY_CLEANSTACK | + SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; + +/** For convenience, standard but not mandatory verify flags. */ +static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; + +#endif // BITCOIN_POLICY_H diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 20394fc2c..7d1db0b60 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -11,6 +11,7 @@ #include "main.h" #include "merkleblock.h" #include "net.h" +#include "policy/policy.h" #include "primitives/transaction.h" #include "rpcserver.h" #include "script/script.h" diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 4543ca303..8b43183b6 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -5,9 +5,10 @@ #include "script/sign.h" -#include "primitives/transaction.h" #include "key.h" #include "keystore.h" +#include "policy/policy.h" +#include "primitives/transaction.h" #include "script/standard.h" #include "uint256.h" diff --git a/src/script/standard.h b/src/script/standard.h index 3b401dfe4..c4ad17dd8 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -39,23 +39,6 @@ extern unsigned nMaxDatacarrierBytes; */ static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH; -/** - * Standard script verification flags that standard transactions will comply - * with. However scripts violating these flags may still be present in valid - * blocks and we must accept those blocks. - */ -static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | - SCRIPT_VERIFY_DERSIG | - SCRIPT_VERIFY_STRICTENC | - SCRIPT_VERIFY_MINIMALDATA | - SCRIPT_VERIFY_NULLDUMMY | - SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | - SCRIPT_VERIFY_CLEANSTACK | - SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; - -/** For convenience, standard but not mandatory verify flags. */ -static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; - enum txnouttype { TX_NONSTANDARD, diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index c8cfe2872..16c9a4a86 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -5,6 +5,7 @@ #include "key.h" #include "keystore.h" #include "main.h" +#include "policy/policy.h" #include "script/script.h" #include "script/script_error.h" #include "script/sign.h" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index eee57900b..46037ef66 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -12,6 +12,7 @@ #include "consensus/validation.h" #include "main.h" #include "net.h" +#include "policy/policy.h" #include "script/script.h" #include "script/sign.h" #include "timedata.h" From 9238ecb41752e097443d0bc117df35ebd4ac932e Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 11 Oct 2014 22:41:05 +0000 Subject: [PATCH 0074/1283] Policy: MOVEONLY: 3 functions to policy.o: - [script/standard.o] IsStandard - [main.o] IsStandardTx - [main.o] AreInputsStandard Also, don't use namespace std in policy.cpp --- src/Makefile.am | 1 + src/main.cpp | 138 ------------------------- src/main.h | 24 ----- src/policy/policy.cpp | 178 +++++++++++++++++++++++++++++++++ src/policy/policy.h | 17 ++++ src/script/standard.cpp | 20 ---- src/script/standard.h | 1 - src/test/multisig_tests.cpp | 2 +- src/test/transaction_tests.cpp | 1 + 9 files changed, 198 insertions(+), 184 deletions(-) create mode 100644 src/policy/policy.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 5515b2f18..b82c6dc37 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -177,6 +177,7 @@ libbitcoin_server_a_SOURCES = \ net.cpp \ noui.cpp \ policy/fees.cpp \ + policy/policy.cpp \ pow.cpp \ rest.cpp \ rpcblockchain.cpp \ diff --git a/src/main.cpp b/src/main.cpp index 05130f308..f966f6869 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -606,76 +606,6 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) return nEvicted; } - - - - - - -bool IsStandardTx(const CTransaction& tx, string& reason) -{ - if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) { - reason = "version"; - return false; - } - - // Extremely large transactions with lots of inputs can cost the network - // almost as much to process as they cost the sender in fees, because - // computing signature hashes is O(ninputs*txsize). Limiting transactions - // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks. - unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); - if (sz >= MAX_STANDARD_TX_SIZE) { - reason = "tx-size"; - return false; - } - - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { - // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed - // keys. (remember the 520 byte limit on redeemScript size) That works - // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627 - // bytes of scriptSig, which we round off to 1650 bytes for some minor - // future-proofing. That's also enough to spend a 20-of-20 - // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not - // considered standard) - if (txin.scriptSig.size() > 1650) { - reason = "scriptsig-size"; - return false; - } - if (!txin.scriptSig.IsPushOnly()) { - reason = "scriptsig-not-pushonly"; - return false; - } - } - - unsigned int nDataOut = 0; - txnouttype whichType; - BOOST_FOREACH(const CTxOut& txout, tx.vout) { - if (!::IsStandard(txout.scriptPubKey, whichType)) { - reason = "scriptpubkey"; - return false; - } - - if (whichType == TX_NULL_DATA) - nDataOut++; - else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) { - reason = "bare-multisig"; - return false; - } else if (txout.IsDust(::minRelayTxFee)) { - reason = "dust"; - return false; - } - } - - // only one OP_RETURN txout is permitted - if (nDataOut > 1) { - reason = "multi-op-return"; - return false; - } - - return true; -} - bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) { if (tx.nLockTime == 0) @@ -694,74 +624,6 @@ bool CheckFinalTx(const CTransaction &tx) return IsFinalTx(tx, chainActive.Height() + 1, GetAdjustedTime()); } -/** - * Check transaction inputs to mitigate two - * potential denial-of-service attacks: - * - * 1. scriptSigs with extra data stuffed into them, - * not consumed by scriptPubKey (or P2SH script) - * 2. P2SH scripts with a crazy number of expensive - * CHECKSIG/CHECKMULTISIG operations - */ -bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) -{ - if (tx.IsCoinBase()) - return true; // Coinbases don't use vin normally - - for (unsigned int i = 0; i < tx.vin.size(); i++) - { - const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]); - - vector > vSolutions; - txnouttype whichType; - // get the scriptPubKey corresponding to this input: - const CScript& prevScript = prev.scriptPubKey; - if (!Solver(prevScript, whichType, vSolutions)) - return false; - int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions); - if (nArgsExpected < 0) - return false; - - // Transactions with extra stuff in their scriptSigs are - // non-standard. Note that this EvalScript() call will - // be quick, because if there are any operations - // beside "push data" in the scriptSig - // IsStandardTx() will have already returned false - // and this method isn't called. - vector > stack; - if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker())) - return false; - - if (whichType == TX_SCRIPTHASH) - { - if (stack.empty()) - return false; - CScript subscript(stack.back().begin(), stack.back().end()); - vector > vSolutions2; - txnouttype whichType2; - if (Solver(subscript, whichType2, vSolutions2)) - { - int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2); - if (tmpExpected < 0) - return false; - nArgsExpected += tmpExpected; - } - else - { - // Any other Script with less than 15 sigops OK: - unsigned int sigops = subscript.GetSigOpCount(true); - // ... extra data left on the stack after execution is OK, too: - return (sigops <= MAX_P2SH_SIGOPS); - } - } - - if (stack.size() != (unsigned int)nArgsExpected) - return false; - } - - return true; -} - unsigned int GetLegacySigOpCount(const CTransaction& tx) { unsigned int nSigOps = 0; diff --git a/src/main.h b/src/main.h index 85a144642..8f72a955a 100644 --- a/src/main.h +++ b/src/main.h @@ -261,25 +261,6 @@ struct CDiskTxPos : public CDiskBlockPos CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); -/** - * Check transaction inputs, and make sure any - * pay-to-script-hash transactions are evaluating IsStandard scripts - * - * Why bother? To avoid denial-of-service attacks; an attacker - * can submit a standard HASH... OP_EQUAL transaction, - * which will get accepted into blocks. The redemption - * script can be anything; an attacker could use a very - * expensive-to-check-upon-redemption script like: - * DUP CHECKSIG DROP ... repeated 100 times... OP_1 - */ - -/** - * Check for standard transaction types - * @param[in] mapInputs Map of previous transactions that have outputs we're spending - * @return True if all inputs (scriptSigs) use only standard transaction forms - */ -bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); - /** * Count ECDSA signature operations the old-fashioned (pre-0.6) way * @return number of sigops this transaction's outputs will produce when spent @@ -311,11 +292,6 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach /** Context-independent validity checks */ bool CheckTransaction(const CTransaction& tx, CValidationState& state); -/** Check for standard transaction types - * @return True if all outputs (scriptPubKeys) use only standard transaction forms - */ -bool IsStandardTx(const CTransaction& tx, std::string& reason); - /** * Check if transaction is final and can be included in a block with the * specified height and time. Consensus critical. diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp new file mode 100644 index 000000000..169fef4af --- /dev/null +++ b/src/policy/policy.cpp @@ -0,0 +1,178 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +// NOTE: This file is intended to be customised by the end user, and includes only local node policy logic + +#include "policy/policy.h" + +#include "main.h" +#include "tinyformat.h" +#include "util.h" +#include "utilstrencodings.h" + +#include + + /** + * Check transaction inputs to mitigate two + * potential denial-of-service attacks: + * + * 1. scriptSigs with extra data stuffed into them, + * not consumed by scriptPubKey (or P2SH script) + * 2. P2SH scripts with a crazy number of expensive + * CHECKSIG/CHECKMULTISIG operations + * + * Check transaction inputs, and make sure any + * pay-to-script-hash transactions are evaluating IsStandard scripts + * + * Why bother? To avoid denial-of-service attacks; an attacker + * can submit a standard HASH... OP_EQUAL transaction, + * which will get accepted into blocks. The redemption + * script can be anything; an attacker could use a very + * expensive-to-check-upon-redemption script like: + * DUP CHECKSIG DROP ... repeated 100 times... OP_1 + */ + +bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) +{ + std::vector > vSolutions; + if (!Solver(scriptPubKey, whichType, vSolutions)) + return false; + + if (whichType == TX_MULTISIG) + { + unsigned char m = vSolutions.front()[0]; + unsigned char n = vSolutions.back()[0]; + // Support up to x-of-3 multisig txns as standard + if (n < 1 || n > 3) + return false; + if (m < 1 || m > n) + return false; + } + + return whichType != TX_NONSTANDARD; +} + +bool IsStandardTx(const CTransaction& tx, std::string& reason) +{ + if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) { + reason = "version"; + return false; + } + + // Extremely large transactions with lots of inputs can cost the network + // almost as much to process as they cost the sender in fees, because + // computing signature hashes is O(ninputs*txsize). Limiting transactions + // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks. + unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); + if (sz >= MAX_STANDARD_TX_SIZE) { + reason = "tx-size"; + return false; + } + + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed + // keys. (remember the 520 byte limit on redeemScript size) That works + // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627 + // bytes of scriptSig, which we round off to 1650 bytes for some minor + // future-proofing. That's also enough to spend a 20-of-20 + // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not + // considered standard) + if (txin.scriptSig.size() > 1650) { + reason = "scriptsig-size"; + return false; + } + if (!txin.scriptSig.IsPushOnly()) { + reason = "scriptsig-not-pushonly"; + return false; + } + } + + unsigned int nDataOut = 0; + txnouttype whichType; + BOOST_FOREACH(const CTxOut& txout, tx.vout) { + if (!::IsStandard(txout.scriptPubKey, whichType)) { + reason = "scriptpubkey"; + return false; + } + + if (whichType == TX_NULL_DATA) + nDataOut++; + else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) { + reason = "bare-multisig"; + return false; + } else if (txout.IsDust(::minRelayTxFee)) { + reason = "dust"; + return false; + } + } + + // only one OP_RETURN txout is permitted + if (nDataOut > 1) { + reason = "multi-op-return"; + return false; + } + + return true; +} + +bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) +{ + if (tx.IsCoinBase()) + return true; // Coinbases don't use vin normally + + for (unsigned int i = 0; i < tx.vin.size(); i++) + { + const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]); + + std::vector > vSolutions; + txnouttype whichType; + // get the scriptPubKey corresponding to this input: + const CScript& prevScript = prev.scriptPubKey; + if (!Solver(prevScript, whichType, vSolutions)) + return false; + int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions); + if (nArgsExpected < 0) + return false; + + // Transactions with extra stuff in their scriptSigs are + // non-standard. Note that this EvalScript() call will + // be quick, because if there are any operations + // beside "push data" in the scriptSig + // IsStandardTx() will have already returned false + // and this method isn't called. + std::vector > stack; + if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker())) + return false; + + if (whichType == TX_SCRIPTHASH) + { + if (stack.empty()) + return false; + CScript subscript(stack.back().begin(), stack.back().end()); + std::vector > vSolutions2; + txnouttype whichType2; + if (Solver(subscript, whichType2, vSolutions2)) + { + int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2); + if (tmpExpected < 0) + return false; + nArgsExpected += tmpExpected; + } + else + { + // Any other Script with less than 15 sigops OK: + unsigned int sigops = subscript.GetSigOpCount(true); + // ... extra data left on the stack after execution is OK, too: + return (sigops <= MAX_P2SH_SIGOPS); + } + } + + if (stack.size() != (unsigned int)nArgsExpected) + return false; + } + + return true; +} diff --git a/src/policy/policy.h b/src/policy/policy.h index 48e192d55..1551aecde 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -10,6 +10,10 @@ #include "script/interpreter.h" #include "script/standard.h" +#include + +class CCoinsViewCache; + /** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; @@ -38,4 +42,17 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY /** For convenience, standard but not mandatory verify flags. */ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; +bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); + /** + * Check for standard transaction types + * @return True if all outputs (scriptPubKeys) use only standard transaction forms + */ +bool IsStandardTx(const CTransaction& tx, std::string& reason); + /** + * Check for standard transaction types + * @param[in] mapInputs Map of previous transactions that have outputs we're spending + * @return True if all inputs (scriptSigs) use only standard transaction forms + */ +bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); + #endif // BITCOIN_POLICY_H diff --git a/src/script/standard.cpp b/src/script/standard.cpp index ce50e3aad..66657127a 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -180,26 +180,6 @@ int ScriptSigArgsExpected(txnouttype t, const std::vector vSolutions; - if (!Solver(scriptPubKey, whichType, vSolutions)) - return false; - - if (whichType == TX_MULTISIG) - { - unsigned char m = vSolutions.front()[0]; - unsigned char n = vSolutions.back()[0]; - // Support up to x-of-3 multisig txns as standard - if (n < 1 || n > 3) - return false; - if (m < 1 || m > n) - return false; - } - - return whichType != TX_NONSTANDARD; -} - bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) { vector vSolutions; diff --git a/src/script/standard.h b/src/script/standard.h index c4ad17dd8..46ae5f9f1 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -69,7 +69,6 @@ const char* GetTxnOutputType(txnouttype t); bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet); int ScriptSigArgsExpected(txnouttype t, const std::vector >& vSolutions); -bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet); diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 6b189a6b5..b65c299ad 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -4,7 +4,7 @@ #include "key.h" #include "keystore.h" -#include "main.h" +#include "policy/policy.h" #include "script/script.h" #include "script/script_error.h" #include "script/interpreter.h" diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 9ce7aae96..260524f7c 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -12,6 +12,7 @@ #include "key.h" #include "keystore.h" #include "main.h" +#include "policy/policy.h" #include "script/script.h" #include "script/script_error.h" From 6b1066fab41523d25d75b45a10e4b0f61d7c61d0 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 2 Jun 2015 20:46:41 -0400 Subject: [PATCH 0075/1283] Ignore whitelisting during IBD for unrequested blocks. --- src/main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e0997515b..87750f9ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4478,8 +4478,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->AddInventoryKnown(inv); CValidationState state; - // Process all blocks from whitelisted peers, even if not requested. - ProcessNewBlock(state, pfrom, &block, pfrom->fWhitelisted, NULL); + // Process all blocks from whitelisted peers, even if not requested, + // unless we're still syncing with the network. + // Such an unrequested block may still be processed, subject to the + // conditions in AcceptBlock(). + bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); + ProcessNewBlock(state, pfrom, &block, forceProcessing, NULL); int nDoS; if (state.IsInvalid(nDoS)) { pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), From 04b5d235f1560b8285591b963d3636f7ddf74563 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 15 Jun 2015 15:30:05 -0400 Subject: [PATCH 0076/1283] Replace sleep with syncing using pings --- qa/rpc-tests/p2p-acceptblock.py | 34 ++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py index 6431f430a..83c03eeb7 100755 --- a/qa/rpc-tests/p2p-acceptblock.py +++ b/qa/rpc-tests/p2p-acceptblock.py @@ -64,6 +64,8 @@ class TestNode(NodeConnCB): NodeConnCB.__init__(self) self.create_callback_map() self.connection = None + self.ping_counter = 1 + self.last_pong = msg_pong() def add_connection(self, conn): self.connection = conn @@ -87,6 +89,24 @@ class TestNode(NodeConnCB): def send_message(self, message): self.connection.send_message(message) + def on_pong(self, conn, message): + self.last_pong = message + + # Sync up with the node after delivery of a block + def sync_with_ping(self, timeout=30): + self.connection.send_message(msg_ping(nonce=self.ping_counter)) + received_pong = False + sleep_time = 0.05 + while not received_pong and timeout > 0: + time.sleep(sleep_time) + timeout -= sleep_time + with mininode_lock: + if self.last_pong.nonce == self.ping_counter: + received_pong = True + self.ping_counter += 1 + return received_pong + + class AcceptBlockTest(BitcoinTestFramework): def add_options(self, parser): parser.add_option("--testbinary", dest="testbinary", @@ -139,7 +159,7 @@ class AcceptBlockTest(BitcoinTestFramework): test_node.send_message(msg_block(blocks_h2[0])) white_node.send_message(msg_block(blocks_h2[1])) - time.sleep(0.5) + [ x.sync_with_ping() for x in [test_node, white_node] ] assert_equal(self.nodes[0].getblockcount(), 2) assert_equal(self.nodes[1].getblockcount(), 2) print "First height 2 block accepted by both nodes" @@ -152,7 +172,7 @@ class AcceptBlockTest(BitcoinTestFramework): test_node.send_message(msg_block(blocks_h2f[0])) white_node.send_message(msg_block(blocks_h2f[1])) - time.sleep(0.5) # Give time to process the block + [ x.sync_with_ping() for x in [test_node, white_node] ] for x in self.nodes[0].getchaintips(): if x['hash'] == blocks_h2f[0].hash: assert_equal(x['status'], "headers-only") @@ -171,7 +191,7 @@ class AcceptBlockTest(BitcoinTestFramework): test_node.send_message(msg_block(blocks_h3[0])) white_node.send_message(msg_block(blocks_h3[1])) - time.sleep(0.5) + [ x.sync_with_ping() for x in [test_node, white_node] ] # Since the earlier block was not processed by node0, the new block # can't be fully validated. for x in self.nodes[0].getchaintips(): @@ -222,7 +242,7 @@ class AcceptBlockTest(BitcoinTestFramework): white_node.send_message(headers_message) # Send headers leading to tip white_node.send_message(msg_block(tips[1])) # Now deliver the tip try: - time.sleep(0.5) + white_node.sync_with_ping() self.nodes[1].getblock(tips[1].hash) print "Unrequested block far ahead of tip accepted from whitelisted peer" except: @@ -238,7 +258,7 @@ class AcceptBlockTest(BitcoinTestFramework): # the node processes it and incorrectly advances the tip). # But this would be caught later on, when we verify that an inv triggers # a getdata request for this block. - time.sleep(1) + test_node.sync_with_ping() assert_equal(self.nodes[0].getblockcount(), 2) print "Unrequested block that would complete more-work chain was ignored" @@ -250,7 +270,7 @@ class AcceptBlockTest(BitcoinTestFramework): test_node.last_getdata = None test_node.send_message(msg_inv([CInv(2, blocks_h3[0].sha256)])) - time.sleep(0.5) + test_node.sync_with_ping() with mininode_lock: getdata = test_node.last_getdata @@ -261,7 +281,7 @@ class AcceptBlockTest(BitcoinTestFramework): # 7. Send the missing block for the third time (now it is requested) test_node.send_message(msg_block(blocks_h2f[0])) - time.sleep(2) + test_node.sync_with_ping() assert_equal(self.nodes[0].getblockcount(), 290) print "Successfully reorged to longer chain from non-whitelisted peer" From 70ae43e9b7858d03cd64d07bd310f9c85f5b3ee5 Mon Sep 17 00:00:00 2001 From: mruddy Date: Tue, 30 Jun 2015 09:40:44 -0400 Subject: [PATCH 0077/1283] add tests for the decodescript rpc. add mention of the rpc regression tests to the testing seciton of the main readme. --- README.md | 4 ++ qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/decodescript.py | 116 +++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100755 qa/rpc-tests/decodescript.py diff --git a/README.md b/README.md index 4fe6a8749..594d98c39 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,10 @@ lots of money. Developers are strongly encouraged to write unit tests for new code, and to submit new unit tests for old code. Unit tests can be compiled and run (assuming they weren't disabled in configure) with: `make check` +There are also regression and integration tests of the RPC interface, written +in Python, that are run automatically on the build server. +These tests can be run with: `qa/pull-tester/rpc-tests.sh` + Every pull request is built for both Windows and Linux on a dedicated server, and unit and sanity tests are automatically run. The binaries produced may be used for manual QA testing — a link to them will appear in a comment on the diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 2a7caf98d..c032f8a03 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -35,6 +35,7 @@ testScripts=( 'walletbackup.py' 'nodehandling.py' 'reindex.py' + 'decodescript.py' ); testScriptsExt=( 'bipdersig-p2p.py' diff --git a/qa/rpc-tests/decodescript.py b/qa/rpc-tests/decodescript.py new file mode 100755 index 000000000..ce3bc94ef --- /dev/null +++ b/qa/rpc-tests/decodescript.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python2 +# Copyright (c) 2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + +class DecodeScriptTest(BitcoinTestFramework): + """Tests decoding scripts via RPC command "decodescript".""" + + def setup_chain(self): + print('Initializing test directory ' + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 1) + + def setup_network(self, split=False): + self.nodes = start_nodes(1, self.options.tmpdir) + self.is_network_split = False + + def decodescript_script_sig(self): + signature = '304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001' + push_signature = '48' + signature + public_key = '03b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb2' + push_public_key = '21' + public_key + + # below are test cases for all of the standard transaction types + + # 1) P2PK scriptSig + # the scriptSig of a public key scriptPubKey simply pushes a signature onto the stack + rpc_result = self.nodes[0].decodescript(push_signature) + assert_equal(signature, rpc_result['asm']) + + # 2) P2PKH scriptSig + rpc_result = self.nodes[0].decodescript(push_signature + push_public_key) + assert_equal(signature + ' ' + public_key, rpc_result['asm']) + + # 3) multisig scriptSig + # this also tests the leading portion of a P2SH multisig scriptSig + # OP_0 + rpc_result = self.nodes[0].decodescript('00' + push_signature + push_signature) + assert_equal('0 ' + signature + ' ' + signature, rpc_result['asm']) + + # 4) P2SH scriptSig + # an empty P2SH redeemScript is valid and makes for a very simple test case. + # thus, such a spending scriptSig would just need to pass the outer redeemScript + # hash test and leave true on the top of the stack. + rpc_result = self.nodes[0].decodescript('5100') + assert_equal('1 0', rpc_result['asm']) + + # 5) null data scriptSig - no such thing because null data scripts can not be spent. + # thus, no test case for that standard transaction type is here. + + def decodescript_script_pub_key(self): + public_key = '03b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb2' + push_public_key = '21' + public_key + public_key_hash = '11695b6cd891484c2d49ec5aa738ec2b2f897777' + push_public_key_hash = '14' + public_key_hash + + # below are test cases for all of the standard transaction types + + # 1) P2PK scriptPubKey + # OP_CHECKSIG + rpc_result = self.nodes[0].decodescript(push_public_key + 'ac') + assert_equal(public_key + ' OP_CHECKSIG', rpc_result['asm']) + + # 2) P2PKH scriptPubKey + # OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG + rpc_result = self.nodes[0].decodescript('76a9' + push_public_key_hash + '88ac') + assert_equal('OP_DUP OP_HASH160 ' + public_key_hash + ' OP_EQUALVERIFY OP_CHECKSIG', rpc_result['asm']) + + # 3) multisig scriptPubKey + # OP_CHECKMULTISIG + # just imagine that the pub keys used below are different. + # for our purposes here it does not matter that they are the same even though it is unrealistic. + rpc_result = self.nodes[0].decodescript('52' + push_public_key + push_public_key + push_public_key + '53ae') + assert_equal('2 ' + public_key + ' ' + public_key + ' ' + public_key + ' 3 OP_CHECKMULTISIG', rpc_result['asm']) + + # 4) P2SH scriptPubKey + # OP_HASH160 OP_EQUAL. + # push_public_key_hash here should actually be the hash of a redeem script. + # but this works the same for purposes of this test. + rpc_result = self.nodes[0].decodescript('a9' + push_public_key_hash + '87') + assert_equal('OP_HASH160 ' + public_key_hash + ' OP_EQUAL', rpc_result['asm']) + + # 5) null data scriptPubKey + # use a signature look-alike here to make sure that we do not decode random data as a signature. + # this matters if/when signature sighash decoding comes along. + # would want to make sure that no such decoding takes place in this case. + signature_imposter = '48304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001' + # OP_RETURN + rpc_result = self.nodes[0].decodescript('6a' + signature_imposter) + assert_equal('OP_RETURN ' + signature_imposter[2:], rpc_result['asm']) + + # 6) a CLTV redeem script. redeem scripts are in-effect scriptPubKey scripts, so adding a test here. + # OP_NOP2 is also known as OP_CHECKLOCKTIMEVERIFY. + # just imagine that the pub keys used below are different. + # for our purposes here it does not matter that they are the same even though it is unrealistic. + # + # OP_IF + # OP_CHECKSIGVERIFY + # OP_ELSE + # OP_NOP2 OP_DROP + # OP_ENDIF + # OP_CHECKSIG + # + # lock until block 500,000 + rpc_result = self.nodes[0].decodescript('63' + push_public_key + 'ad670320a107b17568' + push_public_key + 'ac') + assert_equal('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_NOP2 OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', rpc_result['asm']) + + def run_test(self): + self.decodescript_script_sig() + self.decodescript_script_pub_key() + +if __name__ == '__main__': + DecodeScriptTest().main() + From a3ba9a553acefd567ccb304b8600d2149ffab9aa Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 29 Jun 2015 15:02:37 -0400 Subject: [PATCH 0078/1283] gitian: make the windows signing process match OSX --- contrib/gitian-descriptors/gitian-win-signer.yml | 15 ++++++++++----- contrib/gitian-descriptors/gitian-win.yml | 7 +++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml index 0bf2ac9b2..2a73050e0 100644 --- a/contrib/gitian-descriptors/gitian-win-signer.yml +++ b/contrib/gitian-descriptors/gitian-win-signer.yml @@ -14,21 +14,26 @@ remotes: files: - "osslsigncode-1.7.1.tar.gz" - "osslsigncode-Backports-to-1.7.1.patch" -- "bitcoin-win32-setup.exe" -- "bitcoin-win64-setup.exe" +- "bitcoin-win-unsigned.tar.gz" script: | BUILD_DIR=`pwd` SIGDIR=${BUILD_DIR}/signature/win + UNSIGNED_DIR=${BUILD_DIR}/unsigned echo "f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 osslsigncode-1.7.1.tar.gz" | sha256sum -c echo "a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 osslsigncode-Backports-to-1.7.1.patch" | sha256sum -c + mkdir -p ${UNSIGNED_DIR} + tar -C ${UNSIGNED_DIR} -xf bitcoin-win-unsigned.tar.gz + tar xf osslsigncode-1.7.1.tar.gz cd osslsigncode-1.7.1 patch -p1 < ${BUILD_DIR}/osslsigncode-Backports-to-1.7.1.patch ./configure --without-gsf --without-curl --disable-dependency-tracking make - - ./osslsigncode attach-signature -in ${BUILD_DIR}/bitcoin-win32-setup.exe -out ${OUTDIR}/bitcoin-win32-setup-signed.exe -sigin ${SIGDIR}/bitcoin-win32-setup.exe.pem - ./osslsigncode attach-signature -in ${BUILD_DIR}/bitcoin-win64-setup.exe -out ${OUTDIR}/bitcoin-win64-setup-signed.exe -sigin ${SIGDIR}/bitcoin-win64-setup.exe.pem + find ${UNSIGNED_DIR} -name "*-unsigned.exe" | while read i; do + INFILE="`basename "${i}"`" + OUTFILE="`echo "${INFILE}" | sed s/-unsigned//`" + ./osslsigncode attach-signature -in "${i}" -out "${OUTDIR}/${OUTFILE}" -sigin "${SIGDIR}/${INFILE}.pem" + done diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 20cfb2985..966820ec5 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -84,6 +84,8 @@ script: | pushd temp tar xf ../$SOURCEDIST find bitcoin-* | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST + mkdir -p $OUTDIR/src + cp ../$SOURCEDIST $OUTDIR/src popd ORIGPATH="$PATH" @@ -109,7 +111,8 @@ script: | find ${DISTNAME} -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i}.zip cd ../.. done - mkdir -p $OUTDIR/src - mv $SOURCEDIST $OUTDIR/src + cd $OUTDIR + rename 's/-setup\.exe$/-setup-unsigned.exe/' *-setup.exe + find . -name "*-setup-unsigned.exe" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz mv ${OUTDIR}/${DISTNAME}-x86_64-*.zip ${OUTDIR}/${DISTNAME}-win64.zip mv ${OUTDIR}/${DISTNAME}-i686-*.zip ${OUTDIR}/${DISTNAME}-win32.zip From 6e849b8309558ec83710d86c0f784566996da58b Mon Sep 17 00:00:00 2001 From: Micha Date: Fri, 26 Jun 2015 15:48:41 +0300 Subject: [PATCH 0079/1283] Ideal release process for Windows detached signing This is an ideal version of what the release process should look like, making it more consistent with the OS X process. Some of the changes described here would need to be made in the descriptors, which is somewhat beyond what I would feel comfortable doing, not really understanding the signature process in depth. [skip ci] --- doc/release-process.md | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index 07005bfbb..5ecb9334f 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -25,7 +25,7 @@ Release Process ###update gitian - In order to take advantage of the new caching features in gitian, be sure to update to a recent version (e9741525c or higher is recommended) + In order to take advantage of the new caching features in gitian, be sure to update to a recent version (`e9741525c` or later is recommended) ###perform gitian builds @@ -66,22 +66,21 @@ Release Process ./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../ ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-win --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml - mv build/out/bitcoin-*.zip ../ - mv build/out/bitcoin-*-win64-setup.exe inputs/bitcoin-win64-setup.exe - mv build/out/bitcoin-*-win32-setup.exe inputs/bitcoin-win32-setup.exe + ./bin/gsign --signer $SIGNER --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml + mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz + mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../ ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml - mv build/out/bitcoin-*-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz + mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../ popd Build output expected: 1. source tarball (bitcoin-${VERSION}.tar.gz) - 2. linux 32-bit and 64-bit binaries dist tarballs (bitcoin-${VERSION}-linux[32|64].tar.gz) - 3. windows 32-bit and 64-bit unsigned installers and dist zips (bitcoin-${VERSION}-win[32|64]-setup.exe, bitcoin-${VERSION}-win[32|64].zip) - 4. OSX unsigned installer (bitcoin-${VERSION}-osx-unsigned.dmg) - 5. Gitian signatures (in gitian.sigs/${VERSION}-/(your gitian key)/ + 2. linux 32-bit and 64-bit dist tarballs (bitcoin-${VERSION}-linux[32|64].tar.gz) + 3. windows 32-bit and 64-bit unsigned installers and dist zips (bitcoin-${VERSION}-win[32|64]-setup-unsigned.exe, bitcoin-${VERSION}-win[32|64].zip) + 4. OSX unsigned installer and dist tarball (bitcoin-${VERSION}-osx-unsigned.dmg, bitcoin-${VERSION}-osx64.tar.gz) + 5. Gitian signatures (in gitian.sigs/${VERSION}-/(your gitian key)/ ###Next steps: @@ -89,7 +88,7 @@ Commit your signature to gitian.sigs: pushd gitian.sigs git add ${VERSION}-linux/${SIGNER} - git add ${VERSION}-win/${SIGNER} + git add ${VERSION}-win-unsigned/${SIGNER} git add ${VERSION}-osx-unsigned/${SIGNER} git commit -a git push # Assuming you can push to the gitian.sigs tree @@ -112,8 +111,8 @@ Commit your signature to gitian.sigs: pushd ./gitian-builder ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml ./bin/gsign --signer $SIGNER --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml - mv build/out/bitcoin-win64-setup-signed.exe ../bitcoin-${VERSION}-win64-setup.exe - mv build/out/bitcoin-win32-setup-signed.exe ../bitcoin-${VERSION}-win32-setup.exe + mv build/out/bitcoin-*win64-setup.exe ../bitcoin-${VERSION}-win64-setup.exe + mv build/out/bitcoin-*win32-setup.exe ../bitcoin-${VERSION}-win32-setup.exe popd Commit your signature for the signed OSX/Windows binaries: From d0fc10a8444484fabc3702e081ec77473c6c41d2 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 10 Apr 2015 12:49:01 +0200 Subject: [PATCH 0080/1283] detach wallet from miner --- src/init.cpp | 9 ++----- src/miner.cpp | 49 ++++++++++++------------------------- src/miner.h | 4 +-- src/rpcmining.cpp | 27 ++++++++------------ src/rpcserver.cpp | 2 -- src/validationinterface.cpp | 6 +++++ src/validationinterface.h | 7 ++++++ src/wallet/wallet.cpp | 11 +++++++++ src/wallet/wallet.h | 7 ++++++ 9 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index c4e3573de..b9510bec9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -156,8 +156,8 @@ void Shutdown() #ifdef ENABLE_WALLET if (pwalletMain) pwalletMain->Flush(false); - GenerateBitcoins(false, NULL, 0); #endif + GenerateBitcoins(false, 0, Params()); StopNode(); UnregisterNodeSignals(GetNodeSignals()); @@ -370,10 +370,8 @@ std::string HelpMessage(HelpMessageMode mode) debugCategories += ", qt"; strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + _("If is not supplied or if = 1, output all debugging information.") + _(" can be:") + " " + debugCategories + "."); -#ifdef ENABLE_WALLET strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0)); strUsage += HelpMessageOpt("-genproclimit=", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1)); -#endif strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)")); strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), 0)); strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), 1)); @@ -1439,11 +1437,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing); scheduler.scheduleEvery(f, nPowTargetSpacing); -#ifdef ENABLE_WALLET // Generate coins in the background - if (pwalletMain) - GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1)); -#endif + GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1), Params()); // ********************************************************* Step 11: finished diff --git a/src/miner.cpp b/src/miner.cpp index f5919ca3a..c51c21b8c 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -17,9 +17,7 @@ #include "timedata.h" #include "util.h" #include "utilmoneystr.h" -#ifdef ENABLE_WALLET -#include "wallet/wallet.h" -#endif +#include "validationinterface.h" #include #include @@ -362,7 +360,6 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& pblock->hashMerkleRoot = pblock->BuildMerkleTree(); } -#ifdef ENABLE_WALLET ////////////////////////////////////////////////////////////////////////////// // // Internal miner @@ -401,17 +398,7 @@ bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phas } } -CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) -{ - CPubKey pubkey; - if (!reservekey.GetReservedKey(pubkey)) - return NULL; - - CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; - return CreateNewBlock(scriptPubKey); -} - -static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) +static bool ProcessBlockFound(CBlock* pblock, const CChainParams& chainparams) { LogPrintf("%s\n", pblock->ToString()); LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue)); @@ -423,14 +410,8 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese return error("BitcoinMiner: generated block is stale"); } - // Remove key from key pool - reservekey.KeepKey(); - - // Track how many getdata requests this block gets - { - LOCK(wallet.cs_wallet); - wallet.mapRequestCount[pblock->GetHash()] = 0; - } + // Inform about the new block + GetMainSignals().BlockFound(*pblock); // Process this block the same as if we had received it from another node CValidationState state; @@ -440,15 +421,12 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese return true; } -void static BitcoinMiner(CWallet *pwallet) +void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbaseScript) { LogPrintf("BitcoinMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); RenameThread("bitcoin-miner"); - const CChainParams& chainparams = Params(); - // Each thread has its own key and counter - CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; try { @@ -474,7 +452,7 @@ void static BitcoinMiner(CWallet *pwallet) unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrev = chainActive.Tip(); - auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); + auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript)); if (!pblocktemplate.get()) { LogPrintf("Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n"); @@ -506,7 +484,7 @@ void static BitcoinMiner(CWallet *pwallet) SetThreadPriority(THREAD_PRIORITY_NORMAL); LogPrintf("BitcoinMiner:\n"); LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex()); - ProcessBlockFound(pblock, *pwallet, reservekey); + ProcessBlockFound(pblock, chainparams); SetThreadPriority(THREAD_PRIORITY_LOWEST); // In regression test mode, stop mining after a block is found. @@ -551,7 +529,7 @@ void static BitcoinMiner(CWallet *pwallet) } } -void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) +void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams) { static boost::thread_group* minerThreads = NULL; @@ -573,9 +551,14 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) if (nThreads == 0 || !fGenerate) return; + CScript coinbaseScript; + GetMainSignals().ScriptForMining(coinbaseScript); + + //throw an error if no script was provided + if (!coinbaseScript.size()) + throw std::runtime_error("No coinbase script available (mining requires a wallet)"); + minerThreads = new boost::thread_group(); for (int i = 0; i < nThreads; i++) - minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet)); + minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams), coinbaseScript)); } - -#endif // ENABLE_WALLET diff --git a/src/miner.h b/src/miner.h index 96a6b70ec..777a09196 100644 --- a/src/miner.h +++ b/src/miner.h @@ -11,6 +11,7 @@ #include class CBlockIndex; +class CChainParams; class CReserveKey; class CScript; class CWallet; @@ -24,10 +25,9 @@ struct CBlockTemplate }; /** Run the miner threads */ -void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads); +void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams); /** Generate a new block, without valid proof-of-work */ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); -CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey); /** Modify the extranonce in a block */ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index f33281461..3e4071bef 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -16,9 +16,6 @@ #include "rpcserver.h" #include "util.h" #include "validationinterface.h" -#ifdef ENABLE_WALLET -#include "wallet/wallet.h" -#endif #include @@ -92,7 +89,6 @@ UniValue getnetworkhashps(const UniValue& params, bool fHelp) return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); } -#ifdef ENABLE_WALLET UniValue getgenerate(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -127,8 +123,6 @@ UniValue generate(const UniValue& params, bool fHelp) + HelpExampleCli("generate", "11") ); - if (pwalletMain == NULL) - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); if (!Params().MineBlocksOnDemand()) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest"); @@ -136,7 +130,13 @@ UniValue generate(const UniValue& params, bool fHelp) int nHeightEnd = 0; int nHeight = 0; int nGenerate = params[0].get_int(); - CReserveKey reservekey(pwalletMain); + + CScript coinbaseScript; + GetMainSignals().ScriptForMining(coinbaseScript); + + //throw an error if no script was provided + if (!coinbaseScript.size()) + throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)"); { // Don't keep cs_main locked LOCK(cs_main); @@ -148,9 +148,9 @@ UniValue generate(const UniValue& params, bool fHelp) UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd) { - auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); + auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript)); if (!pblocktemplate.get()) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty"); + throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; { LOCK(cs_main); @@ -170,7 +170,6 @@ UniValue generate(const UniValue& params, bool fHelp) return blockHashes; } - UniValue setgenerate(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) @@ -193,8 +192,6 @@ UniValue setgenerate(const UniValue& params, bool fHelp) + HelpExampleRpc("setgenerate", "true, 1") ); - if (pwalletMain == NULL) - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); if (Params().MineBlocksOnDemand()) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network"); @@ -212,12 +209,10 @@ UniValue setgenerate(const UniValue& params, bool fHelp) mapArgs["-gen"] = (fGenerate ? "1" : "0"); mapArgs ["-genproclimit"] = itostr(nGenProcLimit); - GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit); + GenerateBitcoins(fGenerate, nGenProcLimit, Params()); return NullUniValue; } -#endif - UniValue getmininginfo(const UniValue& params, bool fHelp) { @@ -257,9 +252,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); obj.push_back(Pair("chain", Params().NetworkIDString())); -#ifdef ENABLE_WALLET obj.push_back(Pair("generate", getgenerate(params, false))); -#endif return obj; } diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 2f2897158..840bf57c2 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -306,12 +306,10 @@ static const CRPCCommand vRPCCommands[] = { "mining", "prioritisetransaction", &prioritisetransaction, true }, { "mining", "submitblock", &submitblock, true }, -#ifdef ENABLE_WALLET /* Coin generation */ { "generating", "getgenerate", &getgenerate, true }, { "generating", "setgenerate", &setgenerate, true }, { "generating", "generate", &generate, true }, -#endif /* Raw transactions */ { "rawtransactions", "createrawtransaction", &createrawtransaction, true }, diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 0532da5f3..96f277915 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -19,9 +19,13 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); + g_signals.ScriptForMining.connect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); + g_signals.BlockFound.connect(boost::bind(&CValidationInterface::UpdateRequestCount, pwalletIn, _1)); } void UnregisterValidationInterface(CValidationInterface* pwalletIn) { + g_signals.BlockFound.disconnect(boost::bind(&CValidationInterface::UpdateRequestCount, pwalletIn, _1)); + g_signals.ScriptForMining.disconnect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); @@ -31,6 +35,8 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { } void UnregisterAllValidationInterfaces() { + g_signals.BlockFound.disconnect_all_slots(); + g_signals.ScriptForMining.disconnect_all_slots(); g_signals.BlockChecked.disconnect_all_slots(); g_signals.Broadcast.disconnect_all_slots(); g_signals.Inventory.disconnect_all_slots(); diff --git a/src/validationinterface.h b/src/validationinterface.h index a911d1efe..2d2427a19 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -10,6 +10,7 @@ class CBlock; struct CBlockLocator; +class CScript; class CTransaction; class CValidationInterface; class CValidationState; @@ -34,6 +35,8 @@ protected: virtual void Inventory(const uint256 &hash) {} virtual void ResendWalletTransactions(int64_t nBestBlockTime) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} + virtual void GetScriptForMining(CScript &script) {}; + virtual void UpdateRequestCount(const CBlock&) {}; friend void ::RegisterValidationInterface(CValidationInterface*); friend void ::UnregisterValidationInterface(CValidationInterface*); friend void ::UnregisterAllValidationInterfaces(); @@ -52,6 +55,10 @@ struct CMainSignals { boost::signals2::signal Broadcast; /** Notifies listeners of a block validation result */ boost::signals2::signal BlockChecked; + /** Notifies listeners that a key for mining is required (coinbase) */ + boost::signals2::signal ScriptForMining; + /** Notifies listeners that a block has been successfully mined */ + boost::signals2::signal BlockFound; }; CMainSignals& GetMainSignals(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index eee57900b..440459fde 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2583,6 +2583,17 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx) } } +void CWallet::GetScriptForMining(CScript &script) +{ + CReserveKey reservekey(this); + reservekey.KeepKey(); + + CPubKey pubkey; + if (!reservekey.GetReservedKey(pubkey)) + return; + script = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; +} + void CWallet::LockCoin(COutPoint& output) { AssertLockHeld(cs_wallet); // setLockedCoins diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b6a8e8671..c8ce5ad22 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -680,6 +680,13 @@ public: } } + void GetScriptForMining(CScript &script); + void UpdateRequestCount(const CBlock& block) + { + LOCK(cs_wallet); + mapRequestCount[block.GetHash()] = 0; + }; + unsigned int GetKeyPoolSize() { AssertLockHeld(cs_wallet); // setKeyPool From 087e65def97fd3a2f61fa11b9f1cd2d7bc2f5f90 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 24 Jun 2015 21:51:47 +0200 Subject: [PATCH 0081/1283] fix GetScriptForMining() CReserveKey::keepKey() issue --- src/wallet/wallet.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 440459fde..997ca1e2f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2586,12 +2586,11 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx) void CWallet::GetScriptForMining(CScript &script) { CReserveKey reservekey(this); - reservekey.KeepKey(); - CPubKey pubkey; if (!reservekey.GetReservedKey(pubkey)) return; script = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; + reservekey.KeepKey(); } void CWallet::LockCoin(COutPoint& output) From a651403e09ccc9ac0a3322e880d6543dd51a14bd Mon Sep 17 00:00:00 2001 From: Shaul Kfir Date: Mon, 16 Mar 2015 21:36:43 -0400 Subject: [PATCH 0082/1283] Add absurdly high fee message to validation state (for RPC propagation) --- src/consensus/validation.h | 8 ++++---- src/main.cpp | 7 ++++--- src/main.h | 3 +++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/consensus/validation.h b/src/consensus/validation.h index a97d983a3..719e090a4 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -28,12 +28,12 @@ private: } mode; int nDoS; std::string strRejectReason; - unsigned char chRejectCode; + unsigned int chRejectCode; bool corruptionPossible; public: CValidationState() : mode(MODE_VALID), nDoS(0), chRejectCode(0), corruptionPossible(false) {} bool DoS(int level, bool ret = false, - unsigned char chRejectCodeIn=0, std::string strRejectReasonIn="", + unsigned int chRejectCodeIn=0, std::string strRejectReasonIn="", bool corruptionIn=false) { chRejectCode = chRejectCodeIn; strRejectReason = strRejectReasonIn; @@ -45,7 +45,7 @@ public: return ret; } bool Invalid(bool ret = false, - unsigned char _chRejectCode=0, std::string _strRejectReason="") { + unsigned int _chRejectCode=0, std::string _strRejectReason="") { return DoS(0, ret, _chRejectCode, _strRejectReason); } bool Error(const std::string& strRejectReasonIn) { @@ -73,7 +73,7 @@ public: bool CorruptionPossible() const { return corruptionPossible; } - unsigned char GetRejectCode() const { return chRejectCode; } + unsigned int GetRejectCode() const { return chRejectCode; } std::string GetRejectReason() const { return strRejectReason; } }; diff --git a/src/main.cpp b/src/main.cpp index 6c4cfe75a..f67f1fd0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1031,9 +1031,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } if (fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000) - return error("AcceptToMemoryPool: absurdly high fees %s, %d > %d", - hash.ToString(), - nFees, ::minRelayTxFee.GetFee(nSize) * 10000); + return state.Invalid(error("AcceptToMemoryPool: absurdly high fees %s, %d > %d", + hash.ToString(), + nFees, ::minRelayTxFee.GetFee(nSize) * 10000), + REJECT_HIGHFEE, "absurdly-high-fee"); // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. diff --git a/src/main.h b/src/main.h index 4e2efaada..e11d5c857 100644 --- a/src/main.h +++ b/src/main.h @@ -497,4 +497,7 @@ extern CBlockTreeDB *pblocktree; */ int GetSpendHeight(const CCoinsViewCache& inputs); +/** local "reject" message codes for RPC which can not be triggered by p2p trasactions */ +static const unsigned int REJECT_HIGHFEE = 0x100; + #endif // BITCOIN_MAIN_H From 5496253966abec287ea61a648cb518d14903f91f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 1 Jul 2015 08:32:30 +0200 Subject: [PATCH 0083/1283] add CReserveScript to allow modular script keeping/returning - use one CReserveScript per mining thread --- src/miner.cpp | 21 +++++++++++---------- src/rpcmining.cpp | 10 +++++++--- src/script/script.h | 9 +++++++++ src/validationinterface.h | 7 ++++--- src/wallet/wallet.cpp | 11 ++++++----- src/wallet/wallet.h | 7 +++++-- 6 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index c51c21b8c..46cde91a4 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -421,7 +421,7 @@ static bool ProcessBlockFound(CBlock* pblock, const CChainParams& chainparams) return true; } -void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbaseScript) +void static BitcoinMiner(const CChainParams& chainparams) { LogPrintf("BitcoinMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); @@ -429,7 +429,14 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas unsigned int nExtraNonce = 0; + boost::shared_ptr coinbaseScript; + GetMainSignals().ScriptForMining(coinbaseScript); + try { + //throw an error if no script was provided + if (!coinbaseScript->reserveScript.size()) + throw std::runtime_error("No coinbase script available (mining requires a wallet)"); + while (true) { if (chainparams.MiningRequiresPeers()) { // Busy-wait for the network to come online so we don't waste time mining @@ -452,7 +459,7 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrev = chainActive.Tip(); - auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript)); + auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript)); if (!pblocktemplate.get()) { LogPrintf("Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n"); @@ -486,6 +493,7 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex()); ProcessBlockFound(pblock, chainparams); SetThreadPriority(THREAD_PRIORITY_LOWEST); + coinbaseScript->KeepScript(); // In regression test mode, stop mining after a block is found. if (chainparams.MineBlocksOnDemand()) @@ -551,14 +559,7 @@ void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainpar if (nThreads == 0 || !fGenerate) return; - CScript coinbaseScript; - GetMainSignals().ScriptForMining(coinbaseScript); - - //throw an error if no script was provided - if (!coinbaseScript.size()) - throw std::runtime_error("No coinbase script available (mining requires a wallet)"); - minerThreads = new boost::thread_group(); for (int i = 0; i < nThreads; i++) - minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams), coinbaseScript)); + minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams))); } diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 3e4071bef..9c6fb10af 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "univalue/univalue.h" @@ -131,11 +132,11 @@ UniValue generate(const UniValue& params, bool fHelp) int nHeight = 0; int nGenerate = params[0].get_int(); - CScript coinbaseScript; + boost::shared_ptr coinbaseScript; GetMainSignals().ScriptForMining(coinbaseScript); //throw an error if no script was provided - if (!coinbaseScript.size()) + if (!coinbaseScript->reserveScript.size()) throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)"); { // Don't keep cs_main locked @@ -148,7 +149,7 @@ UniValue generate(const UniValue& params, bool fHelp) UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd) { - auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript)); + auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; @@ -166,6 +167,9 @@ UniValue generate(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); + + //mark script as important because it was used at least for one coinbase output + coinbaseScript->KeepScript(); } return blockHashes; } diff --git a/src/script/script.h b/src/script/script.h index c09899aab..e39ca57f4 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -609,4 +609,13 @@ public: } }; +class CReserveScript +{ +public: + CScript reserveScript; + virtual void KeepScript() {} + CReserveScript() {} + virtual ~CReserveScript() {} +}; + #endif // BITCOIN_SCRIPT_SCRIPT_H diff --git a/src/validationinterface.h b/src/validationinterface.h index 2d2427a19..34acd4016 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -7,10 +7,11 @@ #define BITCOIN_VALIDATIONINTERFACE_H #include +#include class CBlock; struct CBlockLocator; -class CScript; +class CReserveScript; class CTransaction; class CValidationInterface; class CValidationState; @@ -35,7 +36,7 @@ protected: virtual void Inventory(const uint256 &hash) {} virtual void ResendWalletTransactions(int64_t nBestBlockTime) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} - virtual void GetScriptForMining(CScript &script) {}; + virtual void GetScriptForMining(boost::shared_ptr&) {}; virtual void UpdateRequestCount(const CBlock&) {}; friend void ::RegisterValidationInterface(CValidationInterface*); friend void ::UnregisterValidationInterface(CValidationInterface*); @@ -56,7 +57,7 @@ struct CMainSignals { /** Notifies listeners of a block validation result */ boost::signals2::signal BlockChecked; /** Notifies listeners that a key for mining is required (coinbase) */ - boost::signals2::signal ScriptForMining; + boost::signals2::signal&)> ScriptForMining; /** Notifies listeners that a block has been successfully mined */ boost::signals2::signal BlockFound; }; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 997ca1e2f..238f62a57 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2583,14 +2583,15 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx) } } -void CWallet::GetScriptForMining(CScript &script) +void CWallet::GetScriptForMining(boost::shared_ptr &script) { - CReserveKey reservekey(this); + boost::shared_ptr rKey(new CReserveKey(this)); CPubKey pubkey; - if (!reservekey.GetReservedKey(pubkey)) + if (!rKey->GetReservedKey(pubkey)) return; - script = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; - reservekey.KeepKey(); + + script = rKey; + script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; } void CWallet::LockCoin(COutPoint& output) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c8ce5ad22..1774596af 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -28,6 +28,8 @@ #include #include +#include + /** * Settings */ @@ -680,7 +682,7 @@ public: } } - void GetScriptForMining(CScript &script); + void GetScriptForMining(boost::shared_ptr &script); void UpdateRequestCount(const CBlock& block) { LOCK(cs_wallet); @@ -742,7 +744,7 @@ public: }; /** A key allocated from the key pool. */ -class CReserveKey +class CReserveKey : public CReserveScript { protected: CWallet* pwallet; @@ -763,6 +765,7 @@ public: void ReturnKey(); bool GetReservedKey(CPubKey &pubkey); void KeepKey(); + void KeepScript() { KeepKey(); } }; From a7b9623d189eb4a7d37ff7ad706d6385c3a38e80 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 1 Jul 2015 16:06:49 +0200 Subject: [PATCH 0084/1283] miner: rename UpdateRequestCount signal to ResetRequestCount --- src/miner.cpp | 2 +- src/validationinterface.cpp | 4 ++-- src/validationinterface.h | 4 ++-- src/wallet/wallet.h | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 46cde91a4..2c5cba742 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -411,7 +411,7 @@ static bool ProcessBlockFound(CBlock* pblock, const CChainParams& chainparams) } // Inform about the new block - GetMainSignals().BlockFound(*pblock); + GetMainSignals().BlockFound(pblock->GetHash()); // Process this block the same as if we had received it from another node CValidationState state; diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 96f277915..d365f0300 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -20,11 +20,11 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.ScriptForMining.connect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); - g_signals.BlockFound.connect(boost::bind(&CValidationInterface::UpdateRequestCount, pwalletIn, _1)); + g_signals.BlockFound.connect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); } void UnregisterValidationInterface(CValidationInterface* pwalletIn) { - g_signals.BlockFound.disconnect(boost::bind(&CValidationInterface::UpdateRequestCount, pwalletIn, _1)); + g_signals.BlockFound.disconnect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); g_signals.ScriptForMining.disconnect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); diff --git a/src/validationinterface.h b/src/validationinterface.h index 34acd4016..fb0ce0bda 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -37,7 +37,7 @@ protected: virtual void ResendWalletTransactions(int64_t nBestBlockTime) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} virtual void GetScriptForMining(boost::shared_ptr&) {}; - virtual void UpdateRequestCount(const CBlock&) {}; + virtual void ResetRequestCount(const uint256 &hash) {}; friend void ::RegisterValidationInterface(CValidationInterface*); friend void ::UnregisterValidationInterface(CValidationInterface*); friend void ::UnregisterAllValidationInterfaces(); @@ -59,7 +59,7 @@ struct CMainSignals { /** Notifies listeners that a key for mining is required (coinbase) */ boost::signals2::signal&)> ScriptForMining; /** Notifies listeners that a block has been successfully mined */ - boost::signals2::signal BlockFound; + boost::signals2::signal BlockFound; }; CMainSignals& GetMainSignals(); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 1774596af..f36c98e9f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -683,10 +683,10 @@ public: } void GetScriptForMining(boost::shared_ptr &script); - void UpdateRequestCount(const CBlock& block) + void ResetRequestCount(const uint256 &hash) { LOCK(cs_wallet); - mapRequestCount[block.GetHash()] = 0; + mapRequestCount[hash] = 0; }; unsigned int GetKeyPoolSize() From 47162673c79c757a9c038c4ddc41fb3022223bde Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 1 Jul 2015 17:38:15 +0200 Subject: [PATCH 0085/1283] Use real number of cores for default -par, ignore virtual cores To determine the default for `-par`, the number of script verification threads, use [boost::thread::physical_concurrency()](http://www.boost.org/doc/libs/1_58_0/doc/html/thread/thread_management.html#thread.thread_management.thread.physical_concurrency) which counts only physical cores, not virtual cores. Virtual cores are roughly a set of cached registers to avoid context switches while threading, they cannot actually perform work, so spawning a verification thread for them could even reduce efficiency and will put undue load on the system. Should fix issue #6358, as well as some other reported system overload issues, especially on Intel processors. The function was only introduced in boost 1.56, so provide a utility function `GetNumCores` to fall back for older Boost versions. --- src/init.cpp | 4 ++-- src/miner.cpp | 2 +- src/qt/optionsdialog.cpp | 2 +- src/util.cpp | 10 ++++++++++ src/util.h | 7 +++++++ 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index c4e3573de..de239df6b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -283,7 +283,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-loadblock=", _("Imports blocks from external blk000??.dat file") + " " + _("on startup")); strUsage += HelpMessageOpt("-maxorphantx=", strprintf(_("Keep at most unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS)); strUsage += HelpMessageOpt("-par=", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), - -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS)); + -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS)); #ifndef WIN32 strUsage += HelpMessageOpt("-pid=", strprintf(_("Specify pid file (default: %s)"), "bitcoind.pid")); #endif @@ -774,7 +774,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency nScriptCheckThreads = GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS); if (nScriptCheckThreads <= 0) - nScriptCheckThreads += boost::thread::hardware_concurrency(); + nScriptCheckThreads += GetNumCores(); if (nScriptCheckThreads <= 1) nScriptCheckThreads = 0; else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS) diff --git a/src/miner.cpp b/src/miner.cpp index f5919ca3a..57af2981d 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -560,7 +560,7 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) if (Params().DefaultMinerThreads()) nThreads = Params().DefaultMinerThreads(); else - nThreads = boost::thread::hardware_concurrency(); + nThreads = GetNumCores(); } if (minerThreads != NULL) diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index efb2bf415..87c727335 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -42,7 +42,7 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : /* Main elements init */ ui->databaseCache->setMinimum(nMinDbCache); ui->databaseCache->setMaximum(nMaxDbCache); - ui->threadsScriptVerif->setMinimum(-(int)boost::thread::hardware_concurrency()); + ui->threadsScriptVerif->setMinimum(-GetNumCores()); ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS); /* Network elements init */ diff --git a/src/util.cpp b/src/util.cpp index da5821e53..bb7df2320 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -756,3 +756,13 @@ void SetThreadPriority(int nPriority) #endif // PRIO_THREAD #endif // WIN32 } + +int GetNumCores() +{ +#if BOOST_VERSION >= 105600 + return boost::thread::physical_concurrency(); +#else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores + return boost::thread::hardware_concurrency(); +#endif +} + diff --git a/src/util.h b/src/util.h index 6ec81698e..6019e2501 100644 --- a/src/util.h +++ b/src/util.h @@ -199,6 +199,13 @@ std::string HelpMessageGroup(const std::string& message); */ std::string HelpMessageOpt(const std::string& option, const std::string& message); +/** + * Return the number of physical cores available on the current system. + * @note This does not count virtual cores, such as those provided by HyperThreading + * when boost is newer than 1.56. + */ +int GetNumCores(); + void SetThreadPriority(int nPriority); void RenameThread(const char* name); From 5ed10793c2df970d07cecd760c42205e68779e83 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 27 Jun 2015 08:03:34 +0200 Subject: [PATCH 0086/1283] Show softfork status in getblockchaininfo --- src/rpcblockchain.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 85229e985..0b34225d8 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -469,6 +469,36 @@ UniValue verifychain(const UniValue& params, bool fHelp) return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth); } +/** Implementation of IsSuperMajority with better feedback */ +static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams) +{ + int nFound = 0; + CBlockIndex* pstart = pindex; + for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++) + { + if (pstart->nVersion >= minVersion) + ++nFound; + pstart = pstart->pprev; + } + + UniValue rv(UniValue::VOBJ); + rv.push_back(Pair("status", nFound >= nRequired)); + rv.push_back(Pair("found", nFound)); + rv.push_back(Pair("required", nRequired)); + rv.push_back(Pair("window", consensusParams.nMajorityWindow)); + return rv; +} + +static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) +{ + UniValue rv(UniValue::VOBJ); + rv.push_back(Pair("id", name)); + rv.push_back(Pair("version", version)); + rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))); + rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams))); + return rv; +} + UniValue getblockchaininfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -484,6 +514,19 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" + " \"softforks\": [ (array) status of softforks in progress\n" + " {\n" + " \"id\": \"xxxx\", (string) name of softfork\n" + " \"version\": xx, (numeric) block version\n" + " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n" + " \"status\": xx, (boolean) true if threshold reached\n" + " \"found\": xx, (numeric) number of blocks with the new version found\n" + " \"required\": xx, (numeric) number of blocks required to trigger\n" + " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n" + " },\n" + " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" + " }, ...\n" + " ]\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblockchaininfo", "") @@ -501,6 +544,14 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip()))); obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); obj.push_back(Pair("pruned", fPruneMode)); + + const Consensus::Params& consensusParams = Params().GetConsensus(); + CBlockIndex* tip = chainActive.Tip(); + UniValue softforks(UniValue::VARR); + softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); + softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); + obj.push_back(Pair("softforks", softforks)); + if (fPruneMode) { CBlockIndex *block = chainActive.Tip(); From 72b9452b1d5ff8761466e9810facfd50103cc63b Mon Sep 17 00:00:00 2001 From: Forrest Voight Date: Wed, 1 Jul 2015 21:34:31 -0400 Subject: [PATCH 0087/1283] When processing RPC commands during warmup phase, parse the request object before returning an error so that id value can be used in the response. Prior to this commit, RPC commands sent during Bitcoin's warmup/startup phase were responded to with a JSON-RPC error with an id of null, which violated the JSON-RPC 2.0 spec: id: This member is REQUIRED. It MUST be the same as the value of the id member in the Request Object. If there was an error in detecting the id in the Request object (e.g. Parse error/Invalid Request), it MUST be Null. --- src/rpcserver.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 840bf57c2..b76575fc4 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -930,13 +930,6 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn, if (!valRequest.read(strRequest)) throw JSONRPCError(RPC_PARSE_ERROR, "Parse error"); - // Return immediately if in warmup - { - LOCK(cs_rpcWarmup); - if (fRPCInWarmup) - throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus); - } - string strReply; // singleton request @@ -1008,6 +1001,13 @@ void ServiceConnection(AcceptedConnection *conn) UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms) const { + // Return immediately if in warmup + { + LOCK(cs_rpcWarmup); + if (fRPCInWarmup) + throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus); + } + // Find method const CRPCCommand *pcmd = tableRPC[strMethod]; if (!pcmd) From f581d3d656cf269ea09ac6f130f4bd70b40a9e55 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 19 Jun 2015 15:27:37 +0200 Subject: [PATCH 0088/1283] banlist.dat: store banlist on disk --- qa/rpc-tests/nodehandling.py | 20 +++- src/net.cpp | 186 ++++++++++++++++++++++++++++++++++- src/net.h | 22 +++++ src/netbase.h | 9 ++ src/rpcnet.cpp | 2 + 5 files changed, 236 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py index 9a77bd97e..d89cfcf59 100755 --- a/qa/rpc-tests/nodehandling.py +++ b/qa/rpc-tests/nodehandling.py @@ -48,7 +48,25 @@ class NodeHandlingTest (BitcoinTestFramework): assert_equal(len(self.nodes[2].listbanned()), 0) self.nodes[2].clearbanned() assert_equal(len(self.nodes[2].listbanned()), 0) - + + ##test persisted banlist + self.nodes[2].setban("127.0.0.0/32", "add") + self.nodes[2].setban("127.0.0.0/24", "add") + self.nodes[2].setban("192.168.0.1", "add", 1) #ban for 1 seconds + self.nodes[2].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) #ban for 1000 seconds + listBeforeShutdown = self.nodes[2].listbanned(); + assert_equal("192.168.0.1/255.255.255.255", listBeforeShutdown[2]['address']) #must be here + time.sleep(2) #make 100% sure we expired 192.168.0.1 node time + + #stop node + stop_node(self.nodes[2], 2) + + self.nodes[2] = start_node(2, self.options.tmpdir) + listAfterShutdown = self.nodes[2].listbanned(); + assert_equal("127.0.0.0/255.255.255.0", listAfterShutdown[0]['address']) + assert_equal("127.0.0.0/255.255.255.255", listAfterShutdown[1]['address']) + assert_equal("2001:4000::/ffff:e000:0:0:0:0:0:0", listAfterShutdown[2]['address']) + ########################### # RPC disconnectnode test # ########################### diff --git a/src/net.cpp b/src/net.cpp index 0511256e5..3a549d65c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -445,11 +445,13 @@ void CNode::PushVersion() std::map CNode::setBanned; CCriticalSection CNode::cs_setBanned; +bool CNode::setBannedIsDirty; void CNode::ClearBanned() { LOCK(cs_setBanned); setBanned.clear(); + setBannedIsDirty = true; } bool CNode::IsBanned(CNetAddr ip) @@ -498,6 +500,8 @@ void CNode::Ban(const CSubNet& subNet, int64_t bantimeoffset, bool sinceUnixEpoc LOCK(cs_setBanned); if (setBanned[subNet] < banTime) setBanned[subNet] = banTime; + + setBannedIsDirty = true; } bool CNode::Unban(const CNetAddr &addr) { @@ -508,7 +512,10 @@ bool CNode::Unban(const CNetAddr &addr) { bool CNode::Unban(const CSubNet &subNet) { LOCK(cs_setBanned); if (setBanned.erase(subNet)) + { + setBannedIsDirty = true; return true; + } return false; } @@ -518,6 +525,43 @@ void CNode::GetBanned(std::map &banMap) banMap = setBanned; //create a thread safe copy } +void CNode::SetBanned(const std::map &banMap) +{ + LOCK(cs_setBanned); + setBanned = banMap; + setBannedIsDirty = true; +} + +void CNode::SweepBanned() +{ + int64_t now = GetTime(); + + LOCK(cs_setBanned); + std::map::iterator it = setBanned.begin(); + while(it != setBanned.end()) + { + if(now > (*it).second) + { + setBanned.erase(it++); + setBannedIsDirty = true; + } + else + ++it; + } +} + +bool CNode::BannedSetIsDirty() +{ + LOCK(cs_setBanned); + return setBannedIsDirty; +} + +void CNode::SetBannedSetDirty(bool dirty) +{ + LOCK(cs_setBanned); //reuse setBanned lock for the isDirty flag + setBannedIsDirty = dirty; +} + std::vector CNode::vWhitelistedRange; CCriticalSection CNode::cs_vWhitelistedRange; @@ -1212,6 +1256,17 @@ void DumpAddresses() addrman.size(), GetTimeMillis() - nStart); } +void DumpData() +{ + DumpAddresses(); + + if (CNode::BannedSetIsDirty()) + { + DumpBanlist(); + CNode::SetBannedSetDirty(false); + } +} + void static ProcessOneShot() { string strDest; @@ -1650,6 +1705,17 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) if (!adb.Read(addrman)) LogPrintf("Invalid or missing peers.dat; recreating\n"); } + + //try to read stored banlist + CBanDB bandb; + std::map banmap; + if (!bandb.Read(banmap)) + LogPrintf("Invalid or missing banlist.dat; recreating\n"); + + CNode::SetBanned(banmap); //thread save setter + CNode::SetBannedSetDirty(false); //no need to write down just read or nonexistent data + CNode::SweepBanned(); //sweap out unused entries + LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart); fAddressesInitialized = true; @@ -1690,7 +1756,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) threadGroup.create_thread(boost::bind(&TraceThread, "msghand", &ThreadMessageHandler)); // Dump network addresses - scheduler.scheduleEvery(&DumpAddresses, DUMP_ADDRESSES_INTERVAL); + scheduler.scheduleEvery(&DumpData, DUMP_ADDRESSES_INTERVAL); } bool StopNode() @@ -1703,7 +1769,7 @@ bool StopNode() if (fAddressesInitialized) { - DumpAddresses(); + DumpData(); fAddressesInitialized = false; } @@ -2107,3 +2173,119 @@ void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend) LEAVE_CRITICAL_SECTION(cs_vSend); } + +// +// CBanDB +// + +CBanDB::CBanDB() +{ + pathBanlist = GetDataDir() / "banlist.dat"; +} + +bool CBanDB::Write(const std::map& banSet) +{ + // Generate random temporary filename + unsigned short randv = 0; + GetRandBytes((unsigned char*)&randv, sizeof(randv)); + std::string tmpfn = strprintf("banlist.dat.%04x", randv); + + // serialize banlist, checksum data up to that point, then append csum + CDataStream ssBanlist(SER_DISK, CLIENT_VERSION); + ssBanlist << FLATDATA(Params().MessageStart()); + ssBanlist << banSet; + uint256 hash = Hash(ssBanlist.begin(), ssBanlist.end()); + ssBanlist << hash; + + // open temp output file, and associate with CAutoFile + boost::filesystem::path pathTmp = GetDataDir() / tmpfn; + FILE *file = fopen(pathTmp.string().c_str(), "wb"); + CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); + if (fileout.IsNull()) + return error("%s: Failed to open file %s", __func__, pathTmp.string()); + + // Write and commit header, data + try { + fileout << ssBanlist; + } + catch (const std::exception& e) { + return error("%s: Serialize or I/O error - %s", __func__, e.what()); + } + FileCommit(fileout.Get()); + fileout.fclose(); + + // replace existing banlist.dat, if any, with new banlist.dat.XXXX + if (!RenameOver(pathTmp, pathBanlist)) + return error("%s: Rename-into-place failed", __func__); + + return true; +} + +bool CBanDB::Read(std::map& banSet) +{ + // open input file, and associate with CAutoFile + FILE *file = fopen(pathBanlist.string().c_str(), "rb"); + CAutoFile filein(file, SER_DISK, CLIENT_VERSION); + if (filein.IsNull()) + return error("%s: Failed to open file %s", __func__, pathBanlist.string()); + + // use file size to size memory buffer + int fileSize = boost::filesystem::file_size(pathBanlist); + int dataSize = fileSize - sizeof(uint256); + // Don't try to resize to a negative number if file is small + if (dataSize < 0) + dataSize = 0; + vector vchData; + vchData.resize(dataSize); + uint256 hashIn; + + // read data and checksum from file + try { + filein.read((char *)&vchData[0], dataSize); + filein >> hashIn; + } + catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + filein.fclose(); + + CDataStream ssBanlist(vchData, SER_DISK, CLIENT_VERSION); + + // verify stored checksum matches input data + uint256 hashTmp = Hash(ssBanlist.begin(), ssBanlist.end()); + if (hashIn != hashTmp) + return error("%s: Checksum mismatch, data corrupted", __func__); + + unsigned char pchMsgTmp[4]; + try { + // de-serialize file header (network specific magic number) and .. + ssBanlist >> FLATDATA(pchMsgTmp); + + // ... verify the network matches ours + if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) + return error("%s: Invalid network magic number", __func__); + + // de-serialize address data into one CAddrMan object + ssBanlist >> banSet; + } + catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + + return true; +} + +void DumpBanlist() +{ + int64_t nStart = GetTimeMillis(); + + CNode::SweepBanned(); //clean unused entires (if bantime has expired) + + CBanDB bandb; + std::map banmap; + CNode::GetBanned(banmap); + bandb.Write(banmap); + + LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n", + banmap.size(), GetTimeMillis() - nStart); +} \ No newline at end of file diff --git a/src/net.h b/src/net.h index 69e4c592a..42c859e46 100644 --- a/src/net.h +++ b/src/net.h @@ -287,6 +287,7 @@ protected: // Key is IP address, value is banned-until-time static std::map setBanned; static CCriticalSection cs_setBanned; + static bool setBannedIsDirty; // Whitelisted ranges. Any node connecting from these is automatically // whitelisted (as well as those connecting to whitelisted binds). @@ -613,6 +614,14 @@ public: static bool Unban(const CNetAddr &ip); static bool Unban(const CSubNet &ip); static void GetBanned(std::map &banmap); + static void SetBanned(const std::map &banmap); + + //!check is the banlist has unwritten changes + static bool BannedSetIsDirty(); + //!set the "dirty" flag for the banlist + static void SetBannedSetDirty(bool dirty=true); + //!clean unused entires (if bantime has expired) + static void SweepBanned(); void copyStats(CNodeStats &stats); @@ -644,4 +653,17 @@ public: bool Read(CAddrMan& addr); }; +/** Access to the banlist database (banlist.dat) */ +class CBanDB +{ +private: + boost::filesystem::path pathBanlist; +public: + CBanDB(); + bool Write(const std::map& banSet); + bool Read(std::map& banSet); +}; + +void DumpBanlist(); + #endif // BITCOIN_NET_H diff --git a/src/netbase.h b/src/netbase.h index 27f0eac2a..48c2d3455 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -126,6 +126,15 @@ class CSubNet friend bool operator==(const CSubNet& a, const CSubNet& b); friend bool operator!=(const CSubNet& a, const CSubNet& b); friend bool operator<(const CSubNet& a, const CSubNet& b); + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(network); + READWRITE(FLATDATA(netmask)); + READWRITE(FLATDATA(valid)); + } }; /** A combination of a network address (CNetAddr) and a (TCP) port */ diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 1572b1668..0c3745a7d 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -527,6 +527,7 @@ UniValue setban(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed"); } + DumpBanlist(); //store banlist to disk return NullUniValue; } @@ -568,6 +569,7 @@ UniValue clearbanned(const UniValue& params, bool fHelp) ); CNode::ClearBanned(); + DumpBanlist(); //store banlist to disk return NullUniValue; } From dfa174c2957f2600f05bf0ee9dd17fe18fb54fd7 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 26 Jun 2015 15:21:59 +0200 Subject: [PATCH 0089/1283] CAddrDB/CBanDB: change filesize variables from int to uint64_t --- src/net.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 3a549d65c..03db1f06a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1973,11 +1973,11 @@ bool CAddrDB::Read(CAddrMan& addr) return error("%s: Failed to open file %s", __func__, pathAddr.string()); // use file size to size memory buffer - int fileSize = boost::filesystem::file_size(pathAddr); - int dataSize = fileSize - sizeof(uint256); + uint64_t fileSize = boost::filesystem::file_size(pathAddr); + uint64_t dataSize = 0; // Don't try to resize to a negative number if file is small - if (dataSize < 0) - dataSize = 0; + if (fileSize >= sizeof(uint256)) + dataSize = fileSize - sizeof(uint256); vector vchData; vchData.resize(dataSize); uint256 hashIn; @@ -2230,11 +2230,11 @@ bool CBanDB::Read(std::map& banSet) return error("%s: Failed to open file %s", __func__, pathBanlist.string()); // use file size to size memory buffer - int fileSize = boost::filesystem::file_size(pathBanlist); - int dataSize = fileSize - sizeof(uint256); + uint64_t fileSize = boost::filesystem::file_size(pathBanlist); + uint64_t dataSize = 0; // Don't try to resize to a negative number if file is small - if (dataSize < 0) - dataSize = 0; + if (fileSize >= sizeof(uint256)) + dataSize = fileSize - sizeof(uint256); vector vchData; vchData.resize(dataSize); uint256 hashIn; From 409bccfbf52b531b2a9d60ac2308f56223931a2e Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 26 Jun 2015 21:38:33 +0200 Subject: [PATCH 0090/1283] use CBanEntry as object container for banned nodes - added a reason enum for a ban - added creation time for a ban Using CBanEntry as container will keep banlist.dat extenable. --- src/main.cpp | 2 +- src/net.cpp | 53 +++++++++++++++++-------------- src/net.h | 72 ++++++++++++++++++++++++++++++++++++++---- src/rpcnet.cpp | 12 ++++--- src/test/rpc_tests.cpp | 4 +-- 5 files changed, 106 insertions(+), 37 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6c4cfe75a..a000a81fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4959,7 +4959,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString()); else { - CNode::Ban(pto->addr); + CNode::Ban(pto->addr, BanReasonNodeMisbehaving); } } state.fShouldBan = false; diff --git a/src/net.cpp b/src/net.cpp index 03db1f06a..ade34f575 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -443,7 +443,7 @@ void CNode::PushVersion() -std::map CNode::setBanned; +banmap_t CNode::setBanned; CCriticalSection CNode::cs_setBanned; bool CNode::setBannedIsDirty; @@ -459,12 +459,12 @@ bool CNode::IsBanned(CNetAddr ip) bool fResult = false; { LOCK(cs_setBanned); - for (std::map::iterator it = setBanned.begin(); it != setBanned.end(); it++) + for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++) { CSubNet subNet = (*it).first; - int64_t t = (*it).second; + CBanEntry banEntry = (*it).second; - if(subNet.Match(ip) && GetTime() < t) + if(subNet.Match(ip) && GetTime() < banEntry.nBanUntil) fResult = true; } } @@ -476,30 +476,36 @@ bool CNode::IsBanned(CSubNet subnet) bool fResult = false; { LOCK(cs_setBanned); - std::map::iterator i = setBanned.find(subnet); + banmap_t::iterator i = setBanned.find(subnet); if (i != setBanned.end()) { - int64_t t = (*i).second; - if (GetTime() < t) + CBanEntry banEntry = (*i).second; + if (GetTime() < banEntry.nBanUntil) fResult = true; } } return fResult; } -void CNode::Ban(const CNetAddr& addr, int64_t bantimeoffset, bool sinceUnixEpoch) { +void CNode::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128")); - Ban(subNet, bantimeoffset, sinceUnixEpoch); + Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch); } -void CNode::Ban(const CSubNet& subNet, int64_t bantimeoffset, bool sinceUnixEpoch) { - int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban - if (bantimeoffset > 0) - banTime = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset; +void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { + CBanEntry banEntry(GetTime()); + banEntry.banReason = banReason; + if (bantimeoffset <= 0) + { + bantimeoffset = GetArg("-bantime", 60*60*24); // Default 24-hour ban + sinceUnixEpoch = false; + } + banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset; + LOCK(cs_setBanned); - if (setBanned[subNet] < banTime) - setBanned[subNet] = banTime; + if (setBanned[subNet].nBanUntil < banEntry.nBanUntil) + setBanned[subNet] = banEntry; setBannedIsDirty = true; } @@ -519,13 +525,13 @@ bool CNode::Unban(const CSubNet &subNet) { return false; } -void CNode::GetBanned(std::map &banMap) +void CNode::GetBanned(banmap_t &banMap) { LOCK(cs_setBanned); banMap = setBanned; //create a thread safe copy } -void CNode::SetBanned(const std::map &banMap) +void CNode::SetBanned(const banmap_t &banMap) { LOCK(cs_setBanned); setBanned = banMap; @@ -537,10 +543,11 @@ void CNode::SweepBanned() int64_t now = GetTime(); LOCK(cs_setBanned); - std::map::iterator it = setBanned.begin(); + banmap_t::iterator it = setBanned.begin(); while(it != setBanned.end()) { - if(now > (*it).second) + CBanEntry banEntry = (*it).second; + if(now > banEntry.nBanUntil) { setBanned.erase(it++); setBannedIsDirty = true; @@ -1708,7 +1715,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) //try to read stored banlist CBanDB bandb; - std::map banmap; + banmap_t banmap; if (!bandb.Read(banmap)) LogPrintf("Invalid or missing banlist.dat; recreating\n"); @@ -2183,7 +2190,7 @@ CBanDB::CBanDB() pathBanlist = GetDataDir() / "banlist.dat"; } -bool CBanDB::Write(const std::map& banSet) +bool CBanDB::Write(const banmap_t& banSet) { // Generate random temporary filename unsigned short randv = 0; @@ -2221,7 +2228,7 @@ bool CBanDB::Write(const std::map& banSet) return true; } -bool CBanDB::Read(std::map& banSet) +bool CBanDB::Read(banmap_t& banSet) { // open input file, and associate with CAutoFile FILE *file = fopen(pathBanlist.string().c_str(), "rb"); @@ -2282,7 +2289,7 @@ void DumpBanlist() CNode::SweepBanned(); //clean unused entires (if bantime has expired) CBanDB bandb; - std::map banmap; + banmap_t banmap; CNode::GetBanned(banmap); bandb.Write(banmap); diff --git a/src/net.h b/src/net.h index 42c859e46..f15b85474 100644 --- a/src/net.h +++ b/src/net.h @@ -228,8 +228,66 @@ public: }; +typedef enum BanReason +{ + BanReasonUnknown = 0, + BanReasonNodeMisbehaving = 1, + BanReasonManuallyAdded = 2 +} BanReason; +class CBanEntry +{ +public: + static const int CURRENT_VERSION=1; + int nVersion; + int64_t nCreateTime; + int64_t nBanUntil; + uint8_t banReason; + CBanEntry() + { + SetNull(); + } + + CBanEntry(int64_t nCreateTimeIn) + { + SetNull(); + nCreateTime = nCreateTimeIn; + } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(nCreateTime); + READWRITE(nBanUntil); + READWRITE(banReason); + } + + void SetNull() + { + nVersion = CBanEntry::CURRENT_VERSION; + nCreateTime = 0; + nBanUntil = 0; + banReason = BanReasonUnknown; + } + + std::string banReasonToString() + { + switch (banReason) { + case BanReasonNodeMisbehaving: + return "node misbehabing"; + case BanReasonManuallyAdded: + return "manually added"; + default: + return "unknown"; + } + } +}; + +typedef std::map banmap_t; /** Information about a peer */ class CNode @@ -285,7 +343,7 @@ protected: // Denial-of-service detection/prevention // Key is IP address, value is banned-until-time - static std::map setBanned; + static banmap_t setBanned; static CCriticalSection cs_setBanned; static bool setBannedIsDirty; @@ -609,12 +667,12 @@ public: static void ClearBanned(); // needed for unit testing static bool IsBanned(CNetAddr ip); static bool IsBanned(CSubNet subnet); - static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); - static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); + static void Ban(const CNetAddr &ip, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); + static void Ban(const CSubNet &subNet, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); static bool Unban(const CNetAddr &ip); static bool Unban(const CSubNet &ip); - static void GetBanned(std::map &banmap); - static void SetBanned(const std::map &banmap); + static void GetBanned(banmap_t &banmap); + static void SetBanned(const banmap_t &banmap); //!check is the banlist has unwritten changes static bool BannedSetIsDirty(); @@ -660,8 +718,8 @@ private: boost::filesystem::path pathBanlist; public: CBanDB(); - bool Write(const std::map& banSet); - bool Read(std::map& banSet); + bool Write(const banmap_t& banSet); + bool Read(banmap_t& banSet); }; void DumpBanlist(); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 0c3745a7d..dd631905f 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -515,7 +515,7 @@ UniValue setban(const UniValue& params, bool fHelp) if (params.size() == 4 && params[3].isTrue()) absolute = true; - isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute); + isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); //disconnect possible nodes while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr))) @@ -542,15 +542,19 @@ UniValue listbanned(const UniValue& params, bool fHelp) + HelpExampleRpc("listbanned", "") ); - std::map banMap; + banmap_t banMap; CNode::GetBanned(banMap); UniValue bannedAddresses(UniValue::VARR); - for (std::map::iterator it = banMap.begin(); it != banMap.end(); it++) + for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++) { + CBanEntry banEntry = (*it).second; UniValue rec(UniValue::VOBJ); rec.push_back(Pair("address", (*it).first.ToString())); - rec.push_back(Pair("banned_untill", (*it).second)); + rec.push_back(Pair("banned_until", banEntry.nBanUntil)); + rec.push_back(Pair("ban_created", banEntry.nCreateTime)); + rec.push_back(Pair("ban_reason", banEntry.banReasonToString())); + bannedAddresses.push_back(rec); } diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index c38df0ecf..9e99ff628 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban) ar = r.get_array(); o1 = ar[0].get_obj(); adr = find_value(o1, "address"); - UniValue banned_until = find_value(o1, "banned_untill"); + UniValue banned_until = find_value(o1, "banned_until"); BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0"); BOOST_CHECK_EQUAL(banned_until.get_int64(), 1607731200); // absolute time check @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban) ar = r.get_array(); o1 = ar[0].get_obj(); adr = find_value(o1, "address"); - banned_until = find_value(o1, "banned_untill"); + banned_until = find_value(o1, "banned_until"); BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0"); int64_t now = GetTime(); BOOST_CHECK(banned_until.get_int64() > now); From 3f16971442f1b52f94759b15998bc82e82a90aea Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 2 Jul 2015 20:39:44 +0200 Subject: [PATCH 0091/1283] tests: fix txn_clone.py Solve merge conflict of test added in #5881 with #6097. --- qa/rpc-tests/txn_clone.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/txn_clone.py b/qa/rpc-tests/txn_clone.py index 19bc34e3f..08473e6b5 100755 --- a/qa/rpc-tests/txn_clone.py +++ b/qa/rpc-tests/txn_clone.py @@ -7,8 +7,8 @@ # Test proper accounting with an equivalent malleability clone # -from test_framework import BitcoinTestFramework -from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from test_framework.test_framework import BitcoinTestFramework +from test_framework.authproxy import AuthServiceProxy, JSONRPCException from decimal import Decimal from util import * import os From 177a0e491449b9accfa0cf17c138147539071358 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 29 Jun 2015 20:37:22 +0200 Subject: [PATCH 0092/1283] Adding CSubNet constructor over a single CNetAddr --- src/net.cpp | 4 ++-- src/netbase.cpp | 7 +++++++ src/netbase.h | 3 +++ src/test/netbase_tests.cpp | 11 +++++++++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index ade34f575..950311ee3 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -488,7 +488,7 @@ bool CNode::IsBanned(CSubNet subnet) } void CNode::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { - CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128")); + CSubNet subNet(addr); Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch); } @@ -511,7 +511,7 @@ void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t banti } bool CNode::Unban(const CNetAddr &addr) { - CSubNet subNet(addr.ToString()+(addr.IsIPv4() ? "/32" : "/128")); + CSubNet subNet(addr); return Unban(subNet); } diff --git a/src/netbase.cpp b/src/netbase.cpp index adac5c2d0..c9fc7d67f 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1291,6 +1291,13 @@ CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup) network.ip[x] &= netmask[x]; } +CSubNet::CSubNet(const CNetAddr &addr): + valid(addr.IsValid()) +{ + memset(netmask, 255, sizeof(netmask)); + network = addr; +} + bool CSubNet::Match(const CNetAddr &addr) const { if (!valid || !addr.IsValid()) diff --git a/src/netbase.h b/src/netbase.h index 48c2d3455..6f8882b85 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -118,6 +118,9 @@ class CSubNet CSubNet(); explicit CSubNet(const std::string &strSubnet, bool fAllowLookup = false); + //constructor for single ip subnet (/32 or /128) + explicit CSubNet(const CNetAddr &addr); + bool Match(const CNetAddr &addr) const; std::string ToString() const; diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 0f5e1615c..7154476c7 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -143,6 +143,17 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/128").IsValid()); BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8/129").IsValid()); BOOST_CHECK(!CSubNet("fuzzy").IsValid()); + + //CNetAddr constructor test + BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).IsValid()); + BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.1"))); + BOOST_CHECK(!CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.2"))); + BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).ToString() == "127.0.0.1/255.255.255.255"); + + BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).IsValid()); + BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:8"))); + BOOST_CHECK(!CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:9"))); + BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); } BOOST_AUTO_TEST_SUITE_END() From 5a7304b69dcdb3323fbade3a150be94b42d8ab43 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 2 Jul 2015 20:57:39 +0200 Subject: [PATCH 0093/1283] Move recently introduced CTransAction::IsEquivalentTo to CWalletTx CTransAction::IsEquivalentTo was introduced in #5881. This functionality is only useful to the wallet, and should never have been added to the primitive transaction type. --- src/primitives/transaction.cpp | 9 --------- src/primitives/transaction.h | 3 --- src/wallet/wallet.cpp | 9 +++++++++ src/wallet/wallet.h | 3 +++ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index d864a9b6d..606dbea79 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -87,15 +87,6 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) { return *this; } -bool CTransaction::IsEquivalentTo(const CTransaction& tx) const -{ - CMutableTransaction tx1 = *this; - CMutableTransaction tx2 = tx; - for (unsigned int i = 0; i < tx1.vin.size(); i++) tx1.vin[i].scriptSig = CScript(); - for (unsigned int i = 0; i < tx2.vin.size(); i++) tx2.vin[i].scriptSig = CScript(); - return CTransaction(tx1) == CTransaction(tx2); -} - CAmount CTransaction::GetValueOut() const { CAmount nValueOut = 0; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 0c9ebb7b8..6cfd93a9a 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -222,9 +222,6 @@ public: return hash; } - // True if only scriptSigs are different - bool IsEquivalentTo(const CTransaction& tx) const; - // Return sum of txouts. CAmount GetValueOut() const; // GetValueIn() is a method on CCoinsViewCache, because diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 44e28de0c..5811c0310 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1331,6 +1331,15 @@ bool CWalletTx::IsTrusted() const return true; } +bool CWalletTx::IsEquivalentTo(const CWalletTx& tx) const +{ + CMutableTransaction tx1 = *this; + CMutableTransaction tx2 = tx; + for (unsigned int i = 0; i < tx1.vin.size(); i++) tx1.vin[i].scriptSig = CScript(); + for (unsigned int i = 0; i < tx2.vin.size(); i++) tx2.vin[i].scriptSig = CScript(); + return CTransaction(tx1) == CTransaction(tx2); +} + std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime) { std::vector result; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index f36c98e9f..003266ba1 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -378,6 +378,9 @@ public: return (GetDebit(filter) > 0); } + // True if only scriptSigs are different + bool IsEquivalentTo(const CWalletTx& tx) const; + bool IsTrusted() const; bool WriteToDisk(CWalletDB *pwalletdb); From 56dc70439f4a5cfeec3c49609229d973349e5c8f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 2 Jul 2015 23:23:29 +0200 Subject: [PATCH 0094/1283] tests: fix txn_clone.py (retry) There was a stale .pyc file around from before the move. This should catch all missing modules and finally fix the travis build. --- qa/rpc-tests/txn_clone.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/txn_clone.py b/qa/rpc-tests/txn_clone.py index 08473e6b5..0d276ecc9 100755 --- a/qa/rpc-tests/txn_clone.py +++ b/qa/rpc-tests/txn_clone.py @@ -10,7 +10,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.authproxy import AuthServiceProxy, JSONRPCException from decimal import Decimal -from util import * +from test_framework.util import * import os import shutil From dae0a89d4b66f08c83ccc8c20cf37521084b6257 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 3 Jul 2015 06:38:37 +0000 Subject: [PATCH 0095/1283] assets-attribution: Update typicons to MIT license stephenhutchings commented 3 Jul 2015, 6:35 GMT: > Hi Luke, happy for these to be distributed under the terms of the MIT licence. > Let me know if you need anything further from me. --- doc/assets-attribution.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/assets-attribution.md b/doc/assets-attribution.md index 31fe4e5b7..2cdcc273b 100644 --- a/doc/assets-attribution.md +++ b/doc/assets-attribution.md @@ -6,7 +6,7 @@ The following is a list of assets used in the bitcoin source and their proper at ### Info * Icon Pack: Typicons (http://typicons.com) * Designer: Stephen Hutchings (and more) -* License: CC BY-SA +* License: MIT * Site: [https://github.com/stephenhutchings/typicons.font](https://github.com/stephenhutchings/typicons.font) ### Assets Used @@ -29,7 +29,7 @@ Jonas Schnelli ### Info * Designer: Jonas Schnelli * Bitcoin Icon: (based on the original bitcoin logo from Bitboy) -* Some icons are based on Stephan Hutchings Typicons (these are under CC BY-SA license) +* Some icons are based on Stephan Hutchings Typicons * License: MIT ### Assets Used From 0c376340a4efa2842e9ffd1d93eca9895b4a9391 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 24 Jun 2015 03:36:22 +0000 Subject: [PATCH 0096/1283] acceptnonstdtxn option to skip (most) "non-standard transaction" checks, for testnet/regtest only --- src/init.cpp | 6 ++++++ src/main.cpp | 5 +++-- src/main.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 4473cd9ec..4a658a5da 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -395,6 +395,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-testnet", _("Use the test network")); strUsage += HelpMessageGroup(_("Node relay options:")); + if (showDebug) + strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !Params(CBaseChainParams::TESTNET).RequireStandard())); strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), 1)); strUsage += HelpMessageOpt("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY)); @@ -803,6 +805,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(strprintf(_("Invalid amount for -minrelaytxfee=: '%s'"), mapArgs["-minrelaytxfee"])); } + fRequireStandard = !GetBoolArg("-acceptnonstdtxn", !Params().RequireStandard()); + if (Params().RequireStandard() && !fRequireStandard) + return InitError(strprintf("acceptnonstdtxn is not currently supported for %s chain", chainparams.NetworkIDString())); + #ifdef ENABLE_WALLET if (mapArgs.count("-mintxfee")) { diff --git a/src/main.cpp b/src/main.cpp index e92f64413..f958fb46c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,6 +57,7 @@ bool fTxIndex = false; bool fHavePruned = false; bool fPruneMode = false; bool fIsBareMultisigStd = true; +bool fRequireStandard = true; bool fCheckBlockIndex = false; bool fCheckpointsEnabled = true; size_t nCoinCacheUsage = 5000 * 300; @@ -898,7 +899,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Rather not work on nonstandard transactions (unless -testnet/-regtest) string reason; - if (Params().RequireStandard() && !IsStandardTx(tx, reason)) + if (fRequireStandard && !IsStandardTx(tx, reason)) return state.DoS(0, error("AcceptToMemoryPool: nonstandard transaction: %s", reason), REJECT_NONSTANDARD, reason); @@ -969,7 +970,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } // Check for non-standard pay-to-script-hash in inputs - if (Params().RequireStandard() && !AreInputsStandard(tx, view)) + if (fRequireStandard && !AreInputsStandard(tx, view)) return error("AcceptToMemoryPool: nonstandard transaction input"); // Check that the transaction doesn't have an excessive number of diff --git a/src/main.h b/src/main.h index abaedae20..773c6e90f 100644 --- a/src/main.h +++ b/src/main.h @@ -109,6 +109,7 @@ extern bool fReindex; extern int nScriptCheckThreads; extern bool fTxIndex; extern bool fIsBareMultisigStd; +extern bool fRequireStandard; extern bool fCheckBlockIndex; extern bool fCheckpointsEnabled; extern size_t nCoinCacheUsage; From 6ebac0782f9201e86d507fe7fff71f2c35680682 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 3 Jul 2015 09:13:56 +0200 Subject: [PATCH 0097/1283] Remove ChainParams::DefaultMinerThreads No longer relevant after #5957. This hack existed because of another hack where the numthreads parameter, on regtest, doubled as how many blocks to generate. --- src/chainparams.cpp | 3 --- src/chainparams.h | 3 --- src/miner.cpp | 9 ++------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 778541751..cd31f98c5 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -50,7 +50,6 @@ public: pchMessageStart[3] = 0xd9; vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"); nDefaultPort = 8333; - nMinerThreads = 0; nPruneAfterHeight = 100000; /** @@ -147,7 +146,6 @@ public: pchMessageStart[3] = 0x07; vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"); nDefaultPort = 18333; - nMinerThreads = 0; nPruneAfterHeight = 1000; //! Modify the testnet genesis block so the timestamp is valid for a later start. @@ -206,7 +204,6 @@ public: pchMessageStart[1] = 0xbf; pchMessageStart[2] = 0xb5; pchMessageStart[3] = 0xda; - nMinerThreads = 1; genesis.nTime = 1296688602; genesis.nBits = 0x207fffff; genesis.nNonce = 2; diff --git a/src/chainparams.h b/src/chainparams.h index 8044b553e..c10d6d646 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -50,8 +50,6 @@ public: const std::vector& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } - /** Used if GenerateBitcoins is called with a negative number of threads */ - int DefaultMinerThreads() const { return nMinerThreads; } const CBlock& GenesisBlock() const { return genesis; } bool RequireRPCPassword() const { return fRequireRPCPassword; } /** Make miner wait to have peers to avoid wasting work */ @@ -79,7 +77,6 @@ protected: //! Raw pub key bytes for the broadcast alert signing key. std::vector vAlertPubKey; int nDefaultPort; - int nMinerThreads; uint64_t nPruneAfterHeight; std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; diff --git a/src/miner.cpp b/src/miner.cpp index ca32e9f7b..d3f5094fe 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -541,13 +541,8 @@ void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainpar { static boost::thread_group* minerThreads = NULL; - if (nThreads < 0) { - // In regtest threads defaults to 1 - if (Params().DefaultMinerThreads()) - nThreads = Params().DefaultMinerThreads(); - else - nThreads = GetNumCores(); - } + if (nThreads < 0) + nThreads = GetNumCores(); if (minerThreads != NULL) { From 4bdad99f5000539dcf03ddc92c142fa6deb44c01 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 3 Jul 2015 12:55:53 -0400 Subject: [PATCH 0098/1283] depends: bump boost to 1.58.0 --- depends/packages/boost.mk | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index e7aa48ddf..d27a70134 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,9 +1,8 @@ package=boost -$(package)_version=1_55_0 -$(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.55.0 +$(package)_version=1_58_0 +$(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.58.0 $(package)_file_name=$(package)_$($(package)_version).tar.bz2 -$(package)_sha256_hash=fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 -$(package)_patches=darwin_boost_atomic-1.patch darwin_boost_atomic-2.patch gcc_5_no_cxx11.patch +$(package)_sha256_hash=fdfc204fc33ec79c99b9a74944c3e54bd78be4f7f15e260c0e2700a36dc7d3e5 define $(package)_set_vars $(package)_config_opts_release=variant=release @@ -26,9 +25,6 @@ $(package)_cxxflags_linux=-fPIC endef define $(package)_preprocess_cmds - patch -p2 < $($(package)_patch_dir)/darwin_boost_atomic-1.patch && \ - patch -p2 < $($(package)_patch_dir)/darwin_boost_atomic-2.patch && \ - patch -p2 < $($(package)_patch_dir)/gcc_5_no_cxx11.patch && \ echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;" > user-config.jam endef From 00c5a73136e13813219c7b0846fa1bfd91757e5d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 3 Jul 2015 12:56:17 -0400 Subject: [PATCH 0099/1283] depends: bump miniupnpc to 1.9.20150609 --- depends/packages/miniupnpc.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk index 00101f1b9..e6573986f 100644 --- a/depends/packages/miniupnpc.mk +++ b/depends/packages/miniupnpc.mk @@ -1,8 +1,8 @@ package=miniupnpc -$(package)_version=1.9.20140701 +$(package)_version=1.9.20150609 $(package)_download_path=http://miniupnp.free.fr/files $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=26f3985bad7768b8483b793448ae49414cdc4451d0ec83e7c1944367e15f9f07 +$(package)_sha256_hash=86e6ccec5b660ba6889893d1f3fca21db087c6466b1a90f495a1f87ab1cd1c36 define $(package)_set_vars $(package)_build_opts=CC="$($(package)_cc)" From d5b18517432ee1b7cc0a5b38c186318ff15cac5c Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 3 Jul 2015 12:56:46 -0400 Subject: [PATCH 0100/1283] depends: bump ccache to 3.2.2 --- depends/packages/native_ccache.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk index 3226e89a6..745d7a398 100644 --- a/depends/packages/native_ccache.mk +++ b/depends/packages/native_ccache.mk @@ -1,8 +1,8 @@ package=native_ccache -$(package)_version=3.1.9 +$(package)_version=3.2.2 $(package)_download_path=http://samba.org/ftp/ccache $(package)_file_name=ccache-$($(package)_version).tar.bz2 -$(package)_sha256_hash=04d3e2e438ac8d4cc4b110b68cdd61bd59226c6588739a4a386869467f5ced7c +$(package)_sha256_hash=440f5e15141cc72d2bfff467c977020979810eb800882e3437ad1a7153cce7b2 define $(package)_set_vars $(package)_config_opts= From 142ee60a897781b77e300fc3ef9abbca2e0b0dd0 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 3 Jul 2015 12:57:58 -0400 Subject: [PATCH 0101/1283] depends: bump protobuf to 2.6.1 Also change the download source from googlecode to github. --- depends/packages/native_protobuf.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/packages/native_protobuf.mk b/depends/packages/native_protobuf.mk index ed1a771f0..ce50b366f 100644 --- a/depends/packages/native_protobuf.mk +++ b/depends/packages/native_protobuf.mk @@ -1,8 +1,8 @@ package=native_protobuf -$(package)_version=2.5.0 -$(package)_download_path=https://protobuf.googlecode.com/files +$(package)_version=2.6.1 +$(package)_download_path=https://github.com/google/protobuf/releases/download/v$($(package)_version) $(package)_file_name=protobuf-$($(package)_version).tar.bz2 -$(package)_sha256_hash=13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 +$(package)_sha256_hash=ee445612d544d885ae240ffbcbf9267faa9f593b7b101f21d58beceb92661910 define $(package)_set_vars $(package)_config_opts=--disable-shared From eb4f35dc7d1c561fc2a916aca123eb27118d8284 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 3 Jul 2015 12:58:33 -0400 Subject: [PATCH 0102/1283] depends: bump qrencode to 3.4.4 --- depends/packages/qrencode.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/qrencode.mk b/depends/packages/qrencode.mk index 1ad329e94..7b2124713 100644 --- a/depends/packages/qrencode.mk +++ b/depends/packages/qrencode.mk @@ -1,8 +1,8 @@ package=qrencode -$(package)_version=3.4.3 +$(package)_version=3.4.4 $(package)_download_path=https://fukuchi.org/works/qrencode/ $(package)_file_name=qrencode-$(qrencode_version).tar.bz2 -$(package)_sha256_hash=dfd71487513c871bad485806bfd1fdb304dedc84d2b01a8fb8e0940b50597a98 +$(package)_sha256_hash=efe5188b1ddbcbf98763b819b146be6a90481aac30cfc8d858ab78a19cde1fa5 define $(package)_set_vars $(package)_config_opts=--disable-shared -without-tools --disable-sdltest From c45c7ea0fa38fda453c596bd3161c9362d689381 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 16 Dec 2014 10:50:44 +0100 Subject: [PATCH 0103/1283] [REST] add JSON support for /rest/headers/ --- doc/REST-interface.md | 4 +--- qa/rpc-tests/rest.py | 39 +++++++++++++++++++++++++++++++++++---- src/rest.cpp | 19 +++++++++++++++---- src/rpcblockchain.cpp | 2 -- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/doc/REST-interface.md b/doc/REST-interface.md index 2219ceb65..1ba01362d 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -26,13 +26,11 @@ The HTTP request and response are both handled entirely in-memory, thus making m With the /notxdetails/ option JSON response will only contain the transaction hash instead of the complete transaction details. The option only affects the JSON response. ####Blockheaders -`GET /rest/headers//.` +`GET /rest/headers//.` Given a block hash, Returns amount of blockheaders in upward direction. -JSON is not supported. - ####Chaininfos `GET /rest/chaininfo.json` diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py index 6c51b2fcd..1a2d326cc 100755 --- a/qa/rpc-tests/rest.py +++ b/qa/rpc-tests/rest.py @@ -235,12 +235,43 @@ class RESTTest (BitcoinTestFramework): assert_equal(response_header_str.encode("hex")[0:160], response_header_hex_str[0:160]) # check json format - json_string = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+'json') - json_obj = json.loads(json_string) - assert_equal(json_obj['hash'], bb_hash) + block_json_string = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+'json') + block_json_obj = json.loads(block_json_string) + assert_equal(block_json_obj['hash'], bb_hash) + + # compare with json block header + response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"json", "", True) + assert_equal(response_header_json.status, 200) + response_header_json_str = response_header_json.read() + json_obj = json.loads(response_header_json_str) + assert_equal(len(json_obj), 1) #ensure that there is one header in the json response + assert_equal(json_obj[0]['hash'], bb_hash) #request/response hash should be the same + + #compare with normal RPC block response + rpc_block_json = self.nodes[0].getblock(bb_hash) + assert_equal(json_obj[0]['hash'], rpc_block_json['hash']) + assert_equal(json_obj[0]['confirmations'], rpc_block_json['confirmations']) + assert_equal(json_obj[0]['height'], rpc_block_json['height']) + assert_equal(json_obj[0]['version'], rpc_block_json['version']) + assert_equal(json_obj[0]['merkleroot'], rpc_block_json['merkleroot']) + assert_equal(json_obj[0]['time'], rpc_block_json['time']) + assert_equal(json_obj[0]['nonce'], rpc_block_json['nonce']) + assert_equal(json_obj[0]['bits'], rpc_block_json['bits']) + assert_equal(json_obj[0]['difficulty'], rpc_block_json['difficulty']) + assert_equal(json_obj[0]['chainwork'], rpc_block_json['chainwork']) + assert_equal(json_obj[0]['previousblockhash'], rpc_block_json['previousblockhash']) + + #see if we can get 5 headers in one response + self.nodes[1].generate(5) + self.sync_all() + response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/5/'+bb_hash+self.FORMAT_SEPARATOR+"json", "", True) + assert_equal(response_header_json.status, 200) + response_header_json_str = response_header_json.read() + json_obj = json.loads(response_header_json_str) + assert_equal(len(json_obj), 5) #now we should have 5 header objects # do tx test - tx_hash = json_obj['tx'][0]['txid']; + tx_hash = block_json_obj['tx'][0]['txid']; json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"json") json_obj = json.loads(json_string) assert_equal(json_obj['txid'], tx_hash) diff --git a/src/rest.cpp b/src/rest.cpp index a1bd893be..dfe01495f 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -65,6 +65,7 @@ public: extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +extern UniValue blockheaderToJSON(const CBlockIndex* blockindex); static RestErr RESTERR(enum HTTPStatusCode status, string message) { @@ -134,14 +135,14 @@ static bool rest_headers(AcceptedConnection* conn, if (!ParseHashStr(hashStr, hash)) throw RESTERR(HTTP_BAD_REQUEST, "Invalid hash: " + hashStr); - std::vector headers; + std::vector headers; headers.reserve(count); { LOCK(cs_main); BlockMap::const_iterator it = mapBlockIndex.find(hash); const CBlockIndex *pindex = (it != mapBlockIndex.end()) ? it->second : NULL; while (pindex != NULL && chainActive.Contains(pindex)) { - headers.push_back(pindex->GetBlockHeader()); + headers.push_back(pindex); if (headers.size() == (unsigned long)count) break; pindex = chainActive.Next(pindex); @@ -149,8 +150,8 @@ static bool rest_headers(AcceptedConnection* conn, } CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION); - BOOST_FOREACH(const CBlockHeader &header, headers) { - ssHeader << header; + BOOST_FOREACH(const CBlockIndex *pindex, headers) { + ssHeader << pindex->GetBlockHeader(); } switch (rf) { @@ -166,6 +167,16 @@ static bool rest_headers(AcceptedConnection* conn, return true; } + case RF_JSON: { + UniValue jsonHeaders(UniValue::VARR); + BOOST_FOREACH(const CBlockIndex *pindex, headers) { + jsonHeaders.push_back(blockheaderToJSON(pindex)); + } + string strJSON = jsonHeaders.write() + "\n"; + conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush; + return true; + } + default: { throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: .bin, .hex)"); } diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index b7c3eb172..9cdd0770e 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -77,7 +77,6 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) return result; } - UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) { UniValue result(UniValue::VOBJ); @@ -118,7 +117,6 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx return result; } - UniValue getblockcount(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) From 15e26a6a9afe299b9ca6fced73b876644365879b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 6 Jul 2015 20:06:16 +0200 Subject: [PATCH 0104/1283] qt: Force TLS1.0+ for SSL connections --- src/qt/bitcoin.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 8740b98b7..07250e72c 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #if defined(QT_STATICPLUGIN) #include @@ -515,6 +516,13 @@ int main(int argc, char *argv[]) #ifdef Q_OS_MAC QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); #endif +#if QT_VERSION >= 0x050500 + // Because of the POODLE attack it is recommended to disable SSLv3 (https://disablessl3.com/), + // so set SSL protocols to TLS1.0+. + QSslConfiguration sslconf = QSslConfiguration::defaultConfiguration(); + sslconf.setProtocol(QSsl::TlsV1_0OrLater); + QSslConfiguration::setDefaultConfiguration(sslconf); +#endif // Register meta types used for QMetaObject::invokeMethod qRegisterMetaType< bool* >(); From cb54d17355864fa08826d6511a0d7692b21ef2c9 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Thu, 2 Jul 2015 18:38:34 -0700 Subject: [PATCH 0105/1283] CLTV: Add more tests to improve coverage Four cases included: * The CLTV operand type mismatches the tx locktime. In the script it is 1 (interpreted as block height), but in the tx is 500000000 (interpreted as date) * The stack is empty when executing OP_CLTV * The tx is final by having only one input with MAX_INT sequence number * The operand for CLTV is negative (after OP_0 OP_1 OP_SUB) --- src/test/data/tx_invalid.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index 9def4042d..20bdbd08a 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -137,6 +137,8 @@ ["Argument missing"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "NOP2 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000001b1010000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], ["Argument negative with by-blockheight nLockTime=0"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP2 1"]], @@ -145,10 +147,14 @@ ["Argument negative with by-blocktime nLockTime=500,000,000"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP2 1"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000004005194b1010000000100000000000000000002000000", "P2SH,CHECKLOCKTIMEVERIFY"], ["Input locked"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1ffffffff0100000000000000000002000000", "P2SH,CHECKLOCKTIMEVERIFY"], ["Another input being unlocked isn't sufficient; the CHECKLOCKTIMEVERIFY-using input must be unlocked"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"] , @@ -158,6 +164,8 @@ ["Argument/tx height/time mismatch, both versions"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b100000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]], From 27d760580456d206c5a02ef29797f296f510099c Mon Sep 17 00:00:00 2001 From: Adam Weiss Date: Fri, 15 May 2015 15:31:14 -0400 Subject: [PATCH 0106/1283] Buffer log messages and explicitly open logs Prevents stomping on debug logs in datadirs that are locked by other instances and lost parameter interaction messages that can get wiped by ShrinkDebugFile(). The log is now opened explicitly and all emitted messages are buffered until this open occurs. The version message and log cut have also been moved to the earliest possible sensible location. --- src/init.cpp | 9 ++++- src/util.cpp | 101 ++++++++++++++++++++++++++++++++++++++------------- src/util.h | 1 + 3 files changed, 84 insertions(+), 27 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index abaf9b81d..62d5e4dbd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -667,6 +667,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fLogTimestamps = GetBoolArg("-logtimestamps", true); fLogIPs = GetBoolArg("-logips", false); + LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); + // when specifying an explicit binding address, you want to listen on it // even when -connect or -proxy is specified if (mapArgs.count("-bind")) { @@ -909,8 +912,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #endif if (GetBoolArg("-shrinkdebugfile", !fDebug)) ShrinkDebugFile(); - LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); + + if (fPrintToDebugLog) + OpenDebugLog(); + LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); #ifdef ENABLE_WALLET LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); diff --git a/src/util.cpp b/src/util.cpp index bb7df2320..634d8a705 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -167,23 +167,51 @@ instance_of_cinit; */ static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT; + /** - * We use boost::call_once() to make sure these are initialized - * in a thread-safe manner the first time called: + * We use boost::call_once() to make sure mutexDebugLog and + * vMsgsBeforeOpenLog are initialized in a thread-safe manner. + * + * NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog + * are leaked on exit. This is ugly, but will be cleaned up by + * the OS/libc. When the shutdown sequence is fully audited and + * tested, explicit destruction of these objects can be implemented. */ static FILE* fileout = NULL; static boost::mutex* mutexDebugLog = NULL; +static list *vMsgsBeforeOpenLog; + +static int FileWriteStr(const std::string &str, FILE *fp) +{ + return fwrite(str.data(), 1, str.size(), fp); +} static void DebugPrintInit() { - assert(fileout == NULL); assert(mutexDebugLog == NULL); + mutexDebugLog = new boost::mutex(); + vMsgsBeforeOpenLog = new list; +} +void OpenDebugLog() +{ + boost::call_once(&DebugPrintInit, debugPrintInitFlag); + boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); + + assert(fileout == NULL); + assert(vMsgsBeforeOpenLog); boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; fileout = fopen(pathDebug.string().c_str(), "a"); if (fileout) setbuf(fileout, NULL); // unbuffered - mutexDebugLog = new boost::mutex(); + // dump buffered messages from before we opened the log + while (!vMsgsBeforeOpenLog->empty()) { + FileWriteStr(vMsgsBeforeOpenLog->front(), fileout); + vMsgsBeforeOpenLog->pop_front(); + } + + delete vMsgsBeforeOpenLog; + vMsgsBeforeOpenLog = NULL; } bool LogAcceptCategory(const char* category) @@ -215,44 +243,67 @@ bool LogAcceptCategory(const char* category) return true; } +/** + * fStartedNewLine is a state variable held by the calling context that will + * suppress printing of the timestamp when multiple calls are made that don't + * end in a newline. Initialize it to true, and hold it, in the calling context. + */ +static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine) +{ + string strStamped; + + if (!fLogTimestamps) + return str; + + if (*fStartedNewLine) + strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str; + else + strStamped = str; + + if (!str.empty() && str[str.size()-1] == '\n') + *fStartedNewLine = true; + else + *fStartedNewLine = false; + + return strStamped; +} + int LogPrintStr(const std::string &str) { int ret = 0; // Returns total number of characters written + static bool fStartedNewLine = true; if (fPrintToConsole) { // print to console ret = fwrite(str.data(), 1, str.size(), stdout); fflush(stdout); } - else if (fPrintToDebugLog && AreBaseParamsConfigured()) + else if (fPrintToDebugLog) { - static bool fStartedNewLine = true; boost::call_once(&DebugPrintInit, debugPrintInitFlag); - - if (fileout == NULL) - return ret; - boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); - // reopen the log file, if requested - if (fReopenDebugLog) { - fReopenDebugLog = false; - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; - if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) - setbuf(fileout, NULL); // unbuffered + string strTimestamped = LogTimestampStr(str, &fStartedNewLine); + + // buffer if we haven't opened the log yet + if (fileout == NULL) { + assert(vMsgsBeforeOpenLog); + ret = strTimestamped.length(); + vMsgsBeforeOpenLog->push_back(strTimestamped); } - - // Debug print useful for profiling - if (fLogTimestamps && fStartedNewLine) - ret += fprintf(fileout, "%s ", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str()); - if (!str.empty() && str[str.size()-1] == '\n') - fStartedNewLine = true; else - fStartedNewLine = false; + { + // reopen the log file, if requested + if (fReopenDebugLog) { + fReopenDebugLog = false; + boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) + setbuf(fileout, NULL); // unbuffered + } - ret = fwrite(str.data(), 1, str.size(), fileout); + ret = FileWriteStr(strTimestamped, fileout); + } } - return ret; } diff --git a/src/util.h b/src/util.h index 6019e2501..afc9a378b 100644 --- a/src/util.h +++ b/src/util.h @@ -125,6 +125,7 @@ void ReadConfigFile(std::map& mapSettingsRet, std::map boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif boost::filesystem::path GetTempPath(); +void OpenDebugLog(); void ShrinkDebugFile(); void runCommand(const std::string& strCommand); From 5e058e74179f0e4ad62841ca82536f61b4673a1d Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 6 Jul 2015 08:11:34 +0200 Subject: [PATCH 0107/1283] [Qt] constify foreach uses where possible - this doesn't replace BOOST_FOREACH, it just makes used arguments const where possible --- src/qt/addressbookpage.cpp | 3 +-- src/qt/clientmodel.cpp | 6 +++--- src/qt/coincontroldialog.cpp | 11 ++++------- src/qt/receivecoinsdialog.cpp | 3 +-- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 5485d89f3..54635f1d5 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -254,8 +254,7 @@ void AddressBookPage::done(int retval) // Figure out which address was selected, and return it QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); - foreach (QModelIndex index, indexes) - { + foreach (const QModelIndex& index, indexes) { QVariant address = table->model()->data(index); returnValue = address.toString(); } diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 8e29cdeb0..5ac11324d 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -53,9 +53,9 @@ int ClientModel::getNumConnections(unsigned int flags) const return vNodes.size(); int nNum = 0; - BOOST_FOREACH(CNode* pnode, vNodes) - if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) - nNum++; + BOOST_FOREACH(const CNode* pnode, vNodes) + if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) + nNum++; return nNum; } diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 7531fbddc..eea450353 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -118,7 +118,7 @@ CoinControlDialog::CoinControlDialog(QWidget *parent) : // (un)select all connect(ui->pushButtonSelectAll, SIGNAL(clicked()), this, SLOT(buttonSelectAllClicked())); - // change coin control first column label due Qt4 bug. + // change coin control first column label due Qt4 bug. // see https://github.com/bitcoin/bitcoin/issues/5716 ui->treeWidget->headerItem()->setText(COLUMN_CHECKBOX, QString()); @@ -492,8 +492,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) coinControl->ListSelected(vCoinControl); model->getOutputs(vCoinControl, vOutputs); - BOOST_FOREACH(const COutput& out, vOutputs) - { + BOOST_FOREACH(const COutput& out, vOutputs) { // unselect already spent, very unlikely scenario, this could happen // when selected are spent elsewhere, like rpc or another computer uint256 txhash = out.tx->GetHash(); @@ -691,8 +690,7 @@ void CoinControlDialog::updateView() map > mapCoins; model->listCoins(mapCoins); - BOOST_FOREACH(PAIRTYPE(QString, vector) coins, mapCoins) - { + BOOST_FOREACH(const PAIRTYPE(QString, vector)& coins, mapCoins) { QTreeWidgetItem *itemWalletAddress = new QTreeWidgetItem(); itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); QString sWalletAddress = coins.first; @@ -719,8 +717,7 @@ void CoinControlDialog::updateView() double dPrioritySum = 0; int nChildren = 0; int nInputSum = 0; - BOOST_FOREACH(const COutput& out, coins.second) - { + BOOST_FOREACH(const COutput& out, coins.second) { int nInputSize = 0; nSum += out.tx->vout[out.i].nValue; nChildren++; diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 28cbd3abe..fd225f51a 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -185,8 +185,7 @@ void ReceiveCoinsDialog::on_showRequestButton_clicked() return; QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows(); - foreach (QModelIndex index, selection) - { + foreach (const QModelIndex& index, selection) { on_recentRequestsView_doubleClicked(index); } } From 65ce0215a461318c5d7caf3f35cfeef947171a5a Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 7 Jul 2015 12:15:44 +0200 Subject: [PATCH 0108/1283] [bitcoin-cli] improve error output --- src/bitcoin-cli.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index d45172014..903777ba5 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -190,6 +190,15 @@ int CommandLineRPC(int argc, char *argv[]) throw CConnectionFailed("server in warmup"); strPrint = "error: " + error.write(); nRet = abs(code); + if (error.isObject()) + { + UniValue errCode = find_value(error, "code"); + UniValue errMsg = find_value(error, "message"); + strPrint = errCode.isNull() ? "" : "error code: "+errCode.getValStr()+"\n"; + + if (errMsg.isStr()) + strPrint += "error message:\n"+errMsg.get_str(); + } } else { // Result if (result.isNull()) From 133601f6a59cc68288736f900a9a96178c2344dc Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 7 Jul 2015 18:18:14 +0200 Subject: [PATCH 0109/1283] tests: Fix bitcoin-tx signing testcase Fixes wrong scriptPubkey problem, which caused the transaction to not actually be signed. --- src/test/data/bitcoin-util-test.json | 2 +- src/test/data/txcreatesign.hex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/data/bitcoin-util-test.json b/src/test/data/bitcoin-util-test.json index 6090421cb..afd35af50 100644 --- a/src/test/data/bitcoin-util-test.json +++ b/src/test/data/bitcoin-util-test.json @@ -52,7 +52,7 @@ ["-create", "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", - "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\"}]", + "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", "sign=ALL", "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], "output_cmp": "txcreatesign.hex" diff --git a/src/test/data/txcreatesign.hex b/src/test/data/txcreatesign.hex index 56ce28a86..a46fcc88c 100644 --- a/src/test/data/txcreatesign.hex +++ b/src/test/data/txcreatesign.hex @@ -1 +1 @@ -01000000018594c5bdcaec8f06b78b596f31cd292a294fd031e24eec716f43dac91ea7494d0000000000ffffffff01a0860100000000001976a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac00000000 +01000000018594c5bdcaec8f06b78b596f31cd292a294fd031e24eec716f43dac91ea7494d000000008b48304502210096a75056c9e2cc62b7214777b3d2a592cfda7092520126d4ebfcd6d590c99bd8022051bb746359cf98c0603f3004477eac68701132380db8facba19c89dc5ab5c5e201410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ffffffff01a0860100000000001976a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac00000000 From 8c44e63077ec89d3cb600a2d70e0d7cb0e17f109 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Wed, 8 Jul 2015 22:35:29 +0200 Subject: [PATCH 0110/1283] Add BITCOIND_SIGTERM_TIMEOUT to OpenRC init scripts This allows users to specify, e.g. raise, the default timeout of 60 seconds. Some bitcoind instances, especially long running ones on slow hardware, require a higher timeout for a clean shut down. Also add a comment to bitcoind.openrc's 'retry=', since it is not obvious from the variable name what it does. --- contrib/init/bitcoind.openrc | 6 +++++- contrib/init/bitcoind.openrcconf | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/contrib/init/bitcoind.openrc b/contrib/init/bitcoind.openrc index a94f03680..eda1a96fb 100644 --- a/contrib/init/bitcoind.openrc +++ b/contrib/init/bitcoind.openrc @@ -32,7 +32,11 @@ required_files="${BITCOIND_CONFIGFILE}" start_stop_daemon_args="-u ${BITCOIND_USER} \ -N ${BITCOIND_NICE} -w 2000" pidfile="${BITCOIND_PIDFILE}" -retry=60 + +# The retry schedule to use when stopping the daemon. Could be either +# a timeout in seconds or multiple signal/timeout pairs (like +# "SIGKILL/180 SIGTERM/300") +retry="${BITCOIND_SIGTERM_TIMEOUT}" depend() { need localmount net diff --git a/contrib/init/bitcoind.openrcconf b/contrib/init/bitcoind.openrcconf index d8d7f5833..0cbff6d30 100644 --- a/contrib/init/bitcoind.openrcconf +++ b/contrib/init/bitcoind.openrcconf @@ -25,3 +25,9 @@ # Additional options (avoid -conf and -datadir, use flags above) BITCOIND_OPTS="-disablewallet" +# The timeout in seconds OpenRC will wait for bitcoind to terminate +# after a SIGTERM has been raised. +# Note that this will be mapped as argument to start-stop-daemon's +# '--retry' option, which means you can specify a retry schedule +# here. For more information see man 8 start-stop-daemon. +BITCOIND_SIGTERM_TIMEOUT=60 From 8a0b933aaed45b8d58aaba5bd9a904bb7105cf08 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Thu, 9 Jul 2015 18:10:57 -0700 Subject: [PATCH 0111/1283] Fix intermittent test failure, reduce test time In txn_clone.py, non-essential test transaction tx2 was asserted to be unconfirmed, but would occasionally confirm depending on network behavior. Fix by explicitly sharing with miner and checking for 1 confirmation. Reduce required conflict tests from 4 to 2, by moving one invocation each of txn_clone.py and txn_doublespend.py to the extented test section. This saves about 15 seconds per test run for me. --- qa/pull-tester/rpc-tests.sh | 4 ++-- qa/rpc-tests/txn_clone.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index b28208239..0ef1b1eda 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -19,10 +19,8 @@ testScripts=( 'wallet.py' 'listtransactions.py' 'mempool_resurrect_test.py' - 'txn_doublespend.py' 'txn_doublespend.py --mineblock' 'txn_clone.py' - 'txn_clone.py --mineblock' 'getchaintips.py' 'rawtransactions.py' 'rest.py' @@ -44,6 +42,8 @@ testScriptsExt=( 'bipdersig.py' 'getblocktemplate_longpoll.py' 'getblocktemplate_proposals.py' + 'txn_doublespend.py' + 'txn_clone.py --mineblock' 'pruning.py' 'forknotify.py' 'invalidateblock.py' diff --git a/qa/rpc-tests/txn_clone.py b/qa/rpc-tests/txn_clone.py index 0d276ecc9..e8ced0e5b 100755 --- a/qa/rpc-tests/txn_clone.py +++ b/qa/rpc-tests/txn_clone.py @@ -125,6 +125,8 @@ class TxnMallTest(BitcoinTestFramework): # Reconnect the split network, and sync chain: connect_nodes(self.nodes[1], 2) + self.nodes[2].sendrawtransaction(fund_bar_tx["hex"]) + self.nodes[2].sendrawtransaction(tx2["hex"]) self.nodes[2].generate(1) # Mine another block to make sure we sync sync_blocks(self.nodes) @@ -136,7 +138,7 @@ class TxnMallTest(BitcoinTestFramework): # Verify expected confirmations assert_equal(tx1["confirmations"], -1) assert_equal(tx1_clone["confirmations"], 2) - assert_equal(tx2["confirmations"], 0) + assert_equal(tx2["confirmations"], 1) # Check node0's total balance; should be same as before the clone, + 100 BTC for 2 matured, # less possible orphaned matured subsidy From 85ee55b5c37bedca98ec472439e1710277e8e4b2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 8 Jul 2015 14:47:39 +0200 Subject: [PATCH 0112/1283] rpc: Remove chain-specific RequireRPCPassword I've never liked the chain-specific exception to having to set a password. It gives issues with #6388 which makes it valid to set no password in every case (as it enables random cookie authentication). This pull removes the flag, so that all chains are regarded the same. It also removes the username==password test, which doesn't provide any substantial extra security. --- src/chainparams.cpp | 3 --- src/chainparams.h | 2 -- src/rpcserver.cpp | 3 +-- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 778541751..3d172765c 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -99,7 +99,6 @@ public: vFixedSeeds = std::vector(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main)); - fRequireRPCPassword = true; fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = true; @@ -171,7 +170,6 @@ public: vFixedSeeds = std::vector(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); - fRequireRPCPassword = true; fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = false; @@ -218,7 +216,6 @@ public: vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds. vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds. - fRequireRPCPassword = false; fMiningRequiresPeers = false; fDefaultConsistencyChecks = true; fRequireStandard = false; diff --git a/src/chainparams.h b/src/chainparams.h index 8044b553e..8f13c2814 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -53,7 +53,6 @@ public: /** Used if GenerateBitcoins is called with a negative number of threads */ int DefaultMinerThreads() const { return nMinerThreads; } const CBlock& GenesisBlock() const { return genesis; } - bool RequireRPCPassword() const { return fRequireRPCPassword; } /** Make miner wait to have peers to avoid wasting work */ bool MiningRequiresPeers() const { return fMiningRequiresPeers; } /** Default value for -checkmempool and -checkblockindex argument */ @@ -86,7 +85,6 @@ protected: std::string strNetworkID; CBlock genesis; std::vector vFixedSeeds; - bool fRequireRPCPassword; bool fMiningRequiresPeers; bool fDefaultConsistencyChecks; bool fRequireStandard; diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 287cfb2f1..daf10736b 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -598,8 +598,7 @@ void StartRPCThreads() LogPrint("rpc", "Allowing RPC connections from: %s\n", strAllowed); strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; - if (((mapArgs["-rpcpassword"] == "") || - (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword()) + if (mapArgs["-rpcpassword"] == "") { unsigned char rand_pwd[32]; GetRandBytes(rand_pwd, 32); From 9cc91523dbec6441e327e1e4c83ba751a4680bec Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 6 Jul 2015 10:49:24 +0200 Subject: [PATCH 0113/1283] rpc: Accept scientific notation for monetary amounts in JSON Add a function `ParseFixedPoint` that parses numbers according to the JSON number specification and returns a 64-bit integer. Then this in `AmountFromValue`, rather than `ParseMoney`. Also add lots of tests (thanks to @jonasschnelli for some of them). Fixes issue #6297. --- src/rpcserver.cpp | 2 +- src/test/rpc_tests.cpp | 21 +++++++ src/test/util_tests.cpp | 66 +++++++++++++++++++++ src/utilstrencodings.cpp | 120 +++++++++++++++++++++++++++++++++++++++ src/utilstrencodings.h | 7 +++ 5 files changed, 215 insertions(+), 1 deletion(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 287cfb2f1..aeb51fed5 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -124,7 +124,7 @@ CAmount AmountFromValue(const UniValue& value) if (!value.isReal() && !value.isNum()) throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number"); CAmount amount; - if (!ParseMoney(value.getValStr(), amount)) + if (!ParseFixedPoint(value.getValStr(), 8, &amount)) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); if (!MoneyRange(amount)) throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range"); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 9e99ff628..25599beaf 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -142,6 +142,24 @@ BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values) BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1.00000000")), 100000000LL); BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.9999999")), 2099999999999990LL); BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.99999999")), 2099999999999999LL); + + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1e-8")), COIN/100000000); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.1e-7")), COIN/100000000); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.01e-6")), COIN/100000000); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.0000000000000000000000000000000000000000000000000000000000000000000000000001e+68")), COIN/100000000); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("10000000000000000000000000000000000000000000000000000000000000000e-64")), COIN); + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000e64")), COIN); + + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e-9")), UniValue); //should fail + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("0.000000019")), UniValue); //should fail + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001000000")), 1LL); //should pass, cut trailing 0 + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("19e-9")), UniValue); //should fail + BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.19e-6")), 19); //should pass, leading 0 is present + + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("92233720368.54775808")), UniValue); //overflow error + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e+11")), UniValue); //overflow error + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e11")), UniValue); //overflow error signless + BOOST_CHECK_THROW(AmountFromValue(ValueFromString("93e+9")), UniValue); //overflow error } BOOST_AUTO_TEST_CASE(json_parse_errors) @@ -151,6 +169,9 @@ BOOST_AUTO_TEST_CASE(json_parse_errors) // Valid, with leading or trailing whitespace BOOST_CHECK_EQUAL(ParseNonRFCJSONValue(" 1.0").get_real(), 1.0); BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0 ").get_real(), 1.0); + + BOOST_CHECK_THROW(AmountFromValue(ParseNonRFCJSONValue(".19e-6")), std::runtime_error); //should fail, missing leading 0, therefore invalid JSON + BOOST_CHECK_EQUAL(AmountFromValue(ParseNonRFCJSONValue("0.00000000000000000000000000000000000001e+30 ")), 1); // Invalid, initial garbage BOOST_CHECK_THROW(ParseNonRFCJSONValue("[1.0"), std::runtime_error); BOOST_CHECK_THROW(ParseNonRFCJSONValue("a1.0"), std::runtime_error); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 5cb589425..e956cc5b9 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -418,4 +418,70 @@ BOOST_AUTO_TEST_CASE(test_FormatSubVersion) BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/")); BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; comment2)/")); } + +BOOST_AUTO_TEST_CASE(test_ParseFixedPoint) +{ + int64_t amount = 0; + BOOST_CHECK(ParseFixedPoint("0", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 0LL); + BOOST_CHECK(ParseFixedPoint("1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 100000000LL); + BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 0LL); + BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, -10000000LL); + BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 110000000LL); + BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 110000000LL); + BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 1100000000LL); + BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 11000000LL); + BOOST_CHECK(ParseFixedPoint("1000", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 100000000000LL); + BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount)); + BOOST_CHECK_EQUAL(amount, -100000000000LL); + BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 1LL); + BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 1LL); + BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount)); + BOOST_CHECK_EQUAL(amount, -1LL); + BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 100000000000000001LL); + BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount)); + BOOST_CHECK_EQUAL(amount, 999999999999999999LL); + BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount)); + BOOST_CHECK_EQUAL(amount, -999999999999999999LL); + + BOOST_CHECK(!ParseFixedPoint("", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount)); + BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount)); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 7d1de7d6a..7208ca947 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -538,3 +538,123 @@ int atoi(const std::string& str) { return atoi(str.c_str()); } + +/** Upper bound for mantissa. + * 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer. + * Larger integers cannot consist of arbitrary combinations of 0-9: + * + * 999999999999999999 1^18-1 + * 9223372036854775807 (1<<63)-1 (max int64_t) + * 9999999999999999999 1^19-1 (would overflow) + */ +static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL; + +/** Helper function for ParseFixedPoint */ +static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros) +{ + if(ch == '0') + ++mantissa_tzeros; + else { + for (int i=0; i<=mantissa_tzeros; ++i) { + if (mantissa > (UPPER_BOUND / 10LL)) + return false; /* overflow */ + mantissa *= 10; + } + mantissa += ch - '0'; + mantissa_tzeros = 0; + } + return true; +} + +bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out) +{ + int64_t mantissa = 0; + int64_t exponent = 0; + int mantissa_tzeros = 0; + bool mantissa_sign = false; + bool exponent_sign = false; + int ptr = 0; + int end = val.size(); + int point_ofs = 0; + + if (ptr < end && val[ptr] == '-') { + mantissa_sign = true; + ++ptr; + } + if (ptr < end) + { + if (val[ptr] == '0') { + /* pass single 0 */ + ++ptr; + } else if (val[ptr] >= '1' && val[ptr] <= '9') { + while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { + if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) + return false; /* overflow */ + ++ptr; + } + } else return false; /* missing expected digit */ + } else return false; /* empty string or loose '-' */ + if (ptr < end && val[ptr] == '.') + { + ++ptr; + if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') + { + while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { + if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) + return false; /* overflow */ + ++ptr; + ++point_ofs; + } + } else return false; /* missing expected digit */ + } + if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E')) + { + ++ptr; + if (ptr < end && val[ptr] == '+') + ++ptr; + else if (ptr < end && val[ptr] == '-') { + exponent_sign = true; + ++ptr; + } + if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { + while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { + if (exponent > (UPPER_BOUND / 10LL)) + return false; /* overflow */ + exponent = exponent * 10 + val[ptr] - '0'; + ++ptr; + } + } else return false; /* missing expected digit */ + } + if (ptr != end) + return false; /* trailing garbage */ + + /* finalize exponent */ + if (exponent_sign) + exponent = -exponent; + exponent = exponent - point_ofs + mantissa_tzeros; + + /* finalize mantissa */ + if (mantissa_sign) + mantissa = -mantissa; + + /* convert to one 64-bit fixed-point value */ + exponent += decimals; + if (exponent < 0) + return false; /* cannot represent values smaller than 10^-decimals */ + if (exponent >= 18) + return false; /* cannot represent values larger than or equal to 10^(18-decimals) */ + + for (int i=0; i < exponent; ++i) { + if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL)) + return false; /* overflow */ + mantissa *= 10; + } + if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND) + return false; /* overflow */ + + if (amount_out) + *amount_out = mantissa; + + return true; +} + diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 58329b51b..dcd56751f 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -109,4 +109,11 @@ bool TimingResistantEqual(const T& a, const T& b) return accumulator == 0; } +/** Parse number as fixed point according to JSON number syntax. + * See http://json.org/number.gif + * @returns true on success, false on error. + * @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger. + */ +bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out); + #endif // BITCOIN_UTILSTRENCODINGS_H From 5098c47b2430ded299c21620527ebd0544fe51e2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 9 Jul 2015 13:56:31 -0400 Subject: [PATCH 0114/1283] Implement accurate memory accounting for mempool --- src/memusage.h | 67 +++++++++++++++++++++++++++++++++- src/primitives/transaction.cpp | 5 +++ src/primitives/transaction.h | 9 +++++ src/rpcblockchain.cpp | 2 + src/script/script.cpp | 5 +++ src/script/script.h | 3 ++ src/txmempool.cpp | 14 ++++++- src/txmempool.h | 7 ++++ 8 files changed, 110 insertions(+), 2 deletions(-) diff --git a/src/memusage.h b/src/memusage.h index 9f7de9e2e..7a831e6d3 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -20,12 +21,28 @@ namespace memusage /** Compute the total memory used by allocating alloc bytes. */ static size_t MallocUsage(size_t alloc); +/** Dynamic memory usage for built-in types is zero. */ +static inline size_t DynamicUsage(const int8_t& v) { return 0; } +static inline size_t DynamicUsage(const uint8_t& v) { return 0; } +static inline size_t DynamicUsage(const int16_t& v) { return 0; } +static inline size_t DynamicUsage(const uint16_t& v) { return 0; } +static inline size_t DynamicUsage(const int32_t& v) { return 0; } +static inline size_t DynamicUsage(const uint32_t& v) { return 0; } +static inline size_t DynamicUsage(const int64_t& v) { return 0; } +static inline size_t DynamicUsage(const uint64_t& v) { return 0; } +static inline size_t DynamicUsage(const float& v) { return 0; } +static inline size_t DynamicUsage(const double& v) { return 0; } +template static inline size_t DynamicUsage(X * const &v) { return 0; } +template static inline size_t DynamicUsage(const X * const &v) { return 0; } +template static inline size_t DynamicUsage(std::pair &p) { return 0; } + /** Compute the memory used for dynamically allocated but owned data structures. * For generic data types, this is *not* recursive. DynamicUsage(vector >) * will compute the memory used for the vector's, but not for the ints inside. * This is for efficiency reasons, as these functions are intended to be fast. If * application data structures require more accurate inner accounting, they should - * do the recursion themselves, or use more efficient caching + updating on modification. + * use RecursiveDynamicUsage, iterate themselves, or use more efficient caching + + * updating on modification. */ template static size_t DynamicUsage(const std::vector& v); template static size_t DynamicUsage(const std::set& s); @@ -34,6 +51,12 @@ template static size_t DynamicUsage(const boost::unorder template static size_t DynamicUsage(const boost::unordered_map& s); template static size_t DynamicUsage(const X& x); +template static size_t RecursiveDynamicUsage(const std::vector& v); +template static size_t RecursiveDynamicUsage(const std::set& v); +template static size_t RecursiveDynamicUsage(const std::map& v); +template static size_t RecursiveDynamicUsage(const std::pair& v); +template static size_t RecursiveDynamicUsage(const X& v); + static inline size_t MallocUsage(size_t alloc) { // Measured on libc6 2.19 on Linux. @@ -65,18 +88,54 @@ static inline size_t DynamicUsage(const std::vector& v) return MallocUsage(v.capacity() * sizeof(X)); } +template +static inline size_t RecursiveDynamicUsage(const std::vector& v) +{ + size_t usage = DynamicUsage(v); + BOOST_FOREACH(const X& x, v) { + usage += RecursiveDynamicUsage(x); + } + return usage; +} + template static inline size_t DynamicUsage(const std::set& s) { return MallocUsage(sizeof(stl_tree_node)) * s.size(); } +template +static inline size_t RecursiveDynamicUsage(const std::set& v) +{ + size_t usage = DynamicUsage(v); + BOOST_FOREACH(const X& x, v) { + usage += RecursiveDynamicUsage(x); + } + return usage; +} + template static inline size_t DynamicUsage(const std::map& m) { return MallocUsage(sizeof(stl_tree_node >)) * m.size(); } +template +static inline size_t RecursiveDynamicUsage(const std::map& v) +{ + size_t usage = DynamicUsage(v); + for (typename std::map::const_iterator it = v.begin(); it != v.end(); it++) { + usage += RecursiveDynamicUsage(*it); + } + return usage; +} + +template +static inline size_t RecursiveDynamicUsage(const std::pair& v) +{ + return RecursiveDynamicUsage(v.first) + RecursiveDynamicUsage(v.second); +} + // Boost data structures template @@ -106,6 +165,12 @@ static inline size_t DynamicUsage(const X& x) return x.DynamicMemoryUsage(); } +template +static inline size_t RecursiveDynamicUsage(const X& x) +{ + return DynamicUsage(x); +} + } #endif diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 606dbea79..7ed2d4597 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -72,6 +72,11 @@ void CTransaction::UpdateHash() const *const_cast(&hash) = SerializeHash(*this); } +size_t CTransaction::DynamicMemoryUsage() const +{ + return memusage::RecursiveDynamicUsage(vin) + memusage::RecursiveDynamicUsage(vout); +} + CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { } CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) { diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 6cfd93a9a..77326c64b 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -7,6 +7,7 @@ #define BITCOIN_PRIMITIVES_TRANSACTION_H #include "amount.h" +#include "memusage.h" #include "script/script.h" #include "serialize.h" #include "uint256.h" @@ -48,6 +49,8 @@ public: } std::string ToString() const; + + size_t DynamicMemoryUsage() const { return 0; } }; /** An input of a transaction. It contains the location of the previous @@ -96,6 +99,8 @@ public: } std::string ToString() const; + + size_t DynamicMemoryUsage() const { return scriptSig.DynamicMemoryUsage(); } }; /** An output of a transaction. It contains the public key that the next input @@ -166,6 +171,8 @@ public: } std::string ToString() const; + + size_t DynamicMemoryUsage() const { return scriptPubKey.DynamicMemoryUsage(); } }; struct CMutableTransaction; @@ -249,6 +256,8 @@ public: } std::string ToString() const; + + size_t DynamicMemoryUsage() const; }; /** A mutable version of CTransaction. */ diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 9cdd0770e..c2de6cb24 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -758,6 +758,7 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp) "{\n" " \"size\": xxxxx (numeric) Current tx count\n" " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n" + " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n" "}\n" "\nExamples:\n" + HelpExampleCli("getmempoolinfo", "") @@ -767,6 +768,7 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp) UniValue ret(UniValue::VOBJ); ret.push_back(Pair("size", (int64_t) mempool.size())); ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); + ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); return ret; } diff --git a/src/script/script.cpp b/src/script/script.cpp index fd3392473..b1d2ceeb9 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -260,3 +260,8 @@ std::string CScript::ToString() const } return str; } + +size_t CScript::DynamicMemoryUsage() const +{ + return memusage::DynamicUsage(*(static_cast*>(this))); +} diff --git a/src/script/script.h b/src/script/script.h index e39ca57f4..aea34d05f 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_SCRIPT_SCRIPT_H #define BITCOIN_SCRIPT_SCRIPT_H +#include "memusage.h" #include "crypto/common.h" #include @@ -607,6 +608,8 @@ public: // The default std::vector::clear() does not release memory. std::vector().swap(*this); } + + size_t DynamicMemoryUsage() const; }; class CReserveScript diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 2292191be..4caa5fc82 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -18,7 +18,7 @@ using namespace std; CTxMemPoolEntry::CTxMemPoolEntry(): - nFee(0), nTxSize(0), nModSize(0), nTime(0), dPriority(0.0), hadNoDependencies(false) + nFee(0), nTxSize(0), nModSize(0), nUsageSize(0), nTime(0), dPriority(0.0), hadNoDependencies(false) { nHeight = MEMPOOL_HEIGHT; } @@ -31,6 +31,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, { nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); nModSize = tx.CalculateModifiedSize(nTxSize); + nUsageSize = tx.DynamicMemoryUsage(); } CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other) @@ -101,6 +102,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i); nTransactionsUpdated++; totalTxSize += entry.GetTxSize(); + cachedInnerUsage += entry.DynamicMemoryUsage(); minerPolicyEstimator->processTransaction(entry, fCurrentEstimate); return true; @@ -146,6 +148,7 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem removed.push_back(tx); totalTxSize -= mapTx[hash].GetTxSize(); + cachedInnerUsage -= mapTx[hash].DynamicMemoryUsage(); mapTx.erase(hash); nTransactionsUpdated++; minerPolicyEstimator->removeTx(hash); @@ -226,6 +229,7 @@ void CTxMemPool::clear() mapTx.clear(); mapNextTx.clear(); totalTxSize = 0; + cachedInnerUsage = 0; ++nTransactionsUpdated; } @@ -237,6 +241,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size()); uint64_t checkTotal = 0; + uint64_t innerUsage = 0; CCoinsViewCache mempoolDuplicate(const_cast(pcoins)); @@ -245,6 +250,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const for (std::map::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { unsigned int i = 0; checkTotal += it->second.GetTxSize(); + innerUsage += it->second.DynamicMemoryUsage(); const CTransaction& tx = it->second.GetTx(); bool fDependsWait = false; BOOST_FOREACH(const CTxIn &txin, tx.vin) { @@ -299,6 +305,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const } assert(totalTxSize == checkTotal); + assert(innerUsage == cachedInnerUsage); } void CTxMemPool::queryHashes(vector& vtxid) @@ -419,3 +426,8 @@ bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const { bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const { return mempool.exists(txid) || base->HaveCoins(txid); } + +size_t CTxMemPool::DynamicMemoryUsage() const { + LOCK(cs); + return memusage::DynamicUsage(mapTx) + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + cachedInnerUsage; +} diff --git a/src/txmempool.h b/src/txmempool.h index 7271a5f60..ea36ce1ad 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -40,6 +40,7 @@ private: CAmount nFee; //! Cached to avoid expensive parent-transaction lookups size_t nTxSize; //! ... and avoid recomputing tx size size_t nModSize; //! ... and modified size for priority + size_t nUsageSize; //! ... and total memory usage int64_t nTime; //! Local time when entering the mempool double dPriority; //! Priority when entering the mempool unsigned int nHeight; //! Chain height when entering the mempool @@ -58,6 +59,7 @@ public: int64_t GetTime() const { return nTime; } unsigned int GetHeight() const { return nHeight; } bool WasClearAtEntry() const { return hadNoDependencies; } + size_t DynamicMemoryUsage() const { return nUsageSize; } }; class CBlockPolicyEstimator; @@ -73,6 +75,7 @@ public: CInPoint(const CTransaction* ptxIn, uint32_t nIn) { ptx = ptxIn; n = nIn; } void SetNull() { ptx = NULL; n = (uint32_t) -1; } bool IsNull() const { return (ptx == NULL && n == (uint32_t) -1); } + size_t DynamicMemoryUsage() const { return 0; } }; /** @@ -93,6 +96,7 @@ private: CBlockPolicyEstimator* minerPolicyEstimator; uint64_t totalTxSize; //! sum of all mempool tx' byte sizes + uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves) public: mutable CCriticalSection cs; @@ -139,6 +143,7 @@ public: LOCK(cs); return mapTx.size(); } + uint64_t GetTotalTxSize() { LOCK(cs); @@ -162,6 +167,8 @@ public: /** Write/Read estimates to disk */ bool WriteFeeEstimates(CAutoFile& fileout) const; bool ReadFeeEstimates(CAutoFile& filein); + + size_t DynamicMemoryUsage() const; }; /** From d422f9b1fdb42a51aadaa1bbc157542dca2feb17 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 9 Jul 2015 18:23:27 -0400 Subject: [PATCH 0115/1283] Test whether created sockets are select()able --- src/compat.h | 8 ++++++++ src/net.cpp | 18 ++++++++++++++++++ src/netbase.cpp | 3 +++ 3 files changed, 29 insertions(+) diff --git a/src/compat.h b/src/compat.h index 7a5438a11..f88b6ce36 100644 --- a/src/compat.h +++ b/src/compat.h @@ -92,4 +92,12 @@ typedef u_int SOCKET; size_t strnlen( const char *start, size_t max_len); #endif // HAVE_DECL_STRNLEN +bool static inline IsSelectableSocket(SOCKET s) { +#ifdef WIN32 + return true; +#else + return (s >= 0 && s < FD_SETSIZE); +#endif +} + #endif // BITCOIN_COMPAT_H diff --git a/src/net.cpp b/src/net.cpp index 2c7ba0ca7..3d369c7dd 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -386,6 +386,12 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort(), nConnectTimeout, &proxyConnectionFailed) : ConnectSocket(addrConnect, hSocket, nConnectTimeout, &proxyConnectionFailed)) { + if (!IsSelectableSocket(hSocket)) { + LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n"); + CloseSocket(hSocket); + return NULL; + } + addrman.Attempt(addrConnect); // Add node @@ -949,6 +955,11 @@ void ThreadSocketHandler() if (nErr != WSAEWOULDBLOCK) LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr)); } + else if (!IsSelectableSocket(hSocket)) + { + LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToString()); + CloseSocket(hSocket); + } else if (nInbound >= nMaxInbound) { LogPrint("net", "connection from %s dropped (full)\n", addr.ToString()); @@ -1597,6 +1608,13 @@ bool BindListenPort(const CService &addrBind, string& strError, bool fWhiteliste LogPrintf("%s\n", strError); return false; } + if (!IsSelectableSocket(hListenSocket)) + { + strError = "Error: Couldn't create a listenable socket for incoming connections"; + LogPrintf("%s\n", strError); + return false; + } + #ifndef WIN32 #ifdef SO_NOSIGPIPE diff --git a/src/netbase.cpp b/src/netbase.cpp index c9fc7d67f..b7e2e5791 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -266,6 +266,9 @@ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSock } else { // Other error or blocking int nErr = WSAGetLastError(); if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { + if (!IsSelectableSocket(hSocket)) { + return false; + } struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait)); fd_set fdset; FD_ZERO(&fdset); From e3c42973b2f6fb1ceb277b2681e8ebccd6b588df Mon Sep 17 00:00:00 2001 From: Paul Georgiou Date: Fri, 10 Jul 2015 19:21:21 +0300 Subject: [PATCH 0116/1283] Update Linearize tool to support Windows paths --- contrib/linearize/README.md | 6 +++--- contrib/linearize/linearize-data.py | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/contrib/linearize/README.md b/contrib/linearize/README.md index 157586e4d..06f278f3b 100644 --- a/contrib/linearize/README.md +++ b/contrib/linearize/README.md @@ -3,7 +3,7 @@ Construct a linear, no-fork, best version of the blockchain. ## Step 1: Download hash list - $ ./linearize-hashes.py linearize.cfg > hashlist.txt + $ ./linearize-hashes.py linearize.cfg > hashlist.txt Required configuration file settings for linearize-hashes: * RPC: rpcuser, rpcpassword @@ -14,7 +14,7 @@ Optional config file setting for linearize-hashes: ## Step 2: Copy local block data - $ ./linearize-data.py linearize.cfg + $ ./linearize-data.py linearize.cfg Required configuration file settings: * "input": bitcoind blocks/ directory containing blkNNNNN.dat @@ -26,7 +26,7 @@ output. Optional config file setting for linearize-data: * "netmagic": network magic number -* "max_out_sz": maximum output file size (default 1000*1000*1000) +* "max_out_sz": maximum output file size (default `1000*1000*1000`) * "split_timestamp": Split files when a new month is first seen, in addition to reaching a maximum file size. * "file_timestamp": Set each file's last-modified time to that of the diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index 7947c6bf7..0f6fde2a6 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -12,6 +12,7 @@ import json import struct import re import os +import os.path import base64 import httplib import sys @@ -115,19 +116,20 @@ class BlockDataCopier: self.setFileTime = True if settings['split_timestamp'] != 0: self.timestampSplit = True - # Extents and cache for out-of-order blocks + # Extents and cache for out-of-order blocks self.blockExtents = {} self.outOfOrderData = {} self.outOfOrderSize = 0 # running total size for items in outOfOrderData def writeBlock(self, inhdr, blk_hdr, rawblock): - if not self.fileOutput and ((self.outsz + self.inLen) > self.maxOutSz): + blockSizeOnDisk = len(inhdr) + len(blk_hdr) + len(rawblock) + if not self.fileOutput and ((self.outsz + blockSizeOnDisk) > self.maxOutSz): self.outF.close() if self.setFileTime: os.utime(outFname, (int(time.time()), highTS)) self.outF = None self.outFname = None - self.outFn = outFn + 1 + self.outFn = self.outFn + 1 self.outsz = 0 (blkDate, blkTS) = get_blk_dt(blk_hdr) @@ -147,7 +149,7 @@ class BlockDataCopier: if self.fileOutput: outFname = self.settings['output_file'] else: - outFname = "%s/blk%05d.dat" % (self.settings['output'], outFn) + outFname = os.path.join(self.settings['output'], "blk%05d.dat" % self.outFn) print("Output file " + outFname) self.outF = open(outFname, "wb") @@ -165,7 +167,7 @@ class BlockDataCopier: (self.blkCountIn, self.blkCountOut, len(self.blkindex), 100.0 * self.blkCountOut / len(self.blkindex))) def inFileName(self, fn): - return "%s/blk%05d.dat" % (self.settings['input'], fn) + return os.path.join(self.settings['input'], "blk%05d.dat" % fn) def fetchBlock(self, extent): '''Fetch block contents from disk given extents''' From 6ed38b0b8ff195d4a7117232efc08b29e56ebb60 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 10 Jul 2015 20:11:44 +0200 Subject: [PATCH 0117/1283] [QA] fix possible reorg issue in rawtransaction.py/fundrawtransaction.py RPC test - added missing mempool sync between block generations --- qa/rpc-tests/fundrawtransaction.py | 37 ++++-------------------------- qa/rpc-tests/rawtransactions.py | 1 + 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index e859b2643..3431771bb 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -30,6 +30,7 @@ class RawTransactionsTest(BitcoinTestFramework): feeTolerance = Decimal(0.00000002) #if the fee's positive delta is higher than this value tests will fail, neg. delta always fail the tests self.nodes[2].generate(1) + self.sync_all() self.nodes[0].generate(101) self.sync_all() self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5); @@ -46,17 +47,10 @@ class RawTransactionsTest(BitcoinTestFramework): outputs = { self.nodes[0].getnewaddress() : 1.0 } rawtx = self.nodes[2].createrawtransaction(inputs, outputs) dec_tx = self.nodes[2].decoderawtransaction(rawtx) - rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - totalOut = 0 - for out in dec_tx['vout']: - totalOut += out['value'] - - assert_equal(len(dec_tx['vin']), 1) #one vin coin - assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') - assert_equal(fee + totalOut, 1.5) #the 1.5BTC coin must be taken + assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enought inputs ############################## # simple test with two coins # @@ -69,14 +63,7 @@ class RawTransactionsTest(BitcoinTestFramework): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - totalOut = 0 - for out in dec_tx['vout']: - totalOut += out['value'] - - assert_equal(len(dec_tx['vin']), 2) #one vin coin - assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') - assert_equal(dec_tx['vin'][1]['scriptSig']['hex'], '') - assert_equal(fee + totalOut, 2.5) #the 1.5BTC+1.0BTC coins must have be taken + assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enought inputs ############################## # simple test with two coins # @@ -89,13 +76,8 @@ class RawTransactionsTest(BitcoinTestFramework): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - totalOut = 0 - for out in dec_tx['vout']: - totalOut += out['value'] - - assert_equal(len(dec_tx['vin']), 1) #one vin coin + assert_equal(len(dec_tx['vin']) > 0, True) assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') - assert_equal(fee + totalOut, 5.0) #the 5.0BTC coin must have be taken ################################ @@ -113,11 +95,8 @@ class RawTransactionsTest(BitcoinTestFramework): for out in dec_tx['vout']: totalOut += out['value'] - assert_equal(len(dec_tx['vin']), 2) #one vin coin + assert_equal(len(dec_tx['vin']) > 0, True) assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') - assert_equal(dec_tx['vin'][1]['scriptSig']['hex'], '') - assert_equal(fee + totalOut, 6.0) #the 5.0BTC + 1.0BTC coins must have be taken - ######################################################################### @@ -220,8 +199,6 @@ class RawTransactionsTest(BitcoinTestFramework): assert_equal(matchingOuts, 1) assert_equal(len(dec_tx['vout']), 2) - assert_equal(fee + totalOut, 2.5) #this tx must use the 1.0BTC and the 1.5BTC coin - ########################################### # test a fundrawtransaction with two VINs # @@ -264,8 +241,6 @@ class RawTransactionsTest(BitcoinTestFramework): matchingIns+=1 assert_equal(matchingIns, 2) #we now must see two vins identical to vins given as params - assert_equal(fee + totalOut, 7.5) #this tx must use the 1.0BTC and the 1.5BTC coin - ######################################################### # test a fundrawtransaction with two VINs and two vOUTs # @@ -300,8 +275,6 @@ class RawTransactionsTest(BitcoinTestFramework): assert_equal(matchingOuts, 2) assert_equal(len(dec_tx['vout']), 3) - assert_equal(fee + totalOut, 7.5) #this tx must use the 1.0BTC and the 1.5BTC coin - ############################################## # test a fundrawtransaction with invalid vin # diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index 1378514c8..173faf736 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -40,6 +40,7 @@ class RawTransactionsTest(BitcoinTestFramework): #prepare some coins for multiple *rawtransaction commands self.nodes[2].generate(1) + self.sync_all() self.nodes[0].generate(101) self.sync_all() self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5); From 9da8fc8f26586443b5df3adea1af3e84846374c1 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 10 Jul 2015 21:14:33 +0200 Subject: [PATCH 0118/1283] [QA] remove rawtransactions.py from the extended test list rawtransactions.py is already in the standard test list --- qa/pull-tester/rpc-tests.sh | 1 - qa/rpc-tests/fundrawtransaction.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 0ef1b1eda..72a282bc0 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -54,7 +54,6 @@ testScriptsExt=( 'smartfees.py' 'maxblocksinflight.py' 'invalidblockrequest.py' - 'rawtransactions.py' # 'forknotify.py' 'p2p-acceptblock.py' ); diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 3431771bb..80f1d1e12 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -63,7 +63,7 @@ class RawTransactionsTest(BitcoinTestFramework): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enought inputs + assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enough inputs ############################## # simple test with two coins # From 60d5432697c37a682dc11dbcbc61cb22b8c992de Mon Sep 17 00:00:00 2001 From: randy-waterhouse Date: Sat, 11 Jul 2015 15:39:45 +1200 Subject: [PATCH 0119/1283] Add autogen.sh to source tarball. --- Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile.am b/Makefile.am index 2f478e4b4..ab68d8fa6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -202,6 +202,8 @@ check-local: @qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -jar $(JAVA_COMPARISON_TOOL) qa/tmp/compTool $(COMPARISON_TOOL_REORG_TESTS) 2>&1 endif +dist_noinst_SCRIPTS = autogen.sh + EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.sh qa/pull-tester/run-bitcoin-cli qa/rpc-tests $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) From 59b49cd07482494d9a99068af502be9ceda41ed2 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Sat, 11 Jul 2015 06:52:35 -0400 Subject: [PATCH 0120/1283] Eliminate signed/unsigned comparison warning --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 87750f9ea..875b7b706 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2849,7 +2849,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, // blocks which are too close in height to the tip. Apply this test // regardless of whether pruning is enabled; it should generally be safe to // not process unrequested blocks. - bool fTooFarAhead = (pindex->nHeight - chainActive.Height()) > MIN_BLOCKS_TO_KEEP; + bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP)); // TODO: deal better with return value and error conditions for duplicate // and unrequested blocks. From d3cf546ec2cd77bcced5381c8df8084982e4c4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Fri, 3 Jul 2015 14:29:57 +0200 Subject: [PATCH 0121/1283] Chainparams: Introduce CreateGenesisBlock() static function --- src/chainparams.cpp | 67 +++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index cd31f98c5..8e8811510 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -16,6 +16,45 @@ using namespace std; #include "chainparamsseeds.h" +static CBlock CreateGenesisBlock(const char* pszTimestamp, CScript genesisOutputScript, uint32_t nTime=1231006505, uint32_t nNonce=2083236893, uint32_t nBits=0x1d00ffff, int32_t nVersion=1, const CAmount& genesisReward=50 * COIN) +{ + CMutableTransaction txNew; + txNew.nVersion = 1; + txNew.vin.resize(1); + txNew.vout.resize(1); + txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); + txNew.vout[0].nValue = genesisReward; + txNew.vout[0].scriptPubKey = genesisOutputScript; + + CBlock genesis; + genesis.nTime = nTime; + genesis.nBits = nBits; + genesis.nNonce = nNonce; + genesis.nVersion = nVersion; + genesis.vtx.push_back(txNew); + genesis.hashPrevBlock.SetNull(); + genesis.hashMerkleRoot = genesis.BuildMerkleTree(); + return genesis; +} + +/** + * Build the genesis block. Note that the output of its generation + * transaction cannot be spent since it did not originally exist in the + * database. + * + * CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1) + * CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0) + * CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73) + * CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B) + * vMerkleTree: 4a5e1e + */ +static CBlock CreateGenesisBlock(uint32_t nTime=1231006505, uint32_t nNonce=2083236893, uint32_t nBits=0x1d00ffff, int32_t nVersion=1, const CAmount& genesisReward=50 * COIN) +{ + const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; + CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; + return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward); +} + /** * Main network */ @@ -52,33 +91,7 @@ public: nDefaultPort = 8333; nPruneAfterHeight = 100000; - /** - * Build the genesis block. Note that the output of its generation - * transaction cannot be spent since it did not originally exist in the - * database. - * - * CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1) - * CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0) - * CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73) - * CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B) - * vMerkleTree: 4a5e1e - */ - const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; - CMutableTransaction txNew; - txNew.nVersion = 1; - txNew.vin.resize(1); - txNew.vout.resize(1); - txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); - txNew.vout[0].nValue = 50 * COIN; - txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; - genesis.vtx.push_back(txNew); - genesis.hashPrevBlock.SetNull(); - genesis.hashMerkleRoot = genesis.BuildMerkleTree(); - genesis.nVersion = 1; - genesis.nTime = 1231006505; - genesis.nBits = 0x1d00ffff; - genesis.nNonce = 2083236893; - + genesis = CreateGenesisBlock(); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); From c4973aaaf6655dd3e311b88727ec3f23ed0d0d2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Fri, 3 Jul 2015 14:30:18 +0200 Subject: [PATCH 0122/1283] Chainparams: CTestNetParams and CRegTestParams extend directly from CChainParams ...instead of CMainParams and CTestNetParams respectively Do the same for CBaseChainParams. The inheritance was only reducing readibility in this case --- src/chainparams.cpp | 24 ++++++++++++++++-------- src/chainparamsbase.cpp | 5 +++-- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 8e8811510..301c7508b 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -145,13 +145,17 @@ static CMainParams mainParams; /** * Testnet (v3) */ -class CTestNetParams : public CMainParams { +class CTestNetParams : public CChainParams { public: CTestNetParams() { strNetworkID = "test"; + consensus.nSubsidyHalvingInterval = 210000; consensus.nMajorityEnforceBlockUpgrade = 51; consensus.nMajorityRejectBlockOutdated = 75; consensus.nMajorityWindow = 100; + consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks + consensus.nPowTargetSpacing = 10 * 60; consensus.fPowAllowMinDifficultyBlocks = true; pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; @@ -161,9 +165,7 @@ public: nDefaultPort = 18333; nPruneAfterHeight = 1000; - //! Modify the testnet genesis block so the timestamp is valid for a later start. - genesis.nTime = 1296688602; - genesis.nNonce = 414098458; + genesis = CreateGenesisBlock(1296688602, 414098458); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("0x000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")); @@ -204,7 +206,7 @@ static CTestNetParams testNetParams; /** * Regression test */ -class CRegTestParams : public CTestNetParams { +class CRegTestParams : public CChainParams { public: CRegTestParams() { strNetworkID = "regtest"; @@ -213,13 +215,14 @@ public: consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 1000; consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks + consensus.nPowTargetSpacing = 10 * 60; + consensus.fPowAllowMinDifficultyBlocks = true; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; pchMessageStart[2] = 0xb5; pchMessageStart[3] = 0xda; - genesis.nTime = 1296688602; - genesis.nBits = 0x207fffff; - genesis.nNonce = 2; + genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff); consensus.hashGenesisBlock = genesis.GetHash(); nDefaultPort = 18444; assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); @@ -242,6 +245,11 @@ public: 0, 0 }; + base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,111); + base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,196); + base58Prefixes[SECRET_KEY] = std::vector(1,239); + base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); + base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); } }; static CRegTestParams regTestParams; diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 7d82d689e..9c87bf215 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -25,7 +25,7 @@ static CBaseMainParams mainParams; /** * Testnet (v3) */ -class CBaseTestNetParams : public CBaseMainParams +class CBaseTestNetParams : public CBaseChainParams { public: CBaseTestNetParams() @@ -39,11 +39,12 @@ static CBaseTestNetParams testNetParams; /* * Regression test */ -class CBaseRegTestParams : public CBaseTestNetParams +class CBaseRegTestParams : public CBaseChainParams { public: CBaseRegTestParams() { + nRPCPort = 18332; strDataDir = "regtest"; } }; From ffad5aa1f46742b9e845ade8107505e42a18d7ac Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 13 Jul 2015 08:50:16 +0200 Subject: [PATCH 0123/1283] tests: Remove old sh-based test framework This removes the `conflictedbalance.sh` test as well, but that test has been broken for a long time and isn't part of any scripts. What it does is, IMO, sufficiently tested by other tests. --- qa/rpc-tests/conflictedbalance.sh | 147 ------------------------------ qa/rpc-tests/send.sh | 31 ------- qa/rpc-tests/util.sh | 103 --------------------- 3 files changed, 281 deletions(-) delete mode 100755 qa/rpc-tests/conflictedbalance.sh delete mode 100755 qa/rpc-tests/send.sh delete mode 100644 qa/rpc-tests/util.sh diff --git a/qa/rpc-tests/conflictedbalance.sh b/qa/rpc-tests/conflictedbalance.sh deleted file mode 100755 index 7e4409737..000000000 --- a/qa/rpc-tests/conflictedbalance.sh +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2014 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -# Test marking of spent outputs - -# Create a transaction graph with four transactions, -# A/B/C/D -# C spends A -# D spends B and C - -# Then simulate C being mutated, to create C' -# that is mined. -# A is still (correctly) considered spent. -# B should be treated as unspent - -if [ $# -lt 1 ]; then - echo "Usage: $0 path_to_binaries" - echo "e.g. $0 ../../src" - echo "Env vars BITCOIND and BITCOINCLI may be used to specify the exact binaries used" - exit 1 -fi - -set -f - -BITCOIND=${BITCOIND:-${1}/bitcoind} -CLI=${BITCOINCLI:-${1}/bitcoin-cli} - -DIR="${BASH_SOURCE%/*}" -SENDANDWAIT="${DIR}/send.sh" -if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi -. "$DIR/util.sh" - -D=$(mktemp -d test.XXXXX) - -# Two nodes; one will play the part of merchant, the -# other an evil transaction-mutating miner. - -D1=${D}/node1 -CreateDataDir $D1 port=11000 rpcport=11001 -B1ARGS="-datadir=$D1 -debug=mempool" -$BITCOIND $B1ARGS & -B1PID=$! - -D2=${D}/node2 -CreateDataDir $D2 port=11010 rpcport=11011 -B2ARGS="-datadir=$D2 -debug=mempool" -$BITCOIND $B2ARGS & -B2PID=$! - -# Wait until both nodes are at the same block number -function WaitBlocks { - while : - do - sleep 1 - declare -i BLOCKS1=$( GetBlocks $B1ARGS ) - declare -i BLOCKS2=$( GetBlocks $B2ARGS ) - if (( BLOCKS1 == BLOCKS2 )) - then - break - fi - done -} - -# Wait until node has $N peers -function WaitPeers { - while : - do - declare -i PEERS=$( $CLI $1 getconnectioncount ) - if (( PEERS == "$2" )) - then - break - fi - sleep 1 - done -} - -echo "Generating test blockchain..." - -# Start with B2 connected to B1: -$CLI $B2ARGS addnode 127.0.0.1:11000 onetry -WaitPeers "$B1ARGS" 1 - -# 2 block, 50 XBT each == 100 XBT -# These will be transactions "A" and "B" -$CLI $B1ARGS generate 2 - -WaitBlocks -# 100 blocks, 0 mature == 0 XBT -$CLI $B2ARGS generate 100 -WaitBlocks - -CheckBalance "$B1ARGS" 100 -CheckBalance "$B2ARGS" 0 - -# restart B2 with no connection -$CLI $B2ARGS stop > /dev/null 2>&1 -wait $B2PID -$BITCOIND $B2ARGS & -B2PID=$! - -B1ADDRESS=$( $CLI $B1ARGS getnewaddress ) -B2ADDRESS=$( $CLI $B2ARGS getnewaddress ) - -# Transaction C: send-to-self, spend A -TXID_C=$( $CLI $B1ARGS sendtoaddress $B1ADDRESS 50.0) - -# Transaction D: spends B and C -TXID_D=$( $CLI $B1ARGS sendtoaddress $B2ADDRESS 100.0) - -CheckBalance "$B1ARGS" 0 - -# Mutate TXID_C and add it to B2's memory pool: -RAWTX_C=$( $CLI $B1ARGS getrawtransaction $TXID_C ) - -# ... mutate C to create C' -L=${RAWTX_C:82:2} -NEWLEN=$( printf "%x" $(( 16#$L + 1 )) ) -MUTATEDTX_C=${RAWTX_C:0:82}${NEWLEN}4c${RAWTX_C:84} -# ... give mutated tx1 to B2: -MUTATEDTXID=$( $CLI $B2ARGS sendrawtransaction $MUTATEDTX_C ) - -echo "TXID_C: " $TXID_C -echo "Mutated: " $MUTATEDTXID - -# Re-connect nodes, and have both nodes mine some blocks: -$CLI $B2ARGS addnode 127.0.0.1:11000 onetry -WaitPeers "$B1ARGS" 1 - -# Having B2 mine the next block puts the mutated -# transaction C in the chain: -$CLI $B2ARGS generate 1 -WaitBlocks - -# B1 should still be able to spend 100, because D is conflicted -# so does not count as a spend of B -CheckBalance "$B1ARGS" 100 - -$CLI $B2ARGS stop > /dev/null 2>&1 -wait $B2PID -$CLI $B1ARGS stop > /dev/null 2>&1 -wait $B1PID - -echo "Tests successful, cleaning up" -rm -rf $D -exit 0 diff --git a/qa/rpc-tests/send.sh b/qa/rpc-tests/send.sh deleted file mode 100755 index 2d54cc6de..000000000 --- a/qa/rpc-tests/send.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# Copyright (c) 2014 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -TIMEOUT=10 -SIGNAL=HUP -PIDFILE=.send.pid -if [ $# -eq 0 ]; then - echo -e "Usage:\t$0 " - echo -e "\tRuns and wait ${TIMEOUT} seconds or until SIG${SIGNAL} is received." - echo -e "\tReturns: 0 if SIG${SIGNAL} is received, 1 otherwise." - echo -e "Or:\t$0 -STOP" - echo -e "\tsends SIG${SIGNAL} to running send.sh" - exit 0 -fi - -if [ $1 = "-STOP" ]; then - if [ -s ${PIDFILE} ]; then - kill -s ${SIGNAL} $(<$PIDFILE 2>/dev/null) 2>/dev/null - fi - exit 0 -fi - -trap '[[ ${PID} ]] && kill ${PID}' ${SIGNAL} -trap 'rm -f ${PIDFILE}' EXIT -echo $$ > ${PIDFILE} -"$@" -sleep ${TIMEOUT} & PID=$! -wait ${PID} && exit 1 - -exit 0 diff --git a/qa/rpc-tests/util.sh b/qa/rpc-tests/util.sh deleted file mode 100644 index c2b700430..000000000 --- a/qa/rpc-tests/util.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2014 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -# Functions used by more than one test - -function echoerr { - echo "$@" 1>&2; -} - -# Usage: ExtractKey "" -# Warning: this will only work for the very-well-behaved -# JSON produced by bitcoind, do NOT use it to try to -# parse arbitrary/nested/etc JSON. -function ExtractKey { - echo $2 | tr -d ' "{}\n' | awk -v RS=',' -F: "\$1 ~ /$1/ { print \$2}" -} - -function CreateDataDir { - DIR=$1 - mkdir -p $DIR - CONF=$DIR/bitcoin.conf - echo "regtest=1" >> $CONF - echo "keypool=2" >> $CONF - echo "rpcuser=rt" >> $CONF - echo "rpcpassword=rt" >> $CONF - echo "rpcwait=1" >> $CONF - echo "walletnotify=${SENDANDWAIT} -STOP" >> $CONF - shift - while (( "$#" )); do - echo $1 >> $CONF - shift - done -} - -function AssertEqual { - if (( $( echo "$1 == $2" | bc ) == 0 )) - then - echoerr "AssertEqual: $1 != $2" - declare -f CleanUp > /dev/null 2>&1 - if [[ $? -eq 0 ]] ; then - CleanUp - fi - exit 1 - fi -} - -# CheckBalance -datadir=... amount account minconf -function CheckBalance { - declare -i EXPECT="$2" - B=$( $CLI $1 getbalance $3 $4 ) - if (( $( echo "$B == $EXPECT" | bc ) == 0 )) - then - echoerr "bad balance: $B (expected $2)" - declare -f CleanUp > /dev/null 2>&1 - if [[ $? -eq 0 ]] ; then - CleanUp - fi - exit 1 - fi -} - -# Use: Address [account] -function Address { - $CLI $1 getnewaddress $2 -} - -# Send from to amount -function Send { - from=$1 - to=$2 - amount=$3 - address=$(Address $to) - txid=$( ${SENDANDWAIT} $CLI $from sendtoaddress $address $amount ) -} - -# Use: Unspent -function Unspent { - local r=$( $CLI $1 listunspent | awk -F'[ |:,"]+' "\$2 ~ /$3/ { print \$3 }" | tail -n $2 | head -n 1) - echo $r -} - -# Use: CreateTxn1 -# produces hex from signrawtransaction -function CreateTxn1 { - TXID=$(Unspent $1 $2 txid) - AMOUNT=$(Unspent $1 $2 amount) - VOUT=$(Unspent $1 $2 vout) - RAWTXN=$( $CLI $1 createrawtransaction "[{\"txid\":\"$TXID\",\"vout\":$VOUT}]" "{\"$3\":$AMOUNT}") - ExtractKey hex "$( $CLI $1 signrawtransaction $RAWTXN )" -} - -# Use: SendRawTxn -function SendRawTxn { - ${SENDANDWAIT} $CLI $1 sendrawtransaction $2 -} - -# Use: GetBlocks -# returns number of blocks from getinfo -function GetBlocks { - $CLI $1 getblockcount -} From 71cbeaad9a929ba6a7b62d9b37a09b214ae00c1a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 7 Jul 2015 14:53:48 +0200 Subject: [PATCH 0124/1283] rpc: Implement random-cookie based authentication When no `-rpcpassword` is specified, use a special 'cookie' file for authentication. This file is generated with random content when the daemon starts, and deleted when it exits. Read access to this file controls who can access through RPC. By default this file is stored in the data directory but it be overriden with `-rpccookiefile`. This is similar to Tor CookieAuthentication: see https://www.torproject.org/docs/tor-manual.html.en Alternative to #6258. Like that pull, this allows running bitcoind without any manual configuration. However, daemons should ideally never write to their configuration files, so I prefer this solution. --- src/bitcoin-cli.cpp | 24 ++++++++++------ src/rpcprotocol.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++ src/rpcprotocol.h | 10 +++++++ src/rpcserver.cpp | 31 ++++++++------------- 4 files changed, 105 insertions(+), 27 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 903777ba5..1c5a31287 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -97,12 +97,6 @@ static bool AppInitRPC(int argc, char* argv[]) UniValue CallRPC(const string& strMethod, const UniValue& params) { - if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "") - throw runtime_error(strprintf( - _("You must set rpcpassword= in the configuration file:\n%s\n" - "If the file does not exist, create it with owner-readable-only file permissions."), - GetConfigFile().string().c_str())); - // Connect to localhost bool fUseSSL = GetBoolArg("-rpcssl", false); boost::asio::io_service io_service; @@ -116,10 +110,24 @@ UniValue CallRPC(const string& strMethod, const UniValue& params) if (!fConnected) throw CConnectionFailed("couldn't connect to server"); + // Find credentials to use + std::string strRPCUserColonPass; + if (mapArgs["-rpcpassword"] == "") { + // Try fall back to cookie-based authentication if no password is provided + if (!GetAuthCookie(&strRPCUserColonPass)) { + throw runtime_error(strprintf( + _("You must set rpcpassword= in the configuration file:\n%s\n" + "If the file does not exist, create it with owner-readable-only file permissions."), + GetConfigFile().string().c_str())); + + } + } else { + strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; + } + // HTTP basic authentication - string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]); map mapRequestHeaders; - mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64; + mapRequestHeaders["Authorization"] = string("Basic ") + EncodeBase64(strRPCUserColonPass); // Send request string strRequest = JSONRPCRequest(strMethod, params, 1); diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 89dec2977..2e5c91373 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -6,6 +6,7 @@ #include "rpcprotocol.h" #include "clientversion.h" +#include "random.h" #include "tinyformat.h" #include "util.h" #include "utilstrencodings.h" @@ -13,6 +14,7 @@ #include "version.h" #include +#include #include #include @@ -287,3 +289,68 @@ UniValue JSONRPCError(int code, const string& message) error.push_back(Pair("message", message)); return error; } + +/** Username used when cookie authentication is in use (arbitrary, only for + * recognizability in debugging/logging purposes) + */ +static const std::string COOKIEAUTH_USER = "__cookie__"; +/** Default name for auth cookie file */ +static const std::string COOKIEAUTH_FILE = ".cookie"; + +boost::filesystem::path GetAuthCookieFile() +{ + boost::filesystem::path path(GetArg("-rpccookiefile", COOKIEAUTH_FILE)); + if (!path.is_complete()) path = GetDataDir() / path; + return path; +} + +bool GenerateAuthCookie(std::string *cookie_out) +{ + unsigned char rand_pwd[32]; + GetRandBytes(rand_pwd, 32); + std::string cookie = COOKIEAUTH_USER + ":" + EncodeBase64(&rand_pwd[0],32); + + /** the umask determines what permissions are used to create this file - + * these are set to 077 in init.cpp unless overridden with -sysperms. + */ + std::ofstream file; + boost::filesystem::path filepath = GetAuthCookieFile(); + file.open(filepath.string().c_str()); + if (!file.is_open()) { + LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath.string()); + return false; + } + file << cookie; + file.close(); + LogPrintf("Generated RPC authentication cookie %s\n", filepath.string()); + + if (cookie_out) + *cookie_out = cookie; + return true; +} + +bool GetAuthCookie(std::string *cookie_out) +{ + std::ifstream file; + std::string cookie; + boost::filesystem::path filepath = GetAuthCookieFile(); + file.open(filepath.string().c_str()); + if (!file.is_open()) + return false; + std::getline(file, cookie); + file.close(); + + if (cookie_out) + *cookie_out = cookie; + return true; +} + +void DeleteAuthCookie() +{ + try { + boost::filesystem::remove(GetAuthCookieFile()); + } catch (const boost::filesystem::filesystem_error& e) { + LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, e.what()); + } +} + diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index ccd2439c9..2360ec2c6 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "univalue/univalue.h" @@ -165,4 +166,13 @@ UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const Un std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id); UniValue JSONRPCError(int code, const std::string& message); +/** Get name of RPC authentication cookie file */ +boost::filesystem::path GetAuthCookieFile(); +/** Generate a new RPC authentication cookie and write it to disk */ +bool GenerateAuthCookie(std::string *cookie_out); +/** Read the RPC authentication cookie from disk */ +bool GetAuthCookie(std::string *cookie_out); +/** Delete RPC authentication cookie from disk */ +void DeleteAuthCookie(); + #endif // BITCOIN_RPCPROTOCOL_H diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 8f5ff10a8..bcad06a0c 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -597,27 +597,18 @@ void StartRPCThreads() strAllowed += subnet.ToString() + " "; LogPrint("rpc", "Allowing RPC connections from: %s\n", strAllowed); - strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; if (mapArgs["-rpcpassword"] == "") { - unsigned char rand_pwd[32]; - GetRandBytes(rand_pwd, 32); - uiInterface.ThreadSafeMessageBox(strprintf( - _("To use bitcoind, or the -server option to bitcoin-qt, you must set an rpcpassword in the configuration file:\n" - "%s\n" - "It is recommended you use the following random password:\n" - "rpcuser=bitcoinrpc\n" - "rpcpassword=%s\n" - "(you do not need to remember this password)\n" - "The username and password MUST NOT be the same.\n" - "If the file does not exist, create it with owner-readable-only file permissions.\n" - "It is also recommended to set alertnotify so you are notified of problems;\n" - "for example: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com\n"), - GetConfigFile().string(), - EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32)), - "", CClientUIInterface::MSG_ERROR | CClientUIInterface::SECURE); - StartShutdown(); - return; + LogPrintf("No rpcpassword set - using random cookie authentication\n"); + if (!GenerateAuthCookie(&strRPCUserColonPass)) { + uiInterface.ThreadSafeMessageBox( + _("Error: A fatal internal error occured, see debug.log for details"), // Same message as AbortNode + "", CClientUIInterface::MSG_ERROR); + StartShutdown(); + return; + } + } else { + strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; } assert(rpc_io_service == NULL); @@ -768,6 +759,8 @@ void StopRPCThreads() } deadlineTimers.clear(); + DeleteAuthCookie(); + rpc_io_service->stop(); g_rpcSignals.Stopped(); if (rpc_worker_group != NULL) From 093729055358ecf155b74ce1b2870d3eb9064355 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 13 Jul 2015 13:31:38 +0200 Subject: [PATCH 0125/1283] doc: mention RPC random cookie authentication in release notes --- doc/release-notes.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 6bb8587d7..d5ac70380 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,6 +4,21 @@ release-notes at release time) Notable changes =============== +Random-cookie RPC authentication +--------------------------------- + +When no `-rpcpassword` is specified, the daemon now uses a special 'cookie' +file for authentication. This file is generated with random content when the +daemon starts, and deleted when it exits. Its contents are used as +authentication token. Read access to this file controls who can access through +RPC. By default it is stored in the data directory but its location can be +overridden with the option `-rpccookiefile`. + +This is similar to Tor's CookieAuthentication: see +https://www.torproject.org/docs/tor-manual.html.en + +This allows running bitcoind without having to do any manual configuration. + Example header ---------------------- From c156adac53b448780c7c9ef366c12237a7cea8e1 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Mon, 13 Jul 2015 12:22:55 -0400 Subject: [PATCH 0126/1283] doc: add documentation for shared library libbitcoinconsensus --- doc/README.md | 1 + doc/shared-libraries.md | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 doc/shared-libraries.md diff --git a/doc/README.md b/doc/README.md index ecddf50d4..7b0c39d38 100644 --- a/doc/README.md +++ b/doc/README.md @@ -58,6 +58,7 @@ The Bitcoin repo's [root README](https://github.com/bitcoin/bitcoin/blob/master/ - [Translation Strings Policy](translation_strings_policy.md) - [Unit Tests](unit-tests.md) - [Unauthenticated REST Interface](REST-interface.md) +- [Shared Libraries](shared-libraries.md) - [BIPS](bips.md) - [Dnsseed Policy](dnsseed-policy.md) diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md new file mode 100644 index 000000000..c8f4939e7 --- /dev/null +++ b/doc/shared-libraries.md @@ -0,0 +1,41 @@ +Shared Libraries +================ + +## bitcoinconsensus + +The purpose of this library is to make the verification functionality that is critical to Bitcoin's consensus available to other applications, e.g. to language bindings. + +### API + +The interface is defined in the C header `bitcoinconsensus.h` located in `src/script/bitcoinconsensus.h`. + +#### Version + +`bitcoinconsensus_version` returns an `unsigned int` with the the API version *(currently at an experimental `0`)*. + +#### Script Validation + +`bitcoinconsensus_verify_script` returns an `int` with the status of the verification. It will be `1` if the input script correctly spends the previous output `scriptPubKey`. + +##### Parameters +- `const unsigned char *scriptPubKey` - The previous output script that encumbers spending. +- `unsigned int scriptPubKeyLen` - The number of bytes for the `scriptPubKey`. +- `const unsigned char *txTo` - The transaction with the input that is spending the previous output. +- `unsigned int txToLen` - The number of bytes for the `txTo`. +- `unsigned int nIn` - The index of the input in `txTo` that spends the `scriptPubKey`. +- `unsigned int flags` - The script validation flags *(see below)*. +- `bitcoinconsensus_error* err` - Will have the error/success code for the operation *(see below)*. + +##### Script Flags +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE` +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH` - Evaluate P2SH ([BIP16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki)) subscripts +- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG` - Enforce strict DER ([BIP66](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki)) compliance + +##### Errors +- `bitcoinconsensus_ERR_OK` +- `bitcoinconsensus_ERR_TX_INDEX` - An invalid index for `txTo` +- `bitcoinconsensus_ERR_TX_SIZE_MISMATCH` - `txToLen` did not match with the size of `txTo` +- `bitcoinconsensus_ERR_DESERIALIZE` - An error deserializing `txTo` + +### Example Implementations +- [node-libbitcoinconsensus](https://github.com/bitpay/node-libbitcoinconsensus) (Node.js Bindings) From d4b1d5a8baf18e4c8d62846360c0c1c0c9331d70 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 14 Jul 2015 17:38:03 -0400 Subject: [PATCH 0127/1283] openssl: avoid config file load/race --- src/util.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/util.cpp b/src/util.cpp index bb7df2320..00d0f3a00 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -83,6 +83,7 @@ #include #include #include +#include // Work around clang compilation problem in Boost 1.46: // /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup @@ -134,6 +135,13 @@ public: ppmutexOpenSSL[i] = new CCriticalSection(); CRYPTO_set_locking_callback(locking_callback); + // OpenSSL can optionally load a config file which lists optional loadable modules and engines. + // We don't use them so we don't require the config. However some of our libs may call functions + // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing + // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be + // that the config appears to have been loaded and there are no modules/engines available. + OPENSSL_no_config(); + #ifdef WIN32 // Seed OpenSSL PRNG with current contents of the screen RAND_screen(); From 09d4ddf1c5841b757c2676d508a68baa2dbdc4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=B8=BFtcDrak?= Date: Tue, 14 Jul 2015 23:33:49 +0100 Subject: [PATCH 0128/1283] Updated URL location of netinstall for Debian --- doc/gitian-building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 1fa5b5f98..630b3c04a 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -74,7 +74,7 @@ In the VirtualBox GUI click "Create" and choose the following parameters in the - Disk size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side - Push the `Create` button -Get the [Debian 7.8 net installer](http://cdimage.debian.org/debian-cd/7.8.0/amd64/iso-cd/debian-7.8.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). +Get the [Debian 7.8 net installer](http://cdimage.debian.org/cdimage/archive/7.8.0/amd64/iso-cd/debian-7.8.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). This DVD image can be validated using a SHA256 hashing tool, for example on Unixy OSes by entering the following in a terminal: From b1bac4ea495a16dc0661fcf1af90ff70191f8e74 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Tue, 14 Jul 2015 21:44:03 -0400 Subject: [PATCH 0129/1283] Add description for bitcoinconsensus_ERR_OK --- doc/shared-libraries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md index c8f4939e7..4b8279e8a 100644 --- a/doc/shared-libraries.md +++ b/doc/shared-libraries.md @@ -32,7 +32,7 @@ The interface is defined in the C header `bitcoinconsensus.h` located in `src/s - `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG` - Enforce strict DER ([BIP66](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki)) compliance ##### Errors -- `bitcoinconsensus_ERR_OK` +- `bitcoinconsensus_ERR_OK` - No errors with input parameters *(see the return value of `bitcoinconsensus_verify_script` for the verification status)* - `bitcoinconsensus_ERR_TX_INDEX` - An invalid index for `txTo` - `bitcoinconsensus_ERR_TX_SIZE_MISMATCH` - `txToLen` did not match with the size of `txTo` - `bitcoinconsensus_ERR_DESERIALIZE` - An error deserializing `txTo` From d29ec6c2301e593d577126d1ca85b93307b32bf1 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 14 Jul 2015 13:59:05 +0200 Subject: [PATCH 0130/1283] qt: define QT_NO_KEYWORDS QT_NO_KEYWORDS prevents Qt from defining the `foreach`, `signals`, `slots` and `emit` macros. Avoid overlap between Qt macros and boost - for example #undef hackiness in #6421. --- src/Makefile.qt.include | 2 +- src/qt/addressbookpage.cpp | 2 +- src/qt/addressbookpage.h | 6 +-- src/qt/addresstablemodel.cpp | 2 +- src/qt/addresstablemodel.h | 2 +- src/qt/askpassphrasedialog.h | 2 +- src/qt/bitcoin.cpp | 22 +++++------ src/qt/bitcoinamountfield.cpp | 4 +- src/qt/bitcoinamountfield.h | 4 +- src/qt/bitcoingui.cpp | 10 ++--- src/qt/bitcoingui.h | 8 ++-- src/qt/clientmodel.cpp | 10 ++--- src/qt/clientmodel.h | 4 +- src/qt/coincontroldialog.cpp | 2 +- src/qt/coincontroldialog.h | 2 +- src/qt/editaddressdialog.h | 2 +- src/qt/guiutil.h | 2 +- src/qt/intro.cpp | 10 ++--- src/qt/intro.h | 6 +-- src/qt/macdockiconhandler.h | 2 +- src/qt/notificator.h | 2 +- src/qt/openuridialog.h | 4 +- src/qt/optionsdialog.cpp | 4 +- src/qt/optionsdialog.h | 4 +- src/qt/optionsmodel.cpp | 6 +-- src/qt/optionsmodel.h | 2 +- src/qt/overviewpage.cpp | 2 +- src/qt/overviewpage.h | 6 +-- src/qt/paymentserver.cpp | 58 ++++++++++++++--------------- src/qt/paymentserver.h | 6 +-- src/qt/peertablemodel.cpp | 8 ++-- src/qt/peertablemodel.h | 2 +- src/qt/qvalidatedlineedit.h | 4 +- src/qt/qvaluecombobox.cpp | 2 +- src/qt/qvaluecombobox.h | 4 +- src/qt/receivecoinsdialog.cpp | 2 +- src/qt/receivecoinsdialog.h | 4 +- src/qt/receiverequestdialog.h | 4 +- src/qt/recentrequeststablemodel.cpp | 4 +- src/qt/recentrequeststablemodel.h | 2 +- src/qt/rpcconsole.cpp | 20 +++++----- src/qt/rpcconsole.h | 6 +-- src/qt/sendcoinsdialog.cpp | 6 +-- src/qt/sendcoinsdialog.h | 8 ++-- src/qt/sendcoinsentry.cpp | 2 +- src/qt/sendcoinsentry.h | 6 +-- src/qt/signverifymessagedialog.h | 2 +- src/qt/splashscreen.h | 2 +- src/qt/test/paymentservertests.cpp | 2 +- src/qt/test/paymentservertests.h | 4 +- src/qt/test/uritests.h | 2 +- src/qt/trafficgraphwidget.cpp | 4 +- src/qt/trafficgraphwidget.h | 2 +- src/qt/transactiondesc.cpp | 4 +- src/qt/transactiontablemodel.cpp | 10 ++--- src/qt/transactiontablemodel.h | 2 +- src/qt/transactionview.cpp | 4 +- src/qt/transactionview.h | 6 +-- src/qt/utilitydialog.cpp | 2 +- src/qt/utilitydialog.h | 2 +- src/qt/walletframe.h | 2 +- src/qt/walletmodel.cpp | 18 ++++----- src/qt/walletmodel.h | 4 +- src/qt/walletmodeltransaction.cpp | 2 +- src/qt/walletview.cpp | 8 ++-- src/qt/walletview.h | 4 +- 66 files changed, 184 insertions(+), 184 deletions(-) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 6b7c42285..2ec3468e0 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -322,7 +322,7 @@ RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png) BITCOIN_RC = qt/res/bitcoin-qt-res.rc BITCOIN_QT_INCLUDES = -I$(builddir)/qt -I$(srcdir)/qt -I$(srcdir)/qt/forms \ - -I$(builddir)/qt/forms + -I$(builddir)/qt/forms -DQT_NO_KEYWORDS qt_libbitcoinqt_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 54635f1d5..af6801919 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -254,7 +254,7 @@ void AddressBookPage::done(int retval) // Figure out which address was selected, and return it QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); - foreach (const QModelIndex& index, indexes) { + Q_FOREACH (const QModelIndex& index, indexes) { QVariant address = table->model()->data(index); returnValue = address.toString(); } diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index 5105f09ce..09634ce33 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -45,7 +45,7 @@ public: void setModel(AddressTableModel *model); const QString &getReturnValue() const { return returnValue; } -public slots: +public Q_SLOTS: void done(int retval); private: @@ -59,7 +59,7 @@ private: QAction *deleteAction; // to be able to explicitly disable it QString newAddressToSelect; -private slots: +private Q_SLOTS: /** Delete currently selected address entry */ void on_deleteAddress_clicked(); /** Create a new address for receiving coins and / or add a new address book entry */ @@ -80,7 +80,7 @@ private slots: /** New entry/entries were added to address table */ void selectNewAddress(const QModelIndex &parent, int begin, int /*end*/); -signals: +Q_SIGNALS: void sendCoins(QString addr); }; diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 8e20836c6..c5ac07cfc 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -450,5 +450,5 @@ int AddressTableModel::lookupAddress(const QString &address) const void AddressTableModel::emitDataChanged(int idx) { - emit dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex())); + Q_EMIT dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex())); } diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h index 6b34b2eac..2b7475c4e 100644 --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -84,7 +84,7 @@ private: /** Notify listeners that data changed. */ void emitDataChanged(int index); -public slots: +public Q_SLOTS: /* Update address list from core. */ void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status); diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h index 74d54d18f..d4d832825 100644 --- a/src/qt/askpassphrasedialog.h +++ b/src/qt/askpassphrasedialog.h @@ -40,7 +40,7 @@ private: WalletModel *model; bool fCapsLock; -private slots: +private Q_SLOTS: void textChanged(); protected: diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 07250e72c..ec02c4be9 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -169,11 +169,11 @@ class BitcoinCore: public QObject public: explicit BitcoinCore(); -public slots: +public Q_SLOTS: void initialize(); void shutdown(); -signals: +Q_SIGNALS: void initializeResult(int retval); void shutdownResult(int retval); void runawayException(const QString &message); @@ -216,13 +216,13 @@ public: /// Get window identifier of QMainWindow (BitcoinGUI) WId getMainWinId() const; -public slots: +public Q_SLOTS: void initializeResult(int retval); void shutdownResult(int retval); /// Handle runaway exceptions. Shows a message box with the problem and quits the program. void handleRunawayException(const QString &message); -signals: +Q_SIGNALS: void requestedInitialize(); void requestedShutdown(); void stopThread(); @@ -253,7 +253,7 @@ BitcoinCore::BitcoinCore(): void BitcoinCore::handleRunawayException(const std::exception *e) { PrintExceptionContinue(e, "Runaway exception"); - emit runawayException(QString::fromStdString(strMiscWarning)); + Q_EMIT runawayException(QString::fromStdString(strMiscWarning)); } void BitcoinCore::initialize() @@ -269,7 +269,7 @@ void BitcoinCore::initialize() */ StartDummyRPCThread(); } - emit initializeResult(rv); + Q_EMIT initializeResult(rv); } catch (const std::exception& e) { handleRunawayException(&e); } catch (...) { @@ -286,7 +286,7 @@ void BitcoinCore::shutdown() threadGroup.join_all(); Shutdown(); qDebug() << __func__ << ": Shutdown finished"; - emit shutdownResult(1); + Q_EMIT shutdownResult(1); } catch (const std::exception& e) { handleRunawayException(&e); } catch (...) { @@ -315,7 +315,7 @@ BitcoinApplication::~BitcoinApplication() if(coreThread) { qDebug() << __func__ << ": Stopping thread"; - emit stopThread(); + Q_EMIT stopThread(); coreThread->wait(); qDebug() << __func__ << ": Stopped thread"; } @@ -386,7 +386,7 @@ void BitcoinApplication::requestInitialize() { qDebug() << __func__ << ": Requesting initialize"; startThread(); - emit requestedInitialize(); + Q_EMIT requestedInitialize(); } void BitcoinApplication::requestShutdown() @@ -409,7 +409,7 @@ void BitcoinApplication::requestShutdown() ShutdownWindow::showShutdownWindow(window); // Request shutdown from core thread - emit requestedShutdown(); + Q_EMIT requestedShutdown(); } void BitcoinApplication::initializeResult(int retval) @@ -449,7 +449,7 @@ void BitcoinApplication::initializeResult(int retval) { window->show(); } - emit splashFinished(window); + Q_EMIT splashFinished(window); #ifdef ENABLE_WALLET // Now that initialization/startup is done, process any command-line diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index d31a1e018..d19b9fd4a 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -61,7 +61,7 @@ public: void setValue(const CAmount& value) { lineEdit()->setText(BitcoinUnits::format(currentUnit, value, false, BitcoinUnits::separatorAlways)); - emit valueChanged(); + Q_EMIT valueChanged(); } void stepBy(int steps) @@ -184,7 +184,7 @@ protected: return rv; } -signals: +Q_SIGNALS: void valueChanged(); }; diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index b047e6c51..3703b1f8d 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -56,7 +56,7 @@ public: */ QWidget *setupTabChain(QWidget *prev); -signals: +Q_SIGNALS: void valueChanged(); protected: @@ -67,7 +67,7 @@ private: AmountSpinBox *amount; QValueComboBox *unit; -private slots: +private Q_SLOTS: void unitChanged(int idx); }; diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index efba0f5e1..396435f12 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -600,7 +600,7 @@ void BitcoinGUI::openClicked() OpenURIDialog dlg(this); if(dlg.exec()) { - emit receivedURI(dlg.getURI()); + Q_EMIT receivedURI(dlg.getURI()); } } @@ -886,9 +886,9 @@ void BitcoinGUI::dropEvent(QDropEvent *event) { if(event->mimeData()->hasUrls()) { - foreach(const QUrl &uri, event->mimeData()->urls()) + Q_FOREACH(const QUrl &uri, event->mimeData()->urls()) { - emit receivedURI(uri.toString()); + Q_EMIT receivedURI(uri.toString()); } } event->acceptProposedAction(); @@ -1050,7 +1050,7 @@ UnitDisplayStatusBarControl::UnitDisplayStatusBarControl() : QList units = BitcoinUnits::availableUnits(); int max_width = 0; const QFontMetrics fm(font()); - foreach (const BitcoinUnits::Unit unit, units) + Q_FOREACH (const BitcoinUnits::Unit unit, units) { max_width = qMax(max_width, fm.width(BitcoinUnits::name(unit))); } @@ -1069,7 +1069,7 @@ void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event) void UnitDisplayStatusBarControl::createContextMenu() { menu = new QMenu(); - foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) + Q_FOREACH(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) { QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this); menuAction->setData(QVariant(u)); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 494541f00..4e50b1712 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -136,11 +136,11 @@ private: /** Disconnect core signals from GUI client */ void unsubscribeFromCoreSignals(); -signals: +Q_SIGNALS: /** Signal raised when a URI was entered or dragged to the GUI */ void receivedURI(const QString &uri); -public slots: +public Q_SLOTS: /** Set number of connections shown in the UI */ void setNumConnections(int count); /** Set number of blocks and last block date shown in the UI */ @@ -168,7 +168,7 @@ public slots: void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); #endif // ENABLE_WALLET -private slots: +private Q_SLOTS: #ifdef ENABLE_WALLET /** Switch to overview (home) page */ void gotoOverviewPage(); @@ -232,7 +232,7 @@ private: /** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */ void createContextMenu(); -private slots: +private Q_SLOTS: /** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */ void updateDisplayUnit(int newUnits); /** Tells underlying optionsModel to update its current display unit. */ diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 5ac11324d..92a9ef279 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -117,15 +117,15 @@ void ClientModel::updateTimer() cachedReindexing = fReindex; cachedImporting = fImporting; - emit numBlocksChanged(newNumBlocks, newBlockDate); + Q_EMIT numBlocksChanged(newNumBlocks, newBlockDate); } - emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); + Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); } void ClientModel::updateNumConnections(int numConnections) { - emit numConnectionsChanged(numConnections); + Q_EMIT numConnectionsChanged(numConnections); } void ClientModel::updateAlert(const QString &hash, int status) @@ -138,11 +138,11 @@ void ClientModel::updateAlert(const QString &hash, int status) CAlert alert = CAlert::getAlertByHash(hash_256); if(!alert.IsNull()) { - emit message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR); + Q_EMIT message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR); } } - emit alertsChanged(getStatusBarWarnings()); + Q_EMIT alertsChanged(getStatusBarWarnings()); } bool ClientModel::inInitialBlockDownload() const diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 214701810..68434f404 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -82,7 +82,7 @@ private: void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); -signals: +Q_SIGNALS: void numConnectionsChanged(int count); void numBlocksChanged(int count, const QDateTime& blockDate); void alertsChanged(const QString &warnings); @@ -94,7 +94,7 @@ signals: // Show progress dialog e.g. for verifychain void showProgress(const QString &title, int nProgress); -public slots: +public Q_SLOTS: void updateTimer(); void updateNumConnections(int numConnections); void updateAlert(const QString &hash, int status); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index eea450353..cb888a07c 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -461,7 +461,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) CAmount nPayAmount = 0; bool fDust = false; CMutableTransaction txDummy; - foreach(const CAmount &amount, CoinControlDialog::payAmounts) + Q_FOREACH(const CAmount &amount, CoinControlDialog::payAmounts) { nPayAmount += amount; diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 5ec382838..0566b02c9 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -102,7 +102,7 @@ private: return column; } -private slots: +private Q_SLOTS: void showMenu(const QPoint &); void copyAmount(); void copyLabel(); diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h index 13c6da8ed..d59fce2d4 100644 --- a/src/qt/editaddressdialog.h +++ b/src/qt/editaddressdialog.h @@ -40,7 +40,7 @@ public: QString getAddress() const; void setAddress(const QString &address); -public slots: +public Q_SLOTS: void accept(); private: diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 55df64a25..0ac3db632 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -169,7 +169,7 @@ namespace GUIUtil void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode); void resizeColumn(int nColumnIndex, int width); - private slots: + private Q_SLOTS: void on_sectionResized(int logicalIndex, int oldSize, int newSize); void on_geometriesChanged(); }; diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 9f72602b4..117969758 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -42,10 +42,10 @@ public: ST_ERROR }; -public slots: +public Q_SLOTS: void check(); -signals: +Q_SIGNALS: void reply(int status, const QString &message, quint64 available); private: @@ -102,7 +102,7 @@ void FreespaceChecker::check() replyStatus = ST_ERROR; replyMessage = tr("Cannot create data directory here."); } - emit reply(replyStatus, replyMessage, freeBytesAvailable); + Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable); } @@ -121,7 +121,7 @@ Intro::~Intro() { delete ui; /* Ensure thread is finished before it is deleted */ - emit stopThread(); + Q_EMIT stopThread(); thread->wait(); } @@ -277,7 +277,7 @@ void Intro::checkPath(const QString &dataDir) if(!signalled) { signalled = true; - emit requestCheck(); + Q_EMIT requestCheck(); } mutex.unlock(); } diff --git a/src/qt/intro.h b/src/qt/intro.h index c9735615b..50783f722 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -43,14 +43,14 @@ public: */ static QString getDefaultDataDirectory(); -signals: +Q_SIGNALS: void requestCheck(); void stopThread(); -public slots: +public Q_SLOTS: void setStatus(int status, const QString &message, quint64 bytesAvailable); -private slots: +private Q_SLOTS: void on_dataDirectory_textChanged(const QString &arg1); void on_ellipsisButton_clicked(); void on_dataDirDefault_clicked(); diff --git a/src/qt/macdockiconhandler.h b/src/qt/macdockiconhandler.h index 15a6583ca..8bd867c10 100644 --- a/src/qt/macdockiconhandler.h +++ b/src/qt/macdockiconhandler.h @@ -30,7 +30,7 @@ public: static void cleanup(); void handleDockIconClickEvent(); -signals: +Q_SIGNALS: void dockIconClicked(); private: diff --git a/src/qt/notificator.h b/src/qt/notificator.h index 182e948c7..f2a15e9c3 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -40,7 +40,7 @@ public: Critical /**< An error occurred */ }; -public slots: +public Q_SLOTS: /** Show notification message. @param[in] cls general message class @param[in] title title shown with message diff --git a/src/qt/openuridialog.h b/src/qt/openuridialog.h index d5c434ba9..28b8f56ca 100644 --- a/src/qt/openuridialog.h +++ b/src/qt/openuridialog.h @@ -21,10 +21,10 @@ public: QString getURI(); -protected slots: +protected Q_SLOTS: void accept(); -private slots: +private Q_SLOTS: void on_selectFileButton_clicked(); private: diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 87c727335..173bed3b6 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -73,7 +73,7 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : /* Display elements init */ QDir translations(":translations"); ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant("")); - foreach(const QString &langStr, translations.entryList()) + Q_FOREACH(const QString &langStr, translations.entryList()) { QLocale locale(langStr); @@ -281,7 +281,7 @@ bool OptionsDialog::eventFilter(QObject *object, QEvent *event) { if(object == ui->proxyIp) { - emit proxyIpChecks(ui->proxyIp, ui->proxyPort->text().toInt()); + Q_EMIT proxyIpChecks(ui->proxyIp, ui->proxyPort->text().toInt()); } } return QDialog::eventFilter(object, event); diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index f4e515759..fa983e798 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -33,7 +33,7 @@ public: protected: bool eventFilter(QObject *object, QEvent *event); -private slots: +private Q_SLOTS: /* enable OK button */ void enableOkButton(); /* disable OK button */ @@ -48,7 +48,7 @@ private slots: void clearStatusLabel(); void doProxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort); -signals: +Q_SIGNALS: void proxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort); private: diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 41d6acf35..b4ce8191d 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -286,7 +286,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in case CoinControlFeatures: fCoinControlFeatures = value.toBool(); settings.setValue("fCoinControlFeatures", fCoinControlFeatures); - emit coinControlFeaturesChanged(fCoinControlFeatures); + Q_EMIT coinControlFeaturesChanged(fCoinControlFeatures); break; case DatabaseCache: if (settings.value("nDatabaseCache") != value) { @@ -311,7 +311,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } } - emit dataChanged(index, index); + Q_EMIT dataChanged(index, index); return successful; } @@ -324,7 +324,7 @@ void OptionsModel::setDisplayUnit(const QVariant &value) QSettings settings; nDisplayUnit = value.toInt(); settings.setValue("nDisplayUnit", nDisplayUnit); - emit displayUnitChanged(nDisplayUnit); + Q_EMIT displayUnitChanged(nDisplayUnit); } } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index bf892768e..fc26d65b0 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -81,7 +81,7 @@ private: /// Add option to list of GUI options overridden through command line/config file void addOverriddenOption(const std::string &option); -signals: +Q_SIGNALS: void displayUnitChanged(int unit); void coinControlFeaturesChanged(bool); }; diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 2e33b9adf..bbd95ef47 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -142,7 +142,7 @@ OverviewPage::OverviewPage(QWidget *parent) : void OverviewPage::handleTransactionClicked(const QModelIndex &index) { if(filter) - emit transactionClicked(filter->mapToSource(index)); + Q_EMIT transactionClicked(filter->mapToSource(index)); } OverviewPage::~OverviewPage() diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 64cb1dc4e..de5ac345d 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -35,11 +35,11 @@ public: void setWalletModel(WalletModel *walletModel); void showOutOfSyncWarning(bool fShow); -public slots: +public Q_SLOTS: void setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); -signals: +Q_SIGNALS: void transactionClicked(const QModelIndex &index); private: @@ -56,7 +56,7 @@ private: TxViewDelegate *txdelegate; TransactionFilterProxy *filter; -private slots: +private Q_SLOTS: void updateDisplayUnit(); void handleTransactionClicked(const QModelIndex &index); void updateAlerts(const QString &warnings); diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 09e9949b1..654292903 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -148,7 +148,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) int nRootCerts = 0; const QDateTime currentTime = QDateTime::currentDateTime(); - foreach (const QSslCertificate& cert, certList) { + Q_FOREACH (const QSslCertificate& cert, certList) { // Don't log NULL certificates if (cert.isNull()) continue; @@ -201,7 +201,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) // when uiReady() is called. // // Warning: ipcSendCommandLine() is called early in init, -// so don't use "emit message()", but "QMessageBox::"! +// so don't use "Q_EMIT message()", but "QMessageBox::"! // void PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { @@ -269,7 +269,7 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[]) bool PaymentServer::ipcSendCommandLine() { bool fResult = false; - foreach (const QString& r, savedPaymentRequests) + Q_FOREACH (const QString& r, savedPaymentRequests) { QLocalSocket* socket = new QLocalSocket(); socket->connectToServer(ipcServerName(), QIODevice::WriteOnly); @@ -326,7 +326,7 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : uriServer = new QLocalServer(this); if (!uriServer->listen(name)) { - // constructor is called early in init, so don't use "emit message()" here + // constructor is called early in init, so don't use "Q_EMIT message()" here QMessageBox::critical(0, tr("Payment request error"), tr("Cannot start bitcoin: click-to-pay handler")); } @@ -394,7 +394,7 @@ void PaymentServer::uiReady() initNetManager(); saveURIs = false; - foreach (const QString& s, savedPaymentRequests) + Q_FOREACH (const QString& s, savedPaymentRequests) { handleURIOrFile(s); } @@ -431,7 +431,7 @@ void PaymentServer::handleURIOrFile(const QString& s) else { qWarning() << "PaymentServer::handleURIOrFile: Invalid URL: " << fetchUrl; - emit message(tr("URI handling"), + Q_EMIT message(tr("URI handling"), tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()), CClientUIInterface::ICON_WARNING); } @@ -445,14 +445,14 @@ void PaymentServer::handleURIOrFile(const QString& s) { CBitcoinAddress address(recipient.address.toStdString()); if (!address.IsValid()) { - emit message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address), + Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address), CClientUIInterface::MSG_ERROR); } else - emit receivedPaymentRequest(recipient); + Q_EMIT receivedPaymentRequest(recipient); } else - emit message(tr("URI handling"), + Q_EMIT message(tr("URI handling"), tr("URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."), CClientUIInterface::ICON_WARNING); @@ -466,12 +466,12 @@ void PaymentServer::handleURIOrFile(const QString& s) SendCoinsRecipient recipient; if (!readPaymentRequestFromFile(s, request)) { - emit message(tr("Payment request file handling"), + Q_EMIT message(tr("Payment request file handling"), tr("Payment request file cannot be read! This can be caused by an invalid payment request file."), CClientUIInterface::ICON_WARNING); } else if (processPaymentRequest(request, recipient)) - emit receivedPaymentRequest(recipient); + Q_EMIT receivedPaymentRequest(recipient); return; } @@ -500,7 +500,7 @@ void PaymentServer::handleURIConnection() // // Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine() -// so don't use "emit message()", but "QMessageBox::"! +// so don't use "Q_EMIT message()", but "QMessageBox::"! // bool PaymentServer::readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request) { @@ -533,7 +533,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen if (request.IsInitialized()) { // Payment request network matches client network? if (!verifyNetwork(request.getDetails())) { - emit message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), + Q_EMIT message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), CClientUIInterface::MSG_ERROR); return false; @@ -542,13 +542,13 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen // Make sure any payment requests involved are still valid. // This is re-checked just before sending coins in WalletModel::sendCoins(). if (verifyExpired(request.getDetails())) { - emit message(tr("Payment request rejected"), tr("Payment request expired."), + Q_EMIT message(tr("Payment request rejected"), tr("Payment request expired."), CClientUIInterface::MSG_ERROR); return false; } } else { - emit message(tr("Payment request error"), tr("Payment request is not initialized."), + Q_EMIT message(tr("Payment request error"), tr("Payment request is not initialized."), CClientUIInterface::MSG_ERROR); return false; @@ -562,7 +562,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen QList > sendingTos = request.getPayTo(); QStringList addresses; - foreach(const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { + Q_FOREACH(const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { // Extract and check destination addresses CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) { @@ -573,7 +573,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen // Unauthenticated payment requests to custom bitcoin addresses are not supported // (there is no good way to tell the user where they are paying in a way they'd // have a chance of understanding). - emit message(tr("Payment request rejected"), + Q_EMIT message(tr("Payment request rejected"), tr("Unverified payment requests to custom payment scripts are unsupported."), CClientUIInterface::MSG_ERROR); return false; @@ -583,14 +583,14 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen // but CAmount is defined as int64_t. Because of that we need to verify that amounts are in a valid range // and no overflow has happened. if (!verifyAmount(sendingTo.second)) { - emit message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); return false; } // Extract and check amounts CTxOut txOut(sendingTo.second, sendingTo.first); if (txOut.IsDust(::minRelayTxFee)) { - emit message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") + Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)), CClientUIInterface::MSG_ERROR); @@ -600,7 +600,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen recipient.amount += sendingTo.second; // Also verify that the final amount is still in a valid range after adding additional amounts. if (!verifyAmount(recipient.amount)) { - emit message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); return false; } } @@ -694,7 +694,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) .arg(BIP70_MAX_PAYMENTREQUEST_SIZE); qWarning() << QString("PaymentServer::%1:").arg(__func__) << msg; - emit message(tr("Payment request DoS protection"), msg, CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request DoS protection"), msg, CClientUIInterface::MSG_ERROR); return; } @@ -704,7 +704,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) .arg(reply->errorString()); qWarning() << "PaymentServer::netRequestFinished: " << msg; - emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); return; } @@ -718,12 +718,12 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) if (!request.parse(data)) { qWarning() << "PaymentServer::netRequestFinished: Error parsing payment request"; - emit message(tr("Payment request error"), + Q_EMIT message(tr("Payment request error"), tr("Payment request cannot be parsed!"), CClientUIInterface::MSG_ERROR); } else if (processPaymentRequest(request, recipient)) - emit receivedPaymentRequest(recipient); + Q_EMIT receivedPaymentRequest(recipient); return; } @@ -736,11 +736,11 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) .arg(reply->request().url().toString()); qWarning() << "PaymentServer::netRequestFinished: " << msg; - emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); } else { - emit receivedPaymentACK(GUIUtil::HtmlEscape(paymentACK.memo())); + Q_EMIT receivedPaymentACK(GUIUtil::HtmlEscape(paymentACK.memo())); } } } @@ -750,11 +750,11 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList Q_UNUSED(reply); QString errString; - foreach (const QSslError& err, errs) { + Q_FOREACH (const QSslError& err, errs) { qWarning() << "PaymentServer::reportSslErrors: " << err; errString += err.errorString() + "\n"; } - emit message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); + Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); } void PaymentServer::setOptionsModel(OptionsModel *optionsModel) @@ -765,7 +765,7 @@ void PaymentServer::setOptionsModel(OptionsModel *optionsModel) void PaymentServer::handlePaymentACK(const QString& paymentACKMsg) { // currently we don't futher process or store the paymentACK message - emit message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL); + Q_EMIT message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL); } bool PaymentServer::verifyNetwork(const payments::PaymentDetails& requestDetails) diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index 32ed27983..5df0a14cf 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -98,7 +98,7 @@ public: // Verify the payment request amount is valid static bool verifyAmount(const CAmount& requestAmount); -signals: +Q_SIGNALS: // Fired when a valid payment request is received void receivedPaymentRequest(SendCoinsRecipient); @@ -108,7 +108,7 @@ signals: // Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); -public slots: +public Q_SLOTS: // Signal this when the main window's UI is ready // to display payment requests to the user void uiReady(); @@ -119,7 +119,7 @@ public slots: // Handle an incoming URI, URI with local file scheme or file void handleURIOrFile(const QString& s); -private slots: +private Q_SLOTS: void handleURIConnection(); void netRequestFinished(QNetworkReply*); void reportSslErrors(QNetworkReply*, const QList &); diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index f5904a4d8..85339166b 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -63,7 +63,7 @@ public: #if QT_VERSION >= 0x040700 cachedNodeStats.reserve(vNodes.size()); #endif - foreach (CNode* pnode, vNodes) + Q_FOREACH (CNode* pnode, vNodes) { CNodeCombinedStats stats; stats.nodeStateStats.nMisbehavior = 0; @@ -92,7 +92,7 @@ public: // build index map mapNodeRows.clear(); int row = 0; - foreach (const CNodeCombinedStats& stats, cachedNodeStats) + Q_FOREACH (const CNodeCombinedStats& stats, cachedNodeStats) mapNodeRows.insert(std::pair(stats.nodeStats.nodeid, row++)); } @@ -220,9 +220,9 @@ const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx) void PeerTableModel::refresh() { - emit layoutAboutToBeChanged(); + Q_EMIT layoutAboutToBeChanged(); priv->refreshPeers(); - emit layoutChanged(); + Q_EMIT layoutChanged(); } int PeerTableModel::getRowByNodeId(NodeId nodeid) diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h index bff7bb824..fcb89b761 100644 --- a/src/qt/peertablemodel.h +++ b/src/qt/peertablemodel.h @@ -68,7 +68,7 @@ public: void sort(int column, Qt::SortOrder order); /*@}*/ -public slots: +public Q_SLOTS: void refresh(); private: diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h index f63568d27..8665acda5 100644 --- a/src/qt/qvalidatedlineedit.h +++ b/src/qt/qvalidatedlineedit.h @@ -27,11 +27,11 @@ private: bool valid; const QValidator *checkValidator; -public slots: +public Q_SLOTS: void setValid(bool valid); void setEnabled(bool enabled); -private slots: +private Q_SLOTS: void markValid(); void checkValidity(); }; diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp index f73268c95..800436661 100644 --- a/src/qt/qvaluecombobox.cpp +++ b/src/qt/qvaluecombobox.cpp @@ -27,5 +27,5 @@ void QValueComboBox::setRole(int role) void QValueComboBox::handleSelectionChanged(int idx) { - emit valueChanged(); + Q_EMIT valueChanged(); } diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h index dc85d64cb..5b20e6a5a 100644 --- a/src/qt/qvaluecombobox.h +++ b/src/qt/qvaluecombobox.h @@ -24,13 +24,13 @@ public: /** Specify model role to use as ordinal value (defaults to Qt::UserRole) */ void setRole(int role); -signals: +Q_SIGNALS: void valueChanged(); private: int role; -private slots: +private Q_SLOTS: void handleSelectionChanged(int idx); }; diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index fd225f51a..43b46c63b 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -185,7 +185,7 @@ void ReceiveCoinsDialog::on_showRequestButton_clicked() return; QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows(); - foreach (const QModelIndex& index, selection) { + Q_FOREACH (const QModelIndex& index, selection) { on_recentRequestsView_doubleClicked(index); } } diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 70a1842fa..6bb159482 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -44,7 +44,7 @@ public: void setModel(WalletModel *model); -public slots: +public Q_SLOTS: void clear(); void reject(); void accept(); @@ -60,7 +60,7 @@ private: void copyColumnToClipboard(int column); virtual void resizeEvent(QResizeEvent *event); -private slots: +private Q_SLOTS: void on_receiveButton_clicked(); void on_showRequestButton_clicked(); void on_removeRequestButton_clicked(); diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 3e5f897be..69f84ebbd 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -32,7 +32,7 @@ public: explicit QRImageWidget(QWidget *parent = 0); QImage exportImage(); -public slots: +public Q_SLOTS: void saveImage(); void copyImage(); @@ -55,7 +55,7 @@ public: void setModel(OptionsModel *model); void setInfo(const SendCoinsRecipient &info); -private slots: +private Q_SLOTS: void on_btnCopyURI_clicked(); void on_btnCopyAddress_clicked(); diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 543b977d8..5692a7aae 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -119,7 +119,7 @@ QVariant RecentRequestsTableModel::headerData(int section, Qt::Orientation orien void RecentRequestsTableModel::updateAmountColumnTitle() { columns[Amount] = getAmountTitle(); - emit headerDataChanged(Qt::Horizontal,Amount,Amount); + Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount); } /** Gets title for amount column including current display unit if optionsModel reference available. */ @@ -214,7 +214,7 @@ void RecentRequestsTableModel::addNewRequest(RecentRequestEntry &recipient) void RecentRequestsTableModel::sort(int column, Qt::SortOrder order) { qSort(list.begin(), list.end(), RecentRequestEntryLessThan(column, order)); - emit dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex())); + Q_EMIT dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex())); } void RecentRequestsTableModel::updateDisplayUnit() diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index 85bad126d..64faa72d4 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -89,7 +89,7 @@ public: void addNewRequest(const std::string &recipient); void addNewRequest(RecentRequestEntry &recipient); -public slots: +public Q_SLOTS: void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); void updateDisplayUnit(); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index f828ce253..2fafb83d4 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -60,10 +60,10 @@ class RPCExecutor : public QObject { Q_OBJECT -public slots: +public Q_SLOTS: void request(const QString &command); -signals: +Q_SIGNALS: void reply(int category, const QString &command); }; @@ -95,7 +95,7 @@ bool parseCommandLine(std::vector &args, const std::string &strComm STATE_ESCAPE_DOUBLEQUOTED } state = STATE_EATING_SPACES; std::string curarg; - foreach(char ch, strCommand) + Q_FOREACH(char ch, strCommand) { switch(state) { @@ -158,7 +158,7 @@ void RPCExecutor::request(const QString &command) std::vector args; if(!parseCommandLine(args, command.toStdString())) { - emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); return; } if(args.empty()) @@ -180,7 +180,7 @@ void RPCExecutor::request(const QString &command) else strPrint = result.write(2); - emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint)); + Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint)); } catch (UniValue& objError) { @@ -188,16 +188,16 @@ void RPCExecutor::request(const QString &command) { int code = find_value(objError, "code").get_int(); std::string message = find_value(objError, "message").get_str(); - emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")"); + Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")"); } catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message { // Show raw JSON object - emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write())); + Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write())); } } catch (const std::exception& e) { - emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what())); + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what())); } } @@ -245,7 +245,7 @@ RPCConsole::RPCConsole(QWidget *parent) : RPCConsole::~RPCConsole() { GUIUtil::saveWindowGeometry("nRPCConsoleWindow", this); - emit stopExecutor(); + Q_EMIT stopExecutor(); delete ui; } @@ -431,7 +431,7 @@ void RPCConsole::on_lineEdit_returnPressed() if(!cmd.isEmpty()) { message(CMD_REQUEST, cmd); - emit cmdRequest(cmd); + Q_EMIT cmdRequest(cmd); // Remove command, if already in history history.removeOne(cmd); // Append command to history diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index a309df7ba..6f42aa08b 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -46,7 +46,7 @@ protected: virtual bool eventFilter(QObject* obj, QEvent *event); void keyPressEvent(QKeyEvent *); -private slots: +private Q_SLOTS: void on_lineEdit_returnPressed(); void on_tabWidget_currentChanged(int index); /** open the debug.log from the current datadir */ @@ -61,7 +61,7 @@ private slots: /** Show custom context menu on Peers tab */ void showMenu(const QPoint& point); -public slots: +public Q_SLOTS: void clear(); void message(int category, const QString &message, bool html = false); /** Set number of connections shown in the UI */ @@ -79,7 +79,7 @@ public slots: /** Disconnect a selected node on the Peers tab */ void disconnectSelectedNode(); -signals: +Q_SIGNALS: // For RPC command executor void stopExecutor(); void cmdRequest(const QString &command); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 3d5771156..e13cd714a 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -251,7 +251,7 @@ void SendCoinsDialog::on_sendButton_clicked() // Format confirmation message QStringList formatted; - foreach(const SendCoinsRecipient &rcp, currentTransaction.getRecipients()) + Q_FOREACH(const SendCoinsRecipient &rcp, currentTransaction.getRecipients()) { // generate bold amount string QString amount = "" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount); @@ -305,7 +305,7 @@ void SendCoinsDialog::on_sendButton_clicked() questionString.append("
"); CAmount totalAmount = currentTransaction.getTotalTransactionAmount() + txFee; QStringList alternativeUnits; - foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) + Q_FOREACH(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) { if(u != model->getOptionsModel()->getDisplayUnit()) alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount)); @@ -540,7 +540,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn return; } - emit message(tr("Send Coins"), msgParams.first, msgParams.second); + Q_EMIT message(tr("Send Coins"), msgParams.first, msgParams.second); } void SendCoinsDialog::minimizeFeeSection(bool fMinimize) diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index fc513bf2b..c833da84b 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -45,7 +45,7 @@ public: void pasteEntry(const SendCoinsRecipient &rv); bool handlePaymentRequest(const SendCoinsRecipient &recipient); -public slots: +public Q_SLOTS: void clear(); void reject(); void accept(); @@ -62,13 +62,13 @@ private: bool fFeeMinimized; // Process WalletModel::SendCoinsReturn and generate a pair consisting - // of a message and message flags for use in emit message(). + // of a message and message flags for use in Q_EMIT message(). // Additional parameter msgArg can be used via .arg(msgArg). void processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg = QString()); void minimizeFeeSection(bool fMinimize); void updateFeeMinimizedLabel(); -private slots: +private Q_SLOTS: void on_sendButton_clicked(); void on_buttonChooseFee_clicked(); void on_buttonMinimizeFee_clicked(); @@ -93,7 +93,7 @@ private slots: void updateSmartFeeLabel(); void updateGlobalFeeVariables(); -signals: +Q_SIGNALS: // Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); }; diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index 6eec33ffd..90a8cbdc4 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -114,7 +114,7 @@ void SendCoinsEntry::clear() void SendCoinsEntry::deleteClicked() { - emit removeEntry(this); + Q_EMIT removeEntry(this); } bool SendCoinsEntry::validate() diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index c2d1185bd..d7e655fdc 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -45,15 +45,15 @@ public: void setFocus(); -public slots: +public Q_SLOTS: void clear(); -signals: +Q_SIGNALS: void removeEntry(SendCoinsEntry *entry); void payAmountChanged(); void subtractFeeFromAmountChanged(); -private slots: +private Q_SLOTS: void deleteClicked(); void on_payTo_textChanged(const QString &address); void on_addressBookButton_clicked(); diff --git a/src/qt/signverifymessagedialog.h b/src/qt/signverifymessagedialog.h index 27807adc8..bf841e4f8 100644 --- a/src/qt/signverifymessagedialog.h +++ b/src/qt/signverifymessagedialog.h @@ -35,7 +35,7 @@ private: Ui::SignVerifyMessageDialog *ui; WalletModel *model; -private slots: +private Q_SLOTS: /* sign message */ void on_addressBookButton_SM_clicked(); void on_pasteButton_SM_clicked(); diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index 84e4556dd..29d16d4ea 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -27,7 +27,7 @@ protected: void paintEvent(QPaintEvent *event); void closeEvent(QCloseEvent *event); -public slots: +public Q_SLOTS: /** Slot to call finish() method as it's not defined as slot */ void slotFinish(QWidget *mainWin); diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index e2ec439b2..b28934cd3 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -195,7 +195,7 @@ void PaymentServerTests::paymentServerTests() QVERIFY(r.paymentRequest.IsInitialized()); // Extract address and amount from the request QList > sendingTos = r.paymentRequest.getPayTo(); - foreach (const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { + Q_FOREACH (const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false); diff --git a/src/qt/test/paymentservertests.h b/src/qt/test/paymentservertests.h index c98bbf083..71d61fcbe 100644 --- a/src/qt/test/paymentservertests.h +++ b/src/qt/test/paymentservertests.h @@ -14,7 +14,7 @@ class PaymentServerTests : public QObject { Q_OBJECT -private slots: +private Q_SLOTS: void paymentServerTests(); }; @@ -25,7 +25,7 @@ class RecipientCatcher : public QObject { Q_OBJECT -public slots: +public Q_SLOTS: void getRecipient(SendCoinsRecipient r); public: diff --git a/src/qt/test/uritests.h b/src/qt/test/uritests.h index a0b7dc6c7..434169dcd 100644 --- a/src/qt/test/uritests.h +++ b/src/qt/test/uritests.h @@ -12,7 +12,7 @@ class URITests : public QObject { Q_OBJECT -private slots: +private Q_SLOTS: void uriTests(); }; diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index 0b2eb9eaf..9b67445bc 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -139,10 +139,10 @@ void TrafficGraphWidget::updateRates() } float tmax = 0.0f; - foreach(float f, vSamplesIn) { + Q_FOREACH(float f, vSamplesIn) { if(f > tmax) tmax = f; } - foreach(float f, vSamplesOut) { + Q_FOREACH(float f, vSamplesOut) { if(f > tmax) tmax = f; } fMax = tmax; diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h index 4c6b17fe7..6336a8d14 100644 --- a/src/qt/trafficgraphwidget.h +++ b/src/qt/trafficgraphwidget.h @@ -27,7 +27,7 @@ public: protected: void paintEvent(QPaintEvent *); -public slots: +public Q_SLOTS: void updateRates(); void setGraphRangeMins(int mins); void clear(); diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 5662b1665..d7ee3d4c7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -243,14 +243,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "" + tr("Transaction ID") + ": " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "
"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) - foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm) + Q_FOREACH (const PAIRTYPE(string, string)& r, wtx.vOrderForm) if (r.first == "Message") strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(r.second, true) + "
"; // // PaymentRequest info: // - foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm) + Q_FOREACH (const PAIRTYPE(string, string)& r, wtx.vOrderForm) { if (r.first == "PaymentRequest") { diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 34464b407..e3d64387f 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -142,7 +142,7 @@ public: { parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1); int insert_idx = lowerIndex; - foreach(const TransactionRecord &rec, toInsert) + Q_FOREACH(const TransactionRecord &rec, toInsert) { cachedWallet.insert(insert_idx, rec); insert_idx += 1; @@ -245,7 +245,7 @@ TransactionTableModel::~TransactionTableModel() void TransactionTableModel::updateAmountColumnTitle() { columns[Amount] = BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit()); - emit headerDataChanged(Qt::Horizontal,Amount,Amount); + Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount); } void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction) @@ -262,8 +262,8 @@ void TransactionTableModel::updateConfirmations() // Invalidate status (number of confirmations) and (possibly) description // for all rows. Qt is smart enough to only actually request the data for the // visible rows. - emit dataChanged(index(0, Status), index(priv->size()-1, Status)); - emit dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress)); + Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status)); + Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress)); } int TransactionTableModel::rowCount(const QModelIndex &parent) const @@ -650,7 +650,7 @@ void TransactionTableModel::updateDisplayUnit() { // emit dataChanged to update Amount column with the current unit updateAmountColumnTitle(); - emit dataChanged(index(0, Amount), index(priv->size()-1, Amount)); + Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount)); } // queue notifications to show a non freezing progress dialog e.g. for rescan diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index 30a15df9e..25c82c764 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -98,7 +98,7 @@ private: QVariant txWatchonlyDecoration(const TransactionRecord *wtx) const; QVariant txAddressDecoration(const TransactionRecord *wtx) const; -public slots: +public Q_SLOTS: /* New transaction, or transaction changed status */ void updateTransaction(const QString &hash, int status, bool showTransaction); void updateConfirmations(); diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 526940632..998789b3a 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -341,11 +341,11 @@ void TransactionView::exportClicked() writer.addColumn(tr("ID"), 0, TransactionTableModel::TxIDRole); if(!writer.write()) { - emit message(tr("Exporting Failed"), tr("There was an error trying to save the transaction history to %1.").arg(filename), + Q_EMIT message(tr("Exporting Failed"), tr("There was an error trying to save the transaction history to %1.").arg(filename), CClientUIInterface::MSG_ERROR); } else { - emit message(tr("Exporting Successful"), tr("The transaction history was successfully saved to %1.").arg(filename), + Q_EMIT message(tr("Exporting Successful"), tr("The transaction history was successfully saved to %1.").arg(filename), CClientUIInterface::MSG_INFORMATION); } } diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index 092d91904..6c35362be 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -83,7 +83,7 @@ private: bool eventFilter(QObject *obj, QEvent *event); -private slots: +private Q_SLOTS: void contextualMenu(const QPoint &); void dateRangeChanged(); void showDetails(); @@ -95,13 +95,13 @@ private slots: void openThirdPartyTxUrl(QString url); void updateWatchOnlyColumn(bool fHaveWatchOnly); -signals: +Q_SIGNALS: void doubleClicked(const QModelIndex&); /** Fired when a message should be reported to the user */ void message(const QString &title, const QString &message, unsigned int style); -public slots: +public Q_SLOTS: void chooseDate(int idx); void chooseType(int idx); void chooseWatchonly(int idx); diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 386cf31d7..5e26f3e01 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -84,7 +84,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) : QTextCharFormat bold; bold.setFontWeight(QFont::Bold); - foreach (const QString &line, coreOptions.split("\n")) { + Q_FOREACH (const QString &line, coreOptions.split("\n")) { if (line.startsWith(" -")) { cursor.currentTable()->appendRows(1); diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h index 288b985f1..47282ae2d 100644 --- a/src/qt/utilitydialog.h +++ b/src/qt/utilitydialog.h @@ -31,7 +31,7 @@ private: Ui::HelpMessageDialog *ui; QString text; -private slots: +private Q_SLOTS: void on_okButton_accepted(); }; diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index eea97defc..5a5e2ab94 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -47,7 +47,7 @@ private: WalletView *currentWalletView(); -public slots: +public Q_SLOTS: /** Switch to overview (home) page */ void gotoOverviewPage(); /** Switch to history (transactions) page */ diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 9b8be76be..2691fa930 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -107,7 +107,7 @@ void WalletModel::updateStatus() EncryptionStatus newEncryptionStatus = getEncryptionStatus(); if(cachedEncryptionStatus != newEncryptionStatus) - emit encryptionStatusChanged(newEncryptionStatus); + Q_EMIT encryptionStatusChanged(newEncryptionStatus); } void WalletModel::pollBalanceChanged() @@ -159,7 +159,7 @@ void WalletModel::checkBalanceChanged() cachedWatchOnlyBalance = newWatchOnlyBalance; cachedWatchUnconfBalance = newWatchUnconfBalance; cachedWatchImmatureBalance = newWatchImmatureBalance; - emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance, + Q_EMIT balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance, newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance); } } @@ -180,7 +180,7 @@ void WalletModel::updateAddressBook(const QString &address, const QString &label void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly) { fHaveWatchOnly = fHaveWatchonly; - emit notifyWatchonlyChanged(fHaveWatchonly); + Q_EMIT notifyWatchonlyChanged(fHaveWatchonly); } bool WalletModel::validateAddress(const QString &address) @@ -205,7 +205,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact int nAddresses = 0; // Pre-check input data for validity - foreach(const SendCoinsRecipient &rcp, recipients) + Q_FOREACH(const SendCoinsRecipient &rcp, recipients) { if (rcp.fSubtractFeeFromAmount) fSubtractFeeFromAmount = true; @@ -285,7 +285,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact { return SendCoinsReturn(AmountWithFeeExceedsBalance); } - emit message(tr("Send Coins"), QString::fromStdString(strFailReason), + Q_EMIT message(tr("Send Coins"), QString::fromStdString(strFailReason), CClientUIInterface::MSG_ERROR); return TransactionCreationFailed; } @@ -306,7 +306,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran LOCK2(cs_main, wallet->cs_wallet); CWalletTx *newTx = transaction.getTransaction(); - foreach(const SendCoinsRecipient &rcp, transaction.getRecipients()) + Q_FOREACH(const SendCoinsRecipient &rcp, transaction.getRecipients()) { if (rcp.paymentRequest.IsInitialized()) { @@ -337,7 +337,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran // Add addresses / update labels that we've sent to to the address book, // and emit coinsSent signal for each recipient - foreach(const SendCoinsRecipient &rcp, transaction.getRecipients()) + Q_FOREACH(const SendCoinsRecipient &rcp, transaction.getRecipients()) { // Don't touch the address book when we have a payment request if (!rcp.paymentRequest.IsInitialized()) @@ -361,7 +361,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran } } } - emit coinsSent(wallet, rcp, transaction_array); + Q_EMIT coinsSent(wallet, rcp, transaction_array); } checkBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits @@ -521,7 +521,7 @@ WalletModel::UnlockContext WalletModel::requestUnlock() if(was_locked) { // Request UI to unlock wallet - emit requireUnlock(); + Q_EMIT requireUnlock(); } // If wallet is still locked, unlock was failed or cancelled, mark context as invalid bool valid = getEncryptionStatus() != Locked; diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index e26343888..40bc62354 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -227,7 +227,7 @@ private: void unsubscribeFromCoreSignals(); void checkBalanceChanged(); -signals: +Q_SIGNALS: // Signal that balance in wallet changed void balanceChanged(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance); @@ -252,7 +252,7 @@ signals: // Watch-only address added void notifyWatchonlyChanged(bool fHaveWatchonly); -public slots: +public Q_SLOTS: /* Wallet status might have changed */ void updateStatus(); /* New transaction, or transaction changed status */ diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 206bb7c77..6a9b2d5bd 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -81,7 +81,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet) CAmount WalletModelTransaction::getTotalTransactionAmount() { CAmount totalTransactionAmount = 0; - foreach(const SendCoinsRecipient &rcp, recipients) + Q_FOREACH(const SendCoinsRecipient &rcp, recipients) { totalTransactionAmount += rcp.amount; } diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 956c8b891..c5f556b44 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -153,7 +153,7 @@ void WalletView::processNewTransaction(const QModelIndex& parent, int start, int QString address = ttm->data(index, TransactionTableModel::AddressRole).toString(); QString label = ttm->data(index, TransactionTableModel::LabelRole).toString(); - emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label); + Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label); } void WalletView::gotoOverviewPage() @@ -215,7 +215,7 @@ void WalletView::showOutOfSyncWarning(bool fShow) void WalletView::updateEncryptionStatus() { - emit encryptionStatusChanged(walletModel->getEncryptionStatus()); + Q_EMIT encryptionStatusChanged(walletModel->getEncryptionStatus()); } void WalletView::encryptWallet(bool status) @@ -239,11 +239,11 @@ void WalletView::backupWallet() return; if (!walletModel->backupWallet(filename)) { - emit message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename), + Q_EMIT message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename), CClientUIInterface::MSG_ERROR); } else { - emit message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename), + Q_EMIT message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename), CClientUIInterface::MSG_INFORMATION); } } diff --git a/src/qt/walletview.h b/src/qt/walletview.h index 1840e21e9..87c5d7bfb 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -65,7 +65,7 @@ private: QProgressDialog *progressDialog; -public slots: +public Q_SLOTS: /** Switch to overview (home) page */ void gotoOverviewPage(); /** Switch to history (transactions) page */ @@ -105,7 +105,7 @@ public slots: /** Show progress dialog e.g. for rescan */ void showProgress(const QString &title, int nProgress); -signals: +Q_SIGNALS: /** Signal that we want to show the main window */ void showNormalIfMinimized(); /** Fired when a message should be reported to the user */ From 9fbca205d4eaaf82be718b69c6533078aeb3081c Mon Sep 17 00:00:00 2001 From: tailsjoin Date: Mon, 13 Jul 2015 16:43:30 +0000 Subject: [PATCH 0131/1283] doc: Remove recommendation to add old repos for libd4.8* It is unreasonable to ask to change the global package configuration just to build a package. Not only that, this is potentially harmful to the system. Also do a few punctuation fixes in REST-interface.md. --- doc/REST-interface.md | 11 ++++------- doc/build-unix.md | 15 ++------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/doc/REST-interface.md b/doc/REST-interface.md index 1ba01362d..3268ade7a 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -9,8 +9,7 @@ Supported API ####Transactions `GET /rest/tx/.` -Given a transaction hash, -Returns a transaction, in binary, hex-encoded binary or JSON formats. +Given a transaction hash: returns a transaction in binary, hex-encoded binary, or JSON formats. For full TX query capability, one must enable the transaction index via "txindex=1" command line / configuration option. @@ -18,8 +17,7 @@ For full TX query capability, one must enable the transaction index via "txindex `GET /rest/block/.` `GET /rest/block/notxdetails/.` -Given a block hash, -Returns a block, in binary, hex-encoded binary or JSON formats. +Given a block hash: returns a block, in binary, hex-encoded binary or JSON formats. The HTTP request and response are both handled entirely in-memory, thus making maximum memory usage at least 2.66MB (1 MB max block, plus hex encoding) per request. @@ -28,8 +26,7 @@ With the /notxdetails/ option JSON response will only contain the transaction ha ####Blockheaders `GET /rest/headers//.` -Given a block hash, -Returns amount of blockheaders in upward direction. +Given a block hash: returns amount of blockheaders in upward direction. ####Chaininfos `GET /rest/chaininfo.json` @@ -79,4 +76,4 @@ $ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff76 Risks ------------- -Running a webbrowser 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 `