mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Merge pull request #1848 from codablock/pr_backport_bitcoin_0.14-3
Backport missing PRs from Bitcoin 0.14 - Part 3
This commit is contained in:
commit
0adb4b714a
3
.gitignore
vendored
3
.gitignore
vendored
@ -110,10 +110,7 @@ linux-build
|
||||
win32-build
|
||||
qa/pull-tester/run-bitcoind-for-test.sh
|
||||
qa/pull-tester/tests_config.py
|
||||
qa/pull-tester/test.*/*
|
||||
qa/tmp
|
||||
qa/cache/*
|
||||
share/BitcoindComparisonTool.jar
|
||||
|
||||
!src/leveldb*/Makefile
|
||||
|
||||
|
@ -87,6 +87,15 @@ before it will be merged. The basic squashing workflow is shown below.
|
||||
# save and quit
|
||||
git push -f # (force push to GitHub)
|
||||
|
||||
If you have problems with squashing (or other workflows with `git`), you can
|
||||
alternatively enable "Allow edits from maintainers" in the right GitHub
|
||||
sidebar and ask for help in the pull request.
|
||||
|
||||
Please refrain from creating several pull requests for the same change.
|
||||
Use the pull request that is already open (or was created earlier) to amend
|
||||
changes. This preserves the discussion and review that happened earlier for
|
||||
the respective change set.
|
||||
|
||||
The length of time required for peer review is unpredictable and will vary from
|
||||
pull request to pull request.
|
||||
|
||||
@ -198,3 +207,11 @@ Release Policy
|
||||
--------------
|
||||
|
||||
The project leader is the release manager for each Dash Core release.
|
||||
|
||||
Copyright
|
||||
---------
|
||||
|
||||
By contributing to this repository, you agree to license your work under the
|
||||
MIT license unless specified otherwise in `contrib/debian/copyright` or at
|
||||
the top of the file itself. Any work contributed where you are not the original
|
||||
author must contain its license header with the original author(s) and source.
|
||||
|
@ -491,6 +491,7 @@ if test x$use_hardening != xno; then
|
||||
|
||||
AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"])
|
||||
AX_CHECK_LINK_FLAG([[-Wl,--nxcompat]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"])
|
||||
AX_CHECK_LINK_FLAG([[-Wl,--high-entropy-va]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--high-entropy-va"])
|
||||
AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"])
|
||||
AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"])
|
||||
|
||||
|
@ -1,11 +1,3 @@
|
||||
Wallet Tools
|
||||
---------------------
|
||||
|
||||
### [SpendFrom](/contrib/spendfrom) ###
|
||||
|
||||
Use the raw transactions API to send coins received on a particular
|
||||
address (or addresses).
|
||||
|
||||
Repository Tools
|
||||
---------------------
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/bin/sh
|
||||
# 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.
|
||||
|
||||
DIR="$1"
|
||||
COMMIT="$2"
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2014-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.
|
||||
'''
|
||||
Run this script every time you change one of the png files. Using pngcrush, it will optimize the png files, remove various color profiles, remove ancillary chunks (alla) and text chunks (text).
|
||||
#pngcrush -brute -ow -rem gAMA -rem cHRM -rem iCCP -rem sRGB -rem alla -rem text
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
'''
|
||||
Perform basic ELF security checks on a series of executables.
|
||||
Exit status will be 0 if successful, and the program will be silent.
|
||||
@ -12,6 +15,7 @@ import os
|
||||
|
||||
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
|
||||
OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump')
|
||||
NONFATAL = {'HIGH_ENTROPY_VA'} # checks which are non-fatal for now but only generate a warning
|
||||
|
||||
def check_ELF_PIE(executable):
|
||||
'''
|
||||
@ -114,26 +118,50 @@ def check_ELF_Canary(executable):
|
||||
|
||||
def get_PE_dll_characteristics(executable):
|
||||
'''
|
||||
Get PE DllCharacteristics bits
|
||||
Get PE DllCharacteristics bits.
|
||||
Returns a tuple (arch,bits) where arch is 'i386:x86-64' or 'i386'
|
||||
and bits is the DllCharacteristics value.
|
||||
'''
|
||||
p = subprocess.Popen([OBJDUMP_CMD, '-x', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
|
||||
(stdout, stderr) = p.communicate()
|
||||
if p.returncode:
|
||||
raise IOError('Error opening file')
|
||||
arch = ''
|
||||
bits = 0
|
||||
for line in stdout.split('\n'):
|
||||
tokens = line.split()
|
||||
if len(tokens)>=2 and tokens[0] == 'architecture:':
|
||||
arch = tokens[1].rstrip(',')
|
||||
if len(tokens)>=2 and tokens[0] == 'DllCharacteristics':
|
||||
return int(tokens[1],16)
|
||||
return 0
|
||||
bits = int(tokens[1],16)
|
||||
return (arch,bits)
|
||||
|
||||
IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020
|
||||
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
|
||||
IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100
|
||||
|
||||
def check_PE_PIE(executable):
|
||||
def check_PE_DYNAMIC_BASE(executable):
|
||||
'''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)'''
|
||||
return bool(get_PE_dll_characteristics(executable) & 0x40)
|
||||
(arch,bits) = get_PE_dll_characteristics(executable)
|
||||
reqbits = IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
|
||||
return (bits & reqbits) == reqbits
|
||||
|
||||
# On 64 bit, must support high-entropy 64-bit address space layout randomization in addition to DYNAMIC_BASE
|
||||
# to have secure ASLR.
|
||||
def check_PE_HIGH_ENTROPY_VA(executable):
|
||||
'''PIE: DllCharacteristics bit 0x20 signifies high-entropy ASLR'''
|
||||
(arch,bits) = get_PE_dll_characteristics(executable)
|
||||
if arch == 'i386:x86-64':
|
||||
reqbits = IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
|
||||
else: # Unnecessary on 32-bit
|
||||
assert(arch == 'i386')
|
||||
reqbits = 0
|
||||
return (bits & reqbits) == reqbits
|
||||
|
||||
def check_PE_NX(executable):
|
||||
'''NX: DllCharacteristics bit 0x100 signifies nxcompat (DEP)'''
|
||||
return bool(get_PE_dll_characteristics(executable) & 0x100)
|
||||
(arch,bits) = get_PE_dll_characteristics(executable)
|
||||
return (bits & IMAGE_DLL_CHARACTERISTICS_NX_COMPAT) == IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
|
||||
|
||||
CHECKS = {
|
||||
'ELF': [
|
||||
@ -143,7 +171,8 @@ CHECKS = {
|
||||
('Canary', check_ELF_Canary)
|
||||
],
|
||||
'PE': [
|
||||
('PIE', check_PE_PIE),
|
||||
('DYNAMIC_BASE', check_PE_DYNAMIC_BASE),
|
||||
('HIGH_ENTROPY_VA', check_PE_HIGH_ENTROPY_VA),
|
||||
('NX', check_PE_NX)
|
||||
]
|
||||
}
|
||||
@ -168,12 +197,18 @@ if __name__ == '__main__':
|
||||
continue
|
||||
|
||||
failed = []
|
||||
warning = []
|
||||
for (name, func) in CHECKS[etype]:
|
||||
if not func(filename):
|
||||
failed.append(name)
|
||||
if name in NONFATAL:
|
||||
warning.append(name)
|
||||
else:
|
||||
failed.append(name)
|
||||
if failed:
|
||||
print('%s: failed %s' % (filename, ' '.join(failed)))
|
||||
retval = 1
|
||||
if warning:
|
||||
print('%s: warning %s' % (filename, ' '.join(warning)))
|
||||
except IOError:
|
||||
print('%s: cannot open' % filename)
|
||||
retval = 1
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
'''
|
||||
Test script for security-check.py
|
||||
'''
|
||||
|
@ -1,3 +1,7 @@
|
||||
# Copyright (c) 2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
# What to do
|
||||
sign=false
|
||||
verify=false
|
||||
|
@ -1,4 +1,8 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
set -e
|
||||
|
||||
UNSIGNED="$1"
|
||||
|
@ -1,4 +1,8 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
set -e
|
||||
|
||||
ROOTDIR=dist
|
||||
|
@ -1,4 +1,8 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
set -e
|
||||
|
||||
INPUTFILE="Xcode_7.3.1.dmg"
|
||||
|
@ -1,3 +1,7 @@
|
||||
# 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.
|
||||
|
||||
#network interface on which to limit traffic
|
||||
IF="eth0"
|
||||
#limit of the network interface in question
|
||||
|
@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Helpful little script that spits out a comma-separated list of
|
||||
# language codes for Qt icons that should be included
|
||||
# in binary Dash Core distributions
|
||||
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
sys.exit("Usage: %s $QTDIR/translations $BITCOINDIR/src/qt/locale"%sys.argv[0])
|
||||
|
||||
d1 = sys.argv[1]
|
||||
d2 = sys.argv[2]
|
||||
|
||||
l1 = set([ re.search(r'qt_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d1, 'qt_*.qm')) ])
|
||||
l2 = set([ re.search(r'dash_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d2, 'dash_*.qm')) ])
|
||||
|
||||
print ",".join(sorted(l1.intersection(l2)))
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2013-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.
|
||||
#
|
||||
# Generate seeds.txt from Pieter's DNS seeder
|
||||
#
|
||||
|
@ -1,35 +0,0 @@
|
||||
### SpendFrom ###
|
||||
|
||||
Use the raw transactions API to send coins received on a particular
|
||||
address (or addresses).
|
||||
|
||||
### Usage: ###
|
||||
Depends on [jsonrpc](http://json-rpc.org/).
|
||||
|
||||
spendfrom.py --from=FROMADDRESS1[,FROMADDRESS2] --to=TOADDRESS --amount=amount \
|
||||
--fee=fee --datadir=/path/to/.dashcore --testnet --dry_run
|
||||
|
||||
With no arguments, outputs a list of amounts associated with addresses.
|
||||
|
||||
With arguments, sends coins received by the `FROMADDRESS` addresses to the `TOADDRESS`.
|
||||
|
||||
### Notes ###
|
||||
|
||||
- You may explicitly specify how much fee to pay (a fee more than 1% of the amount
|
||||
will fail, though, to prevent dash-losing accidents). Spendfrom may fail if
|
||||
it thinks the transaction would never be confirmed (if the amount being sent is
|
||||
too small, or if the transaction is too many bytes for the fee).
|
||||
|
||||
- If a change output needs to be created, the change will be sent to the last
|
||||
`FROMADDRESS` (if you specify just one `FROMADDRESS`, change will go back to it).
|
||||
|
||||
- If `--datadir` is not specified, the default datadir is used.
|
||||
|
||||
- The `--dry_run` option will just create and sign the transaction and print
|
||||
the transaction data (as hexadecimal), instead of broadcasting it.
|
||||
|
||||
- If the transaction is created and broadcast successfully, a transaction id
|
||||
is printed.
|
||||
|
||||
- If this was a tool for end-users and not programmers, it would have much friendlier
|
||||
error-handling.
|
@ -1,9 +0,0 @@
|
||||
from distutils.core import setup
|
||||
setup(name='btcspendfrom',
|
||||
version='1.0',
|
||||
description='Command-line utility for bitcoin "coin control"',
|
||||
author='Gavin Andresen',
|
||||
author_email='gavin@bitcoinfoundation.org',
|
||||
requires=['jsonrpc'],
|
||||
scripts=['spendfrom.py'],
|
||||
)
|
@ -1,267 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Use the raw transactions API to spend dashs 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 dashd or Dash-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 Dash Core data directory"""
|
||||
if platform.system() == "Darwin":
|
||||
return os.path.expanduser("~/Library/Application Support/DashCore/")
|
||||
elif platform.system() == "Windows":
|
||||
return os.path.join(os.environ['APPDATA'], "DashCore")
|
||||
return os.path.expanduser("~/.dashcore")
|
||||
|
||||
def read_bitcoin_config(dbdir):
|
||||
"""Read the dash.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, "dash.conf"))))
|
||||
return dict(config_parser.items("all"))
|
||||
|
||||
def connect_JSON(config):
|
||||
"""Connect to a Dash Core 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'] = 19998 if testnet else 9998
|
||||
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 dashd 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(dashd):
|
||||
info = dashd.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: ")
|
||||
dashd.walletpassphrase(passphrase, 5)
|
||||
except:
|
||||
sys.stderr.write("Wrong passphrase\n")
|
||||
|
||||
info = dashd.getinfo()
|
||||
return int(info['unlocked_until']) > time.time()
|
||||
|
||||
def list_available(dashd):
|
||||
address_summary = dict()
|
||||
|
||||
address_to_account = dict()
|
||||
for info in dashd.listreceivedbyaddress(0):
|
||||
address_to_account[info["address"]] = info["account"]
|
||||
|
||||
unspent = dashd.listunspent(0)
|
||||
for output in unspent:
|
||||
# listunspent doesn't give addresses, so:
|
||||
rawtx = dashd.getrawtransaction(output['txid'], 1)
|
||||
vout = rawtx["vout"][output['vout']]
|
||||
pk = vout["scriptPubKey"]
|
||||
|
||||
# This code only deals with ordinary pay-to-dash-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(dashd, fromaddresses, toaddress, amount, fee):
|
||||
all_coins = list_available(dashd)
|
||||
|
||||
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 dashd.
|
||||
#
|
||||
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 = dashd.createrawtransaction(inputs, outputs)
|
||||
signed_rawtx = dashd.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(dashd, txinfo):
|
||||
result = Decimal("0.0")
|
||||
for vin in txinfo['vin']:
|
||||
in_info = dashd.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(dashd, txdata_hex, max_fee):
|
||||
class FeeError(RuntimeError):
|
||||
pass
|
||||
try:
|
||||
txinfo = dashd.decoderawtransaction(txdata_hex)
|
||||
total_in = compute_amount_in(dashd, 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 dashs from")
|
||||
parser.add_option("--to", dest="to", default=None,
|
||||
help="address to get send dashs 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 dash.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
|
||||
dashd = connect_JSON(config)
|
||||
|
||||
if options.amount is None:
|
||||
address_summary = list_available(dashd)
|
||||
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(dashd) == False:
|
||||
pass # Keep asking for passphrase until they get it right
|
||||
txdata = create_tx(dashd, options.fromaddresses.split(","), options.to, amount, fee)
|
||||
sanity_test_fee(dashd, txdata, amount*Decimal("0.01"))
|
||||
if options.dry_run:
|
||||
print(txdata)
|
||||
else:
|
||||
txid = dashd.sendrawtransaction(txdata)
|
||||
print(txid)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -1,3 +1,6 @@
|
||||
# Copyright (c) 2012 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
'''
|
||||
Bitcoin base58 encoding and decoding.
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2012 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
'''
|
||||
Generate valid and invalid base58 address and private key test vectors.
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/bin/bash
|
||||
# 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.
|
||||
|
||||
if [ -d "$1" ]; then
|
||||
cd "$1"
|
||||
|
@ -1,4 +1,8 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
INPUT=$(cat /dev/stdin)
|
||||
VALID=false
|
||||
REVSIG=false
|
||||
|
@ -1,4 +1,8 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
if ! [[ "$2" =~ ^(git@)?(www.)?github.com(:|/)dashpay/dash(.git)?$ ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
@ -1,4 +1,8 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
# Not technically POSIX-compliant due to use of "local", but almost every
|
||||
# shell anyone uses today supports it, so its probably fine
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
### This script attempts to download the signature file SHA256SUMS.asc from bitcoin.org
|
||||
### It first checks if the signature passes, and then downloads the files specified in
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import array
|
||||
import binascii
|
||||
|
@ -1,8 +1,8 @@
|
||||
package=expat
|
||||
$(package)_version=2.1.1
|
||||
$(package)_version=2.2.0
|
||||
$(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version)
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=aff584e5a2f759dcfc6d48671e9529f6afe1e30b0cd6a4cec200cbe3f793de67
|
||||
$(package)_sha256_hash=d9e50ff2d19b3538bd2127902a89987474e1a4db8e43a66a4d1a712ab9a504ff
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--disable-static
|
||||
|
@ -1,8 +1,8 @@
|
||||
package=fontconfig
|
||||
$(package)_version=2.11.1
|
||||
$(package)_version=2.12.1
|
||||
$(package)_download_path=http://www.freedesktop.org/software/fontconfig/release/
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=dc62447533bca844463a3c3fd4083b57c90f18a70506e7a9f4936b5a1e516a99
|
||||
$(package)_sha256_hash=b449a3e10c47e1d1c7a6ec6e2016cca73d3bd68fbbd4f0ae5cc6b573f7d6c7f3
|
||||
$(package)_dependencies=freetype expat
|
||||
|
||||
define $(package)_set_vars
|
||||
|
@ -1,8 +1,8 @@
|
||||
package=native_ccache
|
||||
$(package)_version=3.2.5
|
||||
$(package)_version=3.3.1
|
||||
$(package)_download_path=https://samba.org/ftp/ccache
|
||||
$(package)_file_name=ccache-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=7a553809e90faf9de3a23ee9c5b5f786cfd4836bf502744bedb824a24bee1097
|
||||
$(package)_sha256_hash=cb6e4bafbb19ba0a2ec43386b123a5f92a20e1e3384c071d5d13e0cb3c84bf73
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=
|
||||
|
@ -16,7 +16,7 @@ Then install [Homebrew](http://brew.sh).
|
||||
Dependencies
|
||||
----------------------
|
||||
|
||||
brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf --c++11 qt5 libevent
|
||||
brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config homebrew/versions/protobuf260 --c++11 qt5 libevent
|
||||
|
||||
NOTE: Building with Qt4 is still supported, however, doing so could result in a broken UI. Therefore, building with Qt5 is recommended.
|
||||
|
||||
|
@ -27,6 +27,7 @@ To build executables for Windows 32-bit:
|
||||
cd depends
|
||||
make HOST=i686-w64-mingw32 -j4
|
||||
cd ..
|
||||
./autogen.sh # not required when building from tarball
|
||||
./configure --prefix=`pwd`/depends/i686-w64-mingw32
|
||||
make
|
||||
|
||||
@ -35,6 +36,7 @@ To build executables for Windows 64-bit:
|
||||
cd depends
|
||||
make HOST=x86_64-w64-mingw32 -j4
|
||||
cd ..
|
||||
./autogen.sh # not required when building from tarball
|
||||
./configure --prefix=`pwd`/depends/x86_64-w64-mingw32
|
||||
make
|
||||
|
||||
|
@ -95,14 +95,14 @@ After creating the VM, we need to configure it.
|
||||
|
||||
- Click `Ok` twice to save.
|
||||
|
||||
Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.5.0/amd64/iso-cd/debian-8.5.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
|
||||
Get the [Debian 8.x net installer](http://cdimage.debian.org/mirror/cdimage/archive/8.5.0/amd64/iso-cd/debian-8.5.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](https://www.debian.org/CD/verify) using a SHA256 hashing tool, for example on
|
||||
Unixy OSes by entering the following in a terminal:
|
||||
|
||||
echo "ad4e8c27c561ad8248d5ebc1d36eb172f884057bfeb2c22ead823f59fa8c3dff debian-8.5.0-amd64-netinst.iso" | sha256sum -c
|
||||
# (must return OK)
|
||||
|
||||
Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded iso.
|
||||
Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded ISO.
|
||||
|
||||
![](gitian-building/select_startup_disk.png)
|
||||
|
||||
@ -344,8 +344,8 @@ There will be a lot of warnings printed during the build of the image. These can
|
||||
Getting and building the inputs
|
||||
--------------------------------
|
||||
|
||||
Follow the instructions in [doc/release-process.md](release-process.md#fetch-and-build-inputs-first-time-or-when-dependency-versions-change)
|
||||
in the Dash Core repository under 'Fetch and build inputs' to install sources which require
|
||||
Follow the instructions in [doc/release-process.md](release-process.md#fetch-and-create-inputs-first-time-or-when-dependency-versions-change)
|
||||
in the Dash Core repository under 'Fetch and create inputs' to install sources which require
|
||||
manual intervention. Also optionally follow the next step: 'Seed the Gitian sources cache
|
||||
and offline git repositories' which will fetch the remaining files required for building
|
||||
offline.
|
||||
|
@ -19,8 +19,7 @@ This is *not* a hard limit; only a threshold to minimize the outbound
|
||||
traffic. When the limit is about to be reached, the uploaded data is cut by no
|
||||
longer serving historic blocks (blocks older than one week).
|
||||
Keep in mind that new nodes require other nodes that are willing to serve
|
||||
historic blocks. **The recommended minimum is 144 blocks per day (max. 144MB
|
||||
per day)**
|
||||
historic blocks.
|
||||
|
||||
Whitelisted peers will never be disconnected, although their traffic counts for
|
||||
calculating the target.
|
||||
|
@ -6,7 +6,7 @@ The Dash Core project has been designed to support multiple localisations. This
|
||||
### Helping to translate (using Transifex)
|
||||
Transifex is setup to monitor the Github repo for updates, and when code containing new translations is found, Transifex will process any changes. It may take several hours after a pull-request has been merged, to appear in the Transifex web interface.
|
||||
|
||||
Multiple language support is critical in assisting Dash’s global adoption, and growth. One of Dash’s greatest strengths is cross-boarder money transfers, any help making that easier is greatly appreciated.
|
||||
Multiple language support is critical in assisting Dash’s global adoption, and growth. One of Dash’s greatest strengths is cross-border money transfers, any help making that easier is greatly appreciated.
|
||||
|
||||
See the [Transifex Dash project](https://www.transifex.com/projects/p/dash/) to assist in translations. You should also join the translation mailing list for announcements - see details below.
|
||||
|
||||
|
@ -225,8 +225,8 @@ def runtests():
|
||||
time_sum += duration
|
||||
|
||||
print('\n' + BOLD[1] + name + BOLD[0] + ":")
|
||||
print(stdout)
|
||||
print('stderr:\n' if not stderr == '' else '', stderr)
|
||||
print('' if passed else stdout + '\n', end='')
|
||||
print('' if stderr == '' else 'stderr:\n' + stderr + '\n', end='')
|
||||
results += "%s | %s | %s s\n" % (name.ljust(max_len_name), str(passed).ljust(6), duration)
|
||||
print("Pass: %s%s%s, Duration: %s s\n" % (BOLD[1], passed, BOLD[0], duration))
|
||||
results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(6), time_sum) + BOLD[0]
|
||||
|
@ -12,9 +12,15 @@ from test_framework.test_framework import BitcoinTestFramework
|
||||
|
||||
class CreateCache(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# Test network and test nodes are not required:
|
||||
self.num_nodes = 0
|
||||
self.nodes = []
|
||||
|
||||
def setup_network(self):
|
||||
# Don't setup any test nodes
|
||||
self.options.noshutdown = True
|
||||
pass
|
||||
|
||||
def run_test(self):
|
||||
pass
|
||||
|
@ -6,6 +6,7 @@
|
||||
from test_framework.mininode import *
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import re
|
||||
import time
|
||||
from test_framework.blocktools import create_block, create_coinbase
|
||||
|
||||
@ -21,6 +22,10 @@ VB_THRESHOLD = 108 # versionbits activation threshold for regtest
|
||||
VB_TOP_BITS = 0x20000000
|
||||
VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment
|
||||
|
||||
WARN_UNKNOWN_RULES_MINED = "Unknown block versions being mined! It's possible unknown rules are in effect"
|
||||
WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT)
|
||||
VB_PATTERN = re.compile("^Warning.*versionbit")
|
||||
|
||||
# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending
|
||||
# p2p messages to a node, generating the messages in the main testing logic.
|
||||
class TestNode(NodeConnCB):
|
||||
@ -65,16 +70,12 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
|
||||
# Open and close to create zero-length file
|
||||
with open(self.alert_filename, 'w') as f:
|
||||
with open(self.alert_filename, 'w') as _:
|
||||
pass
|
||||
self.node_options = ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, self.node_options))
|
||||
|
||||
import re
|
||||
self.vb_pattern = re.compile("^Warning.*versionbit")
|
||||
self.extra_args = [["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]]
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args)
|
||||
|
||||
# Send numblocks blocks via peer with nVersionToUse set.
|
||||
def send_blocks_with_version(self, peer, numblocks, nVersionToUse):
|
||||
@ -83,7 +84,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
||||
block_time = self.nodes[0].getblockheader(tip)["time"]+1
|
||||
tip = int(tip, 16)
|
||||
|
||||
for i in range(numblocks):
|
||||
for _ in range(numblocks):
|
||||
block = create_block(tip, create_coinbase(height+1), block_time)
|
||||
block.nVersion = nVersionToUse
|
||||
block.solve()
|
||||
@ -96,7 +97,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
||||
def test_versionbits_in_alert_file(self):
|
||||
with open(self.alert_filename, 'r') as f:
|
||||
alert_text = f.read()
|
||||
assert(self.vb_pattern.match(alert_text))
|
||||
assert(VB_PATTERN.match(alert_text))
|
||||
|
||||
def run_test(self):
|
||||
# Setup the p2p connection and start up the network thread.
|
||||
@ -122,8 +123,10 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
||||
# Fill rest of period with regular version blocks
|
||||
self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD + 1)
|
||||
# Check that we're not getting any versionbit-related errors in
|
||||
# getinfo()
|
||||
assert(not self.vb_pattern.match(self.nodes[0].getinfo()["errors"]))
|
||||
# get*info()
|
||||
assert(not VB_PATTERN.match(self.nodes[0].getinfo()["errors"]))
|
||||
assert(not VB_PATTERN.match(self.nodes[0].getmininginfo()["errors"]))
|
||||
assert(not VB_PATTERN.match(self.nodes[0].getnetworkinfo()["warnings"]))
|
||||
|
||||
# 3. Now build one period of blocks with >= VB_THRESHOLD blocks signaling
|
||||
# some unknown bit
|
||||
@ -132,8 +135,10 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
||||
# Might not get a versionbits-related alert yet, as we should
|
||||
# have gotten a different alert due to more than 51/100 blocks
|
||||
# being of unexpected version.
|
||||
# Check that getinfo() shows some kind of error.
|
||||
assert(len(self.nodes[0].getinfo()["errors"]) != 0)
|
||||
# Check that get*info() shows some kind of error.
|
||||
assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getinfo()["errors"])
|
||||
assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getmininginfo()["errors"])
|
||||
assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getnetworkinfo()["warnings"])
|
||||
|
||||
# Mine a period worth of expected blocks so the generic block-version warning
|
||||
# is cleared, and restart the node. This should move the versionbit state
|
||||
@ -142,20 +147,21 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
||||
stop_node(self.nodes[0], 0)
|
||||
wait_bitcoinds()
|
||||
# Empty out the alert file
|
||||
with open(self.alert_filename, 'w') as f:
|
||||
with open(self.alert_filename, 'w') as _:
|
||||
pass
|
||||
self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""])
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args)
|
||||
|
||||
# Connecting one block should be enough to generate an error.
|
||||
self.nodes[0].generate(1)
|
||||
assert(len(self.nodes[0].getinfo()["errors"]) != 0)
|
||||
assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getinfo()["errors"])
|
||||
assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["errors"])
|
||||
assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getnetworkinfo()["warnings"])
|
||||
stop_node(self.nodes[0], 0)
|
||||
wait_bitcoinds()
|
||||
self.test_versionbits_in_alert_file()
|
||||
|
||||
# Test framework expects the node to still be running...
|
||||
self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""])
|
||||
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args)
|
||||
|
||||
if __name__ == '__main__':
|
||||
VersionBitsWarningTest().main()
|
||||
|
@ -44,7 +44,7 @@ class RPCBindTest(BitcoinTestFramework):
|
||||
|
||||
def run_allowip_test(self, allow_ips, rpchost, rpcport):
|
||||
'''
|
||||
Start a node with rpcwallow IP, and request getinfo
|
||||
Start a node with rpcallow IP, and request getnetworkinfo
|
||||
at a non-localhost IP.
|
||||
'''
|
||||
base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips]
|
||||
@ -52,7 +52,7 @@ class RPCBindTest(BitcoinTestFramework):
|
||||
try:
|
||||
# connect to node through non-loopback interface
|
||||
node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0)
|
||||
node.getinfo()
|
||||
node.getnetworkinfo()
|
||||
finally:
|
||||
node = None # make sure connection will be garbage collected and closed
|
||||
stop_nodes(self.nodes)
|
||||
|
@ -55,7 +55,11 @@ log = logging.getLogger("BitcoinRPC")
|
||||
|
||||
class JSONRPCException(Exception):
|
||||
def __init__(self, rpc_error):
|
||||
Exception.__init__(self)
|
||||
try:
|
||||
errmsg = '%(message)s (%(code)i)' % rpc_error
|
||||
except (KeyError, TypeError):
|
||||
errmsg = ''
|
||||
Exception.__init__(self, errmsg)
|
||||
self.error = rpc_error
|
||||
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
# BlockStore: a helper class that keeps a map of blocks and implements
|
||||
# helper functions for responding to getheaders and getdata,
|
||||
# and for constructing a getheaders message
|
||||
|
@ -121,7 +121,8 @@ class BitcoinTestFramework(object):
|
||||
self.add_options(parser)
|
||||
(self.options, self.args) = parser.parse_args()
|
||||
|
||||
self.options.tmpdir += '/' + str(self.options.port_seed)
|
||||
# backup dir variable for removal at cleanup
|
||||
self.options.root, self.options.tmpdir = self.options.tmpdir, self.options.tmpdir + '/' + str(self.options.port_seed)
|
||||
|
||||
if self.options.trace_rpc:
|
||||
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
|
||||
@ -172,6 +173,8 @@ class BitcoinTestFramework(object):
|
||||
if not self.options.nocleanup and not self.options.noshutdown and success:
|
||||
print("Cleaning up")
|
||||
shutil.rmtree(self.options.tmpdir)
|
||||
if not os.listdir(self.options.root):
|
||||
os.rmdir(self.options.root)
|
||||
else:
|
||||
print("Not cleaning up dir %s" % self.options.tmpdir)
|
||||
|
||||
|
@ -18,9 +18,10 @@ class WalletTest (BitcoinTestFramework):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 4
|
||||
self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)]
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(3, self.options.tmpdir)
|
||||
self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3], redirect_stderr=True)
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
@ -155,7 +156,7 @@ class WalletTest (BitcoinTestFramework):
|
||||
txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
||||
sync_mempools(self.nodes)
|
||||
|
||||
self.nodes.append(start_node(3, self.options.tmpdir))
|
||||
self.nodes.append(start_node(3, self.options.tmpdir, self.extra_args[3], redirect_stderr=True))
|
||||
connect_nodes_bi(self.nodes, 0, 3)
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
|
@ -45,12 +45,12 @@ class WalletBackupTest(BitcoinTestFramework):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 4
|
||||
# nodes 1, 2,3 are spenders, let's give them a keypool=100
|
||||
self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []]
|
||||
|
||||
# This mirrors how the network was setup in the bash test
|
||||
def setup_network(self, split=False):
|
||||
# nodes 1, 2,3 are spenders, let's give them a keypool=100
|
||||
extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []]
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args)
|
||||
connect_nodes(self.nodes[0], 3)
|
||||
connect_nodes(self.nodes[1], 3)
|
||||
connect_nodes(self.nodes[2], 3)
|
||||
@ -79,6 +79,7 @@ class WalletBackupTest(BitcoinTestFramework):
|
||||
# Must sync mempools before mining.
|
||||
sync_mempools(self.nodes)
|
||||
self.nodes[3].generate(1)
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
# As above, this mirrors the original bash test.
|
||||
def start_three(self):
|
||||
|
@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2012-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
'''
|
||||
Extract _("...") strings for translation and convert to Qt stringdefs so that
|
||||
they can be picked up by Qt linguist.
|
||||
|
@ -1,35 +0,0 @@
|
||||
# Based on: http://code.google.com/p/ostinato/source/browse/protobuf.pri
|
||||
#
|
||||
# Qt qmake integration with Google Protocol Buffers compiler protoc
|
||||
#
|
||||
# To compile protocol buffers with qt qmake, specify PROTOS variable and
|
||||
# include this file
|
||||
#
|
||||
# Example:
|
||||
# PROTOS = a.proto b.proto
|
||||
# include(protobuf.pri)
|
||||
#
|
||||
# Set PROTO_PATH if you need to set the protoc --proto_path search path
|
||||
# Set PROTOC to the path to the protoc compiler if it is not in your $PATH
|
||||
#
|
||||
|
||||
isEmpty(PROTO_DIR):PROTO_DIR = .
|
||||
isEmpty(PROTOC):PROTOC = protoc
|
||||
|
||||
PROTOPATHS =
|
||||
for(p, PROTO_PATH):PROTOPATHS += --proto_path=$${p}
|
||||
|
||||
protobuf_decl.name = protobuf header
|
||||
protobuf_decl.input = PROTOS
|
||||
protobuf_decl.output = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.h
|
||||
protobuf_decl.commands = $${PROTOC} --cpp_out="$${PROTO_DIR}" $${PROTOPATHS} --proto_path=${QMAKE_FILE_IN_PATH} ${QMAKE_FILE_NAME}
|
||||
protobuf_decl.variable_out = GENERATED_FILES
|
||||
QMAKE_EXTRA_COMPILERS += protobuf_decl
|
||||
|
||||
protobuf_impl.name = protobuf implementation
|
||||
protobuf_impl.input = PROTOS
|
||||
protobuf_impl.output = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.cc
|
||||
protobuf_impl.depends = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.h
|
||||
protobuf_impl.commands = $$escape_expand(\\n)
|
||||
protobuf_impl.variable_out = GENERATED_SOURCES
|
||||
QMAKE_EXTRA_COMPILERS += protobuf_impl
|
@ -3,6 +3,7 @@ TESTS += qt/test/test_dash-qt
|
||||
|
||||
TEST_QT_MOC_CPP = \
|
||||
qt/test/moc_compattests.cpp \
|
||||
qt/test/moc_rpcnestedtests.cpp \
|
||||
qt/test/moc_trafficgraphdatatests.cpp \
|
||||
qt/test/moc_uritests.cpp
|
||||
|
||||
@ -12,6 +13,7 @@ endif
|
||||
|
||||
TEST_QT_H = \
|
||||
qt/test/compattests.h \
|
||||
qt/test/rpcnestedtests.h \
|
||||
qt/test/uritests.h \
|
||||
qt/test/paymentrequestdata.h \
|
||||
qt/test/paymentservertests.h \
|
||||
@ -22,6 +24,7 @@ qt_test_test_dash_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_
|
||||
|
||||
qt_test_test_dash_qt_SOURCES = \
|
||||
qt/test/compattests.cpp \
|
||||
qt/test/rpcnestedtests.cpp \
|
||||
qt/test/test_main.cpp \
|
||||
qt/test/uritests.cpp \
|
||||
qt/test/trafficgraphdatatests.cpp \
|
||||
|
@ -255,6 +255,11 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP
|
||||
int nId;
|
||||
CAddrInfo* pinfo = Find(addr, &nId);
|
||||
|
||||
// Do not set a penality for a source's self-announcement
|
||||
if (addr == source) {
|
||||
nTimePenalty = 0;
|
||||
}
|
||||
|
||||
if (pinfo) {
|
||||
// periodically update nTime
|
||||
bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
|
||||
|
@ -280,8 +280,8 @@ void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
|
||||
|
||||
void CRollingBloomFilter::insert(const uint256& hash)
|
||||
{
|
||||
vector<unsigned char> data(hash.begin(), hash.end());
|
||||
insert(data);
|
||||
vector<unsigned char> vData(hash.begin(), hash.end());
|
||||
insert(vData);
|
||||
}
|
||||
|
||||
bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
|
||||
@ -300,8 +300,8 @@ bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
|
||||
|
||||
bool CRollingBloomFilter::contains(const uint256& hash) const
|
||||
{
|
||||
vector<unsigned char> data(hash.begin(), hash.end());
|
||||
return contains(data);
|
||||
vector<unsigned char> vData(hash.begin(), hash.end());
|
||||
return contains(vData);
|
||||
}
|
||||
|
||||
void CRollingBloomFilter::reset()
|
||||
|
@ -131,17 +131,42 @@ static int AppInitRPC(int argc, char* argv[])
|
||||
/** Reply structure for request_done to fill in */
|
||||
struct HTTPReply
|
||||
{
|
||||
HTTPReply(): status(0), error(-1) {}
|
||||
|
||||
int status;
|
||||
int error;
|
||||
std::string body;
|
||||
};
|
||||
|
||||
const char *http_errorstring(int code)
|
||||
{
|
||||
switch(code) {
|
||||
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
|
||||
case EVREQ_HTTP_TIMEOUT:
|
||||
return "timeout reached";
|
||||
case EVREQ_HTTP_EOF:
|
||||
return "EOF reached";
|
||||
case EVREQ_HTTP_INVALID_HEADER:
|
||||
return "error while reading header, or invalid header";
|
||||
case EVREQ_HTTP_BUFFER_ERROR:
|
||||
return "error encountered while reading or writing";
|
||||
case EVREQ_HTTP_REQUEST_CANCEL:
|
||||
return "request was canceled";
|
||||
case EVREQ_HTTP_DATA_TOO_LONG:
|
||||
return "response body is larger than allowed";
|
||||
#endif
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void http_request_done(struct evhttp_request *req, void *ctx)
|
||||
{
|
||||
HTTPReply *reply = static_cast<HTTPReply*>(ctx);
|
||||
|
||||
if (req == NULL) {
|
||||
/* If req is NULL, it means an error occurred while connecting, but
|
||||
* I'm not sure how to find out which one. We also don't really care.
|
||||
/* If req is NULL, it means an error occurred while connecting: the
|
||||
* error code will have been passed to http_error_cb.
|
||||
*/
|
||||
reply->status = 0;
|
||||
return;
|
||||
@ -160,6 +185,14 @@ static void http_request_done(struct evhttp_request *req, void *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
|
||||
static void http_error_cb(enum evhttp_request_error err, void *ctx)
|
||||
{
|
||||
HTTPReply *reply = static_cast<HTTPReply*>(ctx);
|
||||
reply->error = err;
|
||||
}
|
||||
#endif
|
||||
|
||||
UniValue CallRPC(const string& strMethod, const UniValue& params)
|
||||
{
|
||||
std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT);
|
||||
@ -180,6 +213,9 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
|
||||
struct evhttp_request *req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII
|
||||
if (req == NULL)
|
||||
throw runtime_error("create http request failed");
|
||||
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
|
||||
evhttp_request_set_error_cb(req, http_error_cb);
|
||||
#endif
|
||||
|
||||
// Get credentials
|
||||
std::string strRPCUserColonPass;
|
||||
@ -219,7 +255,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
|
||||
event_base_free(base);
|
||||
|
||||
if (response.status == 0)
|
||||
throw CConnectionFailed("couldn't connect to server");
|
||||
throw CConnectionFailed(strprintf("couldn't connect to server (%d %s)", response.error, http_errorstring(response.error)));
|
||||
else if (response.status == HTTP_UNAUTHORIZED)
|
||||
throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
|
||||
else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
|
||||
|
80
src/init.cpp
80
src/init.cpp
@ -869,10 +869,7 @@ void InitParameterInteraction()
|
||||
if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) {
|
||||
if (SoftSetBoolArg("-whitelistrelay", false))
|
||||
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n", __func__);
|
||||
#ifdef ENABLE_WALLET
|
||||
if (SoftSetBoolArg("-walletbroadcast", false))
|
||||
LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
|
||||
#endif
|
||||
// walletbroadcast is disabled in CWallet::ParameterInteraction()
|
||||
}
|
||||
|
||||
// Forcing relay from whitelisted hosts implies we will accept relays from them in the first place.
|
||||
@ -970,12 +967,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
return InitError("Initializing networking failed");
|
||||
|
||||
#ifndef WIN32
|
||||
if (GetBoolArg("-sysperms", false)) {
|
||||
#ifdef ENABLE_WALLET
|
||||
if (!GetBoolArg("-disablewallet", false))
|
||||
return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
|
||||
#endif
|
||||
} else {
|
||||
if (!GetBoolArg("-sysperms", false)) {
|
||||
umask(077);
|
||||
}
|
||||
|
||||
@ -1003,15 +995,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
|
||||
// also see: InitParameterInteraction()
|
||||
|
||||
// if using block pruning, then disable txindex
|
||||
// if using block pruning, then disallow txindex
|
||||
if (GetArg("-prune", 0)) {
|
||||
if (GetBoolArg("-txindex", DEFAULT_TXINDEX))
|
||||
return InitError(_("Prune mode is incompatible with -txindex."));
|
||||
#ifdef ENABLE_WALLET
|
||||
if (GetBoolArg("-rescan", false)) {
|
||||
return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again."));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mapArgs.count("-devnet")) {
|
||||
@ -1116,9 +1103,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
|
||||
RegisterAllCoreRPCCommands(tableRPC);
|
||||
#ifdef ENABLE_WALLET
|
||||
bool fDisableWallet = GetBoolArg("-disablewallet", false);
|
||||
if (!fDisableWallet)
|
||||
RegisterWalletRPCCommands(tableRPC);
|
||||
RegisterWalletRPCCommands(tableRPC);
|
||||
#endif
|
||||
|
||||
nConnectTimeout = GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT);
|
||||
@ -1134,10 +1119,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
if (mapArgs.count("-minrelaytxfee"))
|
||||
{
|
||||
CAmount n = 0;
|
||||
if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0)
|
||||
::minRelayTxFee = CFeeRate(n);
|
||||
else
|
||||
if (!ParseMoney(mapArgs["-minrelaytxfee"], n))
|
||||
return InitError(AmountErrMsg("minrelaytxfee", mapArgs["-minrelaytxfee"]));
|
||||
// High fee check is done afterward in CWallet::ParameterInteraction()
|
||||
::minRelayTxFee = CFeeRate(n);
|
||||
}
|
||||
|
||||
fRequireStandard = !GetBoolArg("-acceptnonstdtxn", !Params().RequireStandard());
|
||||
@ -1256,29 +1241,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
|
||||
// ********************************************************* Step 5: Backup wallet and verify wallet database integrity
|
||||
#ifdef ENABLE_WALLET
|
||||
if (!fDisableWallet) {
|
||||
std::string strWarning;
|
||||
std::string strError;
|
||||
if (!CWallet::InitAutoBackup())
|
||||
return false;
|
||||
|
||||
nWalletBackups = GetArg("-createwalletbackups", 10);
|
||||
nWalletBackups = std::max(0, std::min(10, nWalletBackups));
|
||||
if (!CWallet::Verify())
|
||||
return false;
|
||||
|
||||
std::string strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
|
||||
|
||||
if(!AutoBackupWallet(NULL, strWalletFile, strWarning, strError)) {
|
||||
if (!strWarning.empty())
|
||||
InitWarning(strWarning);
|
||||
if (!strError.empty())
|
||||
return InitError(strError);
|
||||
}
|
||||
|
||||
if (!CWallet::Verify())
|
||||
return false;
|
||||
|
||||
// Initialize KeePass Integration
|
||||
keePassInt.init();
|
||||
|
||||
} // (!fDisableWallet)
|
||||
// Initialize KeePass Integration
|
||||
keePassInt.init();
|
||||
#endif // ENABLE_WALLET
|
||||
// ********************************************************* Step 6: network initialization
|
||||
// Note that we absolutely cannot open any actual connections
|
||||
@ -1287,7 +1257,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
// need to reindex later.
|
||||
|
||||
assert(!g_connman);
|
||||
g_connman = std::unique_ptr<CConnman>(new CConnman());
|
||||
g_connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max())));
|
||||
CConnman& connman = *g_connman;
|
||||
|
||||
peerLogic.reset(new PeerLogicValidation(&connman));
|
||||
@ -1432,8 +1402,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
pdsNotificationInterface = new CDSNotificationInterface(connman);
|
||||
RegisterValidationInterface(pdsNotificationInterface);
|
||||
|
||||
uint64_t nMaxOutboundLimit = 0; //unlimited unless -maxuploadtarget is set
|
||||
uint64_t nMaxOutboundTimeframe = MAX_UPLOAD_TIMEFRAME;
|
||||
|
||||
if (mapArgs.count("-maxuploadtarget")) {
|
||||
connman.SetMaxOutboundTarget(GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024);
|
||||
nMaxOutboundLimit = GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024;
|
||||
}
|
||||
|
||||
// ********************************************************* Step 7: load block chain
|
||||
@ -1623,17 +1596,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
|
||||
// ********************************************************* Step 8: load wallet
|
||||
#ifdef ENABLE_WALLET
|
||||
if (fDisableWallet) {
|
||||
pwalletMain = NULL;
|
||||
LogPrintf("Wallet disabled!\n");
|
||||
} else {
|
||||
CWallet::InitLoadWallet();
|
||||
if (!pwalletMain)
|
||||
return false;
|
||||
}
|
||||
#else // ENABLE_WALLET
|
||||
if (!CWallet::InitLoadWallet())
|
||||
return false;
|
||||
#else
|
||||
LogPrintf("No wallet support compiled in!\n");
|
||||
#endif // !ENABLE_WALLET
|
||||
#endif
|
||||
|
||||
// ********************************************************* Step 9: data directory maintenance
|
||||
|
||||
@ -1847,6 +1814,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
connOptions.nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
|
||||
connOptions.nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
|
||||
|
||||
connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe;
|
||||
connOptions.nMaxOutboundLimit = nMaxOutboundLimit;
|
||||
|
||||
if (!connman.Start(scheduler, strNodeError, connOptions))
|
||||
return InitError(strNodeError);
|
||||
|
||||
|
@ -243,12 +243,12 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
|
||||
bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const {
|
||||
out.nDepth = nDepth + 1;
|
||||
CKeyID id = key.GetPubKey().GetID();
|
||||
memcpy(&out.vchFingerprint[0], &id, 4);
|
||||
out.nChild = nChild;
|
||||
return key.Derive(out.key, out.chaincode, nChild, chaincode);
|
||||
out.nChild = _nChild;
|
||||
return key.Derive(out.key, out.chaincode, _nChild, chaincode);
|
||||
}
|
||||
|
||||
void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
|
||||
|
32
src/net.cpp
32
src/net.cpp
@ -70,6 +70,7 @@ const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
|
||||
constexpr const CConnman::CFullyConnectedOnly CConnman::FullyConnectedOnly;
|
||||
constexpr const CConnman::CAllNodes CConnman::AllNodes;
|
||||
|
||||
static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
|
||||
//
|
||||
// Global state variables
|
||||
//
|
||||
@ -411,7 +412,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
||||
addrman.Attempt(addrConnect, fCountFailure);
|
||||
|
||||
// Add node
|
||||
CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addrConnect, pszDest ? pszDest : "", false, true);
|
||||
CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), pszDest ? pszDest : "", false, true);
|
||||
|
||||
pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices);
|
||||
pnode->nTimeConnected = GetSystemTimeInSeconds();
|
||||
@ -1077,7 +1078,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
|
||||
return;
|
||||
}
|
||||
|
||||
CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addr, "", true);
|
||||
CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), "", true);
|
||||
pnode->fWhitelisted = whitelisted;
|
||||
GetNodeSignals().InitializeNode(pnode, *this);
|
||||
|
||||
@ -2127,7 +2128,7 @@ void CConnman::SetNetworkActive(bool active)
|
||||
uiInterface.NotifyNetworkActiveChanged(fNetworkActive);
|
||||
}
|
||||
|
||||
CConnman::CConnman()
|
||||
CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSeed1(nSeed1In)
|
||||
{
|
||||
fNetworkActive = true;
|
||||
setBannedIsDirty = false;
|
||||
@ -2153,9 +2154,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
|
||||
{
|
||||
nTotalBytesRecv = 0;
|
||||
nTotalBytesSent = 0;
|
||||
nMaxOutboundLimit = 0;
|
||||
nMaxOutboundTotalBytesSentInCycle = 0;
|
||||
nMaxOutboundTimeframe = 60*60*24; //1 day
|
||||
nMaxOutboundCycleStartTime = 0;
|
||||
|
||||
nRelevantServices = connOptions.nRelevantServices;
|
||||
@ -2167,6 +2166,9 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
|
||||
nSendBufferMaxSize = connOptions.nSendBufferMaxSize;
|
||||
nReceiveFloodSize = connOptions.nReceiveFloodSize;
|
||||
|
||||
nMaxOutboundLimit = connOptions.nMaxOutboundLimit;
|
||||
nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe;
|
||||
|
||||
SetBestHeight(connOptions.nBestHeight);
|
||||
|
||||
clientInterface = connOptions.uiInterface;
|
||||
@ -2220,7 +2222,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
|
||||
if (pnodeLocalHost == NULL) {
|
||||
CNetAddr local;
|
||||
LookupHost("127.0.0.1", local, false);
|
||||
pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices));
|
||||
pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices), 0);
|
||||
GetNodeSignals().InitializeNode(pnodeLocalHost, *this);
|
||||
}
|
||||
|
||||
@ -2518,11 +2520,7 @@ void CConnman::RecordBytesSent(uint64_t bytes)
|
||||
void CConnman::SetMaxOutboundTarget(uint64_t limit)
|
||||
{
|
||||
LOCK(cs_totalBytesSent);
|
||||
uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MaxBlockSize(true);
|
||||
nMaxOutboundLimit = limit;
|
||||
|
||||
if (limit > 0 && limit < recommendedMinimum)
|
||||
LogPrintf("Max outbound target is very small (%s bytes) and will be overshot. Recommended minimum is %s bytes.\n", nMaxOutboundLimit, recommendedMinimum);
|
||||
}
|
||||
|
||||
uint64_t CConnman::GetMaxOutboundTarget()
|
||||
@ -2622,9 +2620,9 @@ int CConnman::GetBestHeight() const
|
||||
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
|
||||
unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; }
|
||||
|
||||
CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn, bool fNetworkNodeIn) :
|
||||
CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, const std::string& addrNameIn, bool fInboundIn, bool fNetworkNodeIn) :
|
||||
addr(addrIn),
|
||||
nKeyedNetGroup(CalculateKeyedNetGroup(addrIn)),
|
||||
nKeyedNetGroup(nKeyedNetGroupIn),
|
||||
addrKnown(5000, 0.001),
|
||||
filterInventoryKnown(50000, 0.000001),
|
||||
nSendVersion(0)
|
||||
@ -2859,12 +2857,14 @@ void CConnman::ReleaseNodeVector(const std::vector<CNode*>& vecNodes)
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ uint64_t CNode::CalculateKeyedNetGroup(const CAddress& ad)
|
||||
CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id)
|
||||
{
|
||||
static const uint64_t k0 = GetRand(std::numeric_limits<uint64_t>::max());
|
||||
static const uint64_t k1 = GetRand(std::numeric_limits<uint64_t>::max());
|
||||
return CSipHasher(nSeed0, nSeed1).Write(id);
|
||||
}
|
||||
|
||||
uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& ad)
|
||||
{
|
||||
std::vector<unsigned char> vchNetGroup(ad.GetGroup());
|
||||
|
||||
return CSipHasher(k0, k1).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize();
|
||||
return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize();
|
||||
}
|
||||
|
18
src/net.h
18
src/net.h
@ -11,6 +11,7 @@
|
||||
#include "amount.h"
|
||||
#include "bloom.h"
|
||||
#include "compat.h"
|
||||
#include "hash.h"
|
||||
#include "limitedmap.h"
|
||||
#include "netaddress.h"
|
||||
#include "protocol.h"
|
||||
@ -80,6 +81,8 @@ static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ;
|
||||
static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125;
|
||||
/** The default for -maxuploadtarget. 0 = Unlimited */
|
||||
static const uint64_t DEFAULT_MAX_UPLOAD_TARGET = 0;
|
||||
/** The default timeframe for -maxuploadtarget. 1 day. */
|
||||
static const uint64_t MAX_UPLOAD_TIMEFRAME = 60 * 60 * 24;
|
||||
/** Default for blocks only*/
|
||||
static const bool DEFAULT_BLOCKSONLY = false;
|
||||
|
||||
@ -128,8 +131,10 @@ public:
|
||||
CClientUIInterface* uiInterface = nullptr;
|
||||
unsigned int nSendBufferMaxSize = 0;
|
||||
unsigned int nReceiveFloodSize = 0;
|
||||
uint64_t nMaxOutboundTimeframe = 0;
|
||||
uint64_t nMaxOutboundLimit = 0;
|
||||
};
|
||||
CConnman();
|
||||
CConnman(uint64_t seed0, uint64_t seed1);
|
||||
~CConnman();
|
||||
bool Start(CScheduler& scheduler, std::string& strNodeError, Options options);
|
||||
void Stop();
|
||||
@ -386,6 +391,8 @@ public:
|
||||
void SetBestHeight(int height);
|
||||
int GetBestHeight() const;
|
||||
|
||||
/** Get a unique deterministic randomizer. */
|
||||
CSipHasher GetDeterministicRandomizer(uint64_t id);
|
||||
|
||||
unsigned int GetReceiveFloodSize() const;
|
||||
private:
|
||||
@ -405,6 +412,8 @@ private:
|
||||
void ThreadDNSAddressSeed();
|
||||
void ThreadMnbRequestConnections();
|
||||
|
||||
uint64_t CalculateKeyedNetGroup(const CAddress& ad);
|
||||
|
||||
void WakeMessageHandler();
|
||||
|
||||
CNode* FindNode(const CNetAddr& ip);
|
||||
@ -491,6 +500,9 @@ private:
|
||||
std::atomic<int> nBestHeight;
|
||||
CClientUIInterface* clientInterface;
|
||||
|
||||
/** SipHasher seeds for deterministic randomness */
|
||||
const uint64_t nSeed0, nSeed1;
|
||||
|
||||
/** flag for waking the message processor. */
|
||||
bool fMsgProcWake;
|
||||
|
||||
@ -784,7 +796,7 @@ public:
|
||||
CAmount lastSentFeeFilter;
|
||||
int64_t nextSendTimeFeeFilter;
|
||||
|
||||
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false, bool fNetworkNodeIn = false);
|
||||
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, const std::string &addrNameIn = "", bool fInboundIn = false, bool fNetworkNodeIn = false);
|
||||
~CNode();
|
||||
|
||||
private:
|
||||
@ -793,9 +805,9 @@ private:
|
||||
CNode(const CNode&);
|
||||
void operator=(const CNode&);
|
||||
|
||||
static uint64_t CalculateKeyedNetGroup(const CAddress& ad);
|
||||
|
||||
uint64_t nLocalHostNonce;
|
||||
// Services offered to this peer
|
||||
ServiceFlags nLocalServices;
|
||||
int nMyStartingHeight;
|
||||
int nSendVersion;
|
||||
|
@ -70,6 +70,8 @@ map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_main);
|
||||
map<COutPoint, set<map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(cs_main);
|
||||
void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
static const uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL; // SHA256("main address relay")[0:8]
|
||||
|
||||
// Internal stuff
|
||||
namespace {
|
||||
/** Number of nodes with fSyncStarted. */
|
||||
@ -815,11 +817,9 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
|
||||
// Relay to a limited number of other nodes
|
||||
// Use deterministic randomness to send to the same nodes for 24 hours
|
||||
// at a time so the addrKnowns of the chosen nodes prevent repeats
|
||||
static const uint64_t salt0 = GetRand(std::numeric_limits<uint64_t>::max());
|
||||
static const uint64_t salt1 = GetRand(std::numeric_limits<uint64_t>::max());
|
||||
uint64_t hashAddr = addr.GetHash();
|
||||
multimap<uint64_t, CNode*> mapMix;
|
||||
const CSipHasher hasher = CSipHasher(salt0, salt1).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
|
||||
const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
|
||||
|
||||
auto sortfunc = [&mapMix, &hasher](CNode* pnode) {
|
||||
if (pnode->nVersion >= CADDR_TIME_VERSION) {
|
||||
@ -1754,9 +1754,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
}
|
||||
if (!fRejectedParents) {
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
||||
CInv inv(MSG_TX, txin.prevout.hash);
|
||||
pfrom->AddInventoryKnown(inv);
|
||||
if (!AlreadyHave(inv)) pfrom->AskFor(inv);
|
||||
CInv _inv(MSG_TX, txin.prevout.hash);
|
||||
pfrom->AddInventoryKnown(_inv);
|
||||
if (!AlreadyHave(_inv)) pfrom->AskFor(_inv);
|
||||
}
|
||||
AddOrphanTx(tx, pfrom->GetId());
|
||||
|
||||
@ -2402,9 +2402,9 @@ class CompareInvMempoolOrder
|
||||
{
|
||||
CTxMemPool *mp;
|
||||
public:
|
||||
CompareInvMempoolOrder(CTxMemPool *mempool)
|
||||
CompareInvMempoolOrder(CTxMemPool *_mempool)
|
||||
{
|
||||
mp = mempool;
|
||||
mp = _mempool;
|
||||
}
|
||||
|
||||
bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
|
||||
|
@ -264,12 +264,12 @@ void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
|
||||
pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE);
|
||||
}
|
||||
|
||||
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
|
||||
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
|
||||
out.nDepth = nDepth + 1;
|
||||
CKeyID id = pubkey.GetID();
|
||||
memcpy(&out.vchFingerprint[0], &id, 4);
|
||||
out.nChild = nChild;
|
||||
return pubkey.Derive(out.pubkey, out.chaincode, nChild, chaincode);
|
||||
out.nChild = _nChild;
|
||||
return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode);
|
||||
}
|
||||
|
||||
/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
|
||||
|
@ -88,9 +88,9 @@ public:
|
||||
}
|
||||
|
||||
//! Construct a public key from a byte vector.
|
||||
CPubKey(const std::vector<unsigned char>& vch)
|
||||
CPubKey(const std::vector<unsigned char>& _vch)
|
||||
{
|
||||
Set(vch.begin(), vch.end());
|
||||
Set(_vch.begin(), _vch.end());
|
||||
}
|
||||
|
||||
//! Simple read-only vector-like interface to the pubkey data.
|
||||
|
@ -22,12 +22,12 @@
|
||||
#include <QMessageBox>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode mode, Tabs tab, QWidget *parent) :
|
||||
AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AddressBookPage),
|
||||
model(0),
|
||||
mode(mode),
|
||||
tab(tab)
|
||||
mode(_mode),
|
||||
tab(_tab)
|
||||
{
|
||||
QString theme = GUIUtil::getThemeName();
|
||||
ui->setupUi(this);
|
||||
@ -108,14 +108,14 @@ AddressBookPage::~AddressBookPage()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AddressBookPage::setModel(AddressTableModel *model)
|
||||
void AddressBookPage::setModel(AddressTableModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
if(!model)
|
||||
this->model = _model;
|
||||
if(!_model)
|
||||
return;
|
||||
|
||||
proxyModel = new QSortFilterProxyModel(this);
|
||||
proxyModel->setSourceModel(model);
|
||||
proxyModel->setSourceModel(_model);
|
||||
proxyModel->setDynamicSortFilter(true);
|
||||
proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
@ -148,7 +148,7 @@ void AddressBookPage::setModel(AddressTableModel *model)
|
||||
this, SLOT(selectionChanged()));
|
||||
|
||||
// Select row for newly created address
|
||||
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(selectNewAddress(QModelIndex,int,int)));
|
||||
connect(_model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(selectNewAddress(QModelIndex,int,int)));
|
||||
|
||||
selectionChanged();
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ struct AddressTableEntry
|
||||
QString address;
|
||||
|
||||
AddressTableEntry() {}
|
||||
AddressTableEntry(Type type, const QString &label, const QString &address):
|
||||
type(type), label(label), address(address) {}
|
||||
AddressTableEntry(Type _type, const QString &_label, const QString &_address):
|
||||
type(_type), label(_label), address(_address) {}
|
||||
};
|
||||
|
||||
struct AddressTableEntryLessThan
|
||||
@ -74,8 +74,8 @@ public:
|
||||
QList<AddressTableEntry> cachedAddressTable;
|
||||
AddressTableModel *parent;
|
||||
|
||||
AddressTablePriv(CWallet *wallet, AddressTableModel *parent):
|
||||
wallet(wallet), parent(parent) {}
|
||||
AddressTablePriv(CWallet *_wallet, AddressTableModel *_parent):
|
||||
wallet(_wallet), parent(_parent) {}
|
||||
|
||||
void refreshAddressTable()
|
||||
{
|
||||
@ -165,8 +165,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) :
|
||||
QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0)
|
||||
AddressTableModel::AddressTableModel(CWallet *_wallet, WalletModel *parent) :
|
||||
QAbstractTableModel(parent),walletModel(parent),wallet(_wallet),priv(0)
|
||||
{
|
||||
columns << tr("Label") << tr("Address");
|
||||
priv = new AddressTablePriv(wallet, this);
|
||||
|
@ -19,10 +19,10 @@
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
|
||||
AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AskPassphraseDialog),
|
||||
mode(mode),
|
||||
mode(_mode),
|
||||
model(0),
|
||||
fCapsLock(false)
|
||||
{
|
||||
@ -85,9 +85,9 @@ AskPassphraseDialog::~AskPassphraseDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AskPassphraseDialog::setModel(WalletModel *model)
|
||||
void AskPassphraseDialog::setModel(WalletModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
this->model = _model;
|
||||
}
|
||||
|
||||
void AskPassphraseDialog::accept()
|
||||
|
@ -79,8 +79,9 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
|
||||
|
||||
const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
|
||||
|
||||
BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
|
||||
BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
enableWallet(false),
|
||||
clientModel(0),
|
||||
walletFrame(0),
|
||||
unitDisplayControl(0),
|
||||
@ -124,7 +125,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n
|
||||
modalOverlay(0),
|
||||
prevBlocks(0),
|
||||
spinnerFrame(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
/* Open CSS when configured */
|
||||
this->setStyleSheet(GUIUtil::loadStyleSheet());
|
||||
@ -133,10 +134,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n
|
||||
|
||||
QString windowTitle = tr(PACKAGE_NAME) + " - ";
|
||||
#ifdef ENABLE_WALLET
|
||||
/* if compiled with wallet support, -disablewallet can still disable the wallet */
|
||||
enableWallet = !GetBoolArg("-disablewallet", false);
|
||||
#else
|
||||
enableWallet = false;
|
||||
enableWallet = WalletModel::isWalletEnabled();
|
||||
#endif // ENABLE_WALLET
|
||||
if(enableWallet)
|
||||
{
|
||||
@ -161,13 +159,13 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n
|
||||
setUnifiedTitleAndToolBarOnMac(true);
|
||||
#endif
|
||||
|
||||
rpcConsole = new RPCConsole(platformStyle, 0);
|
||||
rpcConsole = new RPCConsole(_platformStyle, 0);
|
||||
helpMessageDialog = new HelpMessageDialog(this, HelpMessageDialog::cmdline);
|
||||
#ifdef ENABLE_WALLET
|
||||
if(enableWallet)
|
||||
{
|
||||
/** Create wallet frame*/
|
||||
walletFrame = new WalletFrame(platformStyle, this);
|
||||
walletFrame = new WalletFrame(_platformStyle, this);
|
||||
} else
|
||||
#endif // ENABLE_WALLET
|
||||
{
|
||||
@ -587,10 +585,10 @@ void BitcoinGUI::createToolBars()
|
||||
#endif // ENABLE_WALLET
|
||||
}
|
||||
|
||||
void BitcoinGUI::setClientModel(ClientModel *clientModel)
|
||||
void BitcoinGUI::setClientModel(ClientModel *_clientModel)
|
||||
{
|
||||
this->clientModel = clientModel;
|
||||
if(clientModel)
|
||||
this->clientModel = _clientModel;
|
||||
if(_clientModel)
|
||||
{
|
||||
// Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
|
||||
// while the client has not yet fully loaded
|
||||
@ -618,31 +616,32 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
|
||||
|
||||
// Keep up to date with client
|
||||
updateNetworkState();
|
||||
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
|
||||
connect(clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
|
||||
setNumConnections(_clientModel->getNumConnections());
|
||||
connect(_clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
|
||||
connect(_clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
|
||||
|
||||
modalOverlay->setKnownBestHeight(clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(clientModel->getHeaderTipTime()));
|
||||
setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL), false);
|
||||
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
|
||||
modalOverlay->setKnownBestHeight(_clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(_clientModel->getHeaderTipTime()));
|
||||
setNumBlocks(_clientModel->getNumBlocks(), _clientModel->getLastBlockDate(), _clientModel->getVerificationProgress(NULL), false);
|
||||
connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
|
||||
|
||||
connect(clientModel, SIGNAL(additionalDataSyncProgressChanged(double)), this, SLOT(setAdditionalDataSyncProgress(double)));
|
||||
connect(_clientModel, SIGNAL(additionalDataSyncProgressChanged(double)), this, SLOT(setAdditionalDataSyncProgress(double)));
|
||||
|
||||
// Receive and report messages from client model
|
||||
connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
|
||||
connect(_clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
|
||||
|
||||
// Show progress dialog
|
||||
connect(clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
|
||||
connect(_clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
|
||||
|
||||
rpcConsole->setClientModel(clientModel);
|
||||
rpcConsole->setClientModel(_clientModel);
|
||||
#ifdef ENABLE_WALLET
|
||||
if(walletFrame)
|
||||
{
|
||||
walletFrame->setClientModel(clientModel);
|
||||
walletFrame->setClientModel(_clientModel);
|
||||
}
|
||||
#endif // ENABLE_WALLET
|
||||
unitDisplayControl->setOptionsModel(clientModel->getOptionsModel());
|
||||
unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel());
|
||||
|
||||
OptionsModel* optionsModel = clientModel->getOptionsModel();
|
||||
OptionsModel* optionsModel = _clientModel->getOptionsModel();
|
||||
if(optionsModel)
|
||||
{
|
||||
// be aware of the tray icon disable state change reported by the OptionsModel object.
|
||||
@ -1509,17 +1508,17 @@ void UnitDisplayStatusBarControl::createContextMenu()
|
||||
}
|
||||
|
||||
/** Lets the control know about the Options Model (and its signals) */
|
||||
void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *optionsModel)
|
||||
void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel)
|
||||
{
|
||||
if (optionsModel)
|
||||
if (_optionsModel)
|
||||
{
|
||||
this->optionsModel = optionsModel;
|
||||
this->optionsModel = _optionsModel;
|
||||
|
||||
// be aware of a display unit change reported by the OptionsModel object.
|
||||
connect(optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int)));
|
||||
connect(_optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int)));
|
||||
|
||||
// initialize the display units label with the current value in the model.
|
||||
updateDisplayUnit(optionsModel->getDisplayUnit());
|
||||
updateDisplayUnit(_optionsModel->getDisplayUnit());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,9 +34,9 @@ static const int64_t nClientStartupTime = GetTime();
|
||||
static int64_t nLastHeaderTipUpdateNotification = 0;
|
||||
static int64_t nLastBlockTipUpdateNotification = 0;
|
||||
|
||||
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
|
||||
ClientModel::ClientModel(OptionsModel *_optionsModel, QObject *parent) :
|
||||
QObject(parent),
|
||||
optionsModel(optionsModel),
|
||||
optionsModel(_optionsModel),
|
||||
peerTableModel(0),
|
||||
cachedMasternodeCountString(""),
|
||||
banTableModel(0),
|
||||
|
@ -39,11 +39,11 @@ QList<CAmount> CoinControlDialog::payAmounts;
|
||||
CCoinControl* CoinControlDialog::coinControl = new CCoinControl();
|
||||
bool CoinControlDialog::fSubtractFeeFromAmount = false;
|
||||
|
||||
CoinControlDialog::CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||
CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::CoinControlDialog),
|
||||
model(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@ -163,15 +163,15 @@ CoinControlDialog::~CoinControlDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CoinControlDialog::setModel(WalletModel *model)
|
||||
void CoinControlDialog::setModel(WalletModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
this->model = _model;
|
||||
|
||||
if(model && model->getOptionsModel() && model->getAddressTableModel())
|
||||
if(_model && _model->getOptionsModel() && _model->getAddressTableModel())
|
||||
{
|
||||
updateView();
|
||||
updateLabelLocked();
|
||||
CoinControlDialog::updateLabels(model, this);
|
||||
CoinControlDialog::updateLabels(_model, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,15 +8,15 @@
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
CSVModelWriter::CSVModelWriter(const QString &filename, QObject *parent) :
|
||||
CSVModelWriter::CSVModelWriter(const QString &_filename, QObject *parent) :
|
||||
QObject(parent),
|
||||
filename(filename), model(0)
|
||||
filename(_filename), model(0)
|
||||
{
|
||||
}
|
||||
|
||||
void CSVModelWriter::setModel(const QAbstractItemModel *model)
|
||||
void CSVModelWriter::setModel(const QAbstractItemModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
this->model = _model;
|
||||
}
|
||||
|
||||
void CSVModelWriter::addColumn(const QString &title, int column, int role)
|
||||
|
@ -12,11 +12,11 @@
|
||||
#include <QDataWidgetMapper>
|
||||
#include <QMessageBox>
|
||||
|
||||
EditAddressDialog::EditAddressDialog(Mode mode, QWidget *parent) :
|
||||
EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::EditAddressDialog),
|
||||
mapper(0),
|
||||
mode(mode),
|
||||
mode(_mode),
|
||||
model(0)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
@ -50,13 +50,13 @@ EditAddressDialog::~EditAddressDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditAddressDialog::setModel(AddressTableModel *model)
|
||||
void EditAddressDialog::setModel(AddressTableModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
if(!model)
|
||||
this->model = _model;
|
||||
if(!_model)
|
||||
return;
|
||||
|
||||
mapper->setModel(model);
|
||||
mapper->setModel(_model);
|
||||
mapper->addMapping(ui->labelEdit, AddressTableModel::Label);
|
||||
mapper->addMapping(ui->addressEdit, AddressTableModel::Address);
|
||||
}
|
||||
@ -138,8 +138,8 @@ QString EditAddressDialog::getAddress() const
|
||||
return address;
|
||||
}
|
||||
|
||||
void EditAddressDialog::setAddress(const QString &address)
|
||||
void EditAddressDialog::setAddress(const QString &_address)
|
||||
{
|
||||
this->address = address;
|
||||
ui->addressEdit->setText(address);
|
||||
this->address = _address;
|
||||
ui->addressEdit->setText(_address);
|
||||
}
|
||||
|
@ -501,9 +501,9 @@ void SubstituteFonts(const QString& language)
|
||||
#endif
|
||||
}
|
||||
|
||||
ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent) :
|
||||
ToolTipToRichTextFilter::ToolTipToRichTextFilter(int _size_threshold, QObject *parent) :
|
||||
QObject(parent),
|
||||
size_threshold(size_threshold)
|
||||
size_threshold(_size_threshold)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -64,9 +64,9 @@ private:
|
||||
|
||||
#include "intro.moc"
|
||||
|
||||
FreespaceChecker::FreespaceChecker(Intro *intro)
|
||||
FreespaceChecker::FreespaceChecker(Intro *_intro)
|
||||
{
|
||||
this->intro = intro;
|
||||
this->intro = _intro;
|
||||
}
|
||||
|
||||
void FreespaceChecker::check()
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017 The Bitcoin Core developers
|
||||
// Copyright (c) 2016 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017 The Bitcoin Core developers
|
||||
// Copyright (c) 2016 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -62,9 +62,9 @@ void NetworkStyle::rotateColors(QImage& img, const int iconColorHueShift, const
|
||||
}
|
||||
|
||||
// titleAddText needs to be const char* for tr()
|
||||
NetworkStyle::NetworkStyle(const QString &appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *titleAddText):
|
||||
appName(appName),
|
||||
titleAddText(qApp->translate("SplashScreen", titleAddText))
|
||||
NetworkStyle::NetworkStyle(const QString &_appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *_titleAddText):
|
||||
appName(_appName),
|
||||
titleAddText(qApp->translate("SplashScreen", _titleAddText))
|
||||
{
|
||||
// Allow for separate UI settings for testnets
|
||||
QApplication::setApplicationName(appName);
|
||||
|
@ -33,17 +33,17 @@
|
||||
const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128;
|
||||
#endif
|
||||
|
||||
Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon, QWidget *parent) :
|
||||
QObject(parent),
|
||||
parent(parent),
|
||||
programName(programName),
|
||||
Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon, QWidget *_parent) :
|
||||
QObject(_parent),
|
||||
parent(_parent),
|
||||
programName(_programName),
|
||||
mode(None),
|
||||
trayIcon(trayicon)
|
||||
trayIcon(_trayIcon)
|
||||
#ifdef USE_DBUS
|
||||
,interface(0)
|
||||
#endif
|
||||
{
|
||||
if(trayicon && trayicon->supportsMessages())
|
||||
if(_trayIcon && _trayIcon->supportsMessages())
|
||||
{
|
||||
mode = QSystemTray;
|
||||
}
|
||||
|
@ -157,22 +157,22 @@ OptionsDialog::~OptionsDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void OptionsDialog::setModel(OptionsModel *model)
|
||||
void OptionsDialog::setModel(OptionsModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
this->model = _model;
|
||||
|
||||
if(model)
|
||||
if(_model)
|
||||
{
|
||||
/* check if client restart is needed and show persistent message */
|
||||
if (model->isRestartRequired())
|
||||
if (_model->isRestartRequired())
|
||||
showRestartWarning(true);
|
||||
|
||||
QString strLabel = model->getOverriddenByCommandLine();
|
||||
QString strLabel = _model->getOverriddenByCommandLine();
|
||||
if (strLabel.isEmpty())
|
||||
strLabel = tr("none");
|
||||
ui->overriddenByCommandLineLabel->setText(strLabel);
|
||||
|
||||
mapper->setModel(model);
|
||||
mapper->setModel(_model);
|
||||
setMapper();
|
||||
mapper->toFirst();
|
||||
|
||||
|
@ -38,7 +38,7 @@ class TxViewDelegate : public QAbstractItemDelegate
|
||||
Q_OBJECT
|
||||
public:
|
||||
TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr):
|
||||
QAbstractItemDelegate(parent), unit(BitcoinUnits::DASH),
|
||||
QAbstractItemDelegate(), unit(BitcoinUnits::DASH),
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
// https://en.bitcoin.it/wiki/Payment_Request
|
||||
//
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package payments;
|
||||
option java_package = "org.bitcoin.protocols.payments";
|
||||
option java_outer_classname = "Protos";
|
||||
|
@ -750,9 +750,9 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError>
|
||||
Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
|
||||
}
|
||||
|
||||
void PaymentServer::setOptionsModel(OptionsModel *optionsModel)
|
||||
void PaymentServer::setOptionsModel(OptionsModel *_optionsModel)
|
||||
{
|
||||
this->optionsModel = optionsModel;
|
||||
this->optionsModel = _optionsModel;
|
||||
}
|
||||
|
||||
void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
|
||||
|
@ -73,11 +73,11 @@ QIcon ColorizeIcon(const QString& filename, const QColor& colorbase)
|
||||
}
|
||||
|
||||
|
||||
PlatformStyle::PlatformStyle(const QString &name, bool imagesOnButtons, bool colorizeIcons, bool useExtraSpacing):
|
||||
name(name),
|
||||
imagesOnButtons(imagesOnButtons),
|
||||
colorizeIcons(colorizeIcons),
|
||||
useExtraSpacing(useExtraSpacing),
|
||||
PlatformStyle::PlatformStyle(const QString &_name, bool _imagesOnButtons, bool _colorizeIcons, bool _useExtraSpacing):
|
||||
name(_name),
|
||||
imagesOnButtons(_imagesOnButtons),
|
||||
colorizeIcons(_colorizeIcons),
|
||||
useExtraSpacing(_useExtraSpacing),
|
||||
singleColor(0,0,0),
|
||||
textColor(0,0,0)
|
||||
{
|
||||
|
@ -15,14 +15,14 @@ QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) :
|
||||
connect(this, SIGNAL(textChanged(QString)), this, SLOT(markValid()));
|
||||
}
|
||||
|
||||
void QValidatedLineEdit::setValid(bool valid)
|
||||
void QValidatedLineEdit::setValid(bool _valid)
|
||||
{
|
||||
if(valid == this->valid)
|
||||
if(_valid == this->valid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(valid)
|
||||
if(_valid)
|
||||
{
|
||||
setStyleSheet("");
|
||||
}
|
||||
@ -30,7 +30,7 @@ void QValidatedLineEdit::setValid(bool valid)
|
||||
{
|
||||
setStyleSheet(STYLE_INVALID);
|
||||
}
|
||||
this->valid = valid;
|
||||
this->valid = _valid;
|
||||
}
|
||||
|
||||
void QValidatedLineEdit::focusInEvent(QFocusEvent *evt)
|
||||
|
@ -20,9 +20,9 @@ void QValueComboBox::setValue(const QVariant &value)
|
||||
setCurrentIndex(findData(value, role));
|
||||
}
|
||||
|
||||
void QValueComboBox::setRole(int role)
|
||||
void QValueComboBox::setRole(int _role)
|
||||
{
|
||||
this->role = role;
|
||||
this->role = _role;
|
||||
}
|
||||
|
||||
void QValueComboBox::handleSelectionChanged(int idx)
|
||||
|
@ -22,17 +22,17 @@
|
||||
#include <QScrollBar>
|
||||
#include <QTextDocument>
|
||||
|
||||
ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||
ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ReceiveCoinsDialog),
|
||||
columnResizingFixer(0),
|
||||
model(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
QString theme = GUIUtil::getThemeName();
|
||||
|
||||
if (!platformStyle->getImagesOnButtons()) {
|
||||
if (!_platformStyle->getImagesOnButtons()) {
|
||||
ui->clearButton->setIcon(QIcon());
|
||||
ui->receiveButton->setIcon(QIcon());
|
||||
ui->showRequestButton->setIcon(QIcon());
|
||||
@ -67,21 +67,21 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidg
|
||||
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
|
||||
}
|
||||
|
||||
void ReceiveCoinsDialog::setModel(WalletModel *model)
|
||||
void ReceiveCoinsDialog::setModel(WalletModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
this->model = _model;
|
||||
|
||||
if(model && model->getOptionsModel())
|
||||
if(_model && _model->getOptionsModel())
|
||||
{
|
||||
model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder);
|
||||
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
_model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder);
|
||||
connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
updateDisplayUnit();
|
||||
|
||||
QTableView* tableView = ui->recentRequestsView;
|
||||
|
||||
tableView->verticalHeader()->hide();
|
||||
tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
tableView->setModel(model->getRecentRequestsTableModel());
|
||||
tableView->setModel(_model->getRecentRequestsTableModel());
|
||||
tableView->setAlternatingRowColors(true);
|
||||
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
|
||||
|
@ -109,20 +109,20 @@ ReceiveRequestDialog::~ReceiveRequestDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ReceiveRequestDialog::setModel(OptionsModel *model)
|
||||
void ReceiveRequestDialog::setModel(OptionsModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
this->model = _model;
|
||||
|
||||
if (model)
|
||||
connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(update()));
|
||||
if (_model)
|
||||
connect(_model, SIGNAL(displayUnitChanged(int)), this, SLOT(update()));
|
||||
|
||||
// update the display unit if necessary
|
||||
update();
|
||||
}
|
||||
|
||||
void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &info)
|
||||
void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &_info)
|
||||
{
|
||||
this->info = info;
|
||||
this->info = _info;
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
FRAMEDIR=$(dirname $0)
|
||||
for i in {0..35}
|
||||
do
|
||||
|
@ -93,8 +93,8 @@ class QtRPCTimerBase: public QObject, public RPCTimerBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QtRPCTimerBase(boost::function<void(void)>& func, int64_t millis):
|
||||
func(func)
|
||||
QtRPCTimerBase(boost::function<void(void)>& _func, int64_t millis):
|
||||
func(_func)
|
||||
{
|
||||
timer.setSingleShot(true);
|
||||
connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
@ -123,9 +123,11 @@ public:
|
||||
#include "rpcconsole.moc"
|
||||
|
||||
/**
|
||||
* Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
|
||||
* Split shell command line into a list of arguments and execute the command(s).
|
||||
* Aims to emulate \c bash and friends.
|
||||
*
|
||||
* - Arguments are delimited with whitespace
|
||||
* - Command nesting is possible with brackets [example: validateaddress(getnewaddress())]
|
||||
* - Arguments are delimited with whitespace or comma
|
||||
* - Extra whitespace at the beginning and end and between arguments will be ignored
|
||||
* - Text can be "double" or 'single' quoted
|
||||
* - The backslash \c \ is used as escape character
|
||||
@ -133,11 +135,15 @@ public:
|
||||
* - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
|
||||
* - Within single quotes, no escaping is possible and no special interpretation takes place
|
||||
*
|
||||
* @param[out] args Parsed arguments will be appended to this list
|
||||
* @param[out] result stringified Result from the executed command(chain)
|
||||
* @param[in] strCommand Command line to split
|
||||
*/
|
||||
bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
|
||||
|
||||
bool RPCConsole::RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand)
|
||||
{
|
||||
std::vector< std::vector<std::string> > stack;
|
||||
stack.push_back(std::vector<std::string>());
|
||||
|
||||
enum CmdParseState
|
||||
{
|
||||
STATE_EATING_SPACES,
|
||||
@ -145,95 +151,180 @@ bool parseCommandLine(std::vector<std::string> &args, const std::string &strComm
|
||||
STATE_SINGLEQUOTED,
|
||||
STATE_DOUBLEQUOTED,
|
||||
STATE_ESCAPE_OUTER,
|
||||
STATE_ESCAPE_DOUBLEQUOTED
|
||||
STATE_ESCAPE_DOUBLEQUOTED,
|
||||
STATE_COMMAND_EXECUTED,
|
||||
STATE_COMMAND_EXECUTED_INNER
|
||||
} state = STATE_EATING_SPACES;
|
||||
std::string curarg;
|
||||
Q_FOREACH(char ch, strCommand)
|
||||
UniValue lastResult;
|
||||
|
||||
std::string strCommandTerminated = strCommand;
|
||||
if (strCommandTerminated.back() != '\n')
|
||||
strCommandTerminated += "\n";
|
||||
for(char ch: strCommandTerminated)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case STATE_ARGUMENT: // In or after argument
|
||||
case STATE_EATING_SPACES: // Handle runs of whitespace
|
||||
switch(ch)
|
||||
case STATE_COMMAND_EXECUTED_INNER:
|
||||
case STATE_COMMAND_EXECUTED:
|
||||
{
|
||||
case '"': state = STATE_DOUBLEQUOTED; break;
|
||||
case '\'': state = STATE_SINGLEQUOTED; break;
|
||||
case '\\': state = STATE_ESCAPE_OUTER; break;
|
||||
case ' ': case '\n': case '\t':
|
||||
if(state == STATE_ARGUMENT) // Space ends argument
|
||||
bool breakParsing = true;
|
||||
switch(ch)
|
||||
{
|
||||
args.push_back(curarg);
|
||||
curarg.clear();
|
||||
case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break;
|
||||
default:
|
||||
if (state == STATE_COMMAND_EXECUTED_INNER)
|
||||
{
|
||||
if (ch != ']')
|
||||
{
|
||||
// append char to the current argument (which is also used for the query command)
|
||||
curarg += ch;
|
||||
break;
|
||||
}
|
||||
if (curarg.size())
|
||||
{
|
||||
// if we have a value query, query arrays with index and objects with a string key
|
||||
UniValue subelement;
|
||||
if (lastResult.isArray())
|
||||
{
|
||||
for(char argch: curarg)
|
||||
if (!std::isdigit(argch))
|
||||
throw std::runtime_error("Invalid result query");
|
||||
subelement = lastResult[atoi(curarg.c_str())];
|
||||
}
|
||||
else if (lastResult.isObject())
|
||||
subelement = find_value(lastResult, curarg);
|
||||
else
|
||||
throw std::runtime_error("Invalid result query"); //no array or object: abort
|
||||
lastResult = subelement;
|
||||
}
|
||||
|
||||
state = STATE_COMMAND_EXECUTED;
|
||||
break;
|
||||
}
|
||||
// don't break parsing when the char is required for the next argument
|
||||
breakParsing = false;
|
||||
|
||||
// pop the stack and return the result to the current command arguments
|
||||
stack.pop_back();
|
||||
|
||||
// don't stringify the json in case of a string to avoid doublequotes
|
||||
if (lastResult.isStr())
|
||||
curarg = lastResult.get_str();
|
||||
else
|
||||
curarg = lastResult.write(2);
|
||||
|
||||
// if we have a non empty result, use it as stack argument otherwise as general result
|
||||
if (curarg.size())
|
||||
{
|
||||
if (stack.size())
|
||||
stack.back().push_back(curarg);
|
||||
else
|
||||
strResult = curarg;
|
||||
}
|
||||
curarg.clear();
|
||||
// assume eating space state
|
||||
state = STATE_EATING_SPACES;
|
||||
}
|
||||
state = STATE_EATING_SPACES;
|
||||
if (breakParsing)
|
||||
break;
|
||||
}
|
||||
case STATE_ARGUMENT: // In or after argument
|
||||
case STATE_EATING_SPACES: // Handle runs of whitespace
|
||||
switch(ch)
|
||||
{
|
||||
case '"': state = STATE_DOUBLEQUOTED; break;
|
||||
case '\'': state = STATE_SINGLEQUOTED; break;
|
||||
case '\\': state = STATE_ESCAPE_OUTER; break;
|
||||
case '(': case ')': case '\n':
|
||||
if (state == STATE_ARGUMENT)
|
||||
{
|
||||
if (ch == '(' && stack.size() && stack.back().size() > 0)
|
||||
stack.push_back(std::vector<std::string>());
|
||||
if (curarg.size())
|
||||
{
|
||||
// don't allow commands after executed commands on baselevel
|
||||
if (!stack.size())
|
||||
throw std::runtime_error("Invalid Syntax");
|
||||
stack.back().push_back(curarg);
|
||||
}
|
||||
curarg.clear();
|
||||
state = STATE_EATING_SPACES;
|
||||
}
|
||||
if ((ch == ')' || ch == '\n') && stack.size() > 0)
|
||||
{
|
||||
std::string strPrint;
|
||||
// Convert argument list to JSON objects in method-dependent way,
|
||||
// and pass it along with the method name to the dispatcher.
|
||||
lastResult = tableRPC.execute(stack.back()[0], RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end())));
|
||||
|
||||
state = STATE_COMMAND_EXECUTED;
|
||||
curarg.clear();
|
||||
}
|
||||
break;
|
||||
case ' ': case ',': case '\t':
|
||||
if(state == STATE_ARGUMENT) // Space ends argument
|
||||
{
|
||||
if (curarg.size())
|
||||
stack.back().push_back(curarg);
|
||||
curarg.clear();
|
||||
}
|
||||
state = STATE_EATING_SPACES;
|
||||
break;
|
||||
default: curarg += ch; state = STATE_ARGUMENT;
|
||||
}
|
||||
break;
|
||||
default: curarg += ch; state = STATE_ARGUMENT;
|
||||
}
|
||||
break;
|
||||
case STATE_SINGLEQUOTED: // Single-quoted string
|
||||
switch(ch)
|
||||
case STATE_SINGLEQUOTED: // Single-quoted string
|
||||
switch(ch)
|
||||
{
|
||||
case '\'': state = STATE_ARGUMENT; break;
|
||||
default: curarg += ch;
|
||||
case '\'': state = STATE_ARGUMENT; break;
|
||||
default: curarg += ch;
|
||||
}
|
||||
break;
|
||||
case STATE_DOUBLEQUOTED: // Double-quoted string
|
||||
switch(ch)
|
||||
break;
|
||||
case STATE_DOUBLEQUOTED: // Double-quoted string
|
||||
switch(ch)
|
||||
{
|
||||
case '"': state = STATE_ARGUMENT; break;
|
||||
case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
|
||||
default: curarg += ch;
|
||||
case '"': state = STATE_ARGUMENT; break;
|
||||
case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
|
||||
default: curarg += ch;
|
||||
}
|
||||
break;
|
||||
case STATE_ESCAPE_OUTER: // '\' outside quotes
|
||||
curarg += ch; state = STATE_ARGUMENT;
|
||||
break;
|
||||
case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
|
||||
if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
|
||||
curarg += ch; state = STATE_DOUBLEQUOTED;
|
||||
break;
|
||||
break;
|
||||
case STATE_ESCAPE_OUTER: // '\' outside quotes
|
||||
curarg += ch; state = STATE_ARGUMENT;
|
||||
break;
|
||||
case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
|
||||
if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
|
||||
curarg += ch; state = STATE_DOUBLEQUOTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch(state) // final state
|
||||
{
|
||||
case STATE_EATING_SPACES:
|
||||
return true;
|
||||
case STATE_ARGUMENT:
|
||||
args.push_back(curarg);
|
||||
return true;
|
||||
default: // ERROR to end in one of the other states
|
||||
return false;
|
||||
case STATE_COMMAND_EXECUTED:
|
||||
if (lastResult.isStr())
|
||||
strResult = lastResult.get_str();
|
||||
else
|
||||
strResult = lastResult.write(2);
|
||||
case STATE_ARGUMENT:
|
||||
case STATE_EATING_SPACES:
|
||||
return true;
|
||||
default: // ERROR to end in one of the other states
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RPCExecutor::request(const QString &command)
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
if(!parseCommandLine(args, command.toStdString()))
|
||||
{
|
||||
Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
|
||||
return;
|
||||
}
|
||||
if(args.empty())
|
||||
return; // Nothing to do
|
||||
try
|
||||
{
|
||||
std::string strPrint;
|
||||
// Convert argument list to JSON objects in method-dependent way,
|
||||
// and pass it along with the method name to the dispatcher.
|
||||
UniValue result = tableRPC.execute(
|
||||
args[0],
|
||||
RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));
|
||||
|
||||
// Format result reply
|
||||
if (result.isNull())
|
||||
strPrint = "";
|
||||
else if (result.isStr())
|
||||
strPrint = result.get_str();
|
||||
else
|
||||
strPrint = result.write(2);
|
||||
|
||||
Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
|
||||
std::string result;
|
||||
std::string executableCommand = command.toStdString() + "\n";
|
||||
if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand))
|
||||
{
|
||||
Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
|
||||
return;
|
||||
}
|
||||
Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result));
|
||||
}
|
||||
catch (UniValue& objError)
|
||||
{
|
||||
@ -254,12 +345,12 @@ void RPCExecutor::request(const QString &command)
|
||||
}
|
||||
}
|
||||
|
||||
RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||
RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::RPCConsole),
|
||||
clientModel(0),
|
||||
historyPtr(0),
|
||||
platformStyle(platformStyle),
|
||||
platformStyle(_platformStyle),
|
||||
peersTableContextMenu(0),
|
||||
banTableContextMenu(0),
|
||||
consoleFontSize(0)
|
||||
|
@ -37,6 +37,8 @@ public:
|
||||
explicit RPCConsole(const PlatformStyle *platformStyle, QWidget *parent);
|
||||
~RPCConsole();
|
||||
|
||||
static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand);
|
||||
|
||||
void setClientModel(ClientModel *model);
|
||||
|
||||
enum MessageClass {
|
||||
|
@ -33,19 +33,19 @@
|
||||
|
||||
#define SEND_CONFIRM_DELAY 3
|
||||
|
||||
SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||
SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::SendCoinsDialog),
|
||||
clientModel(0),
|
||||
model(0),
|
||||
fNewRecipientAllowed(true),
|
||||
fFeeMinimized(true),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
QString theme = GUIUtil::getThemeName();
|
||||
|
||||
if (!platformStyle->getImagesOnButtons()) {
|
||||
if (!_platformStyle->getImagesOnButtons()) {
|
||||
ui->addButton->setIcon(QIcon());
|
||||
ui->clearButton->setIcon(QIcon());
|
||||
ui->sendButton->setIcon(QIcon());
|
||||
@ -146,40 +146,40 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *pa
|
||||
minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool());
|
||||
}
|
||||
|
||||
void SendCoinsDialog::setClientModel(ClientModel *clientModel)
|
||||
void SendCoinsDialog::setClientModel(ClientModel *_clientModel)
|
||||
{
|
||||
this->clientModel = clientModel;
|
||||
this->clientModel = _clientModel;
|
||||
|
||||
if (clientModel) {
|
||||
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(updateSmartFeeLabel()));
|
||||
if (_clientModel) {
|
||||
connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(updateSmartFeeLabel()));
|
||||
}
|
||||
}
|
||||
|
||||
void SendCoinsDialog::setModel(WalletModel *model)
|
||||
void SendCoinsDialog::setModel(WalletModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
this->model = _model;
|
||||
|
||||
if(model && model->getOptionsModel())
|
||||
if(_model && _model->getOptionsModel())
|
||||
{
|
||||
for(int i = 0; i < ui->entries->count(); ++i)
|
||||
{
|
||||
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
|
||||
if(entry)
|
||||
{
|
||||
entry->setModel(model);
|
||||
entry->setModel(_model);
|
||||
}
|
||||
}
|
||||
|
||||
setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), model->getAnonymizedBalance(),
|
||||
model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance());
|
||||
connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)));
|
||||
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
setBalance(_model->getBalance(), _model->getUnconfirmedBalance(), _model->getImmatureBalance(), _model->getAnonymizedBalance(),
|
||||
_model->getWatchBalance(), _model->getWatchUnconfirmedBalance(), _model->getWatchImmatureBalance());
|
||||
connect(_model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)));
|
||||
connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
updateDisplayUnit();
|
||||
|
||||
// Coin Control
|
||||
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels()));
|
||||
connect(model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool)));
|
||||
ui->frameCoinControl->setVisible(model->getOptionsModel()->getCoinControlFeatures());
|
||||
connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels()));
|
||||
connect(_model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool)));
|
||||
ui->frameCoinControl->setVisible(_model->getOptionsModel()->getCoinControlFeatures());
|
||||
coinControlUpdateLabels();
|
||||
|
||||
// fee section
|
||||
@ -941,9 +941,9 @@ void SendCoinsDialog::coinControlUpdateLabels()
|
||||
}
|
||||
}
|
||||
|
||||
SendConfirmationDialog::SendConfirmationDialog(const QString &title, const QString &text, int secDelay,
|
||||
SendConfirmationDialog::SendConfirmationDialog(const QString &title, const QString &text, int _secDelay,
|
||||
QWidget *parent) :
|
||||
QMessageBox(QMessageBox::Question, title, text, QMessageBox::Yes | QMessageBox::Cancel, parent), secDelay(secDelay)
|
||||
QMessageBox(QMessageBox::Question, title, text, QMessageBox::Yes | QMessageBox::Cancel, parent), secDelay(_secDelay)
|
||||
{
|
||||
setDefaultButton(QMessageBox::Cancel);
|
||||
yesButton = button(QMessageBox::Yes);
|
||||
|
@ -16,11 +16,11 @@
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
|
||||
SendCoinsEntry::SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||
SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *parent) :
|
||||
QStackedWidget(parent),
|
||||
ui(new Ui::SendCoinsEntry),
|
||||
model(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@ -83,12 +83,12 @@ void SendCoinsEntry::on_payTo_textChanged(const QString &address)
|
||||
updateLabel(address);
|
||||
}
|
||||
|
||||
void SendCoinsEntry::setModel(WalletModel *model)
|
||||
void SendCoinsEntry::setModel(WalletModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
this->model = _model;
|
||||
|
||||
if (model && model->getOptionsModel())
|
||||
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
if (_model && _model->getOptionsModel())
|
||||
connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
||||
|
||||
clear();
|
||||
}
|
||||
|
@ -21,11 +21,11 @@
|
||||
|
||||
#include <QClipboard>
|
||||
|
||||
SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||
SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::SignVerifyMessageDialog),
|
||||
model(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@ -73,9 +73,9 @@ SignVerifyMessageDialog::~SignVerifyMessageDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SignVerifyMessageDialog::setModel(WalletModel *model)
|
||||
void SignVerifyMessageDialog::setModel(WalletModel *_model)
|
||||
{
|
||||
this->model = model;
|
||||
this->model = _model;
|
||||
}
|
||||
|
||||
void SignVerifyMessageDialog::setAddress_SM(const QString &address)
|
||||
|
93
src/qt/test/rpcnestedtests.cpp
Normal file
93
src/qt/test/rpcnestedtests.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2016 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "rpcnestedtests.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "validation.h"
|
||||
#include "rpc/register.h"
|
||||
#include "rpc/server.h"
|
||||
#include "rpcconsole.h"
|
||||
#include "test/testutil.h"
|
||||
#include "univalue.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
void RPCNestedTests::rpcNestedTests()
|
||||
{
|
||||
UniValue jsonRPCError;
|
||||
|
||||
// do some test setup
|
||||
// could be moved to a more generic place when we add more tests on QT level
|
||||
const CChainParams& chainparams = Params();
|
||||
RegisterAllCoreRPCCommands(tableRPC);
|
||||
ClearDatadirCache();
|
||||
std::string path = QDir::tempPath().toStdString() + "/" + strprintf("test_bitcoin_qt_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
|
||||
QDir dir(QString::fromStdString(path));
|
||||
dir.mkpath(".");
|
||||
mapArgs["-datadir"] = path;
|
||||
//mempool.setSanityCheck(1.0);
|
||||
pblocktree = new CBlockTreeDB(1 << 20, true);
|
||||
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
|
||||
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
|
||||
InitBlockIndex(chainparams);
|
||||
{
|
||||
CValidationState state;
|
||||
bool ok = ActivateBestChain(state, chainparams);
|
||||
QVERIFY(ok);
|
||||
}
|
||||
|
||||
SetRPCWarmupFinished();
|
||||
|
||||
std::string result;
|
||||
std::string result2;
|
||||
RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[chain]"); //simple result filtering with path
|
||||
QVERIFY(result=="main");
|
||||
|
||||
RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())"); //simple 2 level nesting
|
||||
RPCConsole::RPCExecuteCommandLine(result, "getblock(getblock(getbestblockhash())[hash], true)");
|
||||
|
||||
RPCConsole::RPCExecuteCommandLine(result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter
|
||||
|
||||
RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo");
|
||||
QVERIFY(result.substr(0,1) == "{");
|
||||
|
||||
RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()");
|
||||
QVERIFY(result.substr(0,1) == "{");
|
||||
|
||||
RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo "); //whitespace at the end will be tolerated
|
||||
QVERIFY(result.substr(0,1) == "{");
|
||||
|
||||
#if QT_VERSION >= 0x050300
|
||||
// do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3)
|
||||
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
|
||||
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
|
||||
(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments
|
||||
(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()()()")); //tolerate non command brackts
|
||||
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo(True)"), UniValue); //invalid argument
|
||||
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "a(getblockchaininfo(True))"), UniValue); //method not found
|
||||
#endif
|
||||
|
||||
(RPCConsole::RPCExecuteCommandLine(result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child contaning the quotes in the key
|
||||
QVERIFY(result == "null");
|
||||
|
||||
(RPCConsole::RPCExecuteCommandLine(result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed
|
||||
(RPCConsole::RPCExecuteCommandLine(result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed
|
||||
QVERIFY(result == result2);
|
||||
(RPCConsole::RPCExecuteCommandLine(result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parametres is allowed
|
||||
QVERIFY(result == result2);
|
||||
|
||||
RPCConsole::RPCExecuteCommandLine(result, "getblock(getbestblockhash())[tx][0]");
|
||||
QVERIFY(result == "e0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7");
|
||||
|
||||
delete pcoinsTip;
|
||||
delete pcoinsdbview;
|
||||
delete pblocktree;
|
||||
|
||||
boost::filesystem::remove_all(boost::filesystem::path(path));
|
||||
}
|
25
src/qt/test/rpcnestedtests.h
Normal file
25
src/qt/test/rpcnestedtests.h
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2016 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_QT_TEST_RPC_NESTED_TESTS_H
|
||||
#define BITCOIN_QT_TEST_RPC_NESTED_TESTS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTest>
|
||||
|
||||
#include "txdb.h"
|
||||
#include "txmempool.h"
|
||||
|
||||
class RPCNestedTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void rpcNestedTests();
|
||||
|
||||
private:
|
||||
CCoinsViewDB *pcoinsdbview;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_TEST_RPC_NESTED_TESTS_H
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Copyright (c) 2009-2016 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2017 The Dash Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
@ -7,6 +7,9 @@
|
||||
#include "config/dash-config.h"
|
||||
#endif
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "key.h"
|
||||
#include "rpcnestedtests.h"
|
||||
#include "util.h"
|
||||
#include "uritests.h"
|
||||
#include "compattests.h"
|
||||
@ -30,10 +33,17 @@ Q_IMPORT_PLUGIN(qtwcodecs)
|
||||
Q_IMPORT_PLUGIN(qkrcodecs)
|
||||
#endif
|
||||
|
||||
extern void noui_connect();
|
||||
|
||||
// This is all you need to run all the tests
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
ECC_Start();
|
||||
SetupEnvironment();
|
||||
SetupNetworking();
|
||||
SelectParams(CBaseChainParams::MAIN);
|
||||
noui_connect();
|
||||
|
||||
bool fInvalid = false;
|
||||
|
||||
// Don't remove this, it's needed to access
|
||||
@ -51,6 +61,10 @@ int main(int argc, char *argv[])
|
||||
if (QTest::qExec(&test2) != 0)
|
||||
fInvalid = true;
|
||||
#endif
|
||||
RPCNestedTests test3;
|
||||
if (QTest::qExec(&test3) != 0)
|
||||
fInvalid = true;
|
||||
|
||||
CompatTests test4;
|
||||
if (QTest::qExec(&test4) != 0)
|
||||
fInvalid = true;
|
||||
@ -58,6 +72,6 @@ int main(int argc, char *argv[])
|
||||
TrafficGraphDataTests test5;
|
||||
if (QTest::qExec(&test5) != 0)
|
||||
fInvalid = true;
|
||||
|
||||
ECC_Stop();
|
||||
return fInvalid;
|
||||
}
|
||||
|
@ -66,9 +66,9 @@ void TransactionFilterProxy::setDateRange(const QDateTime &from, const QDateTime
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void TransactionFilterProxy::setAddressPrefix(const QString &addrPrefix)
|
||||
void TransactionFilterProxy::setAddressPrefix(const QString &_addrPrefix)
|
||||
{
|
||||
this->addrPrefix = addrPrefix;
|
||||
this->addrPrefix = _addrPrefix;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
@ -95,9 +95,9 @@ void TransactionFilterProxy::setLimit(int limit)
|
||||
this->limitRows = limit;
|
||||
}
|
||||
|
||||
void TransactionFilterProxy::setShowInactive(bool showInactive)
|
||||
void TransactionFilterProxy::setShowInactive(bool _showInactive)
|
||||
{
|
||||
this->showInactive = showInactive;
|
||||
this->showInactive = _showInactive;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
@ -97,16 +97,16 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
TransactionRecord(uint256 hash, qint64 time):
|
||||
hash(hash), time(time), type(Other), address(""), debit(0),
|
||||
TransactionRecord(uint256 _hash, qint64 _time):
|
||||
hash(_hash), time(_time), type(Other), address(""), debit(0),
|
||||
credit(0), idx(0)
|
||||
{
|
||||
}
|
||||
|
||||
TransactionRecord(uint256 hash, qint64 time,
|
||||
Type type, const std::string &address,
|
||||
const CAmount& debit, const CAmount& credit):
|
||||
hash(hash), time(time), type(type), address(address), debit(debit), credit(credit),
|
||||
TransactionRecord(uint256 _hash, qint64 _time,
|
||||
Type _type, const std::string &_address,
|
||||
const CAmount& _debit, const CAmount& _credit):
|
||||
hash(_hash), time(_time), type(_type), address(_address), debit(_debit), credit(_credit),
|
||||
idx(0)
|
||||
{
|
||||
}
|
||||
|
@ -59,9 +59,9 @@ struct TxLessThan
|
||||
class TransactionTablePriv
|
||||
{
|
||||
public:
|
||||
TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent) :
|
||||
wallet(wallet),
|
||||
parent(parent)
|
||||
TransactionTablePriv(CWallet *_wallet, TransactionTableModel *_parent) :
|
||||
wallet(_wallet),
|
||||
parent(_parent)
|
||||
{
|
||||
}
|
||||
|
||||
@ -235,13 +235,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
TransactionTableModel::TransactionTableModel(const PlatformStyle *platformStyle, CWallet* wallet, WalletModel *parent):
|
||||
TransactionTableModel::TransactionTableModel(const PlatformStyle *_platformStyle, CWallet* _wallet, WalletModel *parent):
|
||||
QAbstractTableModel(parent),
|
||||
wallet(wallet),
|
||||
wallet(_wallet),
|
||||
walletModel(parent),
|
||||
priv(new TransactionTablePriv(wallet, this)),
|
||||
priv(new TransactionTablePriv(_wallet, this)),
|
||||
fProcessingQueuedTransactions(false),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
columns << QString() << QString() << tr("Date") << tr("Type") << tr("Address / Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
|
||||
priv->refreshWallet();
|
||||
@ -738,8 +738,8 @@ struct TransactionNotification
|
||||
{
|
||||
public:
|
||||
TransactionNotification() {}
|
||||
TransactionNotification(uint256 hash, ChangeType status, bool showTransaction):
|
||||
hash(hash), status(status), showTransaction(showTransaction) {}
|
||||
TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction):
|
||||
hash(_hash), status(_status), showTransaction(_showTransaction) {}
|
||||
|
||||
void invoke(QObject *ttm)
|
||||
{
|
||||
|
@ -199,14 +199,14 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
|
||||
connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
|
||||
}
|
||||
|
||||
void TransactionView::setModel(WalletModel *model)
|
||||
void TransactionView::setModel(WalletModel *_model)
|
||||
{
|
||||
QSettings settings;
|
||||
this->model = model;
|
||||
if(model)
|
||||
this->model = _model;
|
||||
if(_model)
|
||||
{
|
||||
transactionProxyModel = new TransactionFilterProxy(this);
|
||||
transactionProxyModel->setSourceModel(model->getTransactionTableModel());
|
||||
transactionProxyModel->setSourceModel(_model->getTransactionTableModel());
|
||||
transactionProxyModel->setDynamicSortFilter(true);
|
||||
transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
@ -233,10 +233,10 @@ void TransactionView::setModel(WalletModel *model)
|
||||
|
||||
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(transactionView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH, this);
|
||||
|
||||
if (model->getOptionsModel())
|
||||
if (_model->getOptionsModel())
|
||||
{
|
||||
// Add third party transaction URLs to context menu
|
||||
QStringList listUrls = model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts);
|
||||
QStringList listUrls = _model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts);
|
||||
for (int i = 0; i < listUrls.size(); ++i)
|
||||
{
|
||||
QString host = QUrl(listUrls[i].trimmed(), QUrl::StrictMode).host();
|
||||
@ -253,10 +253,10 @@ void TransactionView::setModel(WalletModel *model)
|
||||
}
|
||||
|
||||
// show/hide column Watch-only
|
||||
updateWatchOnlyColumn(model->haveWatchOnly());
|
||||
updateWatchOnlyColumn(_model->haveWatchOnly());
|
||||
|
||||
// Watch-only signal
|
||||
connect(model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool)));
|
||||
connect(_model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool)));
|
||||
|
||||
// Update transaction list with persisted settings
|
||||
chooseType(settings.value("transactionType").toInt());
|
||||
|
@ -12,10 +12,10 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
|
||||
WalletFrame::WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui) :
|
||||
WalletFrame::WalletFrame(const PlatformStyle *_platformStyle, BitcoinGUI *_gui) :
|
||||
QFrame(_gui),
|
||||
gui(_gui),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
// Leave HBox hook for adding a list view later
|
||||
QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
|
||||
@ -33,9 +33,9 @@ WalletFrame::~WalletFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void WalletFrame::setClientModel(ClientModel *clientModel)
|
||||
void WalletFrame::setClientModel(ClientModel *_clientModel)
|
||||
{
|
||||
this->clientModel = clientModel;
|
||||
this->clientModel = _clientModel;
|
||||
}
|
||||
|
||||
bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel)
|
||||
|
@ -34,8 +34,8 @@
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
|
||||
QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
|
||||
WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, OptionsModel *_optionsModel, QObject *parent) :
|
||||
QObject(parent), wallet(_wallet), optionsModel(_optionsModel), addressTableModel(0),
|
||||
transactionTableModel(0),
|
||||
recentRequestsTableModel(0),
|
||||
cachedBalance(0),
|
||||
@ -605,11 +605,11 @@ WalletModel::UnlockContext WalletModel::requestUnlock(bool fForMixingOnly)
|
||||
return UnlockContext(this, !fInvalid, !fKeepUnlocked, was_mixing);
|
||||
}
|
||||
|
||||
WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool was_locked, bool was_mixing):
|
||||
wallet(wallet),
|
||||
valid(valid),
|
||||
was_locked(was_locked),
|
||||
was_mixing(was_mixing)
|
||||
WalletModel::UnlockContext::UnlockContext(WalletModel *_wallet, bool _valid, bool _was_locked, bool _was_mixing):
|
||||
wallet(_wallet),
|
||||
valid(_valid),
|
||||
was_locked(_was_locked),
|
||||
was_mixing(_was_mixing)
|
||||
{
|
||||
}
|
||||
|
||||
@ -760,6 +760,11 @@ bool WalletModel::abandonTransaction(uint256 hash) const
|
||||
return wallet->AbandonTransaction(hash);
|
||||
}
|
||||
|
||||
bool WalletModel::isWalletEnabled()
|
||||
{
|
||||
return !GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET);
|
||||
}
|
||||
|
||||
bool WalletModel::hdEnabled() const
|
||||
{
|
||||
return wallet->IsHDEnabled();
|
||||
|
@ -41,8 +41,8 @@ class SendCoinsRecipient
|
||||
{
|
||||
public:
|
||||
explicit SendCoinsRecipient() : amount(0), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) { }
|
||||
explicit SendCoinsRecipient(const QString &addr, const QString &label, const CAmount& amount, const QString &message):
|
||||
address(addr), label(label), amount(amount), message(message), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) {}
|
||||
explicit SendCoinsRecipient(const QString &addr, const QString &_label, const CAmount& _amount, const QString &_message):
|
||||
address(addr), label(_label), amount(_amount), message(_message), fSubtractFeeFromAmount(false), nVersion(SendCoinsRecipient::CURRENT_VERSION) {}
|
||||
|
||||
// If from an unauthenticated payment request, this is used for storing
|
||||
// the addresses, e.g. address-A<br />address-B<br />address-C.
|
||||
@ -154,8 +154,8 @@ public:
|
||||
// Return status record for SendCoins, contains error id + information
|
||||
struct SendCoinsReturn
|
||||
{
|
||||
SendCoinsReturn(StatusCode status = OK):
|
||||
status(status) {}
|
||||
SendCoinsReturn(StatusCode _status = OK):
|
||||
status(_status) {}
|
||||
StatusCode status;
|
||||
};
|
||||
|
||||
@ -214,6 +214,8 @@ public:
|
||||
bool transactionCanBeAbandoned(uint256 hash) const;
|
||||
bool abandonTransaction(uint256 hash) const;
|
||||
|
||||
static bool isWalletEnabled();
|
||||
|
||||
bool hdEnabled() const;
|
||||
|
||||
private:
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
#include "wallet/wallet.h"
|
||||
|
||||
WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &recipients) :
|
||||
recipients(recipients),
|
||||
WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &_recipients) :
|
||||
recipients(_recipients),
|
||||
walletTransaction(0),
|
||||
keyChange(0),
|
||||
fee(0)
|
||||
|
@ -32,11 +32,11 @@
|
||||
#include <QSettings>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent):
|
||||
WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent):
|
||||
QStackedWidget(parent),
|
||||
clientModel(0),
|
||||
walletModel(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
// Create tabs
|
||||
overviewPage = new OverviewPage(platformStyle);
|
||||
@ -132,55 +132,55 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui)
|
||||
}
|
||||
}
|
||||
|
||||
void WalletView::setClientModel(ClientModel *clientModel)
|
||||
void WalletView::setClientModel(ClientModel *_clientModel)
|
||||
{
|
||||
this->clientModel = clientModel;
|
||||
this->clientModel = _clientModel;
|
||||
|
||||
overviewPage->setClientModel(clientModel);
|
||||
sendCoinsPage->setClientModel(clientModel);
|
||||
overviewPage->setClientModel(_clientModel);
|
||||
sendCoinsPage->setClientModel(_clientModel);
|
||||
QSettings settings;
|
||||
if (settings.value("fShowMasternodesTab").toBool()) {
|
||||
masternodeListPage->setClientModel(clientModel);
|
||||
masternodeListPage->setClientModel(_clientModel);
|
||||
}
|
||||
}
|
||||
|
||||
void WalletView::setWalletModel(WalletModel *walletModel)
|
||||
void WalletView::setWalletModel(WalletModel *_walletModel)
|
||||
{
|
||||
this->walletModel = walletModel;
|
||||
this->walletModel = _walletModel;
|
||||
|
||||
// Put transaction list in tabs
|
||||
transactionView->setModel(walletModel);
|
||||
overviewPage->setWalletModel(walletModel);
|
||||
transactionView->setModel(_walletModel);
|
||||
overviewPage->setWalletModel(_walletModel);
|
||||
QSettings settings;
|
||||
if (settings.value("fShowMasternodesTab").toBool()) {
|
||||
masternodeListPage->setWalletModel(walletModel);
|
||||
masternodeListPage->setWalletModel(_walletModel);
|
||||
}
|
||||
receiveCoinsPage->setModel(walletModel);
|
||||
sendCoinsPage->setModel(walletModel);
|
||||
usedReceivingAddressesPage->setModel(walletModel->getAddressTableModel());
|
||||
usedSendingAddressesPage->setModel(walletModel->getAddressTableModel());
|
||||
receiveCoinsPage->setModel(_walletModel);
|
||||
sendCoinsPage->setModel(_walletModel);
|
||||
usedReceivingAddressesPage->setModel(_walletModel->getAddressTableModel());
|
||||
usedSendingAddressesPage->setModel(_walletModel->getAddressTableModel());
|
||||
|
||||
if (walletModel)
|
||||
if (_walletModel)
|
||||
{
|
||||
// Receive and pass through messages from wallet model
|
||||
connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
|
||||
connect(_walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
|
||||
|
||||
// Handle changes in encryption status
|
||||
connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int)));
|
||||
connect(_walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int)));
|
||||
updateEncryptionStatus();
|
||||
|
||||
// update HD status
|
||||
Q_EMIT hdEnabledStatusChanged(walletModel->hdEnabled());
|
||||
Q_EMIT hdEnabledStatusChanged(_walletModel->hdEnabled());
|
||||
|
||||
// Balloon pop-up for new transaction
|
||||
connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
connect(_walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(processNewTransaction(QModelIndex,int,int)));
|
||||
|
||||
// Ask for passphrase if needed
|
||||
connect(walletModel, SIGNAL(requireUnlock(bool)), this, SLOT(unlockWallet(bool)));
|
||||
connect(_walletModel, SIGNAL(requireUnlock(bool)), this, SLOT(unlockWallet(bool)));
|
||||
|
||||
// Show progress dialog
|
||||
connect(walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
|
||||
connect(_walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,9 @@ class reverse_lock
|
||||
{
|
||||
public:
|
||||
|
||||
explicit reverse_lock(Lock& lock) : lock(lock) {
|
||||
lock.unlock();
|
||||
lock.swap(templock);
|
||||
explicit reverse_lock(Lock& _lock) : lock(_lock) {
|
||||
_lock.unlock();
|
||||
_lock.swap(templock);
|
||||
}
|
||||
|
||||
~reverse_lock() {
|
||||
|
@ -497,10 +497,10 @@ UniValue getmempoolancestors(const UniValue& params, bool fHelp)
|
||||
UniValue o(UniValue::VOBJ);
|
||||
BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) {
|
||||
const CTxMemPoolEntry &e = *ancestorIt;
|
||||
const uint256& hash = e.GetTx().GetHash();
|
||||
const uint256& _hash = e.GetTx().GetHash();
|
||||
UniValue info(UniValue::VOBJ);
|
||||
entryToJSON(info, e);
|
||||
o.push_back(Pair(hash.ToString(), info));
|
||||
o.push_back(Pair(_hash.ToString(), info));
|
||||
}
|
||||
return o;
|
||||
}
|
||||
@ -561,10 +561,10 @@ UniValue getmempooldescendants(const UniValue& params, bool fHelp)
|
||||
UniValue o(UniValue::VOBJ);
|
||||
BOOST_FOREACH(CTxMemPool::txiter descendantIt, setDescendants) {
|
||||
const CTxMemPoolEntry &e = *descendantIt;
|
||||
const uint256& hash = e.GetTx().GetHash();
|
||||
const uint256& _hash = e.GetTx().GetHash();
|
||||
UniValue info(UniValue::VOBJ);
|
||||
entryToJSON(info, e);
|
||||
o.push_back(Pair(hash.ToString(), info));
|
||||
o.push_back(Pair(_hash.ToString(), info));
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
@ -630,8 +630,8 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
|
||||
UniValue aRules(UniValue::VARR);
|
||||
UniValue vbavailable(UniValue::VOBJ);
|
||||
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) {
|
||||
Consensus::DeploymentPos pos = Consensus::DeploymentPos(i);
|
||||
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
|
||||
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
|
||||
ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache);
|
||||
switch (state) {
|
||||
case THRESHOLD_DEFINED:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user