diff --git a/contrib/debian/examples/bitcoin.conf b/contrib/debian/examples/bitcoin.conf index 1029a5107..61c744c08 100644 --- a/contrib/debian/examples/bitcoin.conf +++ b/contrib/debian/examples/bitcoin.conf @@ -44,11 +44,11 @@ # Use as many addnode= settings as you like to connect to specific peers #addnode=69.164.218.197 -#addnode=10.0.0.2:8333 +#addnode=10.0.0.2:9333 # Alternatively use as many connect= settings as you like to connect ONLY to specific peers #connect=69.164.218.197 -#connect=10.0.0.1:8333 +#connect=10.0.0.1:9333 # Listening mode, enabled by default except when 'connect' is being used #listen=1 @@ -110,7 +110,7 @@ #rpcallowip=2001:db8:85a3:0:0:8a2e:370:7334/96 # Listen for RPC connections on this TCP port: -#rpcport=8332 +#rpcport=9332 # You can use Bitcoin or bitcoind to send commands to Bitcoin/bitcoind # running on another host using this option: diff --git a/contrib/linearize/example-linearize.cfg b/contrib/linearize/example-linearize.cfg index d019b06b6..7dcca3b5a 100644 --- a/contrib/linearize/example-linearize.cfg +++ b/contrib/linearize/example-linearize.cfg @@ -3,8 +3,8 @@ rpcuser=someuser rpcpassword=somepassword #datadir=~/.bitcoin host=127.0.0.1 -port=8332 -#port=18332 +port=9332 +#port=19332 # bootstrap.dat hashlist settings (linearize-hashes) max_height=313000 diff --git a/contrib/linearize/linearize-hashes.py b/contrib/linearize/linearize-hashes.py index db8eb7021..cc405b631 100755 --- a/contrib/linearize/linearize-hashes.py +++ b/contrib/linearize/linearize-hashes.py @@ -125,7 +125,7 @@ if __name__ == '__main__': if 'host' not in settings: settings['host'] = '127.0.0.1' if 'port' not in settings: - settings['port'] = 8332 + settings['port'] = 9332 if 'min_height' not in settings: settings['min_height'] = 0 if 'max_height' not in settings: diff --git a/contrib/qos/README.md b/contrib/qos/README.md index 0ded87c58..d569b6a6f 100644 --- a/contrib/qos/README.md +++ b/contrib/qos/README.md @@ -1,5 +1,5 @@ -### QoS (Quality of service) ### +### Qos ### -This is a Linux bash script that will set up tc to limit the outgoing bandwidth for connections to the Bitcoin network. It limits outbound TCP traffic with a source or destination port of 8333, but not if the destination IP is within a LAN. +This is a Linux bash script that will set up tc to limit the outgoing bandwidth for connections to the Litecoin network. It limits outbound TCP traffic with a source or destination port of 9333, but not if the destination IP is within a LAN (defined as 192.168.x.x). -This means one can have an always-on bitcoind instance running, and another local bitcoind/bitcoin-qt instance which connects to this node and receives blocks from it. +This means one can have an always-on litecoind instance running, and another local litecoind/litecoin-qt instance which connects to this node and receives blocks from it. diff --git a/contrib/qos/tc.sh b/contrib/qos/tc.sh index 0d1dd65b4..8f9bb7a8b 100644 --- a/contrib/qos/tc.sh +++ b/contrib/qos/tc.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2017 The Bitcoin Core developers +# Copyright (c) 2013 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -6,12 +6,10 @@ IF="eth0" #limit of the network interface in question LINKCEIL="1gbit" -#limit outbound Bitcoin protocol traffic to this rate +#limit outbound Litecoin protocol traffic to this rate LIMIT="160kbit" -#defines the IPv4 address space for which you wish to disable rate limiting -LOCALNET_V4="192.168.0.0/16" -#defines the IPv6 address space for which you wish to disable rate limiting -LOCALNET_V6="fe80::/10" +#defines the address space for which you wish to disable rate limiting +LOCALNET="192.168.0.0/16" #delete existing rules tc qdisc del dev ${IF} root @@ -30,12 +28,6 @@ tc class add dev ${IF} parent 1:1 classid 1:11 htb rate ${LIMIT} ceil ${LIMIT} p tc filter add dev ${IF} parent 1: protocol ip prio 1 handle 1 fw classid 1:10 tc filter add dev ${IF} parent 1: protocol ip prio 2 handle 2 fw classid 1:11 -if [ ! -z "${LOCALNET_V6}" ] ; then - # v6 cannot have the same priority value as v4 - tc filter add dev ${IF} parent 1: protocol ipv6 prio 3 handle 1 fw classid 1:10 - tc filter add dev ${IF} parent 1: protocol ipv6 prio 4 handle 2 fw classid 1:11 -fi - #delete any existing rules #disable for now #ret=0 @@ -44,16 +36,10 @@ fi # ret=$? #done -#limit outgoing traffic to and from port 8333. but not when dealing with a host on the local network -# (defined by $LOCALNET_V4 and $LOCALNET_V6) -# --set-mark marks packages matching these criteria with the number "2" (v4) -# --set-mark marks packages matching these criteria with the number "4" (v6) -# these packets are filtered by the tc filter with "handle 2" +#limit outgoing traffic to and from port 9333. but not when dealing with a host on the local network +# (defined by $LOCALNET) +# --set-mark marks packages matching these criteria with the number "2" +# these packages are filtered by the tc filter with "handle 2" # this filter sends the packages into the 1:11 class, and this class is limited to ${LIMIT} -iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET_V4} -j MARK --set-mark 0x2 -iptables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET_V4} -j MARK --set-mark 0x2 - -if [ ! -z "${LOCALNET_V6}" ] ; then - ip6tables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4 - ip6tables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4 -fi +iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 9333 ! -d ${LOCALNET} -j MARK --set-mark 0x2 +iptables -t mangle -A OUTPUT -p tcp -m tcp --sport 9333 ! -d ${LOCALNET} -j MARK --set-mark 0x2 diff --git a/contrib/rpm/bitcoin.spec b/contrib/rpm/bitcoin.spec index cc54fcaf3..ca089f715 100644 --- a/contrib/rpm/bitcoin.spec +++ b/contrib/rpm/bitcoin.spec @@ -332,10 +332,10 @@ if [ `%{_sbindir}/sestatus |grep -c "disabled"` -eq 0 ]; then for selinuxvariant in %{selinux_variants}; do %{_sbindir}/semodule -s ${selinuxvariant} -i %{_datadir}/selinux/${selinuxvariant}/bitcoin.pp &> /dev/null || : done -%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 8332 -%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 8333 -%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18332 -%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18333 +%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 9332 +%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 9333 +%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 19332 +%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 19333 %{_sbindir}/fixfiles -R bitcoin-server restore &> /dev/null || : %{_sbindir}/restorecon -R %{_localstatedir}/lib/bitcoin || : fi @@ -351,10 +351,10 @@ fi # SELinux if [ $1 -eq 0 ]; then if [ `%{_sbindir}/sestatus |grep -c "disabled"` -eq 0 ]; then - %{_sbindir}/semanage port -d -p tcp 8332 - %{_sbindir}/semanage port -d -p tcp 8333 - %{_sbindir}/semanage port -d -p tcp 18332 - %{_sbindir}/semanage port -d -p tcp 18333 + %{_sbindir}/semanage port -d -p tcp 9332 + %{_sbindir}/semanage port -d -p tcp 9333 + %{_sbindir}/semanage port -d -p tcp 19332 + %{_sbindir}/semanage port -d -p tcp 19333 for selinuxvariant in %{selinux_variants}; do %{_sbindir}/semodule -s ${selinuxvariant} -r bitcoin &> /dev/null || : done diff --git a/contrib/seeds/generate-seeds.py b/contrib/seeds/generate-seeds.py index b0ac92ae0..2c0627035 100755 --- a/contrib/seeds/generate-seeds.py +++ b/contrib/seeds/generate-seeds.py @@ -127,10 +127,10 @@ def main(): g.write(' * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly.\n') g.write(' */\n') with open(os.path.join(indir,'nodes_main.txt'),'r') as f: - process_nodes(g, f, 'pnSeed6_main', 8333) + process_nodes(g, f, 'pnSeed6_main', 9333) g.write('\n') with open(os.path.join(indir,'nodes_test.txt'),'r') as f: - process_nodes(g, f, 'pnSeed6_test', 18333) + process_nodes(g, f, 'pnSeed6_test', 19333) g.write('#endif // BITCOIN_CHAINPARAMSSEEDS_H\n') if __name__ == '__main__': diff --git a/contrib/spendfrom/spendfrom.py b/contrib/spendfrom/spendfrom.py new file mode 100755 index 000000000..8c248a3f9 --- /dev/null +++ b/contrib/spendfrom/spendfrom.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python +# Copyright (c) 2013 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# +# Use the raw transactions API to spend bitcoins received on particular addresses, +# and send any change back to that same address. +# +# Example usage: +# spendfrom.py # Lists available funds +# spendfrom.py --from=ADDRESS --to=ADDRESS --amount=11.00 +# +# Assumes it will talk to a bitcoind or Bitcoin-Qt running +# on localhost. +# +# Depends on jsonrpc +# + +from decimal import * +import getpass +import math +import os +import os.path +import platform +import sys +import time +from jsonrpc import ServiceProxy, json + +BASE_FEE=Decimal("0.001") + +def check_json_precision(): + """Make sure json library being used does not lose precision converting BTC values""" + n = Decimal("20000000.00000003") + satoshis = int(json.loads(json.dumps(float(n)))*1.0e8) + if satoshis != 2000000000000003: + raise RuntimeError("JSON encode/decode loses precision") + +def determine_db_dir(): + """Return the default location of the bitcoin data directory""" + if platform.system() == "Darwin": + return os.path.expanduser("~/Library/Application Support/Bitcoin/") + elif platform.system() == "Windows": + return os.path.join(os.environ['APPDATA'], "Bitcoin") + return os.path.expanduser("~/.bitcoin") + +def read_bitcoin_config(dbdir): + """Read the bitcoin.conf file from dbdir, returns dictionary of settings""" + from ConfigParser import SafeConfigParser + + class FakeSecHead(object): + def __init__(self, fp): + self.fp = fp + self.sechead = '[all]\n' + def readline(self): + if self.sechead: + try: return self.sechead + finally: self.sechead = None + else: + s = self.fp.readline() + if s.find('#') != -1: + s = s[0:s.find('#')].strip() +"\n" + return s + + config_parser = SafeConfigParser() + config_parser.readfp(FakeSecHead(open(os.path.join(dbdir, "bitcoin.conf")))) + return dict(config_parser.items("all")) + +def connect_JSON(config): + """Connect to a bitcoin JSON-RPC server""" + testnet = config.get('testnet', '0') + testnet = (int(testnet) > 0) # 0/1 in config file, convert to True/False + if not 'rpcport' in config: + config['rpcport'] = 19332 if testnet else 9332 + connect = "http://%s:%s@127.0.0.1:%s"%(config['rpcuser'], config['rpcpassword'], config['rpcport']) + try: + result = ServiceProxy(connect) + # ServiceProxy is lazy-connect, so send an RPC command mostly to catch connection errors, + # but also make sure the bitcoind we're talking to is/isn't testnet: + if result.getmininginfo()['testnet'] != testnet: + sys.stderr.write("RPC server at "+connect+" testnet setting mismatch\n") + sys.exit(1) + return result + except: + sys.stderr.write("Error connecting to RPC server at "+connect+"\n") + sys.exit(1) + +def unlock_wallet(bitcoind): + info = bitcoind.getinfo() + if 'unlocked_until' not in info: + return True # wallet is not encrypted + t = int(info['unlocked_until']) + if t <= time.time(): + try: + passphrase = getpass.getpass("Wallet is locked; enter passphrase: ") + bitcoind.walletpassphrase(passphrase, 5) + except: + sys.stderr.write("Wrong passphrase\n") + + info = bitcoind.getinfo() + return int(info['unlocked_until']) > time.time() + +def list_available(bitcoind): + address_summary = dict() + + address_to_account = dict() + for info in bitcoind.listreceivedbyaddress(0): + address_to_account[info["address"]] = info["account"] + + unspent = bitcoind.listunspent(0) + for output in unspent: + # listunspent doesn't give addresses, so: + rawtx = bitcoind.getrawtransaction(output['txid'], 1) + vout = rawtx["vout"][output['vout']] + pk = vout["scriptPubKey"] + + # This code only deals with ordinary pay-to-bitcoin-address + # or pay-to-script-hash outputs right now; anything exotic is ignored. + if pk["type"] != "pubkeyhash" and pk["type"] != "scripthash": + continue + + address = pk["addresses"][0] + if address in address_summary: + address_summary[address]["total"] += vout["value"] + address_summary[address]["outputs"].append(output) + else: + address_summary[address] = { + "total" : vout["value"], + "outputs" : [output], + "account" : address_to_account.get(address, "") + } + + return address_summary + +def select_coins(needed, inputs): + # Feel free to improve this, this is good enough for my simple needs: + outputs = [] + have = Decimal("0.0") + n = 0 + while have < needed and n < len(inputs): + outputs.append({ "txid":inputs[n]["txid"], "vout":inputs[n]["vout"]}) + have += inputs[n]["amount"] + n += 1 + return (outputs, have-needed) + +def create_tx(bitcoind, fromaddresses, toaddress, amount, fee): + all_coins = list_available(bitcoind) + + total_available = Decimal("0.0") + needed = amount+fee + potential_inputs = [] + for addr in fromaddresses: + if addr not in all_coins: + continue + potential_inputs.extend(all_coins[addr]["outputs"]) + total_available += all_coins[addr]["total"] + + if total_available < needed: + sys.stderr.write("Error, only %f BTC available, need %f\n"%(total_available, needed)); + sys.exit(1) + + # + # Note: + # Python's json/jsonrpc modules have inconsistent support for Decimal numbers. + # Instead of wrestling with getting json.dumps() (used by jsonrpc) to encode + # Decimals, I'm casting amounts to float before sending them to bitcoind. + # + outputs = { toaddress : float(amount) } + (inputs, change_amount) = select_coins(needed, potential_inputs) + if change_amount > BASE_FEE: # don't bother with zero or tiny change + change_address = fromaddresses[-1] + if change_address in outputs: + outputs[change_address] += float(change_amount) + else: + outputs[change_address] = float(change_amount) + + rawtx = bitcoind.createrawtransaction(inputs, outputs) + signed_rawtx = bitcoind.signrawtransaction(rawtx) + if not signed_rawtx["complete"]: + sys.stderr.write("signrawtransaction failed\n") + sys.exit(1) + txdata = signed_rawtx["hex"] + + return txdata + +def compute_amount_in(bitcoind, txinfo): + result = Decimal("0.0") + for vin in txinfo['vin']: + in_info = bitcoind.getrawtransaction(vin['txid'], 1) + vout = in_info['vout'][vin['vout']] + result = result + vout['value'] + return result + +def compute_amount_out(txinfo): + result = Decimal("0.0") + for vout in txinfo['vout']: + result = result + vout['value'] + return result + +def sanity_test_fee(bitcoind, txdata_hex, max_fee): + class FeeError(RuntimeError): + pass + try: + txinfo = bitcoind.decoderawtransaction(txdata_hex) + total_in = compute_amount_in(bitcoind, txinfo) + total_out = compute_amount_out(txinfo) + if total_in-total_out > max_fee: + raise FeeError("Rejecting transaction, unreasonable fee of "+str(total_in-total_out)) + + tx_size = len(txdata_hex)/2 + kb = tx_size/1000 # integer division rounds down + if kb > 1 and fee < BASE_FEE: + raise FeeError("Rejecting no-fee transaction, larger than 1000 bytes") + if total_in < 0.01 and fee < BASE_FEE: + raise FeeError("Rejecting no-fee, tiny-amount transaction") + # Exercise for the reader: compute transaction priority, and + # warn if this is a very-low-priority transaction + + except FeeError as err: + sys.stderr.write((str(err)+"\n")) + sys.exit(1) + +def main(): + import optparse + + parser = optparse.OptionParser(usage="%prog [options]") + parser.add_option("--from", dest="fromaddresses", default=None, + help="addresses to get bitcoins from") + parser.add_option("--to", dest="to", default=None, + help="address to get send bitcoins to") + parser.add_option("--amount", dest="amount", default=None, + help="amount to send") + parser.add_option("--fee", dest="fee", default="0.0", + help="fee to include") + parser.add_option("--datadir", dest="datadir", default=determine_db_dir(), + help="location of bitcoin.conf file with RPC username/password (default: %default)") + parser.add_option("--testnet", dest="testnet", default=False, action="store_true", + help="Use the test network") + parser.add_option("--dry_run", dest="dry_run", default=False, action="store_true", + help="Don't broadcast the transaction, just create and print the transaction data") + + (options, args) = parser.parse_args() + + check_json_precision() + config = read_bitcoin_config(options.datadir) + if options.testnet: config['testnet'] = True + bitcoind = connect_JSON(config) + + if options.amount is None: + address_summary = list_available(bitcoind) + for address,info in address_summary.iteritems(): + n_transactions = len(info['outputs']) + if n_transactions > 1: + print("%s %.8f %s (%d transactions)"%(address, info['total'], info['account'], n_transactions)) + else: + print("%s %.8f %s"%(address, info['total'], info['account'])) + else: + fee = Decimal(options.fee) + amount = Decimal(options.amount) + while unlock_wallet(bitcoind) == False: + pass # Keep asking for passphrase until they get it right + txdata = create_tx(bitcoind, options.fromaddresses.split(","), options.to, amount, fee) + sanity_test_fee(bitcoind, txdata, amount*Decimal("0.01")) + if options.dry_run: + print(txdata) + else: + txid = bitcoind.sendrawtransaction(txdata) + print(txid) + +if __name__ == '__main__': + main() diff --git a/doc/REST-interface.md b/doc/REST-interface.md index caf678288..fc4e2ae3f 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -57,7 +57,7 @@ https://github.com/bitcoin/bips/blob/master/bip-0064.mediawiki Example: ``` -$ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff7627ff72e5e8b0f71210f92ea7a4000c5d75-0.json 2>/dev/null | json_pp +$ curl localhost:19332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff7627ff72e5e8b0f71210f92ea7a4000c5d75-0.json 2>/dev/null | json_pp { "chainHeight" : 325347, "chaintipHash" : "00000000fb01a7f3745a717f8caebee056c484e6e0bfe4a9591c235bb70506fb", @@ -99,4 +99,4 @@ Only supports JSON as output format. Risks ------------- -Running a web browser on the same node with a REST enabled bitcoind can be a risk. Accessing prepared XSS websites could read out tx/block data of your node by placing links like `