From 4f92b5fb301fac86453aeeaabfbd064c29674cd8 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 2 Jun 2017 09:27:47 -0400 Subject: [PATCH 001/148] Run Qt wallet tests on travis Currently these test failures are not caught by travis leading to bugs like: https://github.com/bitcoin/bitcoin/pull/10506 --- .travis.yml | 6 +++--- depends/Makefile | 1 + depends/config.site.in | 11 ++++++----- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index fcf4b082f1b..e12d241e381 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,9 +29,9 @@ env: - HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python3-zmq" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" # Win64 - HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine1.6 bc" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports" -# bitcoind - - HOST=x86_64-unknown-linux-gnu PACKAGES="bc python3-zmq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" -# No wallet +# x86_64 Linux (uses qt5 dev package instead of depends Qt to speed up build and avoid timeout) + - HOST=x86_64-unknown-linux-gnu PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" +# x86_64 Linux, No wallet - HOST=x86_64-unknown-linux-gnu PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" # Cross-Mac - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" OSX_SDK=10.11 GOAL="deploy" diff --git a/depends/Makefile b/depends/Makefile index dedb0674cf1..0ddd348e53e 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -134,6 +134,7 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_ -e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS) $(host_$(release_type)_CXXFLAGS))|' \ -e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \ -e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \ + -e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \ -e 's|@no_qt@|$(NO_QT)|' \ -e 's|@no_wallet@|$(NO_WALLET)|' \ -e 's|@no_upnp@|$(NO_UPNP)|' \ diff --git a/depends/config.site.in b/depends/config.site.in index 3d7c9fd43c7..0a4a9c327e2 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -13,10 +13,10 @@ fi if test -z $with_qt_translationdir; then with_qt_translationdir=$depends_prefix/translations fi -if test -z $with_qt_bindir; then +if test -z $with_qt_bindir && test -z "@no_qt@"; then with_qt_bindir=$depends_prefix/native/bin fi -if test -z $with_protoc_bindir; then +if test -z $with_protoc_bindir && test -z "@no_qt@"; then with_protoc_bindir=$depends_prefix/native/bin fi @@ -53,9 +53,10 @@ PKG_CONFIG="`which pkg-config` --static" # These two need to remain exported because pkg-config does not see them # otherwise. That means they must be unexported at the end of configure.ac to # avoid ruining the cache. Sigh. - -export PKG_CONFIG_LIBDIR=$depends_prefix/lib/pkgconfig -export PKG_CONFIG_PATH=$depends_prefix/share/pkgconfig +export PKG_CONFIG_PATH=$depends_prefix/share/pkgconfig:$depends_prefix/lib/pkgconfig +if test -z "@allow_host_packages@"; then + export PKGCONFIG_LIBDIR= +fi CPPFLAGS="-I$depends_prefix/include/ $CPPFLAGS" LDFLAGS="-L$depends_prefix/lib $LDFLAGS" From 6270d624cf6bc235b3e47bbbf5d49039fe1e172a Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 22 Jun 2017 13:44:31 -0400 Subject: [PATCH 002/148] Verify binaries from bitcoincore.org and bitcoin.org --- contrib/verifybinaries/verify.sh | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh index c2cc2b7013a..409f517c9fb 100755 --- a/contrib/verifybinaries/verify.sh +++ b/contrib/verifybinaries/verify.sh @@ -3,7 +3,8 @@ # 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 +### This script attempts to download the signature file SHA256SUMS.asc from +### bitcoincore.org and bitcoin.org and compares them. ### It first checks if the signature passes, and then downloads the files specified in ### the file, and checks if the hashes of these files match those that are specified ### in the signature file. @@ -22,7 +23,9 @@ TMPFILE="hashes.tmp" SIGNATUREFILENAME="SHA256SUMS.asc" RCSUBDIR="test" -BASEDIR="https://bitcoin.org/bin/" +HOST1="https://bitcoincore.org" +HOST2="https://bitcoin.org" +BASEDIR="/bin/" VERSIONPREFIX="bitcoin-core-" RCVERSIONSTRING="rc" @@ -81,7 +84,7 @@ else fi #first we fetch the file containing the signature -WGETOUT=$(wget -N "$BASEDIR$SIGNATUREFILENAME" 2>&1) +WGETOUT=$(wget -N "$HOST1$BASEDIR$SIGNATUREFILENAME" 2>&1) #and then see if wget completed successfully if [ $? -ne 0 ]; then @@ -92,6 +95,22 @@ if [ $? -ne 0 ]; then exit 2 fi +WGETOUT=$(wget -N -O "$SIGNATUREFILENAME.2" "$HOST2$BASEDIR$SIGNATUREFILENAME" 2>&1) +if [ $? -ne 0 ]; then + echo "bitcoin.org failed to provide signature file, but bitcoincore.org did?" + echo "wget output:" + echo "$WGETOUT"|sed 's/^/\t/g' + clean_up $SIGNATUREFILENAME + exit 3 +fi + +SIGFILEDIFFS="$(diff $SIGNATUREFILENAME $SIGNATUREFILENAME.2)" +if [ "$SIGFILEDIFFS" != "" ]; then + echo "bitcoin.org and bitcoincore.org signature files were not equal?" + clean_up $SIGNATUREFILENAME $SIGNATUREFILENAME.2 + exit 4 +fi + #then we check it GPGOUT=$(gpg --yes --decrypt --output "$TMPFILE" "$SIGNATUREFILENAME" 2>&1) @@ -111,7 +130,7 @@ if [ $RET -ne 0 ]; then echo "gpg output:" echo "$GPGOUT"|sed 's/^/\t/g' - clean_up $SIGNATUREFILENAME $TMPFILE + clean_up $SIGNATUREFILENAME $SIGNATUREFILENAME.2 $TMPFILE exit "$RET" fi @@ -131,7 +150,7 @@ FILES=$(awk '{print $2}' "$TMPFILE") for file in $FILES do echo "Downloading $file" - wget --quiet -N "$BASEDIR$file" + wget --quiet -N "$HOST1$BASEDIR$file" done #check hashes @@ -149,7 +168,7 @@ fi if [ -n "$2" ]; then echo "Clean up the binaries" - clean_up $FILES $SIGNATUREFILENAME $TMPFILE + clean_up $FILES $SIGNATUREFILENAME $SIGNATUREFILENAME.2 $TMPFILE else echo "Keep the binaries in $WORKINGDIR" clean_up $TMPFILE From 32cffe6bef8974db6bf1536a24bce8c2b2304c52 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 11 Apr 2017 13:03:03 -0400 Subject: [PATCH 003/148] [tests] Fix import order in getblocktemplate test --- test/functional/getblocktemplate_proposals.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index fca99c7df57..304eaa20e97 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -4,13 +4,13 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test block proposals with getblocktemplate.""" -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * - from binascii import a2b_hex, b2a_hex from hashlib import sha256 from struct import pack +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + def b2x(b): return b2a_hex(b).decode('ascii') From 0a3a5ff454643d148e5a68c12393fa4e187af157 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 11 Apr 2017 13:05:41 -0400 Subject: [PATCH 004/148] [tests] Fix flake8 warnings in getblocktemplate tests --- test/functional/getblocktemplate_proposals.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index 304eaa20e97..51b4dc33e36 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -43,7 +43,7 @@ def genmrklroot(leaflist): if len(cur) & 1: cur.append(cur[-1]) for i in range(0, len(cur), 2): - n.append(dblsha(cur[i] + cur[i+1])) + n.append(dblsha(cur[i] + cur[i + 1])) cur = n return cur[0] @@ -62,7 +62,7 @@ def template_to_hex(tmpl, txlist): return b2x(template_to_bytearray(tmpl, txlist)) def assert_template(node, tmpl, txlist, expect): - rsp = node.getblocktemplate({'data':template_to_hex(tmpl, txlist),'mode':'proposal'}) + rsp = node.getblocktemplate({'data': template_to_hex(tmpl, txlist), 'mode': 'proposal'}) if rsp != expect: raise AssertionError('unexpected: %s' % (rsp,)) @@ -75,7 +75,8 @@ def __init__(self): def run_test(self): node = self.nodes[0] - node.generate(1) # Mine a block to leave initial block download + # Mine a block to leave initial block download + node.generate(1) tmpl = node.getblocktemplate() if 'coinbasetxn' not in tmpl: rawcoinbase = encodeUNum(tmpl['height']) @@ -88,16 +89,10 @@ def run_test(self): # Test 0: Capability advertised assert('proposal' in tmpl['capabilities']) - # NOTE: This test currently FAILS (regtest mode doesn't enforce block height in coinbase) - ## Test 1: Bad height in coinbase - #txlist[0][4+1+36+1+1] += 1 - #assert_template(node, tmpl, txlist, 'FIXME') - #txlist[0][4+1+36+1+1] -= 1 - # Test 2: Bad input hash for gen tx - txlist[0][4+1] += 1 + txlist[0][4 + 1] += 1 assert_template(node, tmpl, txlist, 'bad-cb-missing') - txlist[0][4+1] -= 1 + txlist[0][4 + 1] -= 1 # Test 3: Truncated final tx lastbyte = txlist[-1].pop() @@ -111,7 +106,7 @@ def run_test(self): # Test 5: Add an invalid tx to the end (non-duplicate) txlist.append(bytearray(txlist[0])) - txlist[-1][4+1] = 0xff + txlist[-1][4 + 1] = 0xff assert_template(node, tmpl, txlist, 'bad-txns-inputs-missingorspent') txlist.pop() @@ -133,8 +128,8 @@ def run_test(self): # Test 9: Bad merkle root rawtmpl = template_to_bytearray(tmpl, txlist) - rawtmpl[4+32] = (rawtmpl[4+32] + 1) % 0x100 - rsp = node.getblocktemplate({'data':b2x(rawtmpl),'mode':'proposal'}) + rawtmpl[4 + 32] = (rawtmpl[4 + 32] + 1) % 0x100 + rsp = node.getblocktemplate({'data': b2x(rawtmpl), 'mode': 'proposal'}) if rsp != 'bad-txnmrklroot': raise AssertionError('unexpected: %s' % (rsp,)) From 38b38cd2d1a8db8d4bf5bd88e1cbd14d640c73c7 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 11 Apr 2017 13:10:20 -0400 Subject: [PATCH 005/148] [tests] getblocktemplate_proposals.py: add logging --- test/functional/getblocktemplate_proposals.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index 51b4dc33e36..6fd5279b8e8 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -86,54 +86,54 @@ def run_test(self): tmpl['coinbasetxn'] = {'data': '01000000' + '01' + '0000000000000000000000000000000000000000000000000000000000000000ffffffff' + ('%02x' % (len(rawcoinbase),)) + hexcoinbase + 'fffffffe' + '01' + hexoutval + '00' + '00000000'} txlist = list(bytearray(a2b_hex(a['data'])) for a in (tmpl['coinbasetxn'],) + tuple(tmpl['transactions'])) - # Test 0: Capability advertised + self.log.info("getblocktemplate: Test capability advertised") assert('proposal' in tmpl['capabilities']) - # Test 2: Bad input hash for gen tx + self.log.info("getblocktemplate: Test bad input hash for coinbase transaction") txlist[0][4 + 1] += 1 assert_template(node, tmpl, txlist, 'bad-cb-missing') txlist[0][4 + 1] -= 1 - # Test 3: Truncated final tx + self.log.info("getblocktemplate: Test truncated final transaction") lastbyte = txlist[-1].pop() assert_raises_jsonrpc(-22, "Block decode failed", assert_template, node, tmpl, txlist, 'n/a') txlist[-1].append(lastbyte) - # Test 4: Add an invalid tx to the end (duplicate of gen tx) + self.log.info("getblocktemplate: Test duplicate transaction") txlist.append(txlist[0]) assert_template(node, tmpl, txlist, 'bad-txns-duplicate') txlist.pop() - # Test 5: Add an invalid tx to the end (non-duplicate) + self.log.info("getblocktemplate: Test invalid transaction") txlist.append(bytearray(txlist[0])) txlist[-1][4 + 1] = 0xff assert_template(node, tmpl, txlist, 'bad-txns-inputs-missingorspent') txlist.pop() - # Test 6: Future tx lock time + self.log.info("getblocktemplate: Test nonfinal transaction") txlist[0][-4:] = b'\xff\xff\xff\xff' assert_template(node, tmpl, txlist, 'bad-txns-nonfinal') txlist[0][-4:] = b'\0\0\0\0' - # Test 7: Bad tx count + self.log.info("getblocktemplate: Test bad tx count") txlist.append(b'') assert_raises_jsonrpc(-22, 'Block decode failed', assert_template, node, tmpl, txlist, 'n/a') txlist.pop() - # Test 8: Bad bits + self.log.info("getblocktemplate: Test bad bits") realbits = tmpl['bits'] tmpl['bits'] = '1c0000ff' # impossible in the real world assert_template(node, tmpl, txlist, 'bad-diffbits') tmpl['bits'] = realbits - # Test 9: Bad merkle root + self.log.info("getblocktemplate: Test bad merkle root") rawtmpl = template_to_bytearray(tmpl, txlist) rawtmpl[4 + 32] = (rawtmpl[4 + 32] + 1) % 0x100 rsp = node.getblocktemplate({'data': b2x(rawtmpl), 'mode': 'proposal'}) if rsp != 'bad-txnmrklroot': raise AssertionError('unexpected: %s' % (rsp,)) - # Test 10: Bad timestamps + self.log.info("getblocktemplate: Test bad timestamps") realtime = tmpl['curtime'] tmpl['curtime'] = 0x7fffffff assert_template(node, tmpl, txlist, 'time-too-new') @@ -141,10 +141,10 @@ def run_test(self): assert_template(node, tmpl, txlist, 'time-too-old') tmpl['curtime'] = realtime - # Test 11: Valid block + self.log.info("getblocktemplate: Test valid block") assert_template(node, tmpl, txlist, None) - # Test 12: Orphan block + self.log.info("getblocktemplate: Test not best block") tmpl['previousblockhash'] = 'ff00' * 16 assert_template(node, tmpl, txlist, 'inconclusive-not-best-prevblk') From 66c570a38eb21153599f0478adc5a17ca9821a52 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 11 Apr 2017 15:09:19 -0400 Subject: [PATCH 006/148] [tests] Don't build the coinbase manually in getblocktemplate test --- test/functional/getblocktemplate_proposals.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index 6fd5279b8e8..82a82d01f22 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -8,6 +8,7 @@ from hashlib import sha256 from struct import pack +from test_framework.blocktools import create_coinbase from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * @@ -78,13 +79,13 @@ def run_test(self): # Mine a block to leave initial block download node.generate(1) tmpl = node.getblocktemplate() - if 'coinbasetxn' not in tmpl: - rawcoinbase = encodeUNum(tmpl['height']) - rawcoinbase += b'\x01-' - hexcoinbase = b2x(rawcoinbase) - hexoutval = b2x(pack(' Date: Tue, 11 Apr 2017 15:13:09 -0400 Subject: [PATCH 007/148] [tests] clarify assertions in getblocktemplate test --- test/functional/getblocktemplate_proposals.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index 82a82d01f22..788e3ce2594 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -64,8 +64,7 @@ def template_to_hex(tmpl, txlist): def assert_template(node, tmpl, txlist, expect): rsp = node.getblocktemplate({'data': template_to_hex(tmpl, txlist), 'mode': 'proposal'}) - if rsp != expect: - raise AssertionError('unexpected: %s' % (rsp,)) + assert_equal(rsp, expect) class GetBlockTemplateProposalTest(BitcoinTestFramework): @@ -88,7 +87,7 @@ def run_test(self): txlist = [bytearray(coinbase_tx.serialize())] self.log.info("getblocktemplate: Test capability advertised") - assert('proposal' in tmpl['capabilities']) + assert 'proposal' in tmpl['capabilities'] self.log.info("getblocktemplate: Test bad input hash for coinbase transaction") txlist[0][4 + 1] += 1 @@ -131,8 +130,7 @@ def run_test(self): rawtmpl = template_to_bytearray(tmpl, txlist) rawtmpl[4 + 32] = (rawtmpl[4 + 32] + 1) % 0x100 rsp = node.getblocktemplate({'data': b2x(rawtmpl), 'mode': 'proposal'}) - if rsp != 'bad-txnmrklroot': - raise AssertionError('unexpected: %s' % (rsp,)) + assert_equal(rsp, 'bad-txnmrklroot') self.log.info("getblocktemplate: Test bad timestamps") realtime = tmpl['curtime'] From 82dc59706e3cf0184083ddc10a25674608235f48 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 11 Apr 2017 16:42:12 -0400 Subject: [PATCH 008/148] [tests] don't build blocks manually in getblocktemplate test --- test/functional/getblocktemplate_proposals.py | 149 ++++++++++---------------- 1 file changed, 57 insertions(+), 92 deletions(-) diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index 788e3ce2594..a65d14ce064 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -4,66 +4,21 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test block proposals with getblocktemplate.""" -from binascii import a2b_hex, b2a_hex -from hashlib import sha256 -from struct import pack +from binascii import b2a_hex +import copy from test_framework.blocktools import create_coinbase from test_framework.test_framework import BitcoinTestFramework +from test_framework.mininode import CBlock from test_framework.util import * def b2x(b): return b2a_hex(b).decode('ascii') -# NOTE: This does not work for signed numbers (set the high bit) or zero (use b'\0') -def encodeUNum(n): - s = bytearray(b'\1') - while n > 127: - s[0] += 1 - s.append(n % 256) - n //= 256 - s.append(n) - return bytes(s) - -def varlenEncode(n): - if n < 0xfd: - return pack(' 1: - n = [] - if len(cur) & 1: - cur.append(cur[-1]) - for i in range(0, len(cur), 2): - n.append(dblsha(cur[i] + cur[i + 1])) - cur = n - return cur[0] - -def template_to_bytearray(tmpl, txlist): - blkver = pack(' Date: Tue, 11 Apr 2017 16:39:37 -0400 Subject: [PATCH 009/148] [tests] run successful test in getblocktemplate first --- test/functional/getblocktemplate_proposals.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index a65d14ce064..777b20212cd 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -50,6 +50,9 @@ def run_test(self): block.nNonce = 0 block.vtx = [coinbase_tx] + self.log.info("getblocktemplate: Test valid block") + assert_template(node, block, None) + self.log.info("getblocktemplate: Test bad input hash for coinbase transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].vin[0].prevout.hash += 1 @@ -104,9 +107,6 @@ def run_test(self): bad_block.nTime = 0 assert_template(node, bad_block, 'time-too-old') - self.log.info("getblocktemplate: Test valid block") - assert_template(node, block, None) - self.log.info("getblocktemplate: Test not best block") bad_block = copy.deepcopy(block) bad_block.hashPrevBlock = 123 From b29dd41f0f8482fb6dbaa4f9fa468ac66069f207 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 11 Apr 2017 16:42:35 -0400 Subject: [PATCH 010/148] [tests] add test for submit block --- test/functional/getblocktemplate_proposals.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index 777b20212cd..311d9197aca 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -53,12 +53,17 @@ def run_test(self): self.log.info("getblocktemplate: Test valid block") assert_template(node, block, None) + self.log.info("submitblock: Test block decode failure") + assert_raises_jsonrpc(-22, "Block decode failed", node.submitblock, b2x(block.serialize()[:-15])) + self.log.info("getblocktemplate: Test bad input hash for coinbase transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].vin[0].prevout.hash += 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-cb-missing') + self.log.info("submitblock: Test invalid coinbase transaction") + assert_raises_jsonrpc(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize())) self.log.info("getblocktemplate: Test truncated final transaction") assert_raises_jsonrpc(-22, "Block decode failed", node.getblocktemplate, {'data': b2x(block.serialize()[:-1]), 'mode': 'proposal'}) From 11ba8e9cdd2652835c650b9f72d8421ea10f4116 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 11 Apr 2017 16:47:10 -0400 Subject: [PATCH 011/148] [tests] rename getblocktemplate_proposals.py to mining.py --- test/functional/{getblocktemplate_proposals.py => mining.py} | 9 ++++++--- test/functional/test_runner.py | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) rename test/functional/{getblocktemplate_proposals.py => mining.py} (97%) diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/mining.py similarity index 97% rename from test/functional/getblocktemplate_proposals.py rename to test/functional/mining.py index 311d9197aca..dbd4e29ecae 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/mining.py @@ -2,7 +2,10 @@ # 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. -"""Test block proposals with getblocktemplate.""" +"""Test mining RPCs + +- getblocktemplate proposal mode +- submitblock""" from binascii import b2a_hex import copy @@ -21,7 +24,7 @@ def assert_template(node, block, expect, rehash=True): rsp = node.getblocktemplate({'data': b2x(block.serialize()), 'mode': 'proposal'}) assert_equal(rsp, expect) -class GetBlockTemplateProposalTest(BitcoinTestFramework): +class MiningTest(BitcoinTestFramework): def __init__(self): super().__init__() @@ -118,4 +121,4 @@ def run_test(self): assert_template(node, bad_block, 'inconclusive-not-best-prevblk') if __name__ == '__main__': - GetBlockTemplateProposalTest().main() + MiningTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 9952835951f..d411534ca2f 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -108,6 +108,7 @@ 'signmessages.py', 'nulldummy.py', 'import-rescan.py', + 'mining.py', 'bumpfee.py', 'rpcnamedargs.py', 'listsinceblock.py', @@ -140,7 +141,6 @@ 'bipdersig-p2p.py', 'bipdersig.py', 'example_test.py', - 'getblocktemplate_proposals.py', 'txn_doublespend.py', 'txn_clone.py --mineblock', 'forknotify.py', From 7ec3343df21aae30bf782f77171f5e4d9a1d5e65 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Tue, 27 Jun 2017 10:06:34 -0400 Subject: [PATCH 012/148] add gdb attach process to test README --- test/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/README.md b/test/README.md index 15f6df790f9..868eb667ae2 100644 --- a/test/README.md +++ b/test/README.md @@ -155,6 +155,26 @@ import pdb; pdb.set_trace() anywhere in the test. You will then be able to inspect variables, as well as call methods that interact with the bitcoind nodes-under-test. +If further introspection of the bitcoind instances themselves becomes +necessary, this can be accomplished by first setting a pdb breakpoint +at an appropriate location, running the test to that point, then using +`gdb` to attach to the process and debug. + +For instance, to attach to `self.node[1]` during a run: + +```bash +2017-06-27 14:13:56.686000 TestFramework (INFO): Initializing test directory /tmp/user/1000/testo9vsdjo3 +``` + +use the directory path to get the pid from the pid file: + +```bash +cat /tmp/user/1000/testo9vsdjo3/node1/regtest/bitcoind.pid +gdb /home/example/bitcoind +``` + +Note: gdb attach step may require `sudo` + ### Util tests Util tests can be run locally by running `test/util/bitcoin-util-test.py`. From 18bacec6c2c8493fd6b7011778446b3c7473bb25 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 8 Jun 2017 10:41:19 -0400 Subject: [PATCH 013/148] Make check to distinguish between orphan txs and old txs more efficient. Checking for the existence in the CCoinsViewCache of the outputs of a new tx will result in a disk hit for every output since they will not be found. On the other hand if those outputs exist already, then the inputs must also have been missing, so we can move this check inside the input existence check so in the common case of a new tx it doesn't need to run. The purpose of the check is to avoid spamming the orphanMap with slightly old txs which we have already seen in a block, but it is already only optimistic (depending on the outputs not being spent), so make it even more efficient by only checking the cache and not the entire pcoinsTip. --- src/validation.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index eb6ea42b638..c160da64abe 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -491,24 +491,20 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool CCoinsViewMemPool viewMemPool(pcoinsTip, pool); view.SetBackend(viewMemPool); - // do we already have it? - for (size_t out = 0; out < tx.vout.size(); out++) { - COutPoint outpoint(hash, out); - bool had_coin_in_cache = pcoinsTip->HaveCoinInCache(outpoint); - if (view.HaveCoin(outpoint)) { - if (!had_coin_in_cache) { - coins_to_uncache.push_back(outpoint); - } - return state.Invalid(false, REJECT_DUPLICATE, "txn-already-known"); - } - } - // do all inputs exist? for (const CTxIn txin : tx.vin) { if (!pcoinsTip->HaveCoinInCache(txin.prevout)) { coins_to_uncache.push_back(txin.prevout); } if (!view.HaveCoin(txin.prevout)) { + // Are inputs missing because we already have the tx? + for (size_t out = 0; out < tx.vout.size(); out++) { + // Optimistically just do efficient check of cache for outputs + if (pcoinsTip->HaveCoinInCache(COutPoint(hash, out))) { + return state.Invalid(false, REJECT_DUPLICATE, "txn-already-known"); + } + } + // Otherwise assume this might be an orphan tx for which we just haven't seen parents yet if (pfMissingInputs) { *pfMissingInputs = true; } From d64ac3f4aab13a1a4e8d320b52e7a2b934e011b2 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 20 Apr 2017 20:56:37 +0200 Subject: [PATCH 014/148] [tests] Allow tests to pass when stderr is non-empty Tests which pass with non-empty stderr are reported as "passed with warnings" --- test/functional/test_runner.py | 51 ++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 54f625514bd..82907e736a8 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -27,8 +27,7 @@ import re import logging -# Formatting. Default colors to empty strings. -BOLD, BLUE, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "") +# Formatting. try: # Make sure python thinks it can write unicode to its stdout "\u2713".encode("utf_8").decode(sys.stdout.encoding) @@ -40,17 +39,28 @@ CROSS = "x " CIRCLE = "o " +# Default colors to empty strings. +BOLD, BLUE, RED, GREY, MAGENTA = [("", "")] * 5 if os.name == 'posix': # primitive formatting on supported # terminal via ANSI escape sequences: BOLD = ('\033[0m', '\033[1m') - BLUE = ('\033[0m', '\033[0;34m') - RED = ('\033[0m', '\033[0;31m') GREY = ('\033[0m', '\033[1;30m') + RED = ('\033[0m', '\033[0;31m') + BLUE = ('\033[0m', '\033[0;34m') + MAGENTA = ('\033[0m', '\033[0;35m') TEST_EXIT_PASSED = 0 TEST_EXIT_SKIPPED = 77 +STATUS_PASSED = "Passed" +STATUS_PASSED_WITH_WARNINGS = "Passed with warnings" +STATUS_SKIPPED = "Skipped" +STATUS_FAILED = "Failed" +STATUSES = [STATUS_PASSED, STATUS_PASSED_WITH_WARNINGS, STATUS_SKIPPED, STATUS_FAILED] + +STATUS_MAX_LEN = max([len(st) for st in STATUSES]) + BASE_SCRIPTS= [ # Scripts that are run by the travis build process. # Longest test should go first, to favor running tests in parallel @@ -306,9 +316,11 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove test_result, stdout, stderr = job_queue.get_next() test_results.append(test_result) - if test_result.status == "Passed": + if test_result.status == STATUS_PASSED: logging.debug("\n%s%s%s passed, Duration: %s s" % (BOLD[1], test_result.name, BOLD[0], test_result.time)) - elif test_result.status == "Skipped": + elif test_result.status == STATUS_PASSED_WITH_WARNINGS: + logging.debug("\n%s%s%s passed with warnings, Duration: %s s" % (BOLD[1], test_result.name, BOLD[0], test_result.time)) + elif test_result.status == STATUS_SKIPPED: logging.debug("\n%s%s%s skipped" % (BOLD[1], test_result.name, BOLD[0])) else: print("\n%s%s%s failed, Duration: %s s\n" % (BOLD[1], test_result.name, BOLD[0], test_result.time)) @@ -332,7 +344,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove sys.exit(not all_passed) def print_results(test_results, max_len_name, runtime): - results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] + results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), " STATUS".ljust(STATUS_MAX_LEN + 2), "DURATION") + BOLD[0] test_results.sort(key=lambda result: result.name.lower()) all_passed = True @@ -345,7 +357,7 @@ def print_results(test_results, max_len_name, runtime): results += str(test_result) status = TICK + "Passed" if all_passed else CROSS + "Failed" - results += BOLD[1] + "\n%s | %s | %s s (accumulated) \n" % ("ALL".ljust(max_len_name), status.ljust(9), time_sum) + BOLD[0] + results += BOLD[1] + "\n%s | %s | %s s (accumulated) \n" % ("ALL".ljust(max_len_name), status.ljust(STATUS_MAX_LEN + 2), time_sum) + BOLD[0] results += "Runtime: %s s\n" % (runtime) print(results) @@ -403,11 +415,13 @@ def get_next(self): [stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)] log_out.close(), log_err.close() if proc.returncode == TEST_EXIT_PASSED and stderr == "": - status = "Passed" + status = STATUS_PASSED + elif proc.returncode == TEST_EXIT_PASSED: + status = STATUS_PASSED_WITH_WARNINGS elif proc.returncode == TEST_EXIT_SKIPPED: - status = "Skipped" + status = STATUS_SKIPPED else: - status = "Failed" + status = STATUS_FAILED self.num_running -= 1 self.jobs.remove(j) @@ -422,17 +436,20 @@ def __init__(self, name, status, time): self.padding = 0 def __repr__(self): - if self.status == "Passed": + if self.status == STATUS_PASSED: color = BLUE glyph = TICK - elif self.status == "Failed": - color = RED - glyph = CROSS - elif self.status == "Skipped": + if self.status == STATUS_PASSED_WITH_WARNINGS: + color = MAGENTA + glyph = TICK + elif self.status == STATUS_SKIPPED: color = GREY glyph = CIRCLE + elif self.status == STATUS_FAILED: + color = RED + glyph = CROSS - return color[1] + "%s | %s%s | %s s\n" % (self.name.ljust(self.padding), glyph, self.status.ljust(7), self.time) + color[0] + return color[1] + "%s | %s%s | %s s\n" % (self.name.ljust(self.padding), glyph, self.status.ljust(STATUS_MAX_LEN), self.time) + color[0] @property def was_successful(self): From f2f1d0a83e176f5fa105becdaa6398ec993630f0 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 26 Jun 2017 23:23:48 -0400 Subject: [PATCH 015/148] document script-based return fields for validateaddress --- src/rpc/misc.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index ef19e481c2d..fcbbe1ceed0 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -174,6 +174,14 @@ UniValue validateaddress(const JSONRPCRequest& request) " \"ismine\" : true|false, (boolean) If the address is yours or not\n" " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" + " \"script\" : \"type\" (string, optional) The output script type. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash\n" + " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n" + " \"addresses\" (string, optional) Array of addresses associated with the known redeemscript\n" + " [\n" + " \"address\"\n" + " ,...\n" + " ]\n" + " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output\n" " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n" From 1cc251f50fb2f9cffa762b28e5d8685af4273663 Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Sun, 2 Jul 2017 02:48:00 +0000 Subject: [PATCH 016/148] Explicitly search for bdb5.3. Some systems do not symlink the major version to the minor version. --- build-aux/m4/bitcoin_find_bdb48.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-aux/m4/bitcoin_find_bdb48.m4 b/build-aux/m4/bitcoin_find_bdb48.m4 index 980f1e8f19c..b9bf7bf46e5 100644 --- a/build-aux/m4/bitcoin_find_bdb48.m4 +++ b/build-aux/m4/bitcoin_find_bdb48.m4 @@ -12,7 +12,7 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[ bdbpath=X bdb48path=X bdbdirlist= - for _vn in 4.8 48 4 5 ''; do + for _vn in 4.8 48 4 5 5.3 ''; do for _pfx in b lib ''; do bdbdirlist="$bdbdirlist ${_pfx}db${_vn}" done From 959dd8781ed8982df06b52dd3cecc996cf30f76d Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sun, 2 Jul 2017 21:57:24 +0200 Subject: [PATCH 017/148] Avoid printing incorrect block indexing time due to uninitialized variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: init.cpp: In function ‘bool AppInitMain(boost::thread_group&, CScheduler&)’: init.cpp:1499:56: warning: ‘nStart’ may be used uninitialized in this function [-Wmaybe-uninitialized] LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); ^ --- src/init.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 672ef77e80f..61b26d3618c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1496,7 +1496,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Shutdown requested. Exiting.\n"); return false; } - LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); + if (fLoaded) { + LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); + } fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION); From ff6a834fc32b25376e221fefa8c2a2565b4167cc Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 26 Apr 2017 20:13:24 -0400 Subject: [PATCH 018/148] Use TestingSetup to DRY qt rpcnestedtests --- src/qt/test/rpcnestedtests.cpp | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 26dec3c6108..fbad9e544ae 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -12,6 +12,7 @@ #include "rpc/server.h" #include "rpcconsole.h" #include "test/testutil.h" +#include "test/test_bitcoin.h" #include "univalue.h" #include "util.h" @@ -35,8 +36,6 @@ void RPCNestedTests::rpcNestedTests() { // 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); tableRPC.appendCommand("rpcNestedTest", &vRPCCommands[0]); ClearDatadirCache(); std::string path = QDir::tempPath().toStdString() + "/" + strprintf("test_bitcoin_qt_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); @@ -44,15 +43,8 @@ void RPCNestedTests::rpcNestedTests() dir.mkpath("."); ForceSetArg("-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); - } + + TestingSetup test; SetRPCWarmupFinished(); @@ -145,13 +137,5 @@ void RPCNestedTests::rpcNestedTests() QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using , #endif - UnloadBlockIndex(); - delete pcoinsTip; - pcoinsTip = nullptr; - delete pcoinsdbview; - pcoinsdbview = nullptr; - delete pblocktree; - pblocktree = nullptr; - fs::remove_all(fs::path(path)); } From 3a19fed9db558a5f666d965b6f602f7faf74ab73 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 19 Jan 2017 16:17:14 -0500 Subject: [PATCH 019/148] Make ValidationInterface signals-type-agnostic (by hiding boost::signals stuff in the .cpp) This allows us to give it a bit more intelligence as we move forward, including routing some signals through CScheduler. While the introduction of a "internals" pointer in the class is pretty ugly, the fact that we no longer need to include boost/signals directly from validationinterface.h is very much worth the loss. --- src/validationinterface.cpp | 108 +++++++++++++++++++++++++++++++++----------- src/validationinterface.h | 62 ++++++++++++++----------- 2 files changed, 117 insertions(+), 53 deletions(-) diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index be2f20b8635..7d0ab756e8e 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -5,45 +5,99 @@ #include "validationinterface.h" +#include + +struct MainSignalsInstance { + boost::signals2::signal UpdatedBlockTip; + boost::signals2::signal TransactionAddedToMempool; + boost::signals2::signal &, const CBlockIndex *pindex, const std::vector&)> BlockConnected; + boost::signals2::signal &)> BlockDisconnected; + boost::signals2::signal SetBestChain; + boost::signals2::signal Inventory; + boost::signals2::signal Broadcast; + boost::signals2::signal BlockChecked; + boost::signals2::signal&)> NewPoWValidBlock; +}; + static CMainSignals g_signals; +CMainSignals::CMainSignals() { + m_internals.reset(new MainSignalsInstance()); +} + CMainSignals& GetMainSignals() { return g_signals; } void RegisterValidationInterface(CValidationInterface* pwalletIn) { - g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); - g_signals.TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); - g_signals.BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); - g_signals.BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); - g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); - g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); - g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); - g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); + g_signals.m_internals->UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); + g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); + g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); + g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); + g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); + g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); + g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); + g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); + g_signals.m_internals->NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); } void UnregisterValidationInterface(CValidationInterface* pwalletIn) { - g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); - g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); - g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); - g_signals.TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); - g_signals.BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); - g_signals.BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); - g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); - g_signals.NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); + g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); + g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); + g_signals.m_internals->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); + g_signals.m_internals->SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); + g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); + g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); + g_signals.m_internals->BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); + g_signals.m_internals->UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); + g_signals.m_internals->NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); } void UnregisterAllValidationInterfaces() { - g_signals.BlockChecked.disconnect_all_slots(); - g_signals.Broadcast.disconnect_all_slots(); - g_signals.Inventory.disconnect_all_slots(); - g_signals.SetBestChain.disconnect_all_slots(); - g_signals.TransactionAddedToMempool.disconnect_all_slots(); - g_signals.BlockConnected.disconnect_all_slots(); - g_signals.BlockDisconnected.disconnect_all_slots(); - g_signals.UpdatedBlockTip.disconnect_all_slots(); - g_signals.NewPoWValidBlock.disconnect_all_slots(); + g_signals.m_internals->BlockChecked.disconnect_all_slots(); + g_signals.m_internals->Broadcast.disconnect_all_slots(); + g_signals.m_internals->Inventory.disconnect_all_slots(); + g_signals.m_internals->SetBestChain.disconnect_all_slots(); + g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots(); + g_signals.m_internals->BlockConnected.disconnect_all_slots(); + g_signals.m_internals->BlockDisconnected.disconnect_all_slots(); + g_signals.m_internals->UpdatedBlockTip.disconnect_all_slots(); + g_signals.m_internals->NewPoWValidBlock.disconnect_all_slots(); +} + +void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { + m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); +} + +void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) { + m_internals->TransactionAddedToMempool(ptx); +} + +void CMainSignals::BlockConnected(const std::shared_ptr &pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) { + m_internals->BlockConnected(pblock, pindex, vtxConflicted); +} + +void CMainSignals::BlockDisconnected(const std::shared_ptr &pblock) { + m_internals->BlockDisconnected(pblock); +} + +void CMainSignals::SetBestChain(const CBlockLocator &locator) { + m_internals->SetBestChain(locator); +} + +void CMainSignals::Inventory(const uint256 &hash) { + m_internals->Inventory(hash); +} + +void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) { + m_internals->Broadcast(nBestBlockTime, connman); +} + +void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) { + m_internals->BlockChecked(block, state); +} + +void CMainSignals::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr &block) { + m_internals->NewPoWValidBlock(pindex, block); } diff --git a/src/validationinterface.h b/src/validationinterface.h index 17545018df7..c248781a48e 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -6,7 +6,6 @@ #ifndef BITCOIN_VALIDATIONINTERFACE_H #define BITCOIN_VALIDATIONINTERFACE_H -#include #include #include "primitives/transaction.h" // CTransaction(Ref) @@ -32,49 +31,60 @@ void UnregisterAllValidationInterfaces(); class CValidationInterface { protected: - virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} - virtual void TransactionAddedToMempool(const CTransactionRef &ptxn) {} - virtual void BlockConnected(const std::shared_ptr &block, const CBlockIndex *pindex, const std::vector &txnConflicted) {} - virtual void BlockDisconnected(const std::shared_ptr &block) {} - virtual void SetBestChain(const CBlockLocator &locator) {} - virtual void Inventory(const uint256 &hash) {} - virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {} - virtual void BlockChecked(const CBlock&, const CValidationState&) {} - virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& block) {}; - friend void ::RegisterValidationInterface(CValidationInterface*); - friend void ::UnregisterValidationInterface(CValidationInterface*); - friend void ::UnregisterAllValidationInterfaces(); -}; - -struct CMainSignals { /** Notifies listeners of updated block chain tip */ - boost::signals2::signal UpdatedBlockTip; + virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} /** Notifies listeners of a transaction having been added to mempool. */ - boost::signals2::signal TransactionAddedToMempool; + virtual void TransactionAddedToMempool(const CTransactionRef &ptxn) {} /** * Notifies listeners of a block being connected. * Provides a vector of transactions evicted from the mempool as a result. */ - boost::signals2::signal &, const CBlockIndex *pindex, const std::vector &)> BlockConnected; + virtual void BlockConnected(const std::shared_ptr &block, const CBlockIndex *pindex, const std::vector &txnConflicted) {} /** Notifies listeners of a block being disconnected */ - boost::signals2::signal &)> BlockDisconnected; - /** Notifies listeners of a new active block chain. */ - boost::signals2::signal SetBestChain; + virtual void BlockDisconnected(const std::shared_ptr &block) {} + /** Notifies listeners of the new active block chain on-disk. */ + virtual void SetBestChain(const CBlockLocator &locator) {} /** Notifies listeners about an inventory item being seen on the network. */ - boost::signals2::signal Inventory; + virtual void Inventory(const uint256 &hash) {} /** Tells listeners to broadcast their data. */ - boost::signals2::signal Broadcast; + virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {} /** * Notifies listeners of a block validation result. * If the provided CValidationState IsValid, the provided block * is guaranteed to be the current best block at the time the * callback was generated (not necessarily now) */ - boost::signals2::signal BlockChecked; + virtual void BlockChecked(const CBlock&, const CValidationState&) {} /** * Notifies listeners that a block which builds directly on our current tip * has been received and connected to the headers tree, though not validated yet */ - boost::signals2::signal&)> NewPoWValidBlock; + virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& block) {}; + friend void ::RegisterValidationInterface(CValidationInterface*); + friend void ::UnregisterValidationInterface(CValidationInterface*); + friend void ::UnregisterAllValidationInterfaces(); +}; + +struct MainSignalsInstance; +class CMainSignals { +private: + std::unique_ptr m_internals; + + friend void ::RegisterValidationInterface(CValidationInterface*); + friend void ::UnregisterValidationInterface(CValidationInterface*); + friend void ::UnregisterAllValidationInterfaces(); +public: + CMainSignals(); + + void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); + void TransactionAddedToMempool(const CTransactionRef &); + void BlockConnected(const std::shared_ptr &, const CBlockIndex *pindex, const std::vector &); + void BlockDisconnected(const std::shared_ptr &); + void UpdatedTransaction(const uint256 &); + void SetBestChain(const CBlockLocator &); + void Inventory(const uint256 &); + void Broadcast(int64_t nBestBlockTime, CConnman* connman); + void BlockChecked(const CBlock&, const CValidationState&); + void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr&); }; CMainSignals& GetMainSignals(); From 58e9864083118b538a46124f034c18dd582f4209 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 5 Jul 2017 12:09:58 +0100 Subject: [PATCH 020/148] [rpc] fix verbose argument for getblock in bitcoin-cli --- src/rpc/client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index cb1539dce5b..e87210003bb 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -79,6 +79,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listunspent", 3, "include_unsafe" }, { "listunspent", 4, "query_options" }, { "getblock", 1, "verbosity" }, + { "getblock", 1, "verbose" }, { "getblockheader", 1, "verbose" }, { "getchaintxstats", 0, "nblocks" }, { "gettransaction", 1, "include_watchonly" }, From cfaef69ace6c52aeb4ce347597c6dae61bdce744 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Tue, 13 Jun 2017 10:41:14 -0400 Subject: [PATCH 021/148] remove default argument from GetMinimumFee --- src/qt/coincontroldialog.cpp | 2 +- src/wallet/wallet.cpp | 2 +- src/wallet/wallet.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index af9a888d94f..10a8d6b8873 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -510,7 +510,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) nBytes -= 34; // Fee - nPayFee = CWallet::GetMinimumFee(nBytes, coinControl->nConfirmTarget, ::mempool, ::feeEstimator); + nPayFee = CWallet::GetMinimumFee(nBytes, coinControl->nConfirmTarget, ::mempool, ::feeEstimator, nullptr /* FeeCalculation */, false /* ignoreGlobalPayTxFee */); if (nPayAmount > 0) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 0d1a86dd244..4b00404d2ae 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2724,7 +2724,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT if (coinControl && coinControl->nConfirmTarget > 0) currentConfirmationTarget = coinControl->nConfirmTarget; - CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator, &feeCalc); + CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator, &feeCalc, false /* ignoreGlobalPayTxFee */); if (coinControl && coinControl->fOverrideFeeRate) nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 4f558adc772..232673a2f76 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -963,7 +963,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Estimate the minimum fee considering user set parameters * and the required fee */ - static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc = nullptr, bool ignoreGlobalPayTxFee = false); + static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee); /** * Return the minimum required fee taking into account the * floating relay fee and user set minimum transaction fee From d507c301bc49c72ed7303658a309e7d204134f80 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Tue, 13 Jun 2017 11:28:30 -0400 Subject: [PATCH 022/148] Introduce a fee estimate mode. GetMinimumFee now passes the conservative argument into estimateSmartFee. Call CalculateEstimateType(mode) before calling GetMinimumFee or estimateSmartFee to determine the value of this argument. CCoinControl can now be used to control this mode. --- src/policy/fees.h | 7 +++++++ src/qt/coincontroldialog.cpp | 6 ++++-- src/qt/sendcoinsdialog.cpp | 3 ++- src/qt/walletmodel.cpp | 1 + src/wallet/coincontrol.h | 4 ++++ src/wallet/feebumper.cpp | 3 ++- src/wallet/wallet.cpp | 20 +++++++++++++++++--- src/wallet/wallet.h | 6 +++++- 8 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/policy/fees.h b/src/policy/fees.h index 2029ce37448..8a98e555208 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -90,6 +90,13 @@ enum class FeeReason { std::string StringForFeeReason(FeeReason reason); +/* Used to determine type of fee estimation requested */ +enum class FeeEstimateMode { + UNSET, //! Use default settings based on other criteria + ECONOMICAL, //! Force estimateSmartFee to use non-conservative estimates + CONSERVATIVE, //! Force estimateSmartFee to use conservative estimates +}; + /* Used to return detailed information about a feerate bucket */ struct EstimatorBucket { diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 10a8d6b8873..477cee1c041 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -490,6 +490,8 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) else nBytesInputs += 148; } + bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET); + // calculation if (nQuantity > 0) { @@ -510,7 +512,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) nBytes -= 34; // Fee - nPayFee = CWallet::GetMinimumFee(nBytes, coinControl->nConfirmTarget, ::mempool, ::feeEstimator, nullptr /* FeeCalculation */, false /* ignoreGlobalPayTxFee */); + nPayFee = CWallet::GetMinimumFee(nBytes, coinControl->nConfirmTarget, ::mempool, ::feeEstimator, nullptr /* FeeCalculation */, false /* ignoreGlobalPayTxFee */, conservative_estimate); if (nPayAmount > 0) { @@ -585,7 +587,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) if (payTxFee.GetFeePerK() > 0) dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000; else { - dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(coinControl->nConfirmTarget, NULL, ::mempool).GetFeePerK()) / 1000; + dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(coinControl->nConfirmTarget, NULL, ::mempool, conservative_estimate).GetFeePerK()) / 1000; } QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 12d2d0f31cd..d9439fe248c 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -652,7 +652,8 @@ void SendCoinsDialog::updateSmartFeeLabel() int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; FeeCalculation feeCalc; - CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &feeCalc, ::mempool); + bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET); + CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &feeCalc, ::mempool, conservative_estimate); if (feeRate <= CFeeRate(0)) // not enough data => minfee { ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 7eff783fe84..354225090f7 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -19,6 +19,7 @@ #include "keystore.h" #include "validation.h" #include "net.h" // for g_connman +#include "policy/fees.h" #include "policy/rbf.h" #include "sync.h" #include "ui_interface.h" diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index cb4719ae90c..bdd01bec12a 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -6,6 +6,7 @@ #define BITCOIN_WALLET_COINCONTROL_H #include "policy/feerate.h" +#include "policy/fees.h" #include "primitives/transaction.h" #include "wallet/wallet.h" @@ -26,6 +27,8 @@ class CCoinControl int nConfirmTarget; //! Signal BIP-125 replace by fee. bool signalRbf; + //! Fee estimation mode to control arguments to estimateSmartFee + FeeEstimateMode m_fee_mode; CCoinControl() { @@ -42,6 +45,7 @@ class CCoinControl fOverrideFeeRate = false; nConfirmTarget = 0; signalRbf = fWalletRbf; + m_fee_mode = FeeEstimateMode::UNSET; } bool HasSelected() const diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index 6a9e6cf9ffb..a36f6798f0f 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -165,7 +165,8 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf nNewFee = totalFee; nNewFeeRate = CFeeRate(totalFee, maxNewTxSize); } else { - nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, nullptr, ignoreGlobalPayTxFee); + bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET); + nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, nullptr /* FeeCalculation */, ignoreGlobalPayTxFee, conservative_estimate); nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize); // New fee rate must be at least old rate + minimum incremental relay rate diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4b00404d2ae..a43b5398e04 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2724,7 +2724,10 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT if (coinControl && coinControl->nConfirmTarget > 0) currentConfirmationTarget = coinControl->nConfirmTarget; - CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator, &feeCalc, false /* ignoreGlobalPayTxFee */); + // Allow to override the default fee estimate mode over the CoinControl instance + bool conservative_estimate = CalculateEstimateType(coinControl ? coinControl->m_fee_mode : FeeEstimateMode::UNSET); + + CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator, &feeCalc, false /* ignoreGlobalPayTxFee */, conservative_estimate); if (coinControl && coinControl->fOverrideFeeRate) nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes); @@ -2905,13 +2908,13 @@ CAmount CWallet::GetRequiredFee(unsigned int nTxBytes) return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes)); } -CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee) +CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee, bool conservative_estimate) { // payTxFee is the user-set global for desired feerate CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes); // User didn't set: use -txconfirmtarget to estimate... if (nFeeNeeded == 0 || ignoreGlobalPayTxFee) { - nFeeNeeded = estimator.estimateSmartFee(nConfirmTarget, feeCalc, pool, true).GetFee(nTxBytes); + nFeeNeeded = estimator.estimateSmartFee(nConfirmTarget, feeCalc, pool, conservative_estimate).GetFee(nTxBytes); // ... unless we don't have enough mempool data for estimatefee, then use fallbackFee if (nFeeNeeded == 0) { nFeeNeeded = fallbackFee.GetFee(nTxBytes); @@ -4154,3 +4157,14 @@ bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& { return ::AcceptToMemoryPool(mempool, state, tx, true, NULL, NULL, false, nAbsurdFee); } + +bool CalculateEstimateType(FeeEstimateMode mode) { + switch (mode) { + case FeeEstimateMode::UNSET: + case FeeEstimateMode::CONSERVATIVE: + return true; + case FeeEstimateMode::ECONOMICAL: + return false; + } + return true; +} diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 232673a2f76..813bf530acf 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -80,6 +80,7 @@ class CTxMemPool; class CBlockPolicyEstimator; class CWalletTx; struct FeeCalculation; +enum class FeeEstimateMode; /** (client) version numbers for particular wallet features */ enum WalletFeature @@ -963,7 +964,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Estimate the minimum fee considering user set parameters * and the required fee */ - static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee); + static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee, bool conservative_estimate); /** * Return the minimum required fee taking into account the * floating relay fee and user set minimum transaction fee @@ -1211,4 +1212,7 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const ContainerType &coins } return true; } + +bool CalculateEstimateType(FeeEstimateMode mode); + #endif // BITCOIN_WALLET_WALLET_H From e0738e3d319ab50466bf76c95841bb7275ad4d22 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Tue, 13 Jun 2017 13:44:52 -0400 Subject: [PATCH 023/148] remove default argument from estimateSmartFee --- src/policy/fees.h | 2 +- src/test/policyestimator_tests.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/policy/fees.h b/src/policy/fees.h index 8a98e555208..059415418dd 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -204,7 +204,7 @@ class CBlockPolicyEstimator * the closest target where one can be given. 'conservative' estimates are * valid over longer time horizons also. */ - CFeeRate estimateSmartFee(int confTarget, FeeCalculation *feeCalc, const CTxMemPool& pool, bool conservative = true) const; + CFeeRate estimateSmartFee(int confTarget, FeeCalculation *feeCalc, const CTxMemPool& pool, bool conservative) const; /** Return a specific fee estimate calculation with a given success * threshold and time horizon, and optionally return detailed data about diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 6bfd3156473..8cdd3921096 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -184,8 +184,8 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) mpool.TrimToSize(1); BOOST_CHECK(mpool.GetMinFee(1).GetFeePerK() > feeV[5]); for (int i = 1; i < 10; i++) { - BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool).GetFeePerK() >= feeEst.estimateRawFee(i, 0.85, FeeEstimateHorizon::MED_HALFLIFE).GetFeePerK()); - BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool).GetFeePerK() >= mpool.GetMinFee(1).GetFeePerK()); + BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool, true).GetFeePerK() >= feeEst.estimateRawFee(i, 0.85, FeeEstimateHorizon::MED_HALFLIFE).GetFeePerK()); + BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool, true).GetFeePerK() >= mpool.GetMinFee(1).GetFeePerK()); } } From f0bf33da8357bd6aff100bbe5b84a7f01937e379 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Tue, 13 Jun 2017 14:02:55 -0400 Subject: [PATCH 024/148] Change default fee estimation mode. Fee estimates will default to be non-conservative if the transaction in question is opt-in-RBF. --- src/qt/coincontroldialog.cpp | 2 +- src/qt/sendcoinsdialog.cpp | 5 ++++- src/wallet/feebumper.cpp | 2 +- src/wallet/wallet.cpp | 5 +++-- src/wallet/wallet.h | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 477cee1c041..c19420beb56 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -490,7 +490,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) else nBytesInputs += 148; } - bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET); + bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, coinControl->signalRbf); // calculation if (nQuantity > 0) diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index d9439fe248c..27634eb179b 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -166,6 +166,8 @@ void SendCoinsDialog::setModel(WalletModel *_model) connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls())); connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables())); connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels())); + connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(updateSmartFeeLabel())); + connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels())); ui->customFee->setSingleStep(CWallet::GetRequiredFee(1000)); updateFeeSectionControls(); updateMinFeeLabel(); @@ -652,7 +654,7 @@ void SendCoinsDialog::updateSmartFeeLabel() int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; FeeCalculation feeCalc; - bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET); + bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, ui->optInRBF->isChecked()); CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &feeCalc, ::mempool, conservative_estimate); if (feeRate <= CFeeRate(0)) // not enough data => minfee { @@ -828,6 +830,7 @@ void SendCoinsDialog::coinControlUpdateLabels() } else { CoinControlDialog::coinControl->nConfirmTarget = model->getDefaultConfirmTarget(); } + CoinControlDialog::coinControl->signalRbf = ui->optInRBF->isChecked(); for(int i = 0; i < ui->entries->count(); ++i) { diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index a36f6798f0f..a25530d8bdb 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -165,7 +165,7 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf nNewFee = totalFee; nNewFeeRate = CFeeRate(totalFee, maxNewTxSize); } else { - bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET); + bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, newTxReplaceable); nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, nullptr /* FeeCalculation */, ignoreGlobalPayTxFee, conservative_estimate); nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a43b5398e04..9a5f6b27919 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2725,7 +2725,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT currentConfirmationTarget = coinControl->nConfirmTarget; // Allow to override the default fee estimate mode over the CoinControl instance - bool conservative_estimate = CalculateEstimateType(coinControl ? coinControl->m_fee_mode : FeeEstimateMode::UNSET); + bool conservative_estimate = CalculateEstimateType(coinControl ? coinControl->m_fee_mode : FeeEstimateMode::UNSET, rbf); CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator, &feeCalc, false /* ignoreGlobalPayTxFee */, conservative_estimate); if (coinControl && coinControl->fOverrideFeeRate) @@ -4158,9 +4158,10 @@ bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& return ::AcceptToMemoryPool(mempool, state, tx, true, NULL, NULL, false, nAbsurdFee); } -bool CalculateEstimateType(FeeEstimateMode mode) { +bool CalculateEstimateType(FeeEstimateMode mode, bool opt_in_rbf) { switch (mode) { case FeeEstimateMode::UNSET: + return !opt_in_rbf; // Allow for lower fees if RBF is an option case FeeEstimateMode::CONSERVATIVE: return true; case FeeEstimateMode::ECONOMICAL: diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 813bf530acf..e3715cdf376 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1213,6 +1213,6 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const ContainerType &coins return true; } -bool CalculateEstimateType(FeeEstimateMode mode); +bool CalculateEstimateType(FeeEstimateMode mode, bool opt_in_rbf); #endif // BITCOIN_WALLET_WALLET_H From cda1429d5bfee129a0d1f6f1c65962b30251bafb Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 19 Jan 2017 16:49:22 -0500 Subject: [PATCH 025/148] Give CMainSignals a reference to the global scheduler ...so that it can run some signals in the background later --- src/init.cpp | 3 +++ src/test/test_bitcoin.cpp | 7 +++++++ src/test/test_bitcoin.h | 2 ++ src/validationinterface.cpp | 13 +++++++++++++ src/validationinterface.h | 7 +++++++ 5 files changed, 32 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 672ef77e80f..94bba6820e4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -251,6 +251,7 @@ void Shutdown() } #endif UnregisterAllValidationInterfaces(); + GetMainSignals().UnregisterBackgroundSignalScheduler(); #ifdef ENABLE_WALLET for (CWalletRef pwallet : vpwallets) { delete pwallet; @@ -1203,6 +1204,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler); threadGroup.create_thread(boost::bind(&TraceThread, "scheduler", serviceLoop)); + GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); + /* Start the RPC server already. It will be started in "warmup" mode * and not really process calls already (but it will signify connections * that the server is there and will be ready later). Warmup mode will diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 579e96524cc..e6a8cc779db 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -62,6 +62,12 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000))); fs::create_directories(pathTemp); ForceSetArg("-datadir", pathTemp.string()); + + // Note that because we don't bother running a scheduler thread here, + // callbacks via CValidationInterface are unreliable, but that's OK, + // our unit tests aren't testing multiple parts of the code at once. + GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); + mempool.setSanityCheck(1.0); pblocktree = new CBlockTreeDB(1 << 20, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true); @@ -88,6 +94,7 @@ TestingSetup::~TestingSetup() UnregisterNodeSignals(GetNodeSignals()); threadGroup.interrupt_all(); threadGroup.join_all(); + GetMainSignals().UnregisterBackgroundSignalScheduler(); UnloadBlockIndex(); delete pcoinsTip; delete pcoinsdbview; diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index c9e4a3427fc..dd3b13c8c89 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -10,6 +10,7 @@ #include "key.h" #include "pubkey.h" #include "random.h" +#include "scheduler.h" #include "txdb.h" #include "txmempool.h" @@ -53,6 +54,7 @@ struct TestingSetup: public BasicTestingSetup { fs::path pathTemp; boost::thread_group threadGroup; CConnman* connman; + CScheduler scheduler; TestingSetup(const std::string& chainName = CBaseChainParams::MAIN); ~TestingSetup(); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 7d0ab756e8e..a17a08eee2a 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -4,6 +4,8 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "validationinterface.h" +#include "init.h" +#include "scheduler.h" #include @@ -17,6 +19,8 @@ struct MainSignalsInstance { boost::signals2::signal Broadcast; boost::signals2::signal BlockChecked; boost::signals2::signal&)> NewPoWValidBlock; + + CScheduler *m_scheduler = NULL; }; static CMainSignals g_signals; @@ -25,6 +29,15 @@ CMainSignals::CMainSignals() { m_internals.reset(new MainSignalsInstance()); } +void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) { + assert(!m_internals->m_scheduler); + m_internals->m_scheduler = &scheduler; +} + +void CMainSignals::UnregisterBackgroundSignalScheduler() { + m_internals->m_scheduler = NULL; +} + CMainSignals& GetMainSignals() { return g_signals; diff --git a/src/validationinterface.h b/src/validationinterface.h index c248781a48e..8cae3c6db4e 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -19,6 +19,7 @@ class CReserveScript; class CValidationInterface; class CValidationState; class uint256; +class CScheduler; // These functions dispatch to one or all registered wallets @@ -72,9 +73,15 @@ class CMainSignals { friend void ::RegisterValidationInterface(CValidationInterface*); friend void ::UnregisterValidationInterface(CValidationInterface*); friend void ::UnregisterAllValidationInterfaces(); + public: CMainSignals(); + /** Register a CScheduler to give callbacks which should run in the background (may only be called once) */ + void RegisterBackgroundSignalScheduler(CScheduler& scheduler); + /** Unregister a CScheduler to give callbacks which should run in the background - these callbacks will now be dropped! */ + void UnregisterBackgroundSignalScheduler(); + void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); void TransactionAddedToMempool(const CTransactionRef &); void BlockConnected(const std::shared_ptr &, const CBlockIndex *pindex, const std::vector &); From 2fbf2dbe151e135586cc1bb05b891f2c8ab6c817 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 20 Jan 2017 15:10:43 -0500 Subject: [PATCH 026/148] Add default arg to CScheduler to schedule() a callback now --- src/scheduler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scheduler.h b/src/scheduler.h index 27412a15b46..5da6e6f69f1 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -41,7 +41,7 @@ class CScheduler typedef std::function Function; // Call func at/after time t - void schedule(Function f, boost::chrono::system_clock::time_point t); + void schedule(Function f, boost::chrono::system_clock::time_point t=boost::chrono::system_clock::now()); // Convenience method: call f once deltaSeconds from now void scheduleFromNow(Function f, int64_t deltaMilliSeconds); From 08096bbbc6d6fef86943ca8ce5e6de18744d58ea Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 10 Apr 2017 14:55:49 -0400 Subject: [PATCH 027/148] Support more than one CScheduler thread for serial clients This will be used by CValidationInterface soon. This requires a bit of work as we need to ensure that most of our callbacks happen in-order (to avoid synchronization issues in wallet) - we keep our own internal queue and push things onto it, scheduling a queue-draining function immediately upon new callbacks. --- src/scheduler.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++ src/scheduler.h | 24 +++++++++++++++++++++ src/validationinterface.cpp | 22 ++++++++++++------- src/validationinterface.h | 2 -- 4 files changed, 90 insertions(+), 10 deletions(-) diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 923ba2c231e..a76a87e10a6 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -139,3 +139,55 @@ size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first, } return result; } + + +void SingleThreadedSchedulerClient::MaybeScheduleProcessQueue() { + { + LOCK(m_cs_callbacks_pending); + // Try to avoid scheduling too many copies here, but if we + // accidentally have two ProcessQueue's scheduled at once its + // not a big deal. + if (m_are_callbacks_running) return; + if (m_callbacks_pending.empty()) return; + } + m_pscheduler->schedule(std::bind(&SingleThreadedSchedulerClient::ProcessQueue, this)); +} + +void SingleThreadedSchedulerClient::ProcessQueue() { + std::function callback; + { + LOCK(m_cs_callbacks_pending); + if (m_are_callbacks_running) return; + if (m_callbacks_pending.empty()) return; + m_are_callbacks_running = true; + + callback = std::move(m_callbacks_pending.front()); + m_callbacks_pending.pop_front(); + } + + // RAII the setting of fCallbacksRunning and calling MaybeScheduleProcessQueue + // to ensure both happen safely even if callback() throws. + struct RAIICallbacksRunning { + SingleThreadedSchedulerClient* instance; + RAIICallbacksRunning(SingleThreadedSchedulerClient* _instance) : instance(_instance) {} + ~RAIICallbacksRunning() { + { + LOCK(instance->m_cs_callbacks_pending); + instance->m_are_callbacks_running = false; + } + instance->MaybeScheduleProcessQueue(); + } + } raiicallbacksrunning(this); + + callback(); +} + +void SingleThreadedSchedulerClient::AddToProcessQueue(std::function func) { + assert(m_pscheduler); + + { + LOCK(m_cs_callbacks_pending); + m_callbacks_pending.emplace_back(std::move(func)); + } + MaybeScheduleProcessQueue(); +} diff --git a/src/scheduler.h b/src/scheduler.h index 5da6e6f69f1..82036afdf02 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -14,6 +14,8 @@ #include #include +#include "sync.h" + // // Simple class for background tasks that should be run // periodically or once "after a while" @@ -79,4 +81,26 @@ class CScheduler bool shouldStop() { return stopRequested || (stopWhenEmpty && taskQueue.empty()); } }; +/** + * Class used by CScheduler clients which may schedule multiple jobs + * which are required to be run serially. Does not require such jobs + * to be executed on the same thread, but no two jobs will be executed + * at the same time. + */ +class SingleThreadedSchedulerClient { +private: + CScheduler *m_pscheduler; + + CCriticalSection m_cs_callbacks_pending; + std::list> m_callbacks_pending; + bool m_are_callbacks_running = false; + + void MaybeScheduleProcessQueue(); + void ProcessQueue(); + +public: + SingleThreadedSchedulerClient(CScheduler *pschedulerIn) : m_pscheduler(pschedulerIn) {} + void AddToProcessQueue(std::function func); +}; + #endif diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index a17a08eee2a..8edc7c398da 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -6,6 +6,11 @@ #include "validationinterface.h" #include "init.h" #include "scheduler.h" +#include "sync.h" +#include "util.h" + +#include +#include #include @@ -20,22 +25,23 @@ struct MainSignalsInstance { boost::signals2::signal BlockChecked; boost::signals2::signal&)> NewPoWValidBlock; - CScheduler *m_scheduler = NULL; + // We are not allowed to assume the scheduler only runs in one thread, + // but must ensure all callbacks happen in-order, so we end up creating + // our own queue here :( + SingleThreadedSchedulerClient m_schedulerClient; + + MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {} }; static CMainSignals g_signals; -CMainSignals::CMainSignals() { - m_internals.reset(new MainSignalsInstance()); -} - void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) { - assert(!m_internals->m_scheduler); - m_internals->m_scheduler = &scheduler; + assert(!m_internals); + m_internals.reset(new MainSignalsInstance(&scheduler)); } void CMainSignals::UnregisterBackgroundSignalScheduler() { - m_internals->m_scheduler = NULL; + m_internals.reset(nullptr); } CMainSignals& GetMainSignals() diff --git a/src/validationinterface.h b/src/validationinterface.h index 8cae3c6db4e..fbfe273b10c 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -75,8 +75,6 @@ class CMainSignals { friend void ::UnregisterAllValidationInterfaces(); public: - CMainSignals(); - /** Register a CScheduler to give callbacks which should run in the background (may only be called once) */ void RegisterBackgroundSignalScheduler(CScheduler& scheduler); /** Unregister a CScheduler to give callbacks which should run in the background - these callbacks will now be dropped! */ From 3192975f1d177aa9f0bbd823c6387cfbfa943610 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 27 Jun 2017 19:07:52 -0400 Subject: [PATCH 028/148] Flush CValidationInterface callbacks prior to destruction Note that the CScheduler thread cant be running at this point, it has already been stopped with the rest of the init threadgroup. Thus, just calling any remaining loose callbacks during Shutdown() is sane. --- src/init.cpp | 13 +++++++++++++ src/scheduler.cpp | 9 +++++++++ src/scheduler.h | 3 +++ src/test/test_bitcoin.cpp | 1 + src/validationinterface.cpp | 4 ++++ src/validationinterface.h | 2 ++ 6 files changed, 32 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 94bba6820e4..12f29a4ca87 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -215,6 +215,19 @@ void Shutdown() fFeeEstimatesInitialized = false; } + // FlushStateToDisk generates a SetBestChain callback, which we should avoid missing + FlushStateToDisk(); + + // After there are no more peers/RPC left to give us new data which may generate + // CValidationInterface callbacks, flush them... + GetMainSignals().FlushBackgroundCallbacks(); + + // Any future callbacks will be dropped. This should absolutely be safe - if + // missing a callback results in an unrecoverable situation, unclean shutdown + // would too. The only reason to do the above flushes is to let the wallet catch + // up with our current chain to avoid any strange pruning edge cases and make + // next startup faster by avoiding rescan. + { LOCK(cs_main); if (pcoinsTip != NULL) { diff --git a/src/scheduler.cpp b/src/scheduler.cpp index a76a87e10a6..35bf0da4bec 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -191,3 +191,12 @@ void SingleThreadedSchedulerClient::AddToProcessQueue(std::function } MaybeScheduleProcessQueue(); } + +void SingleThreadedSchedulerClient::EmptyQueue() { + bool should_continue = true; + while (should_continue) { + ProcessQueue(); + LOCK(m_cs_callbacks_pending); + should_continue = !m_callbacks_pending.empty(); + } +} diff --git a/src/scheduler.h b/src/scheduler.h index 82036afdf02..6a079f7749e 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -101,6 +101,9 @@ class SingleThreadedSchedulerClient { public: SingleThreadedSchedulerClient(CScheduler *pschedulerIn) : m_pscheduler(pschedulerIn) {} void AddToProcessQueue(std::function func); + + // Processes all remaining queue members on the calling thread, blocking until queue is empty + void EmptyQueue(); }; #endif diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index e6a8cc779db..3ba81ed17b5 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -94,6 +94,7 @@ TestingSetup::~TestingSetup() UnregisterNodeSignals(GetNodeSignals()); threadGroup.interrupt_all(); threadGroup.join_all(); + GetMainSignals().FlushBackgroundCallbacks(); GetMainSignals().UnregisterBackgroundSignalScheduler(); UnloadBlockIndex(); delete pcoinsTip; diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 8edc7c398da..bf20d606f83 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -44,6 +44,10 @@ void CMainSignals::UnregisterBackgroundSignalScheduler() { m_internals.reset(nullptr); } +void CMainSignals::FlushBackgroundCallbacks() { + m_internals->m_schedulerClient.EmptyQueue(); +} + CMainSignals& GetMainSignals() { return g_signals; diff --git a/src/validationinterface.h b/src/validationinterface.h index fbfe273b10c..568da66df28 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -79,6 +79,8 @@ class CMainSignals { void RegisterBackgroundSignalScheduler(CScheduler& scheduler); /** Unregister a CScheduler to give callbacks which should run in the background - these callbacks will now be dropped! */ void UnregisterBackgroundSignalScheduler(); + /** Call any remaining callbacks on the calling thread */ + void FlushBackgroundCallbacks(); void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); void TransactionAddedToMempool(const CTransactionRef &); From 0aadc11fd88b298c7af2dfb69763b2c67dc6b7b0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 7 Jul 2017 00:54:42 -0700 Subject: [PATCH 029/148] Avoid dereference-of-casted-pointer --- src/core_memusage.h | 2 +- src/primitives/transaction.h | 4 ++-- src/rpc/blockchain.cpp | 2 +- src/script/interpreter.cpp | 4 ++-- src/script/script.h | 8 ++++++++ src/test/dbwrapper_tests.cpp | 6 +++--- src/txdb.cpp | 2 +- src/wallet/walletdb.cpp | 16 ++++++++-------- 8 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/core_memusage.h b/src/core_memusage.h index e4ccd54c423..f038e7b1548 100644 --- a/src/core_memusage.h +++ b/src/core_memusage.h @@ -10,7 +10,7 @@ #include "memusage.h" static inline size_t RecursiveDynamicUsage(const CScript& script) { - return memusage::DynamicUsage(*static_cast(&script)); + return memusage::DynamicUsage(script); } static inline size_t RecursiveDynamicUsage(const COutPoint& out) { diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 00ac0b92b54..f1b5e59373a 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -107,7 +107,7 @@ class CTxIn template inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(prevout); - READWRITE(*(CScriptBase*)(&scriptSig)); + READWRITE(scriptSig); READWRITE(nSequence); } @@ -147,7 +147,7 @@ class CTxOut template inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(nValue); - READWRITE(*(CScriptBase*)(&scriptPubKey)); + READWRITE(scriptPubKey); } void SetNull() diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index c17ca2fa3a1..6178a1c7ab1 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -798,7 +798,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, stats.nTransactions++; for (const auto output : outputs) { ss << VARINT(output.first + 1); - ss << *(const CScriptBase*)(&output.second.out.scriptPubKey); + ss << output.second.out.scriptPubKey; ss << VARINT(output.second.out.nValue); stats.nTransactionOutputs++; stats.nTotalAmount += output.second.out.nValue; diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 7149c938fc8..8a121774a04 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1099,7 +1099,7 @@ class CTransactionSignatureSerializer { // Serialize the script if (nInput != nIn) // Blank out other inputs' signatures - ::Serialize(s, CScriptBase()); + ::Serialize(s, CScript()); else SerializeScriptCode(s); // Serialize the nSequence @@ -1207,7 +1207,7 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig // The prevout may already be contained in hashPrevout, and the nSequence // may already be contain in hashSequence. ss << txTo.vin[nIn].prevout; - ss << static_cast(scriptCode); + ss << scriptCode; ss << amount; ss << txTo.vin[nIn].nSequence; // Outputs (none/one/all, depending on flags) diff --git a/src/script/script.h b/src/script/script.h index bbb37f049e9..d16bfd0e00e 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -8,6 +8,7 @@ #include "crypto/common.h" #include "prevector.h" +#include "serialize.h" #include #include @@ -404,6 +405,13 @@ class CScript : public CScriptBase CScript(std::vector::const_iterator pbegin, std::vector::const_iterator pend) : CScriptBase(pbegin, pend) { } CScript(const unsigned char* pbegin, const unsigned char* pend) : CScriptBase(pbegin, pend) { } + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(static_cast(*this)); + } + CScript& operator+=(const CScript& b) { insert(end(), b.begin(), b.end()); diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index be631ce7a64..093509e61c5 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) uint256 in2 = InsecureRand256(); BOOST_CHECK(dbw.Write(key2, in2)); - std::unique_ptr it(const_cast(&dbw)->NewIterator()); + std::unique_ptr it(const_cast(dbw).NewIterator()); // Be sure to seek past the obfuscation key (if it exists) it->Seek(key); @@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(iterator_ordering) BOOST_CHECK(dbw.Write(key, value)); } - std::unique_ptr it(const_cast(&dbw)->NewIterator()); + std::unique_ptr it(const_cast(dbw).NewIterator()); for (int c=0; c<2; ++c) { int seek_start; if (c == 0) @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) } } - std::unique_ptr it(const_cast(&dbw)->NewIterator()); + std::unique_ptr it(const_cast(dbw).NewIterator()); for (int c=0; c<2; ++c) { int seek_start; if (c == 0) diff --git a/src/txdb.cpp b/src/txdb.cpp index 002f6550bca..aa0b73a4174 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -172,7 +172,7 @@ bool CBlockTreeDB::ReadLastBlockFile(int &nFile) { CCoinsViewCursor *CCoinsViewDB::Cursor() const { - CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast(&db)->NewIterator(), GetBestBlock()); + CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast(db).NewIterator(), GetBestBlock()); /* It seems that there are no "const iterators" for LevelDB. Since we only need read operations on it, use a const-cast to get around that restriction. */ diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index deb09a47710..d2072f6e795 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -94,23 +94,23 @@ bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) { - return WriteIC(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false); + return WriteIC(std::make_pair(std::string("cscript"), hash), redeemScript, false); } bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta) { - if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) { + if (!WriteIC(std::make_pair(std::string("watchmeta"), dest), keyMeta)) { return false; } - return WriteIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); + return WriteIC(std::make_pair(std::string("watchs"), dest), '1'); } bool CWalletDB::EraseWatchOnly(const CScript &dest) { - if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) { + if (!EraseIC(std::make_pair(std::string("watchmeta"), dest))) { return false; } - return EraseIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); + return EraseIC(std::make_pair(std::string("watchs"), dest)); } bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) @@ -323,7 +323,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, { wss.nWatchKeys++; CScript script; - ssKey >> *(CScriptBase*)(&script); + ssKey >> script; char fYes; ssValue >> fYes; if (fYes == '1') @@ -440,7 +440,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, else if (strType == "watchmeta") { CScript script; - ssKey >> *(CScriptBase*)(&script); + ssKey >> script; keyID = CScriptID(script); } @@ -474,7 +474,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, uint160 hash; ssKey >> hash; CScript script; - ssValue >> *(CScriptBase*)(&script); + ssValue >> script; if (!pwallet->LoadCScript(script)) { strErr = "Error reading wallet database: LoadCScript failed"; From 5618b7d1ad3f2a258d46cf67b732ffddd3f34cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jan=C3=ADk?= Date: Tue, 4 Jul 2017 10:08:43 +0200 Subject: [PATCH 030/148] Do not shadow upper local variable `state`. --- src/test/txvalidationcache_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index a74f40251aa..f609cb1af4e 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -196,8 +196,8 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) // Test that invalidity under a set of flags doesn't preclude validity // under other (eg consensus) flags. // spend_tx is invalid according to DERSIG - CValidationState state; { + CValidationState state; PrecomputedTransactionData ptd_spend_tx(spend_tx); BOOST_CHECK(!CheckInputs(spend_tx, state, pcoinsTip, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr)); From d9d1bd3267cf0f9fc6f56250bd8cd3af7596c11e Mon Sep 17 00:00:00 2001 From: romanornr Date: Sat, 8 Jul 2017 18:44:03 +0200 Subject: [PATCH 031/148] nCheckDepth chain height fix --- src/validation.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 09288be1ca4..4831e819d74 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3577,9 +3577,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, return true; // Verify blocks in the best chain - if (nCheckDepth <= 0) - nCheckDepth = 1000000000; // suffices until the year 19000 - if (nCheckDepth > chainActive.Height()) + if (nCheckDepth <= 0 || nCheckDepth > chainActive.Height()) nCheckDepth = chainActive.Height(); nCheckLevel = std::max(0, std::min(4, nCheckLevel)); LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); From e0451e3e2af64cc975dd76389dc3ea4f8b9c2a62 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:18:04 -0500 Subject: [PATCH 032/148] Fix subscript[0] bug in net.cpp if GetGroup returns a 0-sized vector --- src/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 301cf58b870..5bf3af7ea37 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2876,5 +2876,5 @@ uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& ad) const { std::vector vchNetGroup(ad.GetGroup()); - return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(&vchNetGroup[0], vchNetGroup.size()).Finalize(); + return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup.data(), vchNetGroup.size()).Finalize(); } From 500710bd291e0b9f269ef20677a4a849fb76fc06 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:27:10 -0500 Subject: [PATCH 033/148] Fix 2 subscript[0] bugs in pubkey.cpp, and eliminate one extra size check --- src/pubkey.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/pubkey.cpp b/src/pubkey.cpp index a16457ea4ee..91af4e56f2d 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -172,10 +172,7 @@ bool CPubKey::Verify(const uint256 &hash, const std::vector& vchS if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) { return false; } - if (vchSig.size() == 0) { - return false; - } - if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) { + if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) { return false; } /* libsecp256k1's ECDSA verification requires lower-S signatures, which have @@ -274,7 +271,7 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const { /* static */ bool CPubKey::CheckLowS(const std::vector& vchSig) { secp256k1_ecdsa_signature sig; - if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) { + if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, vchSig.data(), vchSig.size())) { return false; } return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig)); From 96f2119e6c391617f0c7f27ce5af44604a7af937 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 12:39:51 -0500 Subject: [PATCH 034/148] Fix subscript[0] in compressor.cpp --- src/compressor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compressor.cpp b/src/compressor.cpp index 20c154fc1e5..f4c12f38d2d 100644 --- a/src/compressor.cpp +++ b/src/compressor.cpp @@ -93,7 +93,7 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector Date: Sun, 19 Feb 2017 13:11:44 -0500 Subject: [PATCH 035/148] Cleanup (safe, it was checked) subscript[0] in MurmurHash3 (and cleanup MurmurHash3 to be more clear). --- src/hash.cpp | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/hash.cpp b/src/hash.cpp index b361c90d162..5a15600be55 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -17,36 +17,34 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector 0) - { - const uint32_t c1 = 0xcc9e2d51; - const uint32_t c2 = 0x1b873593; + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; - const int nblocks = vDataToHash.size() / 4; + const int nblocks = vDataToHash.size() / 4; - //---------- - // body - const uint8_t* blocks = &vDataToHash[0] + nblocks * 4; + //---------- + // body + const uint8_t* blocks = vDataToHash.data(); - for (int i = -nblocks; i; i++) { - uint32_t k1 = ReadLE32(blocks + i*4); + for (int i = 0; i < nblocks; ++i) { + uint32_t k1 = ReadLE32(blocks + i*4); - k1 *= c1; - k1 = ROTL32(k1, 15); - k1 *= c2; + k1 *= c1; + k1 = ROTL32(k1, 15); + k1 *= c2; - h1 ^= k1; - h1 = ROTL32(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - } + h1 ^= k1; + h1 = ROTL32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; + } - //---------- - // tail - const uint8_t* tail = (const uint8_t*)(&vDataToHash[0] + nblocks * 4); + //---------- + // tail + const uint8_t* tail = vDataToHash.data() + nblocks * 4; - uint32_t k1 = 0; + uint32_t k1 = 0; - switch (vDataToHash.size() & 3) { + switch (vDataToHash.size() & 3) { case 3: k1 ^= tail[2] << 16; case 2: @@ -57,7 +55,6 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector Date: Sun, 19 Feb 2017 13:41:13 -0500 Subject: [PATCH 036/148] Fix subscript[0] in base58.cpp --- src/base58.cpp | 12 ++++++------ src/base58.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index efa1beb1e4f..17022a6bc16 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -110,7 +110,7 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) std::string EncodeBase58(const std::vector& vch) { - return EncodeBase58(&vch[0], &vch[0] + vch.size()); + return EncodeBase58(vch.data(), vch.data() + vch.size()); } bool DecodeBase58(const std::string& str, std::vector& vchRet) @@ -160,7 +160,7 @@ void CBase58Data::SetData(const std::vector& vchVersionIn, const vchVersion = vchVersionIn; vchData.resize(nSize); if (!vchData.empty()) - memcpy(&vchData[0], pdata, nSize); + memcpy(vchData.data(), pdata, nSize); } void CBase58Data::SetData(const std::vector& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend) @@ -180,8 +180,8 @@ bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes); vchData.resize(vchTemp.size() - nVersionBytes); if (!vchData.empty()) - memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size()); - memory_cleanse(&vchTemp[0], vchTemp.size()); + memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size()); + memory_cleanse(vchTemp.data(), vchTemp.size()); return true; } @@ -262,7 +262,7 @@ CTxDestination CBitcoinAddress::Get() const if (!IsValid()) return CNoDestination(); uint160 id; - memcpy(&id, &vchData[0], 20); + memcpy(&id, vchData.data(), 20); if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) return CKeyID(id); else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) @@ -276,7 +276,7 @@ bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) return false; uint160 id; - memcpy(&id, &vchData[0], 20); + memcpy(&id, vchData.data(), 20); keyID = CKeyID(id); return true; } diff --git a/src/base58.h b/src/base58.h index 3998283bb13..4de5cc6ce5f 100644 --- a/src/base58.h +++ b/src/base58.h @@ -148,7 +148,7 @@ template class CBitcoinExtK K ret; if (vchData.size() == Size) { // If base58 encoded data does not hold an ext key, return a !IsValid() key - ret.Decode(&vchData[0]); + ret.Decode(vchData.data()); } return ret; } From b6856ebedcd3a1c3cfed5397f477f869688a715b Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:43:46 -0500 Subject: [PATCH 037/148] Fix subscript[0] in netaddress.cpp --- src/netaddress.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 89f257c6422..110e778fbd8 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -573,7 +573,7 @@ std::vector CService::GetKey() const { std::vector vKey; vKey.resize(18); - memcpy(&vKey[0], ip, 16); + memcpy(vKey.data(), ip, 16); vKey[16] = port / 0x100; vKey[17] = port & 0x0FF; return vKey; From ac658e55ff75ed5689f87060087f2ed815c34fe0 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:44:01 -0500 Subject: [PATCH 038/148] Fix subscript[0] in torcontrol --- src/torcontrol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 3665e7e770a..ac13f73e705 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -662,7 +662,7 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2)); cookie = std::vector(status_cookie.second.begin(), status_cookie.second.end()); clientNonce = std::vector(TOR_NONCE_SIZE, 0); - GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE); + GetRandBytes(clientNonce.data(), TOR_NONCE_SIZE); _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2)); } else { if (status_cookie.first) { From 4cac0d1e041db1d7c7eebd6f022f120d08a1610f Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 28 Mar 2017 11:37:06 -0400 Subject: [PATCH 039/148] Fix subscript[0] in validation.cpp --- src/serialize.h | 12 ++++++------ src/validation.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index e82ddf2c5a7..8b86a07a767 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -450,7 +450,7 @@ class LimitedString } string.resize(size); if (size != 0) - s.read((char*)&string[0], size); + s.read((char*)string.data(), size); } template @@ -458,7 +458,7 @@ class LimitedString { WriteCompactSize(s, string.size()); if (!string.empty()) - s.write((char*)&string[0], string.size()); + s.write((char*)string.data(), string.size()); } }; @@ -556,7 +556,7 @@ void Serialize(Stream& os, const std::basic_string& str) { WriteCompactSize(os, str.size()); if (!str.empty()) - os.write((char*)&str[0], str.size() * sizeof(str[0])); + os.write((char*)str.data(), str.size() * sizeof(C)); } template @@ -565,7 +565,7 @@ void Unserialize(Stream& is, std::basic_string& str) unsigned int nSize = ReadCompactSize(is); str.resize(nSize); if (nSize != 0) - is.read((char*)&str[0], nSize * sizeof(str[0])); + is.read((char*)str.data(), nSize * sizeof(C)); } @@ -578,7 +578,7 @@ void Serialize_impl(Stream& os, const prevector& v, const unsigned char&) { WriteCompactSize(os, v.size()); if (!v.empty()) - os.write((char*)&v[0], v.size() * sizeof(T)); + os.write((char*)v.data(), v.size() * sizeof(T)); } template @@ -646,7 +646,7 @@ void Serialize_impl(Stream& os, const std::vector& v, const unsigned char& { WriteCompactSize(os, v.size()); if (!v.empty()) - os.write((char*)&v[0], v.size() * sizeof(T)); + os.write((char*)v.data(), v.size() * sizeof(T)); } template diff --git a/src/validation.cpp b/src/validation.cpp index 09288be1ca4..a21367848b3 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2890,7 +2890,7 @@ std::vector GenerateCoinbaseCommitment(CBlock& block, const CBloc if (consensusParams.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0) { if (commitpos == -1) { uint256 witnessroot = BlockWitnessMerkleRoot(block, NULL); - CHash256().Write(witnessroot.begin(), 32).Write(&ret[0], 32).Finalize(witnessroot.begin()); + CHash256().Write(witnessroot.begin(), 32).Write(ret.data(), 32).Finalize(witnessroot.begin()); CTxOut out; out.nValue = 0; out.scriptPubKey.resize(38); From bc2e7fd984bd669195bf330520f48f55faf81e88 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 28 Mar 2017 11:35:51 -0400 Subject: [PATCH 040/148] Fix subscript[0] in streams.h --- src/streams.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/streams.h b/src/streams.h index 8dc5a19ead4..245fb9cd8fd 100644 --- a/src/streams.h +++ b/src/streams.h @@ -389,7 +389,7 @@ class CDataStream { // Special case: stream << stream concatenates like stream += stream if (!vch.empty()) - s.write((char*)&vch[0], vch.size() * sizeof(vch[0])); + s.write((char*)vch.data(), vch.size() * sizeof(value_type)); } template From e19db7b5ad6af770d803e7120e21fba4b436e8be Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:46:19 -0500 Subject: [PATCH 041/148] Fix subscript[0] in utilstrencodings.cpp --- src/utilstrencodings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 93abaec04b1..feaf1a5e8bb 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -228,7 +228,7 @@ std::vector DecodeBase64(const char* p, bool* pfInvalid) std::string DecodeBase64(const std::string& str) { std::vector vchRet = DecodeBase64(str.c_str()); - return (vchRet.size() == 0) ? std::string() : std::string((const char*)&vchRet[0], vchRet.size()); + return (vchRet.size() == 0) ? std::string() : std::string((const char*)vchRet.data(), vchRet.size()); } std::string EncodeBase32(const unsigned char* pch, size_t len) @@ -415,7 +415,7 @@ std::vector DecodeBase32(const char* p, bool* pfInvalid) std::string DecodeBase32(const std::string& str) { std::vector vchRet = DecodeBase32(str.c_str()); - return (vchRet.size() == 0) ? std::string() : std::string((const char*)&vchRet[0], vchRet.size()); + return (vchRet.size() == 0) ? std::string() : std::string((const char*) vchRet.data(), vchRet.size()); } static bool ParsePrechecks(const std::string& str) From 4b1c0f2e2e870a3285811bd7b68e14c2edd6a827 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 28 Mar 2017 11:17:07 -0400 Subject: [PATCH 042/148] Remove unnecessary branches in utilstrencodings string constructors. --- src/utilstrencodings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index feaf1a5e8bb..2fabb8cf7a3 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -228,7 +228,7 @@ std::vector DecodeBase64(const char* p, bool* pfInvalid) std::string DecodeBase64(const std::string& str) { std::vector vchRet = DecodeBase64(str.c_str()); - return (vchRet.size() == 0) ? std::string() : std::string((const char*)vchRet.data(), vchRet.size()); + return std::string((const char*)vchRet.data(), vchRet.size()); } std::string EncodeBase32(const unsigned char* pch, size_t len) @@ -415,7 +415,7 @@ std::vector DecodeBase32(const char* p, bool* pfInvalid) std::string DecodeBase32(const std::string& str) { std::vector vchRet = DecodeBase32(str.c_str()); - return (vchRet.size() == 0) ? std::string() : std::string((const char*) vchRet.data(), vchRet.size()); + return std::string((const char*)vchRet.data(), vchRet.size()); } static bool ParsePrechecks(const std::string& str) From 30ac7688e398bbe5400a48ecf0726b679ffb845d Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Sun, 19 Feb 2017 13:35:49 -0500 Subject: [PATCH 043/148] Fix subscript[0] potential bugs in key.cpp --- src/key.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 5a75647f1a4..5a991fc1d29 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -138,7 +138,7 @@ CPrivKey CKey::GetPrivKey() const { size_t privkeylen; privkey.resize(279); privkeylen = 279; - ret = ec_privkey_export_der(secp256k1_context_sign, (unsigned char*)&privkey[0], &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); + ret = ec_privkey_export_der(secp256k1_context_sign, (unsigned char*) privkey.data(), &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); assert(ret); privkey.resize(privkeylen); return privkey; @@ -167,7 +167,7 @@ bool CKey::Sign(const uint256 &hash, std::vector& vchSig, uint32_ secp256k1_ecdsa_signature sig; int ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, test_case ? extra_entropy : NULL); assert(ret); - secp256k1_ecdsa_signature_serialize_der(secp256k1_context_sign, (unsigned char*)&vchSig[0], &nSigLen, &sig); + secp256k1_ecdsa_signature_serialize_der(secp256k1_context_sign, (unsigned char*)vchSig.data(), &nSigLen, &sig); vchSig.resize(nSigLen); return true; } @@ -202,7 +202,7 @@ bool CKey::SignCompact(const uint256 &hash, std::vector& vchSig) } bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { - if (!ec_privkey_import_der(secp256k1_context_sign, (unsigned char*)begin(), &privkey[0], privkey.size())) + if (!ec_privkey_import_der(secp256k1_context_sign, (unsigned char*)begin(), privkey.data(), privkey.size())) return false; fCompressed = vchPubKey.IsCompressed(); fValid = true; @@ -245,8 +245,8 @@ void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) { static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'}; std::vector> vout(64); CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(vout.data()); - key.Set(&vout[0], &vout[32], true); - memcpy(chaincode.begin(), &vout[32], 32); + key.Set(vout.data(), vout.data() + 32, true); + memcpy(chaincode.begin(), vout.data() + 32, 32); nDepth = 0; nChild = 0; memset(vchFingerprint, 0, sizeof(vchFingerprint)); From 1e3a3200afd74b22fdbb5d9425722b0c031e7453 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sun, 9 Jul 2017 13:35:39 +0200 Subject: [PATCH 044/148] Simplify "!foo || (foo && bar)" as "!foo || bar" --- src/validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index 09288be1ca4..6aa50a4da0c 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1141,7 +1141,7 @@ static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) // or a chain that is entirely longer than ours and invalid (note that this should be detected by both) // We define it this way because it allows us to only store the highest fork tip (+ base) which meets // the 7-block condition and from this always have the most-likely-to-cause-warning fork - if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) && + if (pfork && (!pindexBestForkTip || pindexNewForkTip->nHeight > pindexBestForkTip->nHeight) && pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) && chainActive.Height() - pindexNewForkTip->nHeight < 72) { From f135923ee2cf1a1a9a436626dc5b9219f8ad97da Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 14 Jun 2017 15:15:40 -0400 Subject: [PATCH 045/148] Add RPC options for RBF, confirmation target, and conservative fee estimation. Add support for setting each of these attributes on a per RPC call basis to sendtoaddress, sendmany, fundrawtransaction (already had RBF), and bumpfee (already had RBF and conf target). --- src/policy/fees.cpp | 14 +++++++ src/policy/fees.h | 2 + src/qt/walletmodel.cpp | 2 +- src/rpc/client.cpp | 4 ++ src/wallet/feebumper.cpp | 4 +- src/wallet/feebumper.h | 3 +- src/wallet/rpcwallet.cpp | 98 +++++++++++++++++++++++++++++++++++++++++------- 7 files changed, 109 insertions(+), 18 deletions(-) diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 771491770ed..c39a2d55c38 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -36,6 +36,20 @@ std::string StringForFeeReason(FeeReason reason) { return reason_string->second; } +bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) { + static const std::map fee_modes = { + {"UNSET", FeeEstimateMode::UNSET}, + {"ECONOMICAL", FeeEstimateMode::ECONOMICAL}, + {"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE}, + }; + auto mode = fee_modes.find(mode_string); + + if (mode == fee_modes.end()) return false; + + fee_estimate_mode = mode->second; + return true; +} + /** * We will instantiate an instance of this class to track transactions that were * included in a block. We will lump transactions into a bucket according to their diff --git a/src/policy/fees.h b/src/policy/fees.h index 059415418dd..fea279e4778 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -97,6 +97,8 @@ enum class FeeEstimateMode { CONSERVATIVE, //! Force estimateSmartFee to use conservative estimates }; +bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode); + /* Used to return detailed information about a feerate bucket */ struct EstimatorBucket { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 354225090f7..60b55da3e70 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -668,7 +668,7 @@ bool WalletModel::bumpFee(uint256 hash) std::unique_ptr feeBump; { LOCK2(cs_main, wallet->cs_wallet); - feeBump.reset(new CFeeBumper(wallet, hash, nTxConfirmTarget, false, 0, true)); + feeBump.reset(new CFeeBumper(wallet, hash, nTxConfirmTarget, false, 0, true, FeeEstimateMode::UNSET)); } if (feeBump->getResult() != BumpFeeResult::OK) { diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index a3ea5390eec..81390d7e477 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -37,6 +37,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getnetworkhashps", 1, "height" }, { "sendtoaddress", 1, "amount" }, { "sendtoaddress", 4, "subtractfeefromamount" }, + { "sendtoaddress", 5 , "replaceable" }, + { "sendtoaddress", 6 , "conf_target" }, { "settxfee", 0, "amount" }, { "getreceivedbyaddress", 1, "minconf" }, { "getreceivedbyaccount", 1, "minconf" }, @@ -69,6 +71,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "sendmany", 1, "amounts" }, { "sendmany", 2, "minconf" }, { "sendmany", 4, "subtractfeefrom" }, + { "sendmany", 5 , "replaceable" }, + { "sendmany", 6 , "conf_target" }, { "addmultisigaddress", 0, "nrequired" }, { "addmultisigaddress", 1, "keys" }, { "createmultisig", 0, "nrequired" }, diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index a25530d8bdb..607ecf4182b 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -66,7 +66,7 @@ bool CFeeBumper::preconditionChecks(const CWallet *pWallet, const CWalletTx& wtx return true; } -CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConfirmTarget, bool ignoreGlobalPayTxFee, CAmount totalFee, bool newTxReplaceable) +CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConfirmTarget, bool ignoreGlobalPayTxFee, CAmount totalFee, bool newTxReplaceable, FeeEstimateMode fee_mode) : txid(std::move(txidIn)), nOldFee(0), @@ -165,7 +165,7 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf nNewFee = totalFee; nNewFeeRate = CFeeRate(totalFee, maxNewTxSize); } else { - bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, newTxReplaceable); + bool conservative_estimate = CalculateEstimateType(fee_mode, newTxReplaceable); nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, nullptr /* FeeCalculation */, ignoreGlobalPayTxFee, conservative_estimate); nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize); diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h index fc323167048..11e2f5f9537 100644 --- a/src/wallet/feebumper.h +++ b/src/wallet/feebumper.h @@ -10,6 +10,7 @@ class CWallet; class CWalletTx; class uint256; +enum class FeeEstimateMode; enum class BumpFeeResult { @@ -24,7 +25,7 @@ enum class BumpFeeResult class CFeeBumper { public: - CFeeBumper(const CWallet *pWalletIn, const uint256 txidIn, int newConfirmTarget, bool ignoreGlobalPayTxFee, CAmount totalFee, bool newTxReplaceable); + CFeeBumper(const CWallet *pWalletIn, const uint256 txidIn, int newConfirmTarget, bool ignoreGlobalPayTxFee, CAmount totalFee, bool newTxReplaceable, FeeEstimateMode fee_mode); BumpFeeResult getResult() const { return currentResult; } const std::vector& getErrors() const { return vErrors; } CAmount getOldFee() const { return nOldFee; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 867ccd42444..5f72e3b6f59 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -356,7 +356,7 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request) return ret; } -static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew) +static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew, CCoinControl *coin_control = nullptr) { CAmount curBalance = pwallet->GetBalance(); @@ -382,7 +382,7 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA int nChangePosRet = -1; CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount}; vecSend.push_back(recipient); - if (!pwallet->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) { + if (!pwallet->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) { if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance) strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired)); throw JSONRPCError(RPC_WALLET_ERROR, strError); @@ -401,9 +401,9 @@ UniValue sendtoaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 2 || request.params.size() > 5) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 8) throw std::runtime_error( - "sendtoaddress \"address\" amount ( \"comment\" \"comment_to\" subtractfeefromamount )\n" + "sendtoaddress \"address\" amount ( \"comment\" \"comment_to\" subtractfeefromamount replaceable conf_target \"estimate_mode\")\n" "\nSend an amount to a given address.\n" + HelpRequiringPassphrase(pwallet) + "\nArguments:\n" @@ -416,6 +416,12 @@ UniValue sendtoaddress(const JSONRPCRequest& request) " transaction, just kept in your wallet.\n" "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n" " The recipient will receive less bitcoins than you enter in the amount field.\n" + "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n" + "7. conf_target (numeric, optional) Confirmation target (in blocks)\n" + "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n" + " \"UNSET\"\n" + " \"ECONOMICAL\"\n" + " \"CONSERVATIVE\"\n" "\nResult:\n" "\"txid\" (string) The transaction id.\n" "\nExamples:\n" @@ -444,12 +450,29 @@ UniValue sendtoaddress(const JSONRPCRequest& request) wtx.mapValue["to"] = request.params[3].get_str(); bool fSubtractFeeFromAmount = false; - if (request.params.size() > 4) + if (request.params.size() > 4 && !request.params[4].isNull()) { fSubtractFeeFromAmount = request.params[4].get_bool(); + } + + CCoinControl coin_control; + if (request.params.size() > 5 && !request.params[5].isNull()) { + coin_control.signalRbf = request.params[5].get_bool(); + } + + if (request.params.size() > 6 && !request.params[6].isNull()) { + coin_control.nConfirmTarget = request.params[6].get_int(); + } + + if (request.params.size() > 7 && !request.params[7].isNull()) { + if (!FeeModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); + } + } + EnsureWalletIsUnlocked(pwallet); - SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx); + SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, &coin_control); return wtx.GetHash().GetHex(); } @@ -888,9 +911,9 @@ UniValue sendmany(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 2 || request.params.size() > 5) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 8) throw std::runtime_error( - "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n" + "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] replaceable conf_target \"estimate_mode\")\n" "\nSend multiple times. Amounts are double-precision floating point numbers." + HelpRequiringPassphrase(pwallet) + "\n" "\nArguments:\n" @@ -910,7 +933,13 @@ UniValue sendmany(const JSONRPCRequest& request) " \"address\" (string) Subtract fee from this address\n" " ,...\n" " ]\n" - "\nResult:\n" + "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n" + "7. conf_target (numeric, optional) Confirmation target (in blocks)\n" + "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n" + " \"UNSET\"\n" + " \"ECONOMICAL\"\n" + " \"CONSERVATIVE\"\n" + "\nResult:\n" "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n" " the number of addresses.\n" "\nExamples:\n" @@ -942,9 +971,24 @@ UniValue sendmany(const JSONRPCRequest& request) wtx.mapValue["comment"] = request.params[3].get_str(); UniValue subtractFeeFromAmount(UniValue::VARR); - if (request.params.size() > 4) + if (request.params.size() > 4 && !request.params[4].isNull()) subtractFeeFromAmount = request.params[4].get_array(); + CCoinControl coin_control; + if (request.params.size() > 5 && !request.params[5].isNull()) { + coin_control.signalRbf = request.params[5].get_bool(); + } + + if (request.params.size() > 6 && !request.params[6].isNull()) { + coin_control.nConfirmTarget = request.params[6].get_int(); + } + + if (request.params.size() > 7 && !request.params[7].isNull()) { + if (!FeeModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); + } + } + std::set setAddress; std::vector vecSend; @@ -989,7 +1033,7 @@ UniValue sendmany(const JSONRPCRequest& request) CAmount nFeeRequired = 0; int nChangePosRet = -1; std::string strFailReason; - bool fCreated = pwallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason); + bool fCreated = pwallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, &coin_control); if (!fCreated) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); CValidationState state; @@ -2658,6 +2702,11 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) " [vout_index,...]\n" " \"replaceable\" (boolean, optional) Marks this transaction as BIP125 replaceable.\n" " Allows this transaction to be replaced by a transaction with higher fees\n" + " \"conf_target\" (numeric, optional) Confirmation target (in blocks)\n" + " \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n" + " \"UNSET\"\n" + " \"ECONOMICAL\"\n" + " \"CONSERVATIVE\"\n" " }\n" " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n" "\nResult:\n" @@ -2710,6 +2759,8 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) {"feeRate", UniValueType()}, // will be checked below {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)}, {"replaceable", UniValueType(UniValue::VBOOL)}, + {"conf_target", UniValueType(UniValue::VNUM)}, + {"estimate_mode", UniValueType(UniValue::VSTR)}, }, true, true); @@ -2746,6 +2797,14 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) if (options.exists("replaceable")) { coinControl.signalRbf = options["replaceable"].get_bool(); } + if (options.exists("conf_target")) { + coinControl.nConfirmTarget = options["conf_target"].get_int(); + } + if (options.exists("estimate_mode")) { + if (!FeeModeFromString(options["estimate_mode"].get_str(), coinControl.m_fee_mode)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); + } + } } } @@ -2823,6 +2882,10 @@ UniValue bumpfee(const JSONRPCRequest& request) " so the new transaction will not be explicitly bip-125 replaceable (though it may\n" " still be replaceable in practice, for example if it has unconfirmed ancestors which\n" " are replaceable).\n" + " \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n" + " \"UNSET\"\n" + " \"ECONOMICAL\"\n" + " \"CONSERVATIVE\"\n" " }\n" "\nResult:\n" "{\n" @@ -2845,6 +2908,7 @@ UniValue bumpfee(const JSONRPCRequest& request) int newConfirmTarget = nTxConfirmTarget; CAmount totalFee = 0; bool replaceable = true; + FeeEstimateMode fee_mode = FeeEstimateMode::UNSET; if (request.params.size() > 1) { UniValue options = request.params[1]; RPCTypeCheckObj(options, @@ -2852,6 +2916,7 @@ UniValue bumpfee(const JSONRPCRequest& request) {"confTarget", UniValueType(UniValue::VNUM)}, {"totalFee", UniValueType(UniValue::VNUM)}, {"replaceable", UniValueType(UniValue::VBOOL)}, + {"estimate_mode", UniValueType(UniValue::VSTR)}, }, true, true); @@ -2876,12 +2941,17 @@ UniValue bumpfee(const JSONRPCRequest& request) if (options.exists("replaceable")) { replaceable = options["replaceable"].get_bool(); } + if (options.exists("estimate_mode")) { + if (!FeeModeFromString(options["estimate_mode"].get_str(), fee_mode)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); + } + } } LOCK2(cs_main, pwallet->cs_wallet); EnsureWalletIsUnlocked(pwallet); - CFeeBumper feeBump(pwallet, hash, newConfirmTarget, ignoreGlobalPayTxFee, totalFee, replaceable); + CFeeBumper feeBump(pwallet, hash, newConfirmTarget, ignoreGlobalPayTxFee, totalFee, replaceable, fee_mode); BumpFeeResult res = feeBump.getResult(); if (res != BumpFeeResult::OK) { @@ -3023,8 +3093,8 @@ static const CRPCCommand commands[] = { "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} }, { "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} }, { "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} }, - { "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","comment","subtractfeefrom"} }, - { "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} }, + { "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} }, + { "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} }, { "wallet", "setaccount", &setaccount, true, {"address","account"} }, { "wallet", "settxfee", &settxfee, true, {"amount"} }, { "wallet", "signmessage", &signmessage, true, {"address","message"} }, From 475c08cb446371dd75fb37e067613effc0572442 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 10 Jul 2017 12:44:13 -0700 Subject: [PATCH 046/148] Add PR description to merge commit in github-merge.py --- contrib/devtools/github-merge.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py index e9816f7d191..c664cf81fa9 100755 --- a/contrib/devtools/github-merge.py +++ b/contrib/devtools/github-merge.py @@ -175,6 +175,7 @@ def main(): if info is None: exit(1) title = info['title'].strip() + body = info['body'].strip() # precedence order for destination branch argument: # - command line argument # - githubmerge.branch setting @@ -229,6 +230,7 @@ def main(): firstline = 'Merge #%s' % (pull,) message = firstline + '\n\n' message += subprocess.check_output([GIT,'log','--no-merges','--topo-order','--pretty=format:%h %s (%an)',base_branch+'..'+head_branch]).decode('utf-8') + message += '\n\nPull request description:\n\n ' + body.replace('\n', '\n ') + '\n' try: subprocess.check_call([GIT,'merge','-q','--commit','--no-edit','--no-ff','-m',message.encode('utf-8'),head_branch]) except subprocess.CalledProcessError as e: From 9c85b91dc1566f7c27c5b8a1a9c7aebe0e3a83cf Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Tue, 6 Jun 2017 13:08:27 -0400 Subject: [PATCH 047/148] Change API to estimaterawfee Report results for all 3 possible time horizons instead of specifying time horizon as an argument. --- src/policy/feerate.h | 1 + src/policy/fees.cpp | 13 +++++++ src/policy/fees.h | 2 ++ src/rpc/client.cpp | 1 - src/rpc/mining.cpp | 100 ++++++++++++++++++++++++++------------------------- 5 files changed, 67 insertions(+), 50 deletions(-) diff --git a/src/policy/feerate.h b/src/policy/feerate.h index e82268b095a..565da6c1541 100644 --- a/src/policy/feerate.h +++ b/src/policy/feerate.h @@ -40,6 +40,7 @@ class CFeeRate friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; } friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; } friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } + friend bool operator!=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK != b.nSatoshisPerK; } CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; } std::string ToString() const; diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 771491770ed..859a2e7804f 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -16,6 +16,19 @@ static constexpr double INF_FEERATE = 1e99; +std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon) { + static const std::map horizon_strings = { + {FeeEstimateHorizon::SHORT_HALFLIFE, "short"}, + {FeeEstimateHorizon::MED_HALFLIFE, "medium"}, + {FeeEstimateHorizon::LONG_HALFLIFE, "long"}, + }; + auto horizon_string = horizon_strings.find(horizon); + + if (horizon_string == horizon_strings.end()) return "unknown"; + + return horizon_string->second; +} + std::string StringForFeeReason(FeeReason reason) { static const std::map fee_reason_strings = { {FeeReason::NONE, "None"}, diff --git a/src/policy/fees.h b/src/policy/fees.h index 2029ce37448..86f143b2338 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -74,6 +74,8 @@ enum FeeEstimateHorizon { LONG_HALFLIFE = 2 }; +std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon); + /* Enumeration of reason for returned fee estimate */ enum class FeeReason { NONE, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 8fac8af3ec6..4c5eb6dc69b 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -113,7 +113,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "estimatesmartfee", 1, "conservative" }, { "estimaterawfee", 0, "nblocks" }, { "estimaterawfee", 1, "threshold" }, - { "estimaterawfee", 2, "horizon" }, { "prioritisetransaction", 1, "dummy" }, { "prioritisetransaction", 2, "fee_delta" }, { "setban", 2, "bantime" }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index e50742f36e3..a15931386b9 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -838,9 +838,9 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) UniValue estimaterawfee(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1|| request.params.size() > 3) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( - "estimaterawfee nblocks (threshold horizon)\n" + "estimaterawfee nblocks (threshold)\n" "\nWARNING: This interface is unstable and may disappear or change!\n" "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n" " implementation of fee estimation. The parameters it can be called with\n" @@ -853,68 +853,70 @@ UniValue estimaterawfee(const JSONRPCRequest& request) "2. threshold (numeric, optional) The proportion of transactions in a given feerate range that must have been\n" " confirmed within nblocks in order to consider those feerates as high enough and proceed to check\n" " lower buckets. Default: 0.95\n" - "3. horizon (numeric, optional) How long a history of estimates to consider. 0=short, 1=medium, 2=long.\n" - " Default: 1\n" "\nResult:\n" "{\n" - " \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n" - " \"decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n" - " \"scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n" - " \"pass\" : { (json object) information about the lowest range of feerates to succeed in meeting the threshold\n" - " \"startrange\" : x.x, (numeric) start of feerate range\n" - " \"endrange\" : x.x, (numeric) end of feerate range\n" - " \"withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n" - " \"totalconfirmed\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed at any point\n" - " \"inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n" - " \"leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n" - " }\n" - " \"fail\" : { ... } (json object) information about the highest range of feerates to fail to meet the threshold\n" + " \"short\" : { (json object) estimate for short time horizon\n" + " \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n" + " \"decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n" + " \"scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n" + " \"pass\" : { (json object) information about the lowest range of feerates to succeed in meeting the threshold\n" + " \"startrange\" : x.x, (numeric) start of feerate range\n" + " \"endrange\" : x.x, (numeric) end of feerate range\n" + " \"withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n" + " \"totalconfirmed\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed at any point\n" + " \"inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n" + " \"leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n" + " },\n" + " \"fail\" : { ... }, (json object) information about the highest range of feerates to fail to meet the threshold\n" + " },\n" + " \"medium\" : { ... }, (json object) estimate for medium time horizon\n" + " \"long\" : { ... } (json object) estimate for long time horizon\n" "}\n" "\n" "A negative feerate is returned if no answer can be given.\n" "\nExample:\n" - + HelpExampleCli("estimaterawfee", "6 0.9 1") + + HelpExampleCli("estimaterawfee", "6 0.9") ); RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM, UniValue::VNUM}, true); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); int nBlocks = request.params[0].get_int(); double threshold = 0.95; - if (!request.params[1].isNull()) + if (!request.params[1].isNull()) { threshold = request.params[1].get_real(); - FeeEstimateHorizon horizon = FeeEstimateHorizon::MED_HALFLIFE; - if (!request.params[2].isNull()) { - int horizonInt = request.params[2].get_int(); - if (horizonInt < 0 || horizonInt > 2) { - throw JSONRPCError(RPC_TYPE_ERROR, "Invalid horizon for fee estimates"); - } else { - horizon = (FeeEstimateHorizon)horizonInt; - } } + UniValue result(UniValue::VOBJ); - CFeeRate feeRate; - EstimationResult buckets; - feeRate = ::feeEstimator.estimateRawFee(nBlocks, threshold, horizon, &buckets); - result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK()))); - result.push_back(Pair("decay", buckets.decay)); - result.push_back(Pair("scale", (int)buckets.scale)); - UniValue passbucket(UniValue::VOBJ); - passbucket.push_back(Pair("startrange", round(buckets.pass.start))); - passbucket.push_back(Pair("endrange", round(buckets.pass.end))); - passbucket.push_back(Pair("withintarget", round(buckets.pass.withinTarget * 100.0) / 100.0)); - passbucket.push_back(Pair("totalconfirmed", round(buckets.pass.totalConfirmed * 100.0) / 100.0)); - passbucket.push_back(Pair("inmempool", round(buckets.pass.inMempool * 100.0) / 100.0)); - passbucket.push_back(Pair("leftmempool", round(buckets.pass.leftMempool * 100.0) / 100.0)); - result.push_back(Pair("pass", passbucket)); - UniValue failbucket(UniValue::VOBJ); - failbucket.push_back(Pair("startrange", round(buckets.fail.start))); - failbucket.push_back(Pair("endrange", round(buckets.fail.end))); - failbucket.push_back(Pair("withintarget", round(buckets.fail.withinTarget * 100.0) / 100.0)); - failbucket.push_back(Pair("totalconfirmed", round(buckets.fail.totalConfirmed * 100.0) / 100.0)); - failbucket.push_back(Pair("inmempool", round(buckets.fail.inMempool * 100.0) / 100.0)); - failbucket.push_back(Pair("leftmempool", round(buckets.fail.leftMempool * 100.0) / 100.0)); - result.push_back(Pair("fail", failbucket)); + for (FeeEstimateHorizon horizon : {FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}) { + CFeeRate feeRate; + EstimationResult buckets; + feeRate = ::feeEstimator.estimateRawFee(nBlocks, threshold, horizon, &buckets); + + UniValue horizon_result(UniValue::VOBJ); + horizon_result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK()))); + if (!(feeRate == CFeeRate(0))) { + horizon_result.push_back(Pair("decay", buckets.decay)); + horizon_result.push_back(Pair("scale", (int)buckets.scale)); + UniValue passbucket(UniValue::VOBJ); + passbucket.push_back(Pair("startrange", round(buckets.pass.start))); + passbucket.push_back(Pair("endrange", round(buckets.pass.end))); + passbucket.push_back(Pair("withintarget", round(buckets.pass.withinTarget * 100.0) / 100.0)); + passbucket.push_back(Pair("totalconfirmed", round(buckets.pass.totalConfirmed * 100.0) / 100.0)); + passbucket.push_back(Pair("inmempool", round(buckets.pass.inMempool * 100.0) / 100.0)); + passbucket.push_back(Pair("leftmempool", round(buckets.pass.leftMempool * 100.0) / 100.0)); + horizon_result.push_back(Pair("pass", passbucket)); + UniValue failbucket(UniValue::VOBJ); + failbucket.push_back(Pair("startrange", round(buckets.fail.start))); + failbucket.push_back(Pair("endrange", round(buckets.fail.end))); + failbucket.push_back(Pair("withintarget", round(buckets.fail.withinTarget * 100.0) / 100.0)); + failbucket.push_back(Pair("totalconfirmed", round(buckets.fail.totalConfirmed * 100.0) / 100.0)); + failbucket.push_back(Pair("inmempool", round(buckets.fail.inMempool * 100.0) / 100.0)); + failbucket.push_back(Pair("leftmempool", round(buckets.fail.leftMempool * 100.0) / 100.0)); + horizon_result.push_back(Pair("fail", failbucket)); + } + result.push_back(Pair(StringForFeeEstimateHorizon(horizon), horizon_result)); + } return result; } @@ -932,7 +934,7 @@ static const CRPCCommand commands[] = { "util", "estimatefee", &estimatefee, true, {"nblocks"} }, { "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks", "conservative"} }, - { "hidden", "estimaterawfee", &estimaterawfee, true, {"nblocks", "threshold", "horizon"} }, + { "hidden", "estimaterawfee", &estimaterawfee, true, {"nblocks", "threshold"} }, }; void RegisterMiningRPCCommands(CRPCTable &t) From 1fafd704dac73594f69de5f9c15f697217653d7a Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 28 Jun 2017 10:03:00 -0400 Subject: [PATCH 048/148] Add function to report highest estimate target tracked per horizon --- src/policy/fees.cpp | 20 +++++++++++++++++++- src/policy/fees.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 859a2e7804f..51e11ea20ef 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -684,7 +684,7 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr break; } default: { - return CFeeRate(0); + throw std::out_of_range("CBlockPoicyEstimator::estimateRawFee unknown FeeEstimateHorizon"); } } @@ -703,6 +703,24 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr return CFeeRate(median); } +unsigned int CBlockPolicyEstimator::HighestTargetTracked(FeeEstimateHorizon horizon) const +{ + switch (horizon) { + case FeeEstimateHorizon::SHORT_HALFLIFE: { + return shortStats->GetMaxConfirms(); + } + case FeeEstimateHorizon::MED_HALFLIFE: { + return feeStats->GetMaxConfirms(); + } + case FeeEstimateHorizon::LONG_HALFLIFE: { + return longStats->GetMaxConfirms(); + } + default: { + throw std::out_of_range("CBlockPoicyEstimator::HighestTargetTracked unknown FeeEstimateHorizon"); + } + } +} + unsigned int CBlockPolicyEstimator::BlockSpan() const { if (firstRecordedHeight == 0) return 0; diff --git a/src/policy/fees.h b/src/policy/fees.h index 86f143b2338..a04dbe49244 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -216,6 +216,9 @@ class CBlockPolicyEstimator /** Empty mempool transactions on shutdown to record failure to confirm for txs still in mempool */ void FlushUnconfirmed(CTxMemPool& pool); + /** Calculation of highest target that estimates are tracked for */ + unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const; + private: unsigned int nBestSeenHeight; unsigned int firstRecordedHeight; From 5e3b7b5686d326814c40e5b70da6697971d27092 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 28 Jun 2017 10:50:32 -0400 Subject: [PATCH 049/148] Improve error reporting for estimaterawfee --- src/rpc/mining.cpp | 71 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index a15931386b9..046c85a76eb 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -849,17 +849,17 @@ UniValue estimaterawfee(const JSONRPCRequest& request) "confirmation within nblocks blocks if possible. Uses virtual transaction size as defined\n" "in BIP 141 (witness data is discounted).\n" "\nArguments:\n" - "1. nblocks (numeric)\n" + "1. nblocks (numeric) Confirmation target in blocks (1 - 1008)\n" "2. threshold (numeric, optional) The proportion of transactions in a given feerate range that must have been\n" " confirmed within nblocks in order to consider those feerates as high enough and proceed to check\n" " lower buckets. Default: 0.95\n" "\nResult:\n" "{\n" - " \"short\" : { (json object) estimate for short time horizon\n" - " \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n" + " \"short\" : { (json object, optional) estimate for short time horizon\n" + " \"feerate\" : x.x, (numeric, optional) estimate fee-per-kilobyte (in BTC)\n" " \"decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n" " \"scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n" - " \"pass\" : { (json object) information about the lowest range of feerates to succeed in meeting the threshold\n" + " \"pass\" : { (json object, optional) information about the lowest range of feerates to succeed in meeting the threshold\n" " \"startrange\" : x.x, (numeric) start of feerate range\n" " \"endrange\" : x.x, (numeric) end of feerate range\n" " \"withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n" @@ -867,13 +867,14 @@ UniValue estimaterawfee(const JSONRPCRequest& request) " \"inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n" " \"leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n" " },\n" - " \"fail\" : { ... }, (json object) information about the highest range of feerates to fail to meet the threshold\n" + " \"fail\" : { ... }, (json object, optional) information about the highest range of feerates to fail to meet the threshold\n" + " \"errors\": [ str... ] (json array of strings, optional) Errors encountered during processing\n" " },\n" - " \"medium\" : { ... }, (json object) estimate for medium time horizon\n" - " \"long\" : { ... } (json object) estimate for long time horizon\n" + " \"medium\" : { ... }, (json object, optional) estimate for medium time horizon\n" + " \"long\" : { ... } (json object) estimate for long time horizon\n" "}\n" "\n" - "A negative feerate is returned if no answer can be given.\n" + "Results are returned for any horizon which tracks blocks up to the confirmation target.\n" "\nExample:\n" + HelpExampleCli("estimaterawfee", "6 0.9") ); @@ -881,39 +882,59 @@ UniValue estimaterawfee(const JSONRPCRequest& request) RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM, UniValue::VNUM}, true); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); int nBlocks = request.params[0].get_int(); + if (nBlocks < 1 || (unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid nblocks"); + } double threshold = 0.95; if (!request.params[1].isNull()) { threshold = request.params[1].get_real(); } + if (threshold < 0 || threshold > 1) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid threshold"); + } UniValue result(UniValue::VOBJ); for (FeeEstimateHorizon horizon : {FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}) { CFeeRate feeRate; EstimationResult buckets; - feeRate = ::feeEstimator.estimateRawFee(nBlocks, threshold, horizon, &buckets); + // Only output results for horizons which track the target + if ((unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(horizon)) continue; + + feeRate = ::feeEstimator.estimateRawFee(nBlocks, threshold, horizon, &buckets); UniValue horizon_result(UniValue::VOBJ); - horizon_result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK()))); - if (!(feeRate == CFeeRate(0))) { + UniValue errors(UniValue::VARR); + UniValue passbucket(UniValue::VOBJ); + passbucket.push_back(Pair("startrange", round(buckets.pass.start))); + passbucket.push_back(Pair("endrange", round(buckets.pass.end))); + passbucket.push_back(Pair("withintarget", round(buckets.pass.withinTarget * 100.0) / 100.0)); + passbucket.push_back(Pair("totalconfirmed", round(buckets.pass.totalConfirmed * 100.0) / 100.0)); + passbucket.push_back(Pair("inmempool", round(buckets.pass.inMempool * 100.0) / 100.0)); + passbucket.push_back(Pair("leftmempool", round(buckets.pass.leftMempool * 100.0) / 100.0)); + UniValue failbucket(UniValue::VOBJ); + failbucket.push_back(Pair("startrange", round(buckets.fail.start))); + failbucket.push_back(Pair("endrange", round(buckets.fail.end))); + failbucket.push_back(Pair("withintarget", round(buckets.fail.withinTarget * 100.0) / 100.0)); + failbucket.push_back(Pair("totalconfirmed", round(buckets.fail.totalConfirmed * 100.0) / 100.0)); + failbucket.push_back(Pair("inmempool", round(buckets.fail.inMempool * 100.0) / 100.0)); + failbucket.push_back(Pair("leftmempool", round(buckets.fail.leftMempool * 100.0) / 100.0)); + + // CFeeRate(0) is used to indicate error as a return value from estimateRawFee + if (feeRate != CFeeRate(0)) { + horizon_result.push_back(Pair("feerate", ValueFromAmount(feeRate.GetFeePerK()))); horizon_result.push_back(Pair("decay", buckets.decay)); horizon_result.push_back(Pair("scale", (int)buckets.scale)); - UniValue passbucket(UniValue::VOBJ); - passbucket.push_back(Pair("startrange", round(buckets.pass.start))); - passbucket.push_back(Pair("endrange", round(buckets.pass.end))); - passbucket.push_back(Pair("withintarget", round(buckets.pass.withinTarget * 100.0) / 100.0)); - passbucket.push_back(Pair("totalconfirmed", round(buckets.pass.totalConfirmed * 100.0) / 100.0)); - passbucket.push_back(Pair("inmempool", round(buckets.pass.inMempool * 100.0) / 100.0)); - passbucket.push_back(Pair("leftmempool", round(buckets.pass.leftMempool * 100.0) / 100.0)); horizon_result.push_back(Pair("pass", passbucket)); - UniValue failbucket(UniValue::VOBJ); - failbucket.push_back(Pair("startrange", round(buckets.fail.start))); - failbucket.push_back(Pair("endrange", round(buckets.fail.end))); - failbucket.push_back(Pair("withintarget", round(buckets.fail.withinTarget * 100.0) / 100.0)); - failbucket.push_back(Pair("totalconfirmed", round(buckets.fail.totalConfirmed * 100.0) / 100.0)); - failbucket.push_back(Pair("inmempool", round(buckets.fail.inMempool * 100.0) / 100.0)); - failbucket.push_back(Pair("leftmempool", round(buckets.fail.leftMempool * 100.0) / 100.0)); + // buckets.fail.start == -1 indicates that all buckets passed, there is no fail bucket to output + if (buckets.fail.start != -1) horizon_result.push_back(Pair("fail", failbucket)); + } else { + // Output only information that is still meaningful in the event of error + horizon_result.push_back(Pair("decay", buckets.decay)); + horizon_result.push_back(Pair("scale", (int)buckets.scale)); horizon_result.push_back(Pair("fail", failbucket)); + errors.push_back("Insufficient data or no feerate found which meets threshold"); + horizon_result.push_back(Pair("errors",errors)); } result.push_back(Pair(StringForFeeEstimateHorizon(horizon), horizon_result)); } From 1f668b646806f94acd851acdbd9939c24e0492d3 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 10 Jul 2017 21:08:19 -0400 Subject: [PATCH 050/148] Expose if CScheduler is being serviced, assert its not in EmptyQueue --- src/scheduler.cpp | 5 +++++ src/scheduler.h | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 35bf0da4bec..36a6d5110d9 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -140,6 +140,10 @@ size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first, return result; } +bool CScheduler::AreThreadsServicingQueue() const { + return nThreadsServicingQueue; +} + void SingleThreadedSchedulerClient::MaybeScheduleProcessQueue() { { @@ -193,6 +197,7 @@ void SingleThreadedSchedulerClient::AddToProcessQueue(std::function } void SingleThreadedSchedulerClient::EmptyQueue() { + assert(!m_pscheduler->AreThreadsServicingQueue()); bool should_continue = true; while (should_continue) { ProcessQueue(); diff --git a/src/scheduler.h b/src/scheduler.h index 6a079f7749e..0365d668b20 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -71,6 +71,9 @@ class CScheduler size_t getQueueInfo(boost::chrono::system_clock::time_point &first, boost::chrono::system_clock::time_point &last) const; + // Returns true if there are threads actively running in serviceQueue() + bool AreThreadsServicingQueue() const; + private: std::multimap taskQueue; boost::condition_variable newTaskScheduled; @@ -103,6 +106,7 @@ class SingleThreadedSchedulerClient { void AddToProcessQueue(std::function func); // Processes all remaining queue members on the calling thread, blocking until queue is empty + // Must be called after the CScheduler has no remaining processing threads! void EmptyQueue(); }; From c8e29d7ff0da853d4243c08b34c15fab3dfcc76f Mon Sep 17 00:00:00 2001 From: Mark Friedenbach Date: Tue, 11 Jul 2017 16:37:40 +0900 Subject: [PATCH 051/148] Replace MAX_OPCODE for OP_NOP10. That OP_NOP10 is the last executable opcode is a bit of a obscure trivia, and the MAX_OPCODE constant already exists. This merely standardizes use of MAX_OPCODE over OP_NOP10 where it makes sense and is more clear. --- src/core_read.cpp | 2 +- src/test/data/script_tests.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core_read.cpp b/src/core_read.cpp index dd9b5726a31..18d02fb913d 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -27,7 +27,7 @@ CScript ParseScript(const std::string& s) if (mapOpNames.empty()) { - for (int op = 0; op <= OP_NOP10; op++) + for (int op = 0; op <= MAX_OPCODE; op++) { // Allow OP_RESERVED to get into mapOpNames if (op < OP_NOP && op != OP_RESERVED) diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 0390d6806d2..698e8982312 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -240,7 +240,7 @@ ["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discouraged NOPs are allowed if not executed"], -["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes above NOP10 invalid if executed"], +["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes above MAX_OPCODE invalid if executed"], ["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], @@ -878,7 +878,7 @@ "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], ["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"], -["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above NOP10 invalid if executed"], +["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above MAX_OPCODE invalid if executed"], ["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], @@ -1001,7 +1001,7 @@ ["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"], ["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"], ["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"], -["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == OP_NOP10 + 1"], +["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == MAX_OPCODE + 1"], ["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], From 253cd7ec4fc9324d2c2c3bc6f32794ded2455eb7 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 30 Jun 2017 12:53:29 -0400 Subject: [PATCH 052/148] Only reserve key for scriptChange once in CreateTransaction This does not affect behavior but allows us to have access to an output to scriptChange even if we currently do not have change in the transaction. --- src/wallet/wallet.cpp | 67 ++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a1b4eb106ee..53f39cf8e3e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2569,6 +2569,38 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT std::vector vAvailableCoins; AvailableCoins(vAvailableCoins, true, coinControl); + // Create change script that will be used if we need change + // TODO: pass in scriptChange instead of reservekey so + // change transaction isn't always pay-to-bitcoin-address + CScript scriptChange; + + // coin control: send change to custom address + if (coinControl && !boost::get(&coinControl->destChange)) + scriptChange = GetScriptForDestination(coinControl->destChange); + + // no coin control: send change to newly generated address + else + { + // Note: We use a new key here to keep it from being obvious which side is the change. + // The drawback is that by not reusing a previous key, the change may be lost if a + // backup is restored, if the backup doesn't have the new private key for the change. + // If we reused the old key, it would be possible to add code to look for and + // rediscover unknown transactions that were written with keys of ours to recover + // post-backup change. + + // Reserve a new key pair from key pool + CPubKey vchPubKey; + bool ret; + ret = reservekey.GetReservedKey(vchPubKey, true); + if (!ret) + { + strFailReason = _("Keypool ran out, please call keypoolrefill first"); + return false; + } + + scriptChange = GetScriptForDestination(vchPubKey.GetID()); + } + nFeeRet = 0; // Start with no fee and loop until there is enough fee while (true) @@ -2627,37 +2659,6 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT if (nChange > 0) { // Fill a vout to ourself - // TODO: pass in scriptChange instead of reservekey so - // change transaction isn't always pay-to-bitcoin-address - CScript scriptChange; - - // coin control: send change to custom address - if (coinControl && !boost::get(&coinControl->destChange)) - scriptChange = GetScriptForDestination(coinControl->destChange); - - // no coin control: send change to newly generated address - else - { - // Note: We use a new key here to keep it from being obvious which side is the change. - // The drawback is that by not reusing a previous key, the change may be lost if a - // backup is restored, if the backup doesn't have the new private key for the change. - // If we reused the old key, it would be possible to add code to look for and - // rediscover unknown transactions that were written with keys of ours to recover - // post-backup change. - - // Reserve a new key pair from key pool - CPubKey vchPubKey; - bool ret; - ret = reservekey.GetReservedKey(vchPubKey, true); - if (!ret) - { - strFailReason = _("Keypool ran out, please call keypoolrefill first"); - return false; - } - - scriptChange = GetScriptForDestination(vchPubKey.GetID()); - } - CTxOut newTxOut(nChange, scriptChange); // Never create dust outputs; if we would, just @@ -2666,7 +2667,6 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT { nChangePosInOut = -1; nFeeRet += nChange; - reservekey.ReturnKey(); } else { @@ -2685,7 +2685,6 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT txNew.vout.insert(position, newTxOut); } } else { - reservekey.ReturnKey(); nChangePosInOut = -1; } @@ -2777,6 +2776,8 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT } } + if (nChangePosInOut == -1) reservekey.ReturnKey(); // Return any reserved key if we don't have change + if (sign) { CTransaction txNewConst(txNew); From 0f402b9263b0579b29aa0f841fc64ad58d3efba6 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 30 Jun 2017 13:16:53 -0400 Subject: [PATCH 053/148] Fix rare edge case of paying too many fees when transaction has no change. Due to the iterative process of selecting new coins in each loop a new fee is calculated that needs to be met each time. In the typical case if the most recent iteration of the loop produced a much smaller transaction and we have now gathered inputs with too many fees, we can just reduce the change. However in the case where there is no change output, it is possible to end up with a transaction which drastically overpays fees. This commit addresses that case, by creating a change output if the overpayment is large enough to support it, this is accomplished by rerunning the transaction creation loop without selecting new coins. Thanks to instagibbs for working on this as well --- src/wallet/wallet.cpp | 53 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 53f39cf8e3e..5e9701c71cd 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2600,8 +2600,12 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT scriptChange = GetScriptForDestination(vchPubKey.GetID()); } + CTxOut change_prototype_txout(0, scriptChange); + size_t change_prototype_size = GetSerializeSize(change_prototype_txout, SER_DISK, 0); nFeeRet = 0; + bool pick_new_inputs = true; + CAmount nValueIn = 0; // Start with no fee and loop until there is enough fee while (true) { @@ -2647,15 +2651,18 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT } // Choose coins to use - CAmount nValueIn = 0; - setCoins.clear(); - if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl)) - { - strFailReason = _("Insufficient funds"); - return false; + if (pick_new_inputs) { + nValueIn = 0; + setCoins.clear(); + if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl)) + { + strFailReason = _("Insufficient funds"); + return false; + } } const CAmount nChange = nValueIn - nValueToSelect; + if (nChange > 0) { // Fill a vout to ourself @@ -2739,16 +2746,30 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT } if (nFeeRet >= nFeeNeeded) { - // Reduce fee to only the needed amount if we have change - // output to increase. This prevents potential overpayment - // in fees if the coins selected to meet nFeeNeeded result - // in a transaction that requires less fee than the prior - // iteration. + // Reduce fee to only the needed amount if possible. This + // prevents potential overpayment in fees if the coins + // selected to meet nFeeNeeded result in a transaction that + // requires less fee than the prior iteration. + // TODO: The case where nSubtractFeeFromAmount > 0 remains // to be addressed because it requires returning the fee to // the payees and not the change output. - // TODO: The case where there is no change output remains - // to be addressed so we avoid creating too small an output. + + // If we have no change and a big enough excess fee, then + // try to construct transaction again only without picking + // new inputs. We now know we only need the smaller fee + // (because of reduced tx size) and so we should add a + // change output. Only try this once. + CAmount fee_needed_for_change = GetMinimumFee(change_prototype_size, currentConfirmationTarget, ::mempool, ::feeEstimator, nullptr, false /* ignoreGlobalPayTxFee */, conservative_estimate); + CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, ::dustRelayFee); + CAmount max_excess_fee = fee_needed_for_change + minimum_value_for_change; + if (nFeeRet > nFeeNeeded + max_excess_fee && nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) { + pick_new_inputs = false; + nFeeRet = nFeeNeeded + fee_needed_for_change; + continue; + } + + // If we have change output already, just increase it if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) { CAmount extraFeePaid = nFeeRet - nFeeNeeded; std::vector::iterator change_position = txNew.vout.begin()+nChangePosInOut; @@ -2757,6 +2778,12 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT } break; // Done, enough fee included. } + else if (!pick_new_inputs) { + // This shouldn't happen, we should have had enough excess + // fee to pay for the new output and still meet nFeeNeeded + strFailReason = _("Transaction fee and change calculation failed"); + return false; + } // Try to reduce change to include necessary fee if (nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) { From 8276e70de15c5c3a7525471ad619edd1237b424a Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Thu, 6 Apr 2017 20:28:19 -0500 Subject: [PATCH 054/148] Adding assert to avoid a memory access violation inside of PartialMerkleTree::CalcHash() Adding comment to assert in PartialMerkleTree::CalcHash() Adding comment on CMerkleBlock indicating it calls something that contains an assert Removing EOL whitespace --- src/merkleblock.cpp | 3 +++ src/merkleblock.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index 78d7cd60010..55f899b649e 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -59,6 +59,9 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, const std::set& txids) } uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector &vTxid) { + //we can never have zero txs in a merkle block, we always need the coinbase tx + //if we do not have this assert, we can hit a memory access violation when indexing into vTxid + assert(vTxid.size() != 0); if (height == 0) { // hash at height 0 is the txids themself return vTxid[pos]; diff --git a/src/merkleblock.h b/src/merkleblock.h index de4c5c8d29e..f590c487dee 100644 --- a/src/merkleblock.h +++ b/src/merkleblock.h @@ -121,6 +121,8 @@ class CPartialMerkleTree /** * Used to relay blocks as header + vector * to filtered nodes. + * + * NOTE: The class assumes that the given CBlock has *at least* 1 transaction. If the CBlock has 0 txs, it will hit an assertion. */ class CMerkleBlock { From 1016dacfaca5014c6af377ca787c36cf5dea88e8 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 12 Jul 2017 14:03:42 -0400 Subject: [PATCH 055/148] Fix signed/unsigned comparison warning introduced in c8e29d7ff0. --- src/core_read.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core_read.cpp b/src/core_read.cpp index 18d02fb913d..7018131a134 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -27,7 +27,7 @@ CScript ParseScript(const std::string& s) if (mapOpNames.empty()) { - for (int op = 0; op <= MAX_OPCODE; op++) + for (unsigned int op = 0; op <= MAX_OPCODE; op++) { // Allow OP_RESERVED to get into mapOpNames if (op < OP_NOP && op != OP_RESERVED) From 228987d84c352de691315474649475f3fbc5de28 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Wed, 12 Jul 2017 14:40:02 -0400 Subject: [PATCH 056/148] getbalance example covers at least 6 confirms --- src/wallet/rpcwallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5f72e3b6f59..873542a9668 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -740,9 +740,9 @@ UniValue getbalance(const JSONRPCRequest& request) "\nResult:\n" "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n" "\nExamples:\n" - "\nThe total amount in the wallet\n" + "\nThe total amount in the wallet with 1 or more confirmations\n" + HelpExampleCli("getbalance", "") + - "\nThe total amount in the wallet at least 5 blocks confirmed\n" + "\nThe total amount in the wallet at least 6 blocks confirmed\n" + HelpExampleCli("getbalance", "\"*\" 6") + "\nAs a json rpc call\n" + HelpExampleRpc("getbalance", "\"*\", 6") From fe4fabaf12b74782ea99821ed8108f17e582060d Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 12 Jul 2017 16:55:28 -0400 Subject: [PATCH 057/148] [refactor] move SplitHostPort() into utilstrencodings This moves SplitHostPort from libbitcoin_common to libbitcoin_util so it is available to bitcoin-cli. --- src/httpserver.cpp | 1 + src/netbase.cpp | 19 ------------------- src/netbase.h | 1 - src/test/netbase_tests.cpp | 1 + src/utilstrencodings.cpp | 19 +++++++++++++++++++ src/utilstrencodings.h | 1 + 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 1c53d8d49d2..290a2efca2b 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -7,6 +7,7 @@ #include "chainparamsbase.h" #include "compat.h" #include "util.h" +#include "utilstrencodings.h" #include "netbase.h" #include "rpc/protocol.h" // For HTTP status codes #include "sync.h" diff --git a/src/netbase.cpp b/src/netbase.cpp index a23f92e1ed0..84e1d8228df 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -58,25 +58,6 @@ std::string GetNetworkName(enum Network net) { } } -void SplitHostPort(std::string in, int &portOut, std::string &hostOut) { - size_t colon = in.find_last_of(':'); - // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator - bool fHaveColon = colon != in.npos; - bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe - bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos); - if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) { - int32_t n; - if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) { - in = in.substr(0, colon); - portOut = n; - } - } - if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']') - hostOut = in.substr(1, in.size()-2); - else - hostOut = in; -} - bool static LookupIntern(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup) { vIP.clear(); diff --git a/src/netbase.h b/src/netbase.h index c9d108aadd1..fd4b34c8f1e 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -39,7 +39,6 @@ class proxyType enum Network ParseNetwork(std::string net); std::string GetNetworkName(enum Network net); -void SplitHostPort(std::string in, int &portOut, std::string &hostOut); bool SetProxy(enum Network net, const proxyType &addrProxy); bool GetProxy(enum Network net, proxyType &proxyInfoOut); bool IsProxy(const CNetAddr &addr); diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index b45a7fcc572..1baf7643e54 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -4,6 +4,7 @@ #include "netbase.h" #include "test/test_bitcoin.h" +#include "utilstrencodings.h" #include diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 93abaec04b1..6a15186b67a 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -91,6 +91,25 @@ std::vector ParseHex(const std::string& str) return ParseHex(str.c_str()); } +void SplitHostPort(std::string in, int &portOut, std::string &hostOut) { + size_t colon = in.find_last_of(':'); + // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator + bool fHaveColon = colon != in.npos; + bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe + bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos); + if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) { + int32_t n; + if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) { + in = in.substr(0, colon); + portOut = n; + } + } + if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']') + hostOut = in.substr(1, in.size()-2); + else + hostOut = in; +} + std::string EncodeBase64(const unsigned char* pch, size_t len) { static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 8b37fe12e08..707fdaad169 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -48,6 +48,7 @@ std::string DecodeBase32(const std::string& str); std::string EncodeBase32(const unsigned char* pch, size_t len); std::string EncodeBase32(const std::string& str); +void SplitHostPort(std::string in, int &portOut, std::string &hostOut); std::string i64tostr(int64_t n); std::string itostr(int n); int64_t atoi64(const char* psz); From 69a4339ef509da633e83fa9968ac646c58b95390 Mon Sep 17 00:00:00 2001 From: Lawrence Nahum Date: Thu, 13 Jul 2017 00:02:10 +0200 Subject: [PATCH 058/148] missing white space in function arg --- src/validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index a21367848b3..8ef90b6ae89 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -455,7 +455,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // Reject transactions with witness before segregated witness activates (override with -prematurewitness) bool witnessEnabled = IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus()); - if (!GetBoolArg("-prematurewitness",false) && tx.HasWitness() && !witnessEnabled) { + if (!GetBoolArg("-prematurewitness", false) && tx.HasWitness() && !witnessEnabled) { return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true); } From bc1be90e377a7a9258ce6b39cac0f183b41f0e51 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 7 Jul 2017 22:03:49 +0200 Subject: [PATCH 059/148] [Qt] replace fee slider with a Dropdown, extend conf. targets --- src/qt/forms/sendcoinsdialog.ui | 64 +++-------------------------------------- src/qt/sendcoinsdialog.cpp | 51 ++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 78 deletions(-) diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 89f9c25d143..e82a3c1533e 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -1068,44 +1068,15 @@ 30 - - + + 0 - - 23 - - - 1 - - - 0 - - - Qt::Horizontal - - - false - - - false - - - QSlider::NoTicks - - - - - - - - normal - - + - + Qt::Horizontal @@ -1117,33 +1088,6 @@ - - - - (count) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - fast - - - diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 12d2d0f31cd..bb54c584e10 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -31,6 +31,25 @@ #include #include +static const std::array confTargets = { {2, 4, 6, 12, 24, 48, 144, 504, 1008} }; +int getConfTargetForIndex(int index) { + if (index+1 > static_cast(confTargets.size())) { + return confTargets.back(); + } + if (index < 0) { + return confTargets[0]; + } + return confTargets[index]; +} +int getIndexForConfTarget(int target) { + for (unsigned int i = 0; i < confTargets.size(); i++) { + if (confTargets[i] >= target) { + return i; + } + } + return confTargets.size() - 1; +} + SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::SendCoinsDialog), @@ -152,9 +171,12 @@ void SendCoinsDialog::setModel(WalletModel *_model) coinControlUpdateLabels(); // fee section - connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, SLOT(updateSmartFeeLabel())); - connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, SLOT(updateGlobalFeeVariables())); - connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, SLOT(coinControlUpdateLabels())); + for (const int &n : confTargets) { + ui->confTargetSelector->addItem(tr("%1 (%2 blocks)").arg(GUIUtil::formatNiceTimeOffset(n*Params().GetConsensus().nPowTargetSpacing)).arg(n)); + } + connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSmartFeeLabel())); + connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGlobalFeeVariables())); + connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(coinControlUpdateLabels())); connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateFeeSectionControls())); connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateGlobalFeeVariables())); connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels())); @@ -177,10 +199,10 @@ void SendCoinsDialog::setModel(WalletModel *_model) // set the smartfee-sliders default value (wallets default conf.target or last stored value) QSettings settings; - if (settings.value("nSmartFeeSliderPosition").toInt() == 0) - ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - model->getDefaultConfirmTarget() + 2); + if (settings.value("nConfTarget").toInt() == 0) + ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(model->getDefaultConfirmTarget())); else - ui->sliderSmartFee->setValue(settings.value("nSmartFeeSliderPosition").toInt()); + ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(settings.value("nConfTarget").toInt())); } } @@ -190,7 +212,7 @@ SendCoinsDialog::~SendCoinsDialog() settings.setValue("fFeeSectionMinimized", fFeeMinimized); settings.setValue("nFeeRadio", ui->groupFee->checkedId()); settings.setValue("nCustomFeeRadio", ui->groupCustomFee->checkedId()); - settings.setValue("nSmartFeeSliderPosition", ui->sliderSmartFee->value()); + settings.setValue("nConfTarget", getConfTargetForIndex(ui->confTargetSelector->currentIndex())); settings.setValue("nTransactionFee", (qint64)ui->customFee->value()); settings.setValue("fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked()); @@ -244,7 +266,7 @@ void SendCoinsDialog::on_sendButton_clicked() if (model->getOptionsModel()->getCoinControlFeatures()) ctrl = *CoinControlDialog::coinControl; if (ui->radioSmartFee->isChecked()) - ctrl.nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; + ctrl.nConfirmTarget = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); else ctrl.nConfirmTarget = 0; @@ -594,14 +616,11 @@ void SendCoinsDialog::setMinimumFee() void SendCoinsDialog::updateFeeSectionControls() { - ui->sliderSmartFee ->setEnabled(ui->radioSmartFee->isChecked()); + ui->confTargetSelector ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelSmartFee ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelSmartFee2 ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelSmartFee3 ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelFeeEstimation ->setEnabled(ui->radioSmartFee->isChecked()); - ui->labelSmartFeeNormal ->setEnabled(ui->radioSmartFee->isChecked()); - ui->labelSmartFeeFast ->setEnabled(ui->radioSmartFee->isChecked()); - ui->confirmationTargetLabel ->setEnabled(ui->radioSmartFee->isChecked()); ui->checkBoxMinimumFee ->setEnabled(ui->radioCustomFee->isChecked()); ui->labelMinFeeWarning ->setEnabled(ui->radioCustomFee->isChecked()); ui->radioCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); @@ -612,11 +631,7 @@ void SendCoinsDialog::updateGlobalFeeVariables() { if (ui->radioSmartFee->isChecked()) { - int nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; payTxFee = CFeeRate(0); - - // show the estimated required time for confirmation - ui->confirmationTargetLabel->setText(GUIUtil::formatDurationStr(nConfirmTarget * Params().GetConsensus().nPowTargetSpacing) + " / " + tr("%n block(s)", "", nConfirmTarget)); } else { @@ -650,7 +665,7 @@ void SendCoinsDialog::updateSmartFeeLabel() if(!model || !model->getOptionsModel()) return; - int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; + int nBlocksToConfirm = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); FeeCalculation feeCalc; CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &feeCalc, ::mempool); if (feeRate <= CFeeRate(0)) // not enough data => minfee @@ -823,7 +838,7 @@ void SendCoinsDialog::coinControlUpdateLabels() CoinControlDialog::payAmounts.clear(); CoinControlDialog::fSubtractFeeFromAmount = false; if (ui->radioSmartFee->isChecked()) { - CoinControlDialog::coinControl->nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; + CoinControlDialog::coinControl->nConfirmTarget = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); } else { CoinControlDialog::coinControl->nConfirmTarget = model->getDefaultConfirmTarget(); } From 2aef1f18296fcd3aa3c91afdf152add8a8e80bd4 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 13 Jul 2017 12:19:17 +0200 Subject: [PATCH 060/148] [Qt] migrate old fee slider value to new dropbown Always round up (conservative) --- src/qt/sendcoinsdialog.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index bb54c584e10..c69a29daccf 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -199,6 +199,13 @@ void SendCoinsDialog::setModel(WalletModel *_model) // set the smartfee-sliders default value (wallets default conf.target or last stored value) QSettings settings; + if (settings.value("nSmartFeeSliderPosition").toInt() != 0) { + // migrate nSmartFeeSliderPosition to nConfTarget + // nConfTarget is available since 0.15 (replaced nSmartFeeSliderPosition) + int nConfirmTarget = 25 - settings.value("nSmartFeeSliderPosition").toInt(); // 25 == old slider range + settings.setValue("nConfTarget", nConfirmTarget); + settings.remove("nSmartFeeSliderPosition"); + } if (settings.value("nConfTarget").toInt() == 0) ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(model->getDefaultConfirmTarget())); else From d34d77a51b846a2459e4447762edcb2b66c95550 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 12 Jul 2017 12:58:20 -0400 Subject: [PATCH 061/148] build: verify that the assembler can handle crc32 functions Also, enable crc32 even if -msse4.2 wasn't added by us, as long as it works. This allows custom flags (such as -march=native) to work as expected. --- configure.ac | 27 +++++++++++++++++++++++++-- src/Makefile.leveldb.include | 2 +- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index a90063d9ded..6b5d891fa54 100644 --- a/configure.ac +++ b/configure.ac @@ -246,9 +246,32 @@ if test "x$CXXFLAGS_overridden" = "xno"; then # Check for optional instruction set support. Enabling these does _not_ imply that all code will # be compiled with them, rather that specific objects/libs may use them after checking for runtime # compatibility. - AX_CHECK_COMPILE_FLAG([-msse4.2],[[enable_sse42=yes; SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-msse4.2],[[SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]]) fi + +TEMP_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS" +AC_MSG_CHECKING(for assembler crc32 support) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #if defined(_MSC_VER) + #include + #elif defined(__GNUC__) && defined(__SSE4_2__) + #include + #endif + ]],[[ + uint64_t l = 0; + l = _mm_crc32_u8(l, 0); + l = _mm_crc32_u32(l, 0); + l = _mm_crc32_u64(l, 0); + return l; + ]])], + [ AC_MSG_RESULT(yes); enable_hwcrc32=yes], + [ AC_MSG_RESULT(no)] +) +CXXFLAGS="$TEMP_CXXFLAGS" + CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" AC_ARG_WITH([utils], @@ -1132,7 +1155,7 @@ AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes]) -AM_CONDITIONAL([ENABLE_SSE42],[test x$enable_sse42 = xyes]) +AM_CONDITIONAL([ENABLE_HWCRC32],[test x$enable_hwcrc32 = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include index ac38141f43d..833f3d2a10c 100644 --- a/src/Makefile.leveldb.include +++ b/src/Makefile.leveldb.include @@ -142,7 +142,7 @@ leveldb_libmemenv_a_SOURCES += leveldb/helpers/memenv/memenv.h leveldb_libleveldb_sse42_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS) leveldb_libleveldb_sse42_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS) -if ENABLE_SSE42 +if ENABLE_HWCRC32 leveldb_libleveldb_sse42_a_CPPFLAGS += -DLEVELDB_PLATFORM_POSIX_SSE leveldb_libleveldb_sse42_a_CXXFLAGS += $(SSE42_CXXFLAGS) endif From dd97a529ad23169f346aa042a808adf702ce8450 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 13 Jul 2017 13:48:28 -0400 Subject: [PATCH 062/148] Properly forbid -salvagewallet and -zapwallettxes for multi wallet. --- src/wallet/wallet.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5e9701c71cd..07b7f58a641 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4033,20 +4033,24 @@ bool CWallet::ParameterInteraction() LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); } - if (GetBoolArg("-salvagewallet", false) && SoftSetBoolArg("-rescan", true)) { + if (GetBoolArg("-salvagewallet", false)) { if (is_multiwallet) { return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet")); } // Rewrite just private keys: rescan to find transactions - LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); + if (SoftSetBoolArg("-rescan", true)) { + LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); + } } // -zapwallettx implies a rescan - if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-rescan", true)) { + if (GetBoolArg("-zapwallettxes", false)) { if (is_multiwallet) { return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes")); } - LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -rescan=1\n", __func__); + if (SoftSetBoolArg("-rescan", true)) { + LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -rescan=1\n", __func__); + } } if (is_multiwallet) { From 5c643241e5d98992c0d5487b65e9c7b6d8005d1a Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 12 Jul 2017 16:59:09 -0400 Subject: [PATCH 063/148] [utils] allow square brackets for ipv6 addresses in bitcoin-cli -rpcconnect can now accept ipv6 addresses with and without square brackets. --- src/bitcoin-cli.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 885b787b4da..92f6a21ebbd 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -10,6 +10,7 @@ #include "chainparamsbase.h" #include "clientversion.h" #include "fs.h" +#include "utilstrencodings.h" #include "rpc/client.h" #include "rpc/protocol.h" #include "util.h" @@ -191,8 +192,14 @@ static void http_error_cb(enum evhttp_request_error err, void *ctx) UniValue CallRPC(const std::string& strMethod, const UniValue& params) { - std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT); - int port = GetArg("-rpcport", BaseParams().RPCPort()); + std::string host; + // In preference order, we choose the following for the port: + // 1. -rpcport + // 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6) + // 3. default port for chain + int port = BaseParams().RPCPort(); + SplitHostPort(GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host); + port = GetArg("-rpcport", port); // Obtain event base raii_event_base base = obtain_event_base(); From 4652791141f0a8a977b324147ccf1a2360b69ca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 13 Jul 2017 23:25:56 +0100 Subject: [PATCH 064/148] Fix uninitialized atomic variables --- src/netbase.cpp | 2 +- src/wallet/db.h | 4 ++-- src/wallet/walletdb.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index a23f92e1ed0..3fb1c18f030 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -563,7 +563,7 @@ static bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDe // do socks negotiation if (proxy.randomize_credentials) { ProxyCredentials random_auth; - static std::atomic_int counter; + static std::atomic_int counter(0); random_auth.username = random_auth.password = strprintf("%i", counter++); if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) return false; diff --git a/src/wallet/db.h b/src/wallet/db.h index 7cccc65660d..4f3ad0c42de 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -95,13 +95,13 @@ class CWalletDBWrapper friend class CDB; public: /** Create dummy DB handle */ - CWalletDBWrapper() : nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr) + CWalletDBWrapper() : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr) { } /** Create DB handle to real database */ CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) : - nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in) + nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in) { } diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index deb09a47710..2a33dca240c 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -747,7 +747,7 @@ DBErrors CWalletDB::ZapWalletTx(std::vector& vWtx) void MaybeCompactWalletDB() { - static std::atomic fOneThread; + static std::atomic fOneThread(false); if (fOneThread.exchange(true)) { return; } From a9e82f6512662054f64ed2bde590b2bb0831fc9d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 13 Jul 2017 16:43:05 -0700 Subject: [PATCH 065/148] Use cpuid intrinsics instead of asm code --- src/random.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 67efc7d945a..bb463aae82d 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -36,6 +36,10 @@ #include +#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +#include +#endif + #include #include @@ -72,17 +76,8 @@ static bool rdrand_supported = false; static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000; static void RDRandInit() { - uint32_t eax, ecx, edx; -#if defined(__i386__) && ( defined(__PIC__) || defined(__PIE__)) - // Avoid clobbering ebx, as that is used for PIC on x86. - uint32_t tmp; - __asm__ ("mov %%ebx, %1; cpuid; mov %1, %%ebx": "=a"(eax), "=g"(tmp), "=c"(ecx), "=d"(edx) : "a"(1)); -#else - uint32_t ebx; - __asm__ ("cpuid": "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1)); -#endif - //! When calling cpuid function #1, ecx register will have this set if RDRAND is available. - if (ecx & CPUID_F1_ECX_RDRAND) { + uint32_t eax, ebx, ecx, edx; + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & CPUID_F1_ECX_RDRAND)) { LogPrintf("Using RdRand as entropy source\n"); rdrand_supported = true; } From a2420ae2f1e0fd9a257a0a506ff40a4dca842474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 14 Jul 2017 15:00:19 +0100 Subject: [PATCH 066/148] Avoid unnecessary work in SetNetworkActive --- src/net.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 5bf3af7ea37..756de4400e9 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2182,16 +2182,18 @@ void CConnman::SetNetworkActive(bool active) { LogPrint(BCLog::NET, "SetNetworkActive: %s\n", active); - if (!active) { - fNetworkActive = false; + if (fNetworkActive == active) { + return; + } + + fNetworkActive = active; + if (!fNetworkActive) { LOCK(cs_vNodes); // Close sockets to all nodes for (CNode* pnode : vNodes) { pnode->CloseSocketDisconnect(); } - } else { - fNetworkActive = true; } uiInterface.NotifyNetworkActiveChanged(fNetworkActive); From 674848fe1c43fb88870cf5ba16fca4e2524da793 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 14 Jul 2017 12:17:33 -0700 Subject: [PATCH 067/148] Clarify entropy source --- src/random.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/random.cpp b/src/random.cpp index bb463aae82d..1ee6158e4b7 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -78,7 +78,7 @@ static void RDRandInit() { uint32_t eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & CPUID_F1_ECX_RDRAND)) { - LogPrintf("Using RdRand as entropy source\n"); + LogPrintf("Using RdRand as an additional entropy source\n"); rdrand_supported = true; } hwrand_initialized.store(true); From 3babbcb48786372d4b22171674c4cc5a6220c294 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sat, 17 Jun 2017 00:18:42 +0000 Subject: [PATCH 068/148] Remove confusing MAX_BLOCK_BASE_SIZE. Some people keep thinking that MAX_BLOCK_BASE_SIZE is a separate size limit from the weight limit when it fact it is superfluous, and used in early tests before the witness data has been validated or just to compute worst case sizes. The size checks that use it would not behave any differently consensus wise if they were eliminated completely. Its correct value is not independently settable but is a function of the weight limit and weight formula. This patch just eliminates it and uses the scale factor as required to compute the worse case constants. It also moves the weight factor out of primitives into consensus, which is a more logical place for it. --- src/bitcoin-tx.cpp | 2 +- src/blockencodings.cpp | 4 +--- src/coins.cpp | 3 ++- src/consensus/consensus.h | 14 ++++++-------- src/consensus/tx_verify.cpp | 2 +- src/consensus/validation.h | 18 ++++++++++++++++++ src/core_write.cpp | 4 ++-- src/merkleblock.cpp | 2 +- src/policy/policy.cpp | 1 + src/primitives/block.cpp | 9 --------- src/primitives/block.h | 3 --- src/primitives/transaction.cpp | 5 ----- src/primitives/transaction.h | 6 +----- src/rpc/mining.cpp | 9 +++++---- src/test/sigopcount_tests.cpp | 1 + src/undo.h | 3 ++- src/validation.cpp | 2 +- 17 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index c6d5db786e7..9acb3fd30e9 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -239,7 +239,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu uint256 txid(uint256S(strTxid)); static const unsigned int minTxOutSz = 9; - static const unsigned int maxVout = MAX_BLOCK_BASE_SIZE / minTxOutSz; + static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz); // extract and validate vout std::string strVout = vStrInputParts[1]; diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 9cac10d2b8a..7adab586e8f 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -15,8 +15,6 @@ #include -#define MIN_TRANSACTION_BASE_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)) - CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID) : nonce(GetRand(std::numeric_limits::max())), shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) { @@ -50,7 +48,7 @@ uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const uint256& txhash) const { ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector>& extra_txn) { if (cmpctblock.header.IsNull() || (cmpctblock.shorttxids.empty() && cmpctblock.prefilledtxn.empty())) return READ_STATUS_INVALID; - if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_BASE_SIZE / MIN_TRANSACTION_BASE_SIZE) + if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_WEIGHT / MIN_SERIALIZEABLE_TRANSACTION_WEIGHT) return READ_STATUS_INVALID; assert(header.IsNull() && txn_available.empty()); diff --git a/src/coins.cpp b/src/coins.cpp index b5dc6197bd6..e30bda930ae 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -245,7 +245,8 @@ bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const return true; } -static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_BASE_SIZE / ::GetSerializeSize(CTxOut(), SER_NETWORK, PROTOCOL_VERSION); // TODO: merge with similar definition in undo.h. +static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut(), SER_NETWORK, PROTOCOL_VERSION); +static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT; const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid) { diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 58b2ed4b3e6..a1bb99a802c 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -6,25 +6,23 @@ #ifndef BITCOIN_CONSENSUS_CONSENSUS_H #define BITCOIN_CONSENSUS_CONSENSUS_H +#include #include /** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */ static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000; /** The maximum allowed weight for a block, see BIP 141 (network rule) */ static const unsigned int MAX_BLOCK_WEIGHT = 4000000; -/** - * The maximum allowed size for a block excluding witness data, in bytes (network rule). - * This parameter is largely superfluous because it is directly implied by the above block - * weight limit, even when BIP 141 is not active. It continues to exist for use in - * various early tests that run before the witness data has been checked. - * All tests related to it could be removed without breaking consensus compatibility. - */ -static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000; /** The maximum allowed number of signature check operations in a block (network rule) */ static const int64_t MAX_BLOCK_SIGOPS_COST = 80000; /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ static const int COINBASE_MATURITY = 100; +static const int WITNESS_SCALE_FACTOR = 4; + +static const size_t MIN_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 60; // 60 is the lower bound for the size of a valid serialized CTransaction +static const size_t MIN_SERIALIZEABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 10; // 10 is the lower bound for the size of a serialized CTransaction + /** Flags for nSequence and nLockTime locks */ enum { /* Interpret sequence numbers as relative lock-time constraints. */ diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index 0671cbc132f..0a71915d1df 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -164,7 +164,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe if (tx.vout.empty()) return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty"); // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability) - if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE) + if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT) return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize"); // Check for negative or overflow output values diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 8fc3ef1b66e..5494ce40eac 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -7,6 +7,10 @@ #define BITCOIN_CONSENSUS_VALIDATION_H #include +#include "version.h" +#include "consensus/consensus.h" +#include "primitives/transaction.h" +#include "primitives/block.h" /** "reject" message codes */ static const unsigned char REJECT_MALFORMED = 0x01; @@ -85,4 +89,18 @@ class CValidationState { std::string GetDebugMessage() const { return strDebugMessage; } }; +static inline int64_t GetTransactionWeight(const CTransaction& tx) +{ + return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); +} + +static inline int64_t GetBlockWeight(const CBlock& block) +{ + // This implements the weight = (stripped_size * 4) + witness_size formula, + // using only serialization with and without witness data. As witness_size + // is equal to total_size - stripped_size, this formula is identical to: + // weight = (stripped_size * 3) + total_size. + return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); +} + #endif // BITCOIN_CONSENSUS_VALIDATION_H diff --git a/src/core_write.cpp b/src/core_write.cpp index 7f38e9e565a..a366ef933c3 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -5,7 +5,8 @@ #include "core_io.h" #include "base58.h" -#include "primitives/transaction.h" +#include "consensus/consensus.h" +#include "consensus/validation.h" #include "script/script.h" #include "script/standard.h" #include "serialize.h" @@ -15,7 +16,6 @@ #include "utilmoneystr.h" #include "utilstrencodings.h" - std::string FormatScript(const CScript& script) { std::string ret; diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index 78d7cd60010..ba5f7b400cc 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -153,7 +153,7 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector &vMatch, std::ve if (nTransactions == 0) return uint256(); // check for excessively high numbers of transactions - if (nTransactions > MAX_BLOCK_BASE_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction + if (nTransactions > MAX_BLOCK_WEIGHT / MIN_TRANSACTION_WEIGHT) return uint256(); // there can never be more hashes provided than one for every txid if (vHash.size() > nTransactions) diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 2f78d2f3474..9f2d623e769 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -7,6 +7,7 @@ #include "policy/policy.h" +#include "consensus/validation.h" #include "validation.h" #include "coins.h" #include "tinyformat.h" diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 9a979094ccb..24be67c84fb 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -31,12 +31,3 @@ std::string CBlock::ToString() const } return s.str(); } - -int64_t GetBlockWeight(const CBlock& block) -{ - // This implements the weight = (stripped_size * 4) + witness_size formula, - // using only serialization with and without witness data. As witness_size - // is equal to total_size - stripped_size, this formula is identical to: - // weight = (stripped_size * 3) + total_size. - return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); -} diff --git a/src/primitives/block.h b/src/primitives/block.h index f03cf48504a..c90a1dfa644 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -152,7 +152,4 @@ struct CBlockLocator } }; -/** Compute the consensus-critical block weight (see BIP 141). */ -int64_t GetBlockWeight(const CBlock& tx); - #endif // BITCOIN_PRIMITIVES_BLOCK_H diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index a0d7793f978..f87934d5868 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -114,8 +114,3 @@ std::string CTransaction::ToString() const str += " " + vout[i].ToString() + "\n"; return str; } - -int64_t GetTransactionWeight(const CTransaction& tx) -{ - return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); -} diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 00ac0b92b54..f1dd51b9fd8 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_PRIMITIVES_TRANSACTION_H #define BITCOIN_PRIMITIVES_TRANSACTION_H +#include #include "amount.h" #include "script/script.h" #include "serialize.h" @@ -13,8 +14,6 @@ static const int SERIALIZE_TRANSACTION_NO_WITNESS = 0x40000000; -static const int WITNESS_SCALE_FACTOR = 4; - /** An outpoint - a combination of a transaction hash and an index n into its vout */ class COutPoint { @@ -411,7 +410,4 @@ typedef std::shared_ptr CTransactionRef; static inline CTransactionRef MakeTransactionRef() { return std::make_shared(); } template static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared(std::forward(txIn)); } -/** Compute the weight of a transaction, as defined by BIP 141 */ -int64_t GetTransactionWeight(const CTransaction &tx); - #endif // BITCOIN_PRIMITIVES_TRANSACTION_H diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 046c85a76eb..10bb341e54a 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -645,15 +645,16 @@ UniValue getblocktemplate(const JSONRPCRequest& request) result.push_back(Pair("mutable", aMutable)); result.push_back(Pair("noncerange", "00000000ffffffff")); int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST; + int64_t nSizeLimit = MAX_BLOCK_SERIALIZED_SIZE; if (fPreSegWit) { assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0); nSigOpLimit /= WITNESS_SCALE_FACTOR; + assert(nSizeLimit % WITNESS_SCALE_FACTOR == 0); + nSizeLimit /= WITNESS_SCALE_FACTOR; } result.push_back(Pair("sigoplimit", nSigOpLimit)); - if (fPreSegWit) { - result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_BASE_SIZE)); - } else { - result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE)); + result.push_back(Pair("sizelimit", nSizeLimit)); + if (!fPreSegWit) { result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT)); } result.push_back(Pair("curtime", pblock->GetBlockTime())); diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index eddb80aed58..d3b8b072288 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "consensus/tx_verify.h" +#include "consensus/validation.h" #include "pubkey.h" #include "key.h" #include "script/script.h" diff --git a/src/undo.h b/src/undo.h index 3749d5d7a8d..0f9d041bbdc 100644 --- a/src/undo.h +++ b/src/undo.h @@ -60,7 +60,8 @@ class TxInUndoDeserializer TxInUndoDeserializer(Coin* coin) : txout(coin) {} }; -static const size_t MAX_INPUTS_PER_BLOCK = MAX_BLOCK_BASE_SIZE / ::GetSerializeSize(CTxIn(), SER_NETWORK, PROTOCOL_VERSION); +static const size_t MIN_TRANSACTION_INPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxIn(), SER_NETWORK, PROTOCOL_VERSION); +static const size_t MAX_INPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_INPUT_WEIGHT; /** Undo information for a CTransaction */ class CTxUndo diff --git a/src/validation.cpp b/src/validation.cpp index 16d11529b01..c101497600c 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2803,7 +2803,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P // checks that use witness data may be performed here. // Size limits - if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_BASE_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE) + if (block.vtx.empty() || block.vtx.size() * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT) return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", false, "size limits failed"); // First transaction must be coinbase, the rest must not be From c73b8be2440e424f304fda22e43240e8b90f9b00 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 12 Jul 2017 14:45:14 -0400 Subject: [PATCH 069/148] Explicitly initialize prevector::_union to avoid new warning Warning from gcc 7.1 is ./prevector.h:450:25: warning: '*((void*)(&)+8).prevector<28, unsigned char>::_union.prevector<28, unsigned char>::direct_or_indirect::.prevector<28, unsigned char>::direct_or_indirect::::indirect' may be used uninitialized in this function [-Wmaybe-uninitialized] --- src/prevector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prevector.h b/src/prevector.h index 02d860bb00e..46640d6fff8 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -220,7 +220,7 @@ class prevector { } } - prevector() : _size(0) {} + prevector() : _size(0), _union{{}} {} explicit prevector(size_type n) : _size(0) { resize(n); From 4a3fc35629a2820cecd15898f112fa730e5adcec Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 19 Apr 2017 12:55:32 -0400 Subject: [PATCH 070/148] Track keypool entries as internal vs external in memory This resolves a super minor performance regressions in several keypool-handling functions --- src/wallet/wallet.cpp | 183 ++++++++++++++++++++++++-------------------------- src/wallet/wallet.h | 19 ++++-- 2 files changed, 102 insertions(+), 100 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 58153dfc3c9..cc4d99d301e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2941,7 +2941,8 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) if (dbw->Rewrite("\x04pool")) { LOCK(cs_wallet); - setKeyPool.clear(); + setInternalKeyPool.clear(); + setExternalKeyPool.clear(); // Note: can't top-up keypool here, because wallet is locked. // User will be prompted to unlock wallet the next operation // that requires a new key. @@ -2969,7 +2970,8 @@ DBErrors CWallet::ZapSelectTx(std::vector& vHashIn, std::vectorRewrite("\x04pool")) { - setKeyPool.clear(); + setInternalKeyPool.clear(); + setExternalKeyPool.clear(); // Note: can't top-up keypool here, because wallet is locked. // User will be prompted to unlock wallet the next operation // that requires a new key. @@ -2994,7 +2996,8 @@ DBErrors CWallet::ZapWalletTx(std::vector& vWtx) if (dbw->Rewrite("\x04pool")) { LOCK(cs_wallet); - setKeyPool.clear(); + setInternalKeyPool.clear(); + setExternalKeyPool.clear(); // Note: can't top-up keypool here, because wallet is locked. // User will be prompted to unlock wallet the next operation // that requires a new key. @@ -3078,9 +3081,12 @@ bool CWallet::NewKeyPool() { LOCK(cs_wallet); CWalletDB walletdb(*dbw); - for (int64_t nIndex : setKeyPool) + for (int64_t nIndex : setInternalKeyPool) walletdb.ErasePool(nIndex); - setKeyPool.clear(); + setInternalKeyPool.clear(); + BOOST_FOREACH(int64_t nIndex, setExternalKeyPool) + walletdb.ErasePool(nIndex); + setExternalKeyPool.clear(); if (!TopUpKeyPool()) { return false; @@ -3092,25 +3098,8 @@ bool CWallet::NewKeyPool() size_t CWallet::KeypoolCountExternalKeys() { - AssertLockHeld(cs_wallet); // setKeyPool - - // immediately return setKeyPool's size if HD or HD_SPLIT is disabled or not supported - if (!IsHDEnabled() || !CanSupportFeature(FEATURE_HD_SPLIT)) - return setKeyPool.size(); - - CWalletDB walletdb(*dbw); - - // count amount of external keys - size_t amountE = 0; - for(const int64_t& id : setKeyPool) - { - CKeyPool tmpKeypool; - if (!walletdb.ReadPool(id, tmpKeypool)) - throw std::runtime_error(std::string(__func__) + ": read failed"); - amountE += !tmpKeypool.fInternal; - } - - return amountE; + AssertLockHeld(cs_wallet); // setExternalKeyPool + return setExternalKeyPool.size(); } bool CWallet::TopUpKeyPool(unsigned int kpSize) @@ -3130,10 +3119,8 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) // count amount of available keys (internal, external) // make sure the keypool of external and internal keys fits the user selected target (-keypool) - int64_t amountExternal = KeypoolCountExternalKeys(); - int64_t amountInternal = setKeyPool.size() - amountExternal; - int64_t missingExternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - amountExternal, (int64_t) 0); - int64_t missingInternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - amountInternal, (int64_t) 0); + int64_t missingExternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setExternalKeyPool.size(), (int64_t) 0); + int64_t missingInternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setInternalKeyPool.size(), (int64_t) 0); if (!IsHDEnabled() || !CanSupportFeature(FEATURE_HD_SPLIT)) { @@ -3147,18 +3134,26 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) int64_t nEnd = 1; if (i < missingInternal) internal = true; - if (!setKeyPool.empty()) - nEnd = *(--setKeyPool.end()) + 1; + if (!setInternalKeyPool.empty()) + nEnd = *(--setInternalKeyPool.end()) + 1; + if (!setExternalKeyPool.empty()) + nEnd = std::max(nEnd, *(--setExternalKeyPool.end()) + 1); + if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey(internal), internal))) throw std::runtime_error(std::string(__func__) + ": writing generated key failed"); - setKeyPool.insert(nEnd); - LogPrintf("keypool added key %d, size=%u, internal=%d\n", nEnd, setKeyPool.size(), internal); + + if (internal) { + setInternalKeyPool.insert(nEnd); + } else { + setExternalKeyPool.insert(nEnd); + } + LogPrintf("keypool added key %d, size=%u (%u internal), new key is %s\n", nEnd, setInternalKeyPool.size() + setExternalKeyPool.size(), setInternalKeyPool.size(), internal ? "internal" : "external"); } } return true; } -void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool internal) +void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal) { nIndex = -1; keypool.vchPubKey = CPubKey(); @@ -3168,30 +3163,30 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool int if (!IsLocked()) TopUpKeyPool(); + bool fReturningInternal = IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT) && fRequestedInternal; + std::set& setKeyPool = fReturningInternal ? setInternalKeyPool : setExternalKeyPool; + // Get the oldest key if(setKeyPool.empty()) return; CWalletDB walletdb(*dbw); - // try to find a key that matches the internal/external filter - for(const int64_t& id : setKeyPool) - { - CKeyPool tmpKeypool; - if (!walletdb.ReadPool(id, tmpKeypool)) - throw std::runtime_error(std::string(__func__) + ": read failed"); - if (!HaveKey(tmpKeypool.vchPubKey.GetID())) - throw std::runtime_error(std::string(__func__) + ": unknown key in key pool"); - if (!IsHDEnabled() || !CanSupportFeature(FEATURE_HD_SPLIT) || tmpKeypool.fInternal == internal) - { - nIndex = id; - keypool = tmpKeypool; - setKeyPool.erase(id); - assert(keypool.vchPubKey.IsValid()); - LogPrintf("keypool reserve %d\n", nIndex); - return; - } + auto it = setKeyPool.begin(); + nIndex = *it; + setKeyPool.erase(it); + if (!walletdb.ReadPool(nIndex, keypool)) { + throw std::runtime_error(std::string(__func__) + ": read failed"); } + if (!HaveKey(keypool.vchPubKey.GetID())) { + throw std::runtime_error(std::string(__func__) + ": unknown key in key pool"); + } + if (keypool.fInternal != fReturningInternal) { + throw std::runtime_error(std::string(__func__) + ": keypool entry misclassified"); + } + + assert(keypool.vchPubKey.IsValid()); + LogPrintf("keypool reserve %d\n", nIndex); } } @@ -3203,12 +3198,16 @@ void CWallet::KeepKey(int64_t nIndex) LogPrintf("keypool keep %d\n", nIndex); } -void CWallet::ReturnKey(int64_t nIndex) +void CWallet::ReturnKey(int64_t nIndex, bool fInternal) { // Return to key pool { LOCK(cs_wallet); - setKeyPool.insert(nIndex); + if (fInternal) { + setInternalKeyPool.insert(nIndex); + } else { + setExternalKeyPool.insert(nIndex); + } } LogPrintf("keypool return %d\n", nIndex); } @@ -3232,41 +3231,12 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal) return true; } -int64_t CWallet::GetOldestKeyPoolTime() -{ - LOCK(cs_wallet); - - // if the keypool is empty, return - if (setKeyPool.empty()) +static int64_t GetOldestKeyTimeInPool(const std::set& setKeyPool, CWalletDB& walletdb) { + if (setKeyPool.empty()) { return GetTime(); + } CKeyPool keypool; - CWalletDB walletdb(*dbw); - - if (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT)) - { - // if HD & HD Chain Split is enabled, response max(oldest-internal-key, oldest-external-key) - int64_t now = GetTime(); - int64_t oldest_external = now, oldest_internal = now; - - for(const int64_t& id : setKeyPool) - { - if (!walletdb.ReadPool(id, keypool)) { - throw std::runtime_error(std::string(__func__) + ": read failed"); - } - if (keypool.fInternal && keypool.nTime < oldest_internal) { - oldest_internal = keypool.nTime; - } - else if (!keypool.fInternal && keypool.nTime < oldest_external) { - oldest_external = keypool.nTime; - } - if (oldest_internal != now && oldest_external != now) { - break; - } - } - return std::max(oldest_internal, oldest_external); - } - // load oldest key from keypool, get time and return int64_t nIndex = *(setKeyPool.begin()); if (!walletdb.ReadPool(nIndex, keypool)) throw std::runtime_error(std::string(__func__) + ": read oldest key in keypool failed"); @@ -3274,6 +3244,21 @@ int64_t CWallet::GetOldestKeyPoolTime() return keypool.nTime; } +int64_t CWallet::GetOldestKeyPoolTime() +{ + LOCK(cs_wallet); + + CWalletDB walletdb(*dbw); + + // load oldest key from keypool, get time and return + int64_t oldestKey = GetOldestKeyTimeInPool(setExternalKeyPool, walletdb); + if (IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT)) { + oldestKey = std::max(GetOldestKeyTimeInPool(setInternalKeyPool, walletdb), oldestKey); + } + + return oldestKey; +} + std::map CWallet::GetAddressBalances() { std::map balances; @@ -3432,6 +3417,7 @@ bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool internal) else { return false; } + fInternal = keypool.fInternal; } assert(vchPubKey.IsValid()); pubkey = vchPubKey; @@ -3449,18 +3435,12 @@ void CReserveKey::KeepKey() void CReserveKey::ReturnKey() { if (nIndex != -1) - pwallet->ReturnKey(nIndex); + pwallet->ReturnKey(nIndex, fInternal); nIndex = -1; vchPubKey = CPubKey(); } -void CWallet::GetAllReserveKeys(std::set& setAddress) const -{ - setAddress.clear(); - - CWalletDB walletdb(*dbw); - - LOCK2(cs_main, cs_wallet); +static void LoadReserveKeysToSet(std::set& setAddress, const std::set& setKeyPool, CWalletDB& walletdb) { for (const int64_t& id : setKeyPool) { CKeyPool keypool; @@ -3468,12 +3448,27 @@ void CWallet::GetAllReserveKeys(std::set& setAddress) const throw std::runtime_error(std::string(__func__) + ": read failed"); assert(keypool.vchPubKey.IsValid()); CKeyID keyID = keypool.vchPubKey.GetID(); - if (!HaveKey(keyID)) - throw std::runtime_error(std::string(__func__) + ": unknown key in key pool"); setAddress.insert(keyID); } } +void CWallet::GetAllReserveKeys(std::set& setAddress) const +{ + setAddress.clear(); + + CWalletDB walletdb(*dbw); + + LOCK2(cs_main, cs_wallet); + LoadReserveKeysToSet(setAddress, setInternalKeyPool, walletdb); + LoadReserveKeysToSet(setAddress, setExternalKeyPool, walletdb); + + for (const CKeyID& keyID : setAddress) { + if (!HaveKey(keyID)) { + throw std::runtime_error(std::string(__func__) + ": unknown key in key pool"); + } + } +} + void CWallet::GetScriptForMining(std::shared_ptr &script) { std::shared_ptr rKey = std::make_shared(this); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index ad606b8535c..c1e05e86115 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -696,7 +696,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* HD derive new child key (on internal or external chain) */ void DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool internal = false); - std::set setKeyPool; + std::set setInternalKeyPool; + std::set setExternalKeyPool; int64_t nTimeFirstKey; @@ -741,7 +742,11 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void LoadKeyPool(int nIndex, const CKeyPool &keypool) { - setKeyPool.insert(nIndex); + if (keypool.fInternal) { + setInternalKeyPool.insert(nIndex); + } else { + setExternalKeyPool.insert(nIndex); + } // If no metadata exists yet, create a default with the pool key's // creation time. Note that this may be overwritten by actually @@ -970,9 +975,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool NewKeyPool(); size_t KeypoolCountExternalKeys(); bool TopUpKeyPool(unsigned int kpSize = 0); - void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool internal); + void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal); void KeepKey(int64_t nIndex); - void ReturnKey(int64_t nIndex); + void ReturnKey(int64_t nIndex, bool fInternal); bool GetKeyFromPool(CPubKey &key, bool internal = false); int64_t GetOldestKeyPoolTime(); void GetAllReserveKeys(std::set& setAddress) const; @@ -1026,8 +1031,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface unsigned int GetKeyPoolSize() { - AssertLockHeld(cs_wallet); // setKeyPool - return setKeyPool.size(); + AssertLockHeld(cs_wallet); // set{Ex,In}ternalKeyPool + return setInternalKeyPool.size() + setExternalKeyPool.size(); } bool SetDefaultKey(const CPubKey &vchPubKey); @@ -1131,11 +1136,13 @@ class CReserveKey : public CReserveScript CWallet* pwallet; int64_t nIndex; CPubKey vchPubKey; + bool fInternal; public: CReserveKey(CWallet* pwalletIn) { nIndex = -1; pwallet = pwalletIn; + fInternal = false; } CReserveKey() = default; From 28301b9780b05b1d80767835987da1317ce4200a Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 19 Apr 2017 13:11:16 -0400 Subject: [PATCH 071/148] Meet code style on lines changed in the previous commit --- src/wallet/wallet.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index cc4d99d301e..61d97524603 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3081,11 +3081,15 @@ bool CWallet::NewKeyPool() { LOCK(cs_wallet); CWalletDB walletdb(*dbw); - for (int64_t nIndex : setInternalKeyPool) + + for (int64_t nIndex : setInternalKeyPool) { walletdb.ErasePool(nIndex); + } setInternalKeyPool.clear(); - BOOST_FOREACH(int64_t nIndex, setExternalKeyPool) + + for (int64_t nIndex : setExternalKeyPool) { walletdb.ErasePool(nIndex); + } setExternalKeyPool.clear(); if (!TopUpKeyPool()) { @@ -3132,12 +3136,16 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) for (int64_t i = missingInternal + missingExternal; i--;) { int64_t nEnd = 1; - if (i < missingInternal) + if (i < missingInternal) { internal = true; - if (!setInternalKeyPool.empty()) + } + + if (!setInternalKeyPool.empty()) { nEnd = *(--setInternalKeyPool.end()) + 1; - if (!setExternalKeyPool.empty()) + } + if (!setExternalKeyPool.empty()) { nEnd = std::max(nEnd, *(--setExternalKeyPool.end()) + 1); + } if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey(internal), internal))) throw std::runtime_error(std::string(__func__) + ": writing generated key failed"); @@ -3238,8 +3246,9 @@ static int64_t GetOldestKeyTimeInPool(const std::set& setKeyPool, CWall CKeyPool keypool; int64_t nIndex = *(setKeyPool.begin()); - if (!walletdb.ReadPool(nIndex, keypool)) + if (!walletdb.ReadPool(nIndex, keypool)) { throw std::runtime_error(std::string(__func__) + ": read oldest key in keypool failed"); + } assert(keypool.vchPubKey.IsValid()); return keypool.nTime; } @@ -3434,8 +3443,9 @@ void CReserveKey::KeepKey() void CReserveKey::ReturnKey() { - if (nIndex != -1) + if (nIndex != -1) { pwallet->ReturnKey(nIndex, fInternal); + } nIndex = -1; vchPubKey = CPubKey(); } From d40a72ccbb71d61b43cbf4d222ca2ab5d3ca7510 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 11 Jul 2017 12:02:42 -0400 Subject: [PATCH 072/148] Clarify *(--.end()) iterator semantics in CWallet::TopUpKeyPool --- src/wallet/wallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 61d97524603..63d0a3c0c40 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3141,10 +3141,10 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) } if (!setInternalKeyPool.empty()) { - nEnd = *(--setInternalKeyPool.end()) + 1; + nEnd = *(setInternalKeyPool.rbegin()) + 1; } if (!setExternalKeyPool.empty()) { - nEnd = std::max(nEnd, *(--setExternalKeyPool.end()) + 1); + nEnd = std::max(nEnd, *(setExternalKeyPool.rbegin()) + 1); } if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey(internal), internal))) From ecd81dfa3cae4cc1ae3638becfbefc76829ada04 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 28 Jun 2017 16:41:55 -0400 Subject: [PATCH 073/148] Make CoinControl a required argument to CreateTransaction --- src/qt/sendcoinsdialog.cpp | 2 +- src/qt/walletmodel.cpp | 4 ++-- src/qt/walletmodel.h | 2 +- src/wallet/rpcwallet.cpp | 9 +++++---- src/wallet/test/wallet_tests.cpp | 4 +++- src/wallet/wallet.cpp | 32 ++++++++++++++------------------ src/wallet/wallet.h | 2 +- 7 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 86401d3bb4b..1a07d466bfe 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -281,7 +281,7 @@ void SendCoinsDialog::on_sendButton_clicked() ctrl.signalRbf = ui->optInRBF->isChecked(); - prepareStatus = model->prepareTransaction(currentTransaction, &ctrl); + prepareStatus = model->prepareTransaction(currentTransaction, ctrl); // process prepareStatus and on error generate message shown to user processSendCoinsReturn(prepareStatus, diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 60b55da3e70..3f90860cc1f 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -191,7 +191,7 @@ bool WalletModel::validateAddress(const QString &address) return addressParsed.IsValid(); } -WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl) +WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl& coinControl) { CAmount total = 0; bool fSubtractFeeFromAmount = false; @@ -258,7 +258,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact return DuplicateAddress; } - CAmount nBalance = getBalance(coinControl); + CAmount nBalance = getBalance(&coinControl); if(total > nBalance) { diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 16b0caed4ef..5258dc66993 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -154,7 +154,7 @@ class WalletModel : public QObject }; // prepare transaction for getting txfee before sending coins - SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl = NULL); + SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl& coinControl); // Send coins to a list of recipients SendCoinsReturn sendCoins(WalletModelTransaction &transaction); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5f72e3b6f59..19169089220 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -356,7 +356,7 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request) return ret; } -static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew, CCoinControl *coin_control = nullptr) +static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew, const CCoinControl& coin_control) { CAmount curBalance = pwallet->GetBalance(); @@ -472,7 +472,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); - SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, &coin_control); + SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, coin_control); return wtx.GetHash().GetHex(); } @@ -898,7 +898,8 @@ UniValue sendfrom(const JSONRPCRequest& request) if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); - SendMoney(pwallet, address.Get(), nAmount, false, wtx); + CCoinControl no_coin_control; // This is a deprecated API + SendMoney(pwallet, address.Get(), nAmount, false, wtx, no_coin_control); return wtx.GetHash().GetHex(); } @@ -1033,7 +1034,7 @@ UniValue sendmany(const JSONRPCRequest& request) CAmount nFeeRequired = 0; int nChangePosRet = -1; std::string strFailReason; - bool fCreated = pwallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, &coin_control); + bool fCreated = pwallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control); if (!fCreated) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); CValidationState state; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 96a1b14b60e..8176a0017c9 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -13,6 +13,7 @@ #include "rpc/server.h" #include "test/test_bitcoin.h" #include "validation.h" +#include "wallet/coincontrol.h" #include "wallet/test/wallet_test_fixture.h" #include @@ -617,7 +618,8 @@ class ListCoinsTestingSetup : public TestChain100Setup CAmount fee; int changePos = -1; std::string error; - BOOST_CHECK(wallet->CreateTransaction({recipient}, wtx, reservekey, fee, changePos, error)); + CCoinControl dummy; + BOOST_CHECK(wallet->CreateTransaction({recipient}, wtx, reservekey, fee, changePos, error, dummy)); CValidationState state; BOOST_CHECK(wallet->CommitTransaction(wtx, reservekey, nullptr, state)); auto it = wallet->mapWallet.find(wtx.GetHash()); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 07b7f58a641..f69ae5268c8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2469,9 +2469,9 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC CReserveKey reservekey(this); CWalletTx wtx; - if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false)) + if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) { return false; - + } if (nChangePosInOut != -1) tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.tx->vout[nChangePosInOut]); @@ -2502,7 +2502,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC } bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, - int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign) + int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign) { CAmount nValue = 0; int nChangePosRequest = nChangePosInOut; @@ -2567,7 +2567,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT LOCK2(cs_main, cs_wallet); { std::vector vAvailableCoins; - AvailableCoins(vAvailableCoins, true, coinControl); + AvailableCoins(vAvailableCoins, true, &coin_control); // Create change script that will be used if we need change // TODO: pass in scriptChange instead of reservekey so @@ -2575,12 +2575,9 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT CScript scriptChange; // coin control: send change to custom address - if (coinControl && !boost::get(&coinControl->destChange)) - scriptChange = GetScriptForDestination(coinControl->destChange); - - // no coin control: send change to newly generated address - else - { + if (!boost::get(&coin_control.destChange)) { + scriptChange = GetScriptForDestination(coin_control.destChange); + } else { // no coin control: send change to newly generated address // Note: We use a new key here to keep it from being obvious which side is the change. // The drawback is that by not reusing a previous key, the change may be lost if a // backup is restored, if the backup doesn't have the new private key for the change. @@ -2654,7 +2651,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT if (pick_new_inputs) { nValueIn = 0; setCoins.clear(); - if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl)) + if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, &coin_control)) { strFailReason = _("Insufficient funds"); return false; @@ -2705,8 +2702,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // to avoid conflicting with other possible uses of nSequence, // and in the spirit of "smallest possible change from prior // behavior." - bool rbf = coinControl ? coinControl->signalRbf : fWalletRbf; - const uint32_t nSequence = rbf ? MAX_BIP125_RBF_SEQUENCE : (std::numeric_limits::max() - 1); + const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (std::numeric_limits::max() - 1); for (const auto& coin : setCoins) txNew.vin.push_back(CTxIn(coin.outpoint,CScript(), nSequence)); @@ -2727,15 +2723,15 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // Allow to override the default confirmation target over the CoinControl instance int currentConfirmationTarget = nTxConfirmTarget; - if (coinControl && coinControl->nConfirmTarget > 0) - currentConfirmationTarget = coinControl->nConfirmTarget; + if (coin_control.nConfirmTarget > 0) + currentConfirmationTarget = coin_control.nConfirmTarget; // Allow to override the default fee estimate mode over the CoinControl instance - bool conservative_estimate = CalculateEstimateType(coinControl ? coinControl->m_fee_mode : FeeEstimateMode::UNSET, rbf); + bool conservative_estimate = CalculateEstimateType(coin_control.m_fee_mode, coin_control.signalRbf); CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator, &feeCalc, false /* ignoreGlobalPayTxFee */, conservative_estimate); - if (coinControl && coinControl->fOverrideFeeRate) - nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes); + if (coin_control.fOverrideFeeRate) + nFeeNeeded = coin_control.nFeeRate.GetFee(nBytes); // If we made it here and we aren't even able to meet the relay fee on the next pass, give up // because we must be at the maximum allowed fee. diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index e3715cdf376..d8717ea179f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -949,7 +949,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * @note passing nChangePosInOut as -1 will result in setting a random position */ bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, - std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); + std::string& strFailReason, const CCoinControl& coin_control, bool sign = true); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state); void ListAccountCreditDebit(const std::string& strAccount, std::list& entries); From 03ee70116189bb358e7c6224ba0ecb745e8161c2 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 28 Jun 2017 17:23:46 -0400 Subject: [PATCH 074/148] Refactor to use CoinControl in GetMinimumFee and FeeBumper Improve parameter precedence in coin_control --- src/qt/coincontroldialog.cpp | 4 +-- src/qt/sendcoinsdialog.cpp | 14 ++++----- src/qt/walletmodel.cpp | 5 +++- src/wallet/coincontrol.h | 16 ++++++----- src/wallet/feebumper.cpp | 8 +++--- src/wallet/feebumper.h | 3 +- src/wallet/rpcwallet.cpp | 33 ++++++++-------------- src/wallet/wallet.cpp | 67 +++++++++++++++++++++++++------------------- src/wallet/wallet.h | 2 +- 9 files changed, 79 insertions(+), 73 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index c19420beb56..7d8ef6571f4 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -512,7 +512,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) nBytes -= 34; // Fee - nPayFee = CWallet::GetMinimumFee(nBytes, coinControl->nConfirmTarget, ::mempool, ::feeEstimator, nullptr /* FeeCalculation */, false /* ignoreGlobalPayTxFee */, conservative_estimate); + nPayFee = CWallet::GetMinimumFee(nBytes, *coinControl, ::mempool, ::feeEstimator, nullptr /* FeeCalculation */); if (nPayAmount > 0) { @@ -587,7 +587,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) if (payTxFee.GetFeePerK() > 0) dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000; else { - dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(coinControl->nConfirmTarget, NULL, ::mempool, conservative_estimate).GetFeePerK()) / 1000; + dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(*coinControl->m_confirm_target, NULL, ::mempool, conservative_estimate).GetFeePerK()) / 1000; } QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 1a07d466bfe..92478fcac6d 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -274,11 +274,11 @@ void SendCoinsDialog::on_sendButton_clicked() CCoinControl ctrl; if (model->getOptionsModel()->getCoinControlFeatures()) ctrl = *CoinControlDialog::coinControl; - if (ui->radioSmartFee->isChecked()) - ctrl.nConfirmTarget = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); - else - ctrl.nConfirmTarget = 0; - + if (ui->radioSmartFee->isChecked()) { + ctrl.m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); + } else { + ctrl.m_confirm_target = boost::none; + } ctrl.signalRbf = ui->optInRBF->isChecked(); prepareStatus = model->prepareTransaction(currentTransaction, ctrl); @@ -848,9 +848,9 @@ void SendCoinsDialog::coinControlUpdateLabels() CoinControlDialog::payAmounts.clear(); CoinControlDialog::fSubtractFeeFromAmount = false; if (ui->radioSmartFee->isChecked()) { - CoinControlDialog::coinControl->nConfirmTarget = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); + CoinControlDialog::coinControl->m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); } else { - CoinControlDialog::coinControl->nConfirmTarget = model->getDefaultConfirmTarget(); + CoinControlDialog::coinControl->m_confirm_target = boost::none; } CoinControlDialog::coinControl->signalRbf = ui->optInRBF->isChecked(); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 3f90860cc1f..ba0e1da0c78 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -24,6 +24,7 @@ #include "sync.h" #include "ui_interface.h" #include "util.h" // for GetBoolArg +#include "wallet/coincontrol.h" #include "wallet/feebumper.h" #include "wallet/wallet.h" #include "wallet/walletdb.h" // for BackupWallet @@ -667,8 +668,10 @@ bool WalletModel::bumpFee(uint256 hash) { std::unique_ptr feeBump; { + CCoinControl coin_control; + coin_control.signalRbf = true; LOCK2(cs_main, wallet->cs_wallet); - feeBump.reset(new CFeeBumper(wallet, hash, nTxConfirmTarget, false, 0, true, FeeEstimateMode::UNSET)); + feeBump.reset(new CFeeBumper(wallet, hash, coin_control, 0)); } if (feeBump->getResult() != BumpFeeResult::OK) { diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index bdd01bec12a..40c8b764b96 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -10,6 +10,8 @@ #include "primitives/transaction.h" #include "wallet/wallet.h" +#include + /** Coin Control Features. */ class CCoinControl { @@ -19,12 +21,12 @@ class CCoinControl bool fAllowOtherInputs; //! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria bool fAllowWatchOnly; - //! Override estimated feerate + //! Override automatic min/max checks on fee, m_feerate must be set if true bool fOverrideFeeRate; - //! Feerate to use if overrideFeeRate is true - CFeeRate nFeeRate; - //! Override the default confirmation target, 0 = use default - int nConfirmTarget; + //! Override the default payTxFee if set + boost::optional m_feerate; + //! Override the default confirmation target if set + boost::optional m_confirm_target; //! Signal BIP-125 replace by fee. bool signalRbf; //! Fee estimation mode to control arguments to estimateSmartFee @@ -41,9 +43,9 @@ class CCoinControl fAllowOtherInputs = false; fAllowWatchOnly = false; setSelected.clear(); - nFeeRate = CFeeRate(0); + m_feerate = boost::none; fOverrideFeeRate = false; - nConfirmTarget = 0; + m_confirm_target = boost::none; signalRbf = fWalletRbf; m_fee_mode = FeeEstimateMode::UNSET; } diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index 607ecf4182b..4bfd8726a54 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "consensus/validation.h" +#include "wallet/coincontrol.h" #include "wallet/feebumper.h" #include "wallet/wallet.h" #include "policy/fees.h" @@ -66,7 +67,7 @@ bool CFeeBumper::preconditionChecks(const CWallet *pWallet, const CWalletTx& wtx return true; } -CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConfirmTarget, bool ignoreGlobalPayTxFee, CAmount totalFee, bool newTxReplaceable, FeeEstimateMode fee_mode) +CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, const CCoinControl& coin_control, CAmount totalFee) : txid(std::move(txidIn)), nOldFee(0), @@ -165,8 +166,7 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf nNewFee = totalFee; nNewFeeRate = CFeeRate(totalFee, maxNewTxSize); } else { - bool conservative_estimate = CalculateEstimateType(fee_mode, newTxReplaceable); - nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, ::feeEstimator, nullptr /* FeeCalculation */, ignoreGlobalPayTxFee, conservative_estimate); + nNewFee = CWallet::GetMinimumFee(maxNewTxSize, coin_control, mempool, ::feeEstimator, nullptr /* FeeCalculation */); nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize); // New fee rate must be at least old rate + minimum incremental relay rate @@ -221,7 +221,7 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf } // Mark new tx not replaceable, if requested. - if (!newTxReplaceable) { + if (!coin_control.signalRbf) { for (auto& input : mtx.vin) { if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe; } diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h index 11e2f5f9537..3d64e53c15c 100644 --- a/src/wallet/feebumper.h +++ b/src/wallet/feebumper.h @@ -10,6 +10,7 @@ class CWallet; class CWalletTx; class uint256; +class CCoinControl; enum class FeeEstimateMode; enum class BumpFeeResult @@ -25,7 +26,7 @@ enum class BumpFeeResult class CFeeBumper { public: - CFeeBumper(const CWallet *pWalletIn, const uint256 txidIn, int newConfirmTarget, bool ignoreGlobalPayTxFee, CAmount totalFee, bool newTxReplaceable, FeeEstimateMode fee_mode); + CFeeBumper(const CWallet *pWalletIn, const uint256 txidIn, const CCoinControl& coin_control, CAmount totalFee); BumpFeeResult getResult() const { return currentResult; } const std::vector& getErrors() const { return vErrors; } CAmount getOldFee() const { return nOldFee; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 19169089220..c636fa81144 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -460,7 +460,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request) } if (request.params.size() > 6 && !request.params[6].isNull()) { - coin_control.nConfirmTarget = request.params[6].get_int(); + coin_control.m_confirm_target = request.params[6].get_int(); } if (request.params.size() > 7 && !request.params[7].isNull()) { @@ -981,7 +981,7 @@ UniValue sendmany(const JSONRPCRequest& request) } if (request.params.size() > 6 && !request.params[6].isNull()) { - coin_control.nConfirmTarget = request.params[6].get_int(); + coin_control.m_confirm_target = request.params[6].get_int(); } if (request.params.size() > 7 && !request.params[7].isNull()) { @@ -2730,13 +2730,9 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) RPCTypeCheck(request.params, {UniValue::VSTR}); CCoinControl coinControl; - coinControl.destChange = CNoDestination(); int changePosition = -1; - coinControl.fAllowWatchOnly = false; // include watching bool lockUnspents = false; bool reserveChangeKey = true; - coinControl.nFeeRate = CFeeRate(0); - coinControl.fOverrideFeeRate = false; UniValue subtractFeeFromOutputs; std::set setSubtractFeeFromOutputs; @@ -2788,7 +2784,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) if (options.exists("feeRate")) { - coinControl.nFeeRate = CFeeRate(AmountFromValue(options["feeRate"])); + coinControl.m_feerate = CFeeRate(AmountFromValue(options["feeRate"])); coinControl.fOverrideFeeRate = true; } @@ -2799,7 +2795,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) coinControl.signalRbf = options["replaceable"].get_bool(); } if (options.exists("conf_target")) { - coinControl.nConfirmTarget = options["conf_target"].get_int(); + coinControl.m_confirm_target = options["conf_target"].get_int(); } if (options.exists("estimate_mode")) { if (!FeeModeFromString(options["estimate_mode"].get_str(), coinControl.m_fee_mode)) { @@ -2905,11 +2901,9 @@ UniValue bumpfee(const JSONRPCRequest& request) hash.SetHex(request.params[0].get_str()); // optional parameters - bool ignoreGlobalPayTxFee = false; - int newConfirmTarget = nTxConfirmTarget; CAmount totalFee = 0; - bool replaceable = true; - FeeEstimateMode fee_mode = FeeEstimateMode::UNSET; + CCoinControl coin_control; + coin_control.signalRbf = true; if (request.params.size() > 1) { UniValue options = request.params[1]; RPCTypeCheckObj(options, @@ -2924,14 +2918,11 @@ UniValue bumpfee(const JSONRPCRequest& request) if (options.exists("confTarget") && options.exists("totalFee")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and totalFee options should not both be set. Please provide either a confirmation target for fee estimation or an explicit total fee for the transaction."); } else if (options.exists("confTarget")) { - // If the user has explicitly set a confTarget in this rpc call, - // then override the default logic that uses the global payTxFee - // instead of the confirmation target. - ignoreGlobalPayTxFee = true; - newConfirmTarget = options["confTarget"].get_int(); - if (newConfirmTarget <= 0) { // upper-bound will be checked by estimatefee/smartfee + int target = options["confTarget"].get_int(); + if (target <= 0) { // FIXME: Check upper bound too throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid confTarget (cannot be <= 0)"); } + coin_control.m_confirm_target = target; } else if (options.exists("totalFee")) { totalFee = options["totalFee"].get_int64(); if (totalFee <= 0) { @@ -2940,10 +2931,10 @@ UniValue bumpfee(const JSONRPCRequest& request) } if (options.exists("replaceable")) { - replaceable = options["replaceable"].get_bool(); + coin_control.signalRbf = options["replaceable"].get_bool(); } if (options.exists("estimate_mode")) { - if (!FeeModeFromString(options["estimate_mode"].get_str(), fee_mode)) { + if (!FeeModeFromString(options["estimate_mode"].get_str(), coin_control.m_fee_mode)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); } } @@ -2952,7 +2943,7 @@ UniValue bumpfee(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); EnsureWalletIsUnlocked(pwallet); - CFeeBumper feeBump(pwallet, hash, newConfirmTarget, ignoreGlobalPayTxFee, totalFee, replaceable, fee_mode); + CFeeBumper feeBump(pwallet, hash, coin_control, totalFee); BumpFeeResult res = feeBump.getResult(); if (res != BumpFeeResult::OK) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f69ae5268c8..f010ff0ca16 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2721,17 +2721,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT vin.scriptWitness.SetNull(); } - // Allow to override the default confirmation target over the CoinControl instance - int currentConfirmationTarget = nTxConfirmTarget; - if (coin_control.nConfirmTarget > 0) - currentConfirmationTarget = coin_control.nConfirmTarget; - - // Allow to override the default fee estimate mode over the CoinControl instance - bool conservative_estimate = CalculateEstimateType(coin_control.m_fee_mode, coin_control.signalRbf); - - CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator, &feeCalc, false /* ignoreGlobalPayTxFee */, conservative_estimate); - if (coin_control.fOverrideFeeRate) - nFeeNeeded = coin_control.nFeeRate.GetFee(nBytes); + CAmount nFeeNeeded = GetMinimumFee(nBytes, coin_control, ::mempool, ::feeEstimator, &feeCalc); // If we made it here and we aren't even able to meet the relay fee on the next pass, give up // because we must be at the maximum allowed fee. @@ -2756,7 +2746,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // new inputs. We now know we only need the smaller fee // (because of reduced tx size) and so we should add a // change output. Only try this once. - CAmount fee_needed_for_change = GetMinimumFee(change_prototype_size, currentConfirmationTarget, ::mempool, ::feeEstimator, nullptr, false /* ignoreGlobalPayTxFee */, conservative_estimate); + CAmount fee_needed_for_change = GetMinimumFee(change_prototype_size, coin_control, ::mempool, ::feeEstimator, nullptr); CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, ::dustRelayFee); CAmount max_excess_fee = fee_needed_for_change + minimum_value_for_change; if (nFeeRet > nFeeNeeded + max_excess_fee && nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) { @@ -2932,33 +2922,52 @@ CAmount CWallet::GetRequiredFee(unsigned int nTxBytes) return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes)); } -CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee, bool conservative_estimate) +CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc) { - // payTxFee is the user-set global for desired feerate - CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes); - // User didn't set: use -txconfirmtarget to estimate... - if (nFeeNeeded == 0 || ignoreGlobalPayTxFee) { - nFeeNeeded = estimator.estimateSmartFee(nConfirmTarget, feeCalc, pool, conservative_estimate).GetFee(nTxBytes); - // ... unless we don't have enough mempool data for estimatefee, then use fallbackFee - if (nFeeNeeded == 0) { - nFeeNeeded = fallbackFee.GetFee(nTxBytes); + /* User control of how to calculate fee uses the following parameter precedence: + 1. coin_control.m_feerate + 2. coin_control.m_confirm_target + 3. payTxFee (user-set global variable) + 4. nTxConfirmTarget (user-set global variable) + The first parameter that is set is used. + */ + CAmount fee_needed; + if (coin_control.m_feerate) { // 1. + fee_needed = coin_control.m_feerate->GetFee(nTxBytes); + if (feeCalc) feeCalc->reason = FeeReason::PAYTXFEE; + // Allow to override automatic min/max check over coin control instance + if (coin_control.fOverrideFeeRate) return fee_needed; + } + else if (!coin_control.m_confirm_target && ::payTxFee != CFeeRate(0)) { // 3. TODO: remove magic value of 0 for global payTxFee + fee_needed = ::payTxFee.GetFee(nTxBytes); + if (feeCalc) feeCalc->reason = FeeReason::PAYTXFEE; + } + else { // 2. or 4. + // We will use smart fee estimation + unsigned int target = coin_control.m_confirm_target ? *coin_control.m_confirm_target : ::nTxConfirmTarget; + // Allow to override the default fee estimate mode over the CoinControl instance + bool conservative_estimate = CalculateEstimateType(coin_control.m_fee_mode, coin_control.signalRbf); + + fee_needed = estimator.estimateSmartFee(target, feeCalc, pool, conservative_estimate).GetFee(nTxBytes); + if (fee_needed == 0) { + // if we don't have enough data for estimateSmartFee, then use fallbackFee + fee_needed = fallbackFee.GetFee(nTxBytes); if (feeCalc) feeCalc->reason = FeeReason::FALLBACK; } - } else { - if (feeCalc) feeCalc->reason = FeeReason::PAYTXFEE; } + // prevent user from paying a fee below minRelayTxFee or minTxFee - CAmount requiredFee = GetRequiredFee(nTxBytes); - if (requiredFee > nFeeNeeded) { - nFeeNeeded = requiredFee; + CAmount required_fee = GetRequiredFee(nTxBytes); + if (required_fee > fee_needed) { + fee_needed = required_fee; if (feeCalc) feeCalc->reason = FeeReason::REQUIRED; } // But always obey the maximum - if (nFeeNeeded > maxTxFee) { - nFeeNeeded = maxTxFee; + if (fee_needed > maxTxFee) { + fee_needed = maxTxFee; if (feeCalc) feeCalc->reason = FeeReason::MAXTXFEE; } - return nFeeNeeded; + return fee_needed; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d8717ea179f..3c866776fbc 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -964,7 +964,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Estimate the minimum fee considering user set parameters * and the required fee */ - static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc, bool ignoreGlobalPayTxFee, bool conservative_estimate); + static CAmount GetMinimumFee(unsigned int nTxBytes, const CCoinControl& coin_control, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, FeeCalculation *feeCalc); /** * Return the minimum required fee taking into account the * floating relay fee and user set minimum transaction fee From 1983ca6cb3d6e741191206b57585a4b88d9ab86e Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 28 Jun 2017 19:24:28 -0400 Subject: [PATCH 075/148] Use CoinControl to pass custom fee setting from QT. This fixes buggy behavior where we were temporarily setting and unsetting the global payTxFee when trying to send a transaction with a custom fee from the GUI. The previous behavior was inconsistent depending on the order of using the RPC call settxfee and clicking various radio buttons in the sendcoinsdialog. The new behavior is that transactions sent with the GUI will always use either the smartfee slider value or the custom fee set on the GUI and they will not affect the global defaults which are only for RPC and initial GUI values. --- src/qt/sendcoinsdialog.cpp | 59 ++++++++++++++++++---------------------------- src/qt/sendcoinsdialog.h | 3 ++- 2 files changed, 25 insertions(+), 37 deletions(-) diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 92478fcac6d..d48b3753ba1 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -175,18 +175,13 @@ void SendCoinsDialog::setModel(WalletModel *_model) ui->confTargetSelector->addItem(tr("%1 (%2 blocks)").arg(GUIUtil::formatNiceTimeOffset(n*Params().GetConsensus().nPowTargetSpacing)).arg(n)); } connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSmartFeeLabel())); - connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGlobalFeeVariables())); connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(coinControlUpdateLabels())); connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateFeeSectionControls())); - connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateGlobalFeeVariables())); connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels())); - connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, SLOT(updateGlobalFeeVariables())); connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels())); - connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(updateGlobalFeeVariables())); connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(coinControlUpdateLabels())); connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(setMinimumFee())); connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls())); - connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables())); connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels())); connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(updateSmartFeeLabel())); connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels())); @@ -194,7 +189,6 @@ void SendCoinsDialog::setModel(WalletModel *_model) updateFeeSectionControls(); updateMinFeeLabel(); updateSmartFeeLabel(); - updateGlobalFeeVariables(); // set default rbf checkbox state ui->optInRBF->setCheckState(model->getDefaultWalletRbf() ? Qt::Checked : Qt::Unchecked); @@ -274,12 +268,8 @@ void SendCoinsDialog::on_sendButton_clicked() CCoinControl ctrl; if (model->getOptionsModel()->getCoinControlFeatures()) ctrl = *CoinControlDialog::coinControl; - if (ui->radioSmartFee->isChecked()) { - ctrl.m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); - } else { - ctrl.m_confirm_target = boost::none; - } - ctrl.signalRbf = ui->optInRBF->isChecked(); + + updateCoinControlState(ctrl); prepareStatus = model->prepareTransaction(currentTransaction, ctrl); @@ -636,18 +626,6 @@ void SendCoinsDialog::updateFeeSectionControls() ui->customFee ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); } -void SendCoinsDialog::updateGlobalFeeVariables() -{ - if (ui->radioSmartFee->isChecked()) - { - payTxFee = CFeeRate(0); - } - else - { - payTxFee = CFeeRate(ui->customFee->value()); - } -} - void SendCoinsDialog::updateFeeMinimizedLabel() { if(!model || !model->getOptionsModel()) @@ -669,15 +647,30 @@ void SendCoinsDialog::updateMinFeeLabel() ); } +void SendCoinsDialog::updateCoinControlState(CCoinControl& ctrl) +{ + if (ui->radioCustomFee->isChecked()) { + ctrl.m_feerate = CFeeRate(ui->customFee->value()); + } else { + ctrl.m_feerate = boost::none; + } + // Avoid using global defaults when sending money from the GUI + // Either custom fee will be used or if not selected, the confirmation target from dropdown box + ctrl.m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); + ctrl.signalRbf = ui->optInRBF->isChecked(); +} + void SendCoinsDialog::updateSmartFeeLabel() { if(!model || !model->getOptionsModel()) return; - - int nBlocksToConfirm = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); + CCoinControl coin_control; + updateCoinControlState(coin_control); + coin_control.m_feerate = boost::none; // Explicitly use only fee estimation rate for smart fee labels FeeCalculation feeCalc; - bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, ui->optInRBF->isChecked()); - CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &feeCalc, ::mempool, conservative_estimate); + bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, coin_control.signalRbf); + CFeeRate feeRate = ::feeEstimator.estimateSmartFee(*coin_control.m_confirm_target, &feeCalc, ::mempool, conservative_estimate); + if (feeRate <= CFeeRate(0)) // not enough data => minfee { ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), @@ -752,8 +745,6 @@ void SendCoinsDialog::coinControlFeatureChanged(bool checked) if (!checked && model) // coin control features disabled CoinControlDialog::coinControl->SetNull(); - // make sure we set back the confirmation target - updateGlobalFeeVariables(); coinControlUpdateLabels(); } @@ -844,15 +835,11 @@ void SendCoinsDialog::coinControlUpdateLabels() if (!model || !model->getOptionsModel()) return; + updateCoinControlState(*CoinControlDialog::coinControl); + // set pay amounts CoinControlDialog::payAmounts.clear(); CoinControlDialog::fSubtractFeeFromAmount = false; - if (ui->radioSmartFee->isChecked()) { - CoinControlDialog::coinControl->m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); - } else { - CoinControlDialog::coinControl->m_confirm_target = boost::none; - } - CoinControlDialog::coinControl->signalRbf = ui->optInRBF->isChecked(); for(int i = 0; i < ui->entries->count(); ++i) { diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index ff7040ac5b3..70b4aa5a03a 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -68,6 +68,8 @@ public Q_SLOTS: void processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg = QString()); void minimizeFeeSection(bool fMinimize); void updateFeeMinimizedLabel(); + // Update the passed in CCoinControl with state from the GUI + void updateCoinControlState(CCoinControl& ctrl); private Q_SLOTS: void on_sendButton_clicked(); @@ -91,7 +93,6 @@ private Q_SLOTS: void updateFeeSectionControls(); void updateMinFeeLabel(); void updateSmartFeeLabel(); - void updateGlobalFeeVariables(); Q_SIGNALS: // Fired when a message should be reported to the user From 2fffaa97381f741786fff2e6ff25f4b9a74037fe Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 29 Jun 2017 11:29:34 -0400 Subject: [PATCH 076/148] Make QT fee displays use GetMinimumFee instead of estimateSmartFee Remove helper function (CalculateEstimateType) for determining whether estimates should be conservative or not, now that this is only called once from GetMinimumFee and incorporate the logic directly there. --- src/qt/coincontroldialog.cpp | 10 ++-------- src/qt/sendcoinsdialog.cpp | 16 ++++++---------- src/wallet/coincontrol.h | 4 ++-- src/wallet/wallet.cpp | 17 ++++------------- src/wallet/wallet.h | 2 -- 5 files changed, 14 insertions(+), 35 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 7d8ef6571f4..f3ee0fbe393 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -490,8 +490,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) else nBytesInputs += 148; } - bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, coinControl->signalRbf); - // calculation if (nQuantity > 0) { @@ -583,12 +581,8 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) QString toolTipDust = tr("This label turns red if any recipient receives an amount smaller than the current dust threshold."); // how many satoshis the estimated fee can vary per byte we guess wrong - double dFeeVary; - if (payTxFee.GetFeePerK() > 0) - dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000; - else { - dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(*coinControl->m_confirm_target, NULL, ::mempool, conservative_estimate).GetFeePerK()) / 1000; - } + double dFeeVary = (double)nPayFee / nBytes; + QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary); l3->setToolTip(toolTip4); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index d48b3753ba1..a01886c3ea8 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -652,7 +652,7 @@ void SendCoinsDialog::updateCoinControlState(CCoinControl& ctrl) if (ui->radioCustomFee->isChecked()) { ctrl.m_feerate = CFeeRate(ui->customFee->value()); } else { - ctrl.m_feerate = boost::none; + ctrl.m_feerate.reset(); } // Avoid using global defaults when sending money from the GUI // Either custom fee will be used or if not selected, the confirmation target from dropdown box @@ -666,15 +666,13 @@ void SendCoinsDialog::updateSmartFeeLabel() return; CCoinControl coin_control; updateCoinControlState(coin_control); - coin_control.m_feerate = boost::none; // Explicitly use only fee estimation rate for smart fee labels + coin_control.m_feerate.reset(); // Explicitly use only fee estimation rate for smart fee labels FeeCalculation feeCalc; - bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, coin_control.signalRbf); - CFeeRate feeRate = ::feeEstimator.estimateSmartFee(*coin_control.m_confirm_target, &feeCalc, ::mempool, conservative_estimate); + CFeeRate feeRate = CFeeRate(CWallet::GetMinimumFee(1000, coin_control, ::mempool, ::feeEstimator, &feeCalc)); - if (feeRate <= CFeeRate(0)) // not enough data => minfee - { - ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), - std::max(CWallet::fallbackFee.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB"); + ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kB"); + + if (feeCalc.reason == FeeReason::FALLBACK) { ui->labelSmartFee2->show(); // (Smart fee not initialized yet. This usually takes a few blocks...) ui->labelFeeEstimation->setText(""); ui->fallbackFeeWarningLabel->setVisible(true); @@ -685,8 +683,6 @@ void SendCoinsDialog::updateSmartFeeLabel() } else { - ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), - std::max(feeRate.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB"); ui->labelSmartFee2->hide(); ui->labelFeeEstimation->setText(tr("Estimated to begin confirmation within %n block(s).", "", feeCalc.returnedTarget)); ui->fallbackFeeWarningLabel->setVisible(false); diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index 40c8b764b96..fc0e7c519ed 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -43,9 +43,9 @@ class CCoinControl fAllowOtherInputs = false; fAllowWatchOnly = false; setSelected.clear(); - m_feerate = boost::none; + m_feerate.reset(); fOverrideFeeRate = false; - m_confirm_target = boost::none; + m_confirm_target.reset(); signalRbf = fWalletRbf; m_fee_mode = FeeEstimateMode::UNSET; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f010ff0ca16..f7f296bd521 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2945,8 +2945,11 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, const CCoinControl& coin_c else { // 2. or 4. // We will use smart fee estimation unsigned int target = coin_control.m_confirm_target ? *coin_control.m_confirm_target : ::nTxConfirmTarget; + // By default estimates are economical iff we are signaling opt-in-RBF + bool conservative_estimate = !coin_control.signalRbf; // Allow to override the default fee estimate mode over the CoinControl instance - bool conservative_estimate = CalculateEstimateType(coin_control.m_fee_mode, coin_control.signalRbf); + if (coin_control.m_fee_mode == FeeEstimateMode::CONSERVATIVE) conservative_estimate = true; + else if (coin_control.m_fee_mode == FeeEstimateMode::ECONOMICAL) conservative_estimate = false; fee_needed = estimator.estimateSmartFee(target, feeCalc, pool, conservative_estimate).GetFee(nTxBytes); if (fee_needed == 0) { @@ -4194,15 +4197,3 @@ bool CMerkleTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& { return ::AcceptToMemoryPool(mempool, state, tx, true, NULL, NULL, false, nAbsurdFee); } - -bool CalculateEstimateType(FeeEstimateMode mode, bool opt_in_rbf) { - switch (mode) { - case FeeEstimateMode::UNSET: - return !opt_in_rbf; // Allow for lower fees if RBF is an option - case FeeEstimateMode::CONSERVATIVE: - return true; - case FeeEstimateMode::ECONOMICAL: - return false; - } - return true; -} diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3c866776fbc..bb9d146a206 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1213,6 +1213,4 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const ContainerType &coins return true; } -bool CalculateEstimateType(FeeEstimateMode mode, bool opt_in_rbf); - #endif // BITCOIN_WALLET_WALLET_H From fd29d3df299bd06c0e6bb218863e0c855b3b91af Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 29 Jun 2017 13:13:23 -0400 Subject: [PATCH 077/148] Remove checking of mempool min fee from estimateSmartFee. This check has been moved to the wallet logic GetMinimumFee. The rpc call to estimatesmartfee will now no longer return a result maxed with the mempool min fee, but automated fee calculations from the wallet will produce the same result as before and coincontrol and sendcoins dialogs in the GUI will correctly display the right prospective fee. changes to policy/fees.cpp include a big whitespace indentation change. --- src/policy/fees.cpp | 110 +++++++++++++++++-------------------- src/policy/fees.h | 2 +- src/rpc/mining.cpp | 3 +- src/test/policyestimator_tests.cpp | 10 ---- src/wallet/wallet.cpp | 8 ++- 5 files changed, 60 insertions(+), 73 deletions(-) diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 03fe11a0d80..45f97652319 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -826,8 +826,10 @@ double CBlockPolicyEstimator::estimateConservativeFee(unsigned int doubleTarget, * estimates, however, required the 95% threshold at 2 * target be met for any * longer time horizons also. */ -CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation *feeCalc, const CTxMemPool& pool, bool conservative) const +CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation *feeCalc, bool conservative) const { + LOCK(cs_feeEstimator); + if (feeCalc) { feeCalc->desiredTarget = confTarget; feeCalc->returnedTarget = confTarget; @@ -835,80 +837,70 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation double median = -1; EstimationResult tempResult; - { - LOCK(cs_feeEstimator); - // Return failure if trying to analyze a target we're not tracking - if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms()) - return CFeeRate(0); + // Return failure if trying to analyze a target we're not tracking + if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms()) + return CFeeRate(0); - // It's not possible to get reasonable estimates for confTarget of 1 - if (confTarget == 1) - confTarget = 2; + // It's not possible to get reasonable estimates for confTarget of 1 + if (confTarget == 1) + confTarget = 2; - unsigned int maxUsableEstimate = MaxUsableEstimate(); - if (maxUsableEstimate <= 1) - return CFeeRate(0); + unsigned int maxUsableEstimate = MaxUsableEstimate(); + if (maxUsableEstimate <= 1) + return CFeeRate(0); - if ((unsigned int)confTarget > maxUsableEstimate) { - confTarget = maxUsableEstimate; - } + if ((unsigned int)confTarget > maxUsableEstimate) { + confTarget = maxUsableEstimate; + } - assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints - /** true is passed to estimateCombined fee for target/2 and target so - * that we check the max confirms for shorter time horizons as well. - * This is necessary to preserve monotonically increasing estimates. - * For non-conservative estimates we do the same thing for 2*target, but - * for conservative estimates we want to skip these shorter horizons - * checks for 2*target because we are taking the max over all time - * horizons so we already have monotonically increasing estimates and - * the purpose of conservative estimates is not to let short term - * fluctuations lower our estimates by too much. - */ - double halfEst = estimateCombinedFee(confTarget/2, HALF_SUCCESS_PCT, true, &tempResult); + assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints + /** true is passed to estimateCombined fee for target/2 and target so + * that we check the max confirms for shorter time horizons as well. + * This is necessary to preserve monotonically increasing estimates. + * For non-conservative estimates we do the same thing for 2*target, but + * for conservative estimates we want to skip these shorter horizons + * checks for 2*target because we are taking the max over all time + * horizons so we already have monotonically increasing estimates and + * the purpose of conservative estimates is not to let short term + * fluctuations lower our estimates by too much. + */ + double halfEst = estimateCombinedFee(confTarget/2, HALF_SUCCESS_PCT, true, &tempResult); + if (feeCalc) { + feeCalc->est = tempResult; + feeCalc->reason = FeeReason::HALF_ESTIMATE; + } + median = halfEst; + double actualEst = estimateCombinedFee(confTarget, SUCCESS_PCT, true, &tempResult); + if (actualEst > median) { + median = actualEst; if (feeCalc) { feeCalc->est = tempResult; - feeCalc->reason = FeeReason::HALF_ESTIMATE; + feeCalc->reason = FeeReason::FULL_ESTIMATE; } - median = halfEst; - double actualEst = estimateCombinedFee(confTarget, SUCCESS_PCT, true, &tempResult); - if (actualEst > median) { - median = actualEst; - if (feeCalc) { - feeCalc->est = tempResult; - feeCalc->reason = FeeReason::FULL_ESTIMATE; - } + } + double doubleEst = estimateCombinedFee(2 * confTarget, DOUBLE_SUCCESS_PCT, !conservative, &tempResult); + if (doubleEst > median) { + median = doubleEst; + if (feeCalc) { + feeCalc->est = tempResult; + feeCalc->reason = FeeReason::DOUBLE_ESTIMATE; } - double doubleEst = estimateCombinedFee(2 * confTarget, DOUBLE_SUCCESS_PCT, !conservative, &tempResult); - if (doubleEst > median) { - median = doubleEst; + } + + if (conservative || median == -1) { + double consEst = estimateConservativeFee(2 * confTarget, &tempResult); + if (consEst > median) { + median = consEst; if (feeCalc) { feeCalc->est = tempResult; - feeCalc->reason = FeeReason::DOUBLE_ESTIMATE; + feeCalc->reason = FeeReason::CONSERVATIVE; } } - - if (conservative || median == -1) { - double consEst = estimateConservativeFee(2 * confTarget, &tempResult); - if (consEst > median) { - median = consEst; - if (feeCalc) { - feeCalc->est = tempResult; - feeCalc->reason = FeeReason::CONSERVATIVE; - } - } - } - } // Must unlock cs_feeEstimator before taking mempool locks + } if (feeCalc) feeCalc->returnedTarget = confTarget; - // If mempool is limiting txs , return at least the min feerate from the mempool - CAmount minPoolFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(); - if (minPoolFee > 0 && minPoolFee > median) { - if (feeCalc) feeCalc->reason = FeeReason::MEMPOOL_MIN; - return CFeeRate(minPoolFee); - } - if (median < 0) return CFeeRate(0); diff --git a/src/policy/fees.h b/src/policy/fees.h index 4c80371c5c5..f4ef7936430 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -208,7 +208,7 @@ class CBlockPolicyEstimator * the closest target where one can be given. 'conservative' estimates are * valid over longer time horizons also. */ - CFeeRate estimateSmartFee(int confTarget, FeeCalculation *feeCalc, const CTxMemPool& pool, bool conservative) const; + CFeeRate estimateSmartFee(int confTarget, FeeCalculation *feeCalc, bool conservative) const; /** Return a specific fee estimate calculation with a given success * threshold and time horizon, and optionally return detailed data about diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 10bb341e54a..5dc468e111b 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -815,7 +815,6 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) "\n" "A negative value is returned if not enough transactions and blocks\n" "have been observed to make an estimate for any number of blocks.\n" - "However it will not return a value below the mempool reject fee.\n" "\nExample:\n" + HelpExampleCli("estimatesmartfee", "6") ); @@ -831,7 +830,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) UniValue result(UniValue::VOBJ); FeeCalculation feeCalc; - CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocks, &feeCalc, ::mempool, conservative); + CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocks, &feeCalc, conservative); result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK()))); result.push_back(Pair("blocks", feeCalc.returnedTarget)); return result; diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 8cdd3921096..fd8f7191f4f 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -177,16 +177,6 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) for (int i = 2; i < 9; i++) { // At 9, the original estimate was already at the bottom (b/c scale = 2) BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee); } - - // Test that if the mempool is limited, estimateSmartFee won't return a value below the mempool min fee - mpool.addUnchecked(tx.GetHash(), entry.Fee(feeV[5]).Time(GetTime()).Height(blocknum).FromTx(tx)); - // evict that transaction which should set a mempool min fee of minRelayTxFee + feeV[5] - mpool.TrimToSize(1); - BOOST_CHECK(mpool.GetMinFee(1).GetFeePerK() > feeV[5]); - for (int i = 1; i < 10; i++) { - BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool, true).GetFeePerK() >= feeEst.estimateRawFee(i, 0.85, FeeEstimateHorizon::MED_HALFLIFE).GetFeePerK()); - BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool, true).GetFeePerK() >= mpool.GetMinFee(1).GetFeePerK()); - } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f7f296bd521..8c4f637306c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2951,12 +2951,18 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, const CCoinControl& coin_c if (coin_control.m_fee_mode == FeeEstimateMode::CONSERVATIVE) conservative_estimate = true; else if (coin_control.m_fee_mode == FeeEstimateMode::ECONOMICAL) conservative_estimate = false; - fee_needed = estimator.estimateSmartFee(target, feeCalc, pool, conservative_estimate).GetFee(nTxBytes); + fee_needed = estimator.estimateSmartFee(target, feeCalc, conservative_estimate).GetFee(nTxBytes); if (fee_needed == 0) { // if we don't have enough data for estimateSmartFee, then use fallbackFee fee_needed = fallbackFee.GetFee(nTxBytes); if (feeCalc) feeCalc->reason = FeeReason::FALLBACK; } + // Obey mempool min fee when using smart fee estimation + CAmount min_mempool_fee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nTxBytes); + if (fee_needed < min_mempool_fee) { + fee_needed = min_mempool_fee; + if (feeCalc) feeCalc->reason = FeeReason::MEMPOOL_MIN; + } } // prevent user from paying a fee below minRelayTxFee or minTxFee From 11590d39b9888403ead8354302e308eca139ba17 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 12 Jul 2017 14:42:57 -0400 Subject: [PATCH 078/148] Properly bound check conf_target in wallet RPC calls --- src/rpc/mining.cpp | 10 ++++++++++ src/rpc/mining.h | 3 +++ src/wallet/rpcwallet.cpp | 14 +++++--------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 5dc468e111b..b8c94d32ecf 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -30,6 +30,16 @@ #include +unsigned int ParseConfirmTarget(const UniValue& value) +{ + int target = value.get_int(); + unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); + if (target < 1 || (unsigned int)target > max_target) { + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid conf_target, must be between %u - %u", 1, max_target)); + } + return (unsigned int)target; +} + /** * Return average network hashes per second based on the last 'lookup' blocks, * or from the last difficulty change if 'lookup' is nonpositive. diff --git a/src/rpc/mining.h b/src/rpc/mining.h index a148d851da0..868d7002b5f 100644 --- a/src/rpc/mining.h +++ b/src/rpc/mining.h @@ -12,4 +12,7 @@ /** Generate blocks (mine) */ UniValue generateBlocks(std::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript); +/** Check bounds on a command line confirm target */ +unsigned int ParseConfirmTarget(const UniValue& value); + #endif diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c636fa81144..f983a61a9f7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -460,7 +460,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request) } if (request.params.size() > 6 && !request.params[6].isNull()) { - coin_control.m_confirm_target = request.params[6].get_int(); + coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]); } if (request.params.size() > 7 && !request.params[7].isNull()) { @@ -981,7 +981,7 @@ UniValue sendmany(const JSONRPCRequest& request) } if (request.params.size() > 6 && !request.params[6].isNull()) { - coin_control.m_confirm_target = request.params[6].get_int(); + coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]); } if (request.params.size() > 7 && !request.params[7].isNull()) { @@ -2795,7 +2795,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) coinControl.signalRbf = options["replaceable"].get_bool(); } if (options.exists("conf_target")) { - coinControl.m_confirm_target = options["conf_target"].get_int(); + coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"]); } if (options.exists("estimate_mode")) { if (!FeeModeFromString(options["estimate_mode"].get_str(), coinControl.m_fee_mode)) { @@ -2917,12 +2917,8 @@ UniValue bumpfee(const JSONRPCRequest& request) if (options.exists("confTarget") && options.exists("totalFee")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and totalFee options should not both be set. Please provide either a confirmation target for fee estimation or an explicit total fee for the transaction."); - } else if (options.exists("confTarget")) { - int target = options["confTarget"].get_int(); - if (target <= 0) { // FIXME: Check upper bound too - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid confTarget (cannot be <= 0)"); - } - coin_control.m_confirm_target = target; + } else if (options.exists("confTarget")) { // TODO: alias this to conf_target + coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"]); } else if (options.exists("totalFee")) { totalFee = options["totalFee"].get_int64(); if (totalFee <= 0) { From 6835cb0ab26c913423cc2307c989579d05aabdcb Mon Sep 17 00:00:00 2001 From: practicalswift Date: Mon, 3 Jul 2017 17:46:43 +0200 Subject: [PATCH 079/148] Avoid static analyzer warnings regarding uninitialized arguments Avoid static analyzer warnings regarding "Function call argument is a pointer to uninitialized value" in cases where we are intentionally using such arguments. This is achieved by using ... `f(b.begin(), b.end())` (`std::array`) ... instead of ... `f(b, b + N)` (`char b[N]`) Rationale: * Reduce false positives by guiding static analyzers regarding our intentions. Before this commit: ``` $ clang-tidy-3.5 -checks=* src/bench/base58.cpp bench/base58.cpp:23:9: warning: Function call argument is a pointer to uninitialized value [clang-analyzer-core.CallAndMessage] EncodeBase58(b, b + 32); ^ $ clang-tidy-3.5 -checks=* src/bench/verify_script.cpp bench/verify_script.cpp:59:5: warning: Function call argument is a pointer to uninitialized value [clang-analyzer-core.CallAndMessage] key.Set(vchKey, vchKey + 32, false); ^ $ ``` After this commit: ``` $ clang-tidy-3.5 -checks=* src/bench/base58.cpp $ clang-tidy-3.5 -checks=* src/bench/verify_script.cpp $ ``` --- src/bench/base58.cpp | 27 +++++++++++++++------------ src/bench/verify_script.cpp | 10 ++++++++-- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp index 3319c179bf5..65e27a615d9 100644 --- a/src/bench/base58.cpp +++ b/src/bench/base58.cpp @@ -7,34 +7,37 @@ #include "validation.h" #include "base58.h" +#include #include #include static void Base58Encode(benchmark::State& state) { - unsigned char buff[32] = { - 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147, - 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90, - 200, 24 + static const std::array buff = { + { + 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147, + 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90, + 200, 24 + } }; - unsigned char* b = buff; while (state.KeepRunning()) { - EncodeBase58(b, b + 32); + EncodeBase58(buff.begin(), buff.end()); } } static void Base58CheckEncode(benchmark::State& state) { - unsigned char buff[32] = { - 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147, - 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90, - 200, 24 + static const std::array buff = { + { + 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147, + 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90, + 200, 24 + } }; - unsigned char* b = buff; std::vector vch; - vch.assign(b, b + 32); + vch.assign(buff.begin(), buff.end()); while (state.KeepRunning()) { EncodeBase58Check(vch); } diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index 23bbadc88d0..ef7381c1201 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -11,6 +11,8 @@ #include "script/sign.h" #include "streams.h" +#include + // FIXME: Dedup with BuildCreditingTransaction in test/script_tests.cpp. static CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) { @@ -55,8 +57,12 @@ static void VerifyScriptBench(benchmark::State& state) // Keypair. CKey key; - const unsigned char vchKey[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - key.Set(vchKey, vchKey + 32, false); + static const std::array vchKey = { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 + } + }; + key.Set(vchKey.begin(), vchKey.end(), false); CPubKey pubkey = key.GetPubKey(); uint160 pubkeyHash; CHash160().Write(pubkey.begin(), pubkey.size()).Finalize(pubkeyHash.begin()); From 0189d8ed19eb435f7b355bb482ec748195a2c0b3 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sat, 15 Jul 2017 14:28:40 +0200 Subject: [PATCH 080/148] Fix typos --- src/blockencodings.cpp | 2 +- src/consensus/consensus.h | 2 +- src/policy/fees.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 7adab586e8f..6f27b7b9dc5 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -48,7 +48,7 @@ uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const uint256& txhash) const { ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector>& extra_txn) { if (cmpctblock.header.IsNull() || (cmpctblock.shorttxids.empty() && cmpctblock.prefilledtxn.empty())) return READ_STATUS_INVALID; - if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_WEIGHT / MIN_SERIALIZEABLE_TRANSACTION_WEIGHT) + if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_WEIGHT / MIN_SERIALIZABLE_TRANSACTION_WEIGHT) return READ_STATUS_INVALID; assert(header.IsNull() && txn_available.empty()); diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index a1bb99a802c..ddd4ee9fab4 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -21,7 +21,7 @@ static const int COINBASE_MATURITY = 100; static const int WITNESS_SCALE_FACTOR = 4; static const size_t MIN_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 60; // 60 is the lower bound for the size of a valid serialized CTransaction -static const size_t MIN_SERIALIZEABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 10; // 10 is the lower bound for the size of a serialized CTransaction +static const size_t MIN_SERIALIZABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 10; // 10 is the lower bound for the size of a serialized CTransaction /** Flags for nSequence and nLockTime locks */ enum { diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 03fe11a0d80..b0a6a2e3d80 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -698,7 +698,7 @@ CFeeRate CBlockPolicyEstimator::estimateRawFee(int confTarget, double successThr break; } default: { - throw std::out_of_range("CBlockPoicyEstimator::estimateRawFee unknown FeeEstimateHorizon"); + throw std::out_of_range("CBlockPolicyEstimator::estimateRawFee unknown FeeEstimateHorizon"); } } @@ -730,7 +730,7 @@ unsigned int CBlockPolicyEstimator::HighestTargetTracked(FeeEstimateHorizon hori return longStats->GetMaxConfirms(); } default: { - throw std::out_of_range("CBlockPoicyEstimator::HighestTargetTracked unknown FeeEstimateHorizon"); + throw std::out_of_range("CBlockPolicyEstimator::HighestTargetTracked unknown FeeEstimateHorizon"); } } } From e061d8d7abb66c234786ea1c855d4cbb1b9b22ef Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sat, 15 Jul 2017 20:04:04 +0200 Subject: [PATCH 081/148] Remove declaration of unused function: void UpdatedTransaction(const uint256 &) --- src/validationinterface.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/validationinterface.h b/src/validationinterface.h index 568da66df28..d6da2bc1fd2 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -86,7 +86,6 @@ class CMainSignals { void TransactionAddedToMempool(const CTransactionRef &); void BlockConnected(const std::shared_ptr &, const CBlockIndex *pindex, const std::vector &); void BlockDisconnected(const std::shared_ptr &); - void UpdatedTransaction(const uint256 &); void SetBestChain(const CBlockLocator &); void Inventory(const uint256 &); void Broadcast(int64_t nBestBlockTime, CConnman* connman); From ff7365e780624a1ef66c12a6d7b61448a3f9294c Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 3 May 2017 11:49:58 -0400 Subject: [PATCH 082/148] [tests] fix flake8 warnings in zapwallettxes.py --- test/functional/zapwallettxes.py | 48 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/test/functional/zapwallettxes.py b/test/functional/zapwallettxes.py index e4d40520ef6..afe944132b4 100755 --- a/test/functional/zapwallettxes.py +++ b/test/functional/zapwallettxes.py @@ -13,8 +13,12 @@ available, but that the unconfirmed transaction has been zapped. """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * - +from test_framework.util import (assert_equal, + assert_raises, + bitcoind_processes, + connect_nodes_bi, + JSONRPCException, + ) class ZapWalletTXesTest (BitcoinTestFramework): @@ -25,56 +29,56 @@ def __init__(self): def setup_network(self): super().setup_network() - connect_nodes_bi(self.nodes,0,2) + connect_nodes_bi(self.nodes, 0, 2) - def run_test (self): + def run_test(self): self.log.info("Mining blocks...") self.nodes[0].generate(1) self.sync_all() self.nodes[1].generate(101) self.sync_all() - + assert_equal(self.nodes[0].getbalance(), 50) - + txid0 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) txid1 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) self.sync_all() self.nodes[0].generate(1) self.sync_all() - + txid2 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) txid3 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) - + tx0 = self.nodes[0].gettransaction(txid0) - assert_equal(tx0['txid'], txid0) #tx0 must be available (confirmed) - + assert_equal(tx0['txid'], txid0) # tx0 must be available (confirmed) + tx1 = self.nodes[0].gettransaction(txid1) - assert_equal(tx1['txid'], txid1) #tx1 must be available (confirmed) - + assert_equal(tx1['txid'], txid1) # tx1 must be available (confirmed) + tx2 = self.nodes[0].gettransaction(txid2) - assert_equal(tx2['txid'], txid2) #tx2 must be available (unconfirmed) - + assert_equal(tx2['txid'], txid2) # tx2 must be available (unconfirmed) + tx3 = self.nodes[0].gettransaction(txid3) - assert_equal(tx3['txid'], txid3) #tx3 must be available (unconfirmed) - + assert_equal(tx3['txid'], txid3) # tx3 must be available (unconfirmed) + #restart bitcoind self.stop_node(0) self.nodes[0] = self.start_node(0,self.options.tmpdir) tx3 = self.nodes[0].gettransaction(txid3) - assert_equal(tx3['txid'], txid3) #tx must be available (unconfirmed) - + assert_equal(tx3['txid'], txid3) # tx must be available (unconfirmed) + self.stop_node(0) #restart bitcoind with zapwallettxes self.nodes[0] = self.start_node(0,self.options.tmpdir, ["-zapwallettxes=1"]) - + assert_raises(JSONRPCException, self.nodes[0].gettransaction, [txid3]) - #there must be an exception because the unconfirmed wallettx0 must be gone by now + # there must be an exception because the unconfirmed wallettx0 must be gone by now tx0 = self.nodes[0].gettransaction(txid0) - assert_equal(tx0['txid'], txid0) #tx0 (confirmed) must still be available because it was confirmed + assert_equal(tx0['txid'], txid0) # tx0 (confirmed) must still be available because it was confirmed if __name__ == '__main__': - ZapWalletTXesTest ().main () + ZapWalletTXesTest().main() From e7a2181b49774f2cc29839ebbdc206bcdb715a7f Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 3 May 2017 13:36:13 -0400 Subject: [PATCH 083/148] [wallet] fix zapwallettxes interaction with persistent mempool zapwallettxes previously did not interact well with persistent mempool. zapwallettxes would cause wallet transactions to be zapped, but they would then be reloaded from the mempool on startup. This commit softsets persistmempool to false if zapwallettxes is enabled so transactions are actually zapped. --- src/wallet/wallet.cpp | 5 +++ test/functional/zapwallettxes.py | 80 ++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 07b7f58a641..4366428f5c7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4043,6 +4043,11 @@ bool CWallet::ParameterInteraction() } } + // -zapwallettx implies dropping the mempool on startup + if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-persistmempool", false)) { + LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -persistmempool=0\n", __func__); + } + // -zapwallettx implies a rescan if (GetBoolArg("-zapwallettxes", false)) { if (is_multiwallet) { diff --git a/test/functional/zapwallettxes.py b/test/functional/zapwallettxes.py index afe944132b4..af867d7a52c 100755 --- a/test/functional/zapwallettxes.py +++ b/test/functional/zapwallettxes.py @@ -4,20 +4,19 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the zapwallettxes functionality. -- start three bitcoind nodes -- create four transactions on node 0 - two are confirmed and two are - unconfirmed. -- restart node 1 and verify that both the confirmed and the unconfirmed +- start two bitcoind nodes +- create two transactions on node 0 - one is confirmed and one is unconfirmed. +- restart node 0 and verify that both the confirmed and the unconfirmed transactions are still available. -- restart node 0 and verify that the confirmed transactions are still - available, but that the unconfirmed transaction has been zapped. +- restart node 0 with zapwallettxes and persistmempool, and verify that both + the confirmed and the unconfirmed transactions are still available. +- restart node 0 with just zapwallettxed and verify that the confirmed + transactions are still available, but that the unconfirmed transaction has + been zapped. """ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import (assert_equal, - assert_raises, - bitcoind_processes, - connect_nodes_bi, - JSONRPCException, + assert_raises_jsonrpc, ) class ZapWalletTXesTest (BitcoinTestFramework): @@ -25,60 +24,53 @@ class ZapWalletTXesTest (BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = True - self.num_nodes = 3 - - def setup_network(self): - super().setup_network() - connect_nodes_bi(self.nodes, 0, 2) + self.num_nodes = 2 def run_test(self): self.log.info("Mining blocks...") self.nodes[0].generate(1) self.sync_all() - self.nodes[1].generate(101) + self.nodes[1].generate(100) self.sync_all() - assert_equal(self.nodes[0].getbalance(), 50) + # This transaction will be confirmed + txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 10) - txid0 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) - txid1 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) - self.sync_all() self.nodes[0].generate(1) self.sync_all() - txid2 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) - txid3 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) - - tx0 = self.nodes[0].gettransaction(txid0) - assert_equal(tx0['txid'], txid0) # tx0 must be available (confirmed) + # This transaction will not be confirmed + txid2 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 20) - tx1 = self.nodes[0].gettransaction(txid1) - assert_equal(tx1['txid'], txid1) # tx1 must be available (confirmed) + # Confirmed and unconfirmed transactions are now in the wallet. + assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) + assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2) - tx2 = self.nodes[0].gettransaction(txid2) - assert_equal(tx2['txid'], txid2) # tx2 must be available (unconfirmed) + # Stop-start node0. Both confirmed and unconfirmed transactions remain in the wallet. + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir) - tx3 = self.nodes[0].gettransaction(txid3) - assert_equal(tx3['txid'], txid3) # tx3 must be available (unconfirmed) + assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) + assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2) - #restart bitcoind + # Stop node0 and restart with zapwallettxes and persistmempool. The unconfirmed + # transaction is zapped from the wallet, but is re-added when the mempool is reloaded. self.stop_node(0) - self.nodes[0] = self.start_node(0,self.options.tmpdir) - - tx3 = self.nodes[0].gettransaction(txid3) - assert_equal(tx3['txid'], txid3) # tx must be available (unconfirmed) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-persistmempool=1", "-zapwallettxes=2"]) - self.stop_node(0) - - #restart bitcoind with zapwallettxes - self.nodes[0] = self.start_node(0,self.options.tmpdir, ["-zapwallettxes=1"]) + assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) + assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2) - assert_raises(JSONRPCException, self.nodes[0].gettransaction, [txid3]) - # there must be an exception because the unconfirmed wallettx0 must be gone by now + # Stop node0 and restart with zapwallettxes, but not persistmempool. + # The unconfirmed transaction is zapped and is no longer in the wallet. + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-zapwallettxes=2"]) - tx0 = self.nodes[0].gettransaction(txid0) - assert_equal(tx0['txid'], txid0) # tx0 (confirmed) must still be available because it was confirmed + # tx1 is still be available because it was confirmed + assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1) + # This will raise an exception because the unconfirmed transaction has been zapped + assert_raises_jsonrpc(-5, 'Invalid or non-wallet transaction id', self.nodes[0].gettransaction, txid2) if __name__ == '__main__': ZapWalletTXesTest().main() From 4c3b538c61532dc68d79bbe34729759a13b73f0c Mon Sep 17 00:00:00 2001 From: John Newbery Date: Fri, 14 Jul 2017 18:17:27 -0400 Subject: [PATCH 084/148] [logs] fix zapwallettxes startup logs --- src/wallet/wallet.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4366428f5c7..7aa2e31743d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4043,18 +4043,19 @@ bool CWallet::ParameterInteraction() } } - // -zapwallettx implies dropping the mempool on startup - if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-persistmempool", false)) { - LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -persistmempool=0\n", __func__); + int zapwallettxes = GetArg("-zapwallettxes", 0); + // -zapwallettxes implies dropping the mempool on startup + if (zapwallettxes != 0 && SoftSetBoolArg("-persistmempool", false)) { + LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -persistmempool=0\n", __func__, zapwallettxes); } - // -zapwallettx implies a rescan - if (GetBoolArg("-zapwallettxes", false)) { + // -zapwallettxes implies a rescan + if (zapwallettxes != 0) { if (is_multiwallet) { return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes")); } if (SoftSetBoolArg("-rescan", true)) { - LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -rescan=1\n", __func__); + LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -rescan=1\n", __func__, zapwallettxes); } } From a8ae0b252a2007568e77f5aca1c7fa3ec5941b72 Mon Sep 17 00:00:00 2001 From: Dag Robole Date: Sat, 15 Jul 2017 21:34:52 +0200 Subject: [PATCH 085/148] Fix resource leak --- src/random.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/random.cpp b/src/random.cpp index 67efc7d945a..6c39d98c568 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -191,6 +191,7 @@ void GetDevURandom(unsigned char *ent32) do { ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have); if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) { + close(f); RandFailure(); } have += n; From 912da1dcc8e52228582f36b0010b498ebc76754b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Nyffenegger?= Date: Fri, 7 Jul 2017 16:54:11 +0200 Subject: [PATCH 086/148] Use AC_ARG_VAR to set ARFLAGS. The user can set ARFLAGS in the ./configure step with ./configure ARFLAGS=... If he chooses not to do so, ARFLAGS will be set to cr. --- configure.ac | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure.ac b/configure.ac index a90063d9ded..e8a8b134b89 100644 --- a/configure.ac +++ b/configure.ac @@ -19,6 +19,12 @@ BITCOIN_GUI_NAME=bitcoin-qt BITCOIN_CLI_NAME=bitcoin-cli BITCOIN_TX_NAME=bitcoin-tx +dnl Unless the user specified ARFLAGS, force it to be cr +AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to if not set]) +if test "x${ARFLAGS+set}" != "xset"; then + ARFLAGS="cr" +fi + AC_CANONICAL_HOST AH_TOP([#ifndef BITCOIN_CONFIG_H]) @@ -1262,4 +1268,5 @@ echo " CPPFLAGS = $CPPFLAGS" echo " CXX = $CXX" echo " CXXFLAGS = $CXXFLAGS" echo " LDFLAGS = $LDFLAGS" +echo " ARFLAGS = $ARFLAGS" echo From 3a53f19718a2207f0d74c32a611ae91703d9da8d Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Fri, 14 Jul 2017 22:36:58 +0000 Subject: [PATCH 087/148] Pushdown walletdb object through GenerateNewKey/DeriveNewChildKey. This is needed but not sufficient for batching the wallet flushing when topping up the keypool. --- src/wallet/wallet.cpp | 14 ++++++++------ src/wallet/wallet.h | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5689cc7b0cd..b3b3c1c10a3 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -87,7 +87,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const return &(it->second); } -CPubKey CWallet::GenerateNewKey(bool internal) +CPubKey CWallet::GenerateNewKey(CWalletDB &walletdb, bool internal) { AssertLockHeld(cs_wallet); // mapKeyMetadata bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets @@ -100,7 +100,7 @@ CPubKey CWallet::GenerateNewKey(bool internal) // use HD key derivation if HD was enabled during wallet creation if (IsHDEnabled()) { - DeriveNewChildKey(metadata, secret, (CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false)); + DeriveNewChildKey(walletdb, metadata, secret, (CanSupportFeature(FEATURE_HD_SPLIT) ? internal : false)); } else { secret.MakeNewKey(fCompressed); } @@ -120,7 +120,7 @@ CPubKey CWallet::GenerateNewKey(bool internal) return pubkey; } -void CWallet::DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool internal) +void CWallet::DeriveNewChildKey(CWalletDB &walletdb, CKeyMetadata& metadata, CKey& secret, bool internal) { // for now we use a fixed keypath scheme of m/0'/0'/k CKey key; //master key seed (256bit) @@ -162,7 +162,7 @@ void CWallet::DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool inter secret = childKey.key; metadata.hdMasterKeyID = hdChain.masterKeyID; // update the chain model in the database - if (!CWalletDB(*dbw).WriteHDChain(hdChain)) + if (!walletdb.WriteHDChain(hdChain)) throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); } @@ -3183,8 +3183,9 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) nEnd = std::max(nEnd, *(setExternalKeyPool.rbegin()) + 1); } - if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey(internal), internal))) + if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey(walletdb, internal), internal))) { throw std::runtime_error(std::string(__func__) + ": writing generated key failed"); + } if (internal) { setInternalKeyPool.insert(nEnd); @@ -3266,7 +3267,8 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal) if (nIndex == -1) { if (IsLocked()) return false; - result = GenerateNewKey(internal); + CWalletDB walletdb(*dbw); + result = GenerateNewKey(walletdb, internal); return true; } KeepKey(nIndex); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 8848448682e..e91a6effd3c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -697,7 +697,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface CHDChain hdChain; /* HD derive new child key (on internal or external chain) */ - void DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret, bool internal = false); + void DeriveNewChildKey(CWalletDB &walletdb, CKeyMetadata& metadata, CKey& secret, bool internal = false); std::set setInternalKeyPool; std::set setExternalKeyPool; @@ -866,7 +866,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * keystore implementation * Generate a new key */ - CPubKey GenerateNewKey(bool internal = false); + CPubKey GenerateNewKey(CWalletDB& walletdb, bool internal = false); //! Adds a key to the store, and saves it to disk. bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override; //! Adds a key to the store, without saving it to disk (used by LoadWallet) From c53369cc24276b64b43636ae0868de9d41ca8b00 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sun, 16 Jul 2017 02:25:25 +0200 Subject: [PATCH 088/148] Remove duplicate include --- src/bitcoin-cli.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 92f6a21ebbd..8b48c7f8e42 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -10,7 +10,6 @@ #include "chainparamsbase.h" #include "clientversion.h" #include "fs.h" -#include "utilstrencodings.h" #include "rpc/client.h" #include "rpc/protocol.h" #include "util.h" From d0413c670b4e5dc79d5cc1bc35571fca745c9a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Nyffenegger?= Date: Sun, 16 Jul 2017 15:52:19 +0200 Subject: [PATCH 089/148] Use range based for loop Instead of iterating over 0 .. 1 and then deciding on an actual desired value, use a range based for loop for the desired value. --- src/test/dbwrapper_tests.cpp | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 093509e61c5..6ed6e7744e3 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -24,8 +24,7 @@ BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(dbwrapper) { // Perform tests both obfuscated and non-obfuscated. - for (int i = 0; i < 2; i++) { - bool obfuscate = (bool)i; + for (bool obfuscate : {false, true}) { fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'k'; @@ -45,8 +44,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper) BOOST_AUTO_TEST_CASE(dbwrapper_batch) { // Perform tests both obfuscated and non-obfuscated. - for (int i = 0; i < 2; i++) { - bool obfuscate = (bool)i; + for (bool obfuscate : {false, true}) { fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); @@ -82,8 +80,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) BOOST_AUTO_TEST_CASE(dbwrapper_iterator) { // Perform tests both obfuscated and non-obfuscated. - for (int i = 0; i < 2; i++) { - bool obfuscate = (bool)i; + for (bool obfuscate : {false, true}) { fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); @@ -211,12 +208,7 @@ BOOST_AUTO_TEST_CASE(iterator_ordering) } std::unique_ptr it(const_cast(dbw).NewIterator()); - for (int c=0; c<2; ++c) { - int seek_start; - if (c == 0) - seek_start = 0x00; - else - seek_start = 0x80; + for (int seek_start : {0x00, 0x80}) { it->Seek((uint8_t)seek_start); for (int x=seek_start; x<256; ++x) { uint8_t key; @@ -287,12 +279,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) } std::unique_ptr it(const_cast(dbw).NewIterator()); - for (int c=0; c<2; ++c) { - int seek_start; - if (c == 0) - seek_start = 0; - else - seek_start = 5; + for (int seek_start : {0, 5}) { snprintf(buf, sizeof(buf), "%d", seek_start); StringContentsSerializer seek_key(buf); it->Seek(seek_key); From 2c2e90d1d4768a7842b2fa840496cea567a8e995 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sun, 16 Jul 2017 12:20:49 +0200 Subject: [PATCH 090/148] =?UTF-8?q?Fix=20incorrect=20Doxygen=20tag=20(@inc?= =?UTF-8?q?e=20=E2=86=92=20@since).=20Make=20Doxygen=20parameter=20names?= =?UTF-8?q?=20match=20actual=20parameter=20names.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/policy/fees.cpp | 2 +- src/protocol.h | 2 +- src/util.h | 6 +++--- src/wallet/rpcwallet.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index b0a6a2e3d80..dbdc5013f0e 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -117,7 +117,7 @@ class TxConfirmStats * Create new TxConfirmStats. This is called by BlockPolicyEstimator's * constructor with default values. * @param defaultBuckets contains the upper limits for the bucket boundaries - * @param maxConfirms max number of confirms to track + * @param maxPeriods max number of periods to track * @param decay how much to decay the historical moving average per block */ TxConfirmStats(const std::vector& defaultBuckets, const std::map& defaultBucketMap, diff --git a/src/protocol.h b/src/protocol.h index eba39ab1e50..7890bb627de 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -163,7 +163,7 @@ extern const char *PONG; /** * The notfound message is a reply to a getdata message which requested an * object the receiving node does not have available for relay. - * @ince protocol version 70001. + * @since protocol version 70001. * @see https://bitcoin.org/en/developer-reference#notfound */ extern const char *NOTFOUND; diff --git a/src/util.h b/src/util.h index 824ad51ac48..e1bdfb1988f 100644 --- a/src/util.h +++ b/src/util.h @@ -215,7 +215,7 @@ class ArgsManager * Return string argument or default value * * @param strArg Argument to get (e.g. "-foo") - * @param default (e.g. "1") + * @param strDefault (e.g. "1") * @return command-line argument or default value */ std::string GetArg(const std::string& strArg, const std::string& strDefault); @@ -224,7 +224,7 @@ class ArgsManager * Return integer argument or default value * * @param strArg Argument to get (e.g. "-foo") - * @param default (e.g. 1) + * @param nDefault (e.g. 1) * @return command-line argument (0 if invalid number) or default value */ int64_t GetArg(const std::string& strArg, int64_t nDefault); @@ -233,7 +233,7 @@ class ArgsManager * Return boolean argument or default value * * @param strArg Argument to get (e.g. "-foo") - * @param default (true or false) + * @param fDefault (true or false) * @return command-line argument or default value */ bool GetBoolArg(const std::string& strArg, bool fDefault); diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index bd5dad18ca5..31e2f6a6999 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -16,7 +16,7 @@ void RegisterWalletRPCCommands(CRPCTable &t); * @param[in] request JSONRPCRequest that wishes to access a wallet * @return NULL if no wallet should be used, or a pointer to the CWallet */ -CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest&); +CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request); std::string HelpRequiringPassphrase(CWallet *); void EnsureWalletIsUnlocked(CWallet *); From dd2185c291a72e2d685746c97d6eb7c22f87226d Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 17 Jul 2017 11:56:00 +0200 Subject: [PATCH 091/148] Register wallet endpoint --- src/httprpc.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index a207d5ece45..69c3e3f49f6 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -233,7 +233,10 @@ bool StartHTTPRPC() return false; RegisterHTTPHandler("/", true, HTTPReq_JSONRPC); - +#ifdef ENABLE_WALLET + // ifdef can be removed once we switch to better endpoint support and API versioning + RegisterHTTPHandler("/wallet/", false, HTTPReq_JSONRPC); +#endif assert(EventBase()); httpRPCTimerInterface = new HTTPRPCTimerInterface(EventBase()); RPCSetTimerInterface(httpRPCTimerInterface); From b1385852ef2ba45fd6926d75497646debf79e686 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Mon, 17 Jul 2017 06:52:09 -0400 Subject: [PATCH 092/148] Remove factor of 3 from definition of dust. This redefines dust to be the value of an output such that it would cost that value in fees to (create and) spend the output at the dust relay rate. The previous definition was that it would cost 1/3 of the value. The default dust relay rate is correspondingly increased to 3000 sat/kB so the actual default dust output value of 546 satoshis for a non-segwit output remains unchanged. This commit is a refactor only unless a dustrelayfee is passed on the commandline in which case that number now needs to be increased by a factor of 3 to get the same behavior. -dustrelayfee is a hidden command line option. Note: It's not exactly a refactor due to edge case changes in rounding as evidenced by the required change to the unit test. --- src/init.cpp | 2 +- src/policy/policy.cpp | 10 ++++++---- src/policy/policy.h | 4 ++-- src/test/transaction_tests.cpp | 10 +++++----- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 1e85642019c..bda0e905b3a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -479,7 +479,7 @@ std::string HelpMessage(HelpMessageMode mode) if (showDebug) { strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", defaultChainParams->RequireStandard())); strUsage += HelpMessageOpt("-incrementalrelayfee=", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE))); - strUsage += HelpMessageOpt("-dustrelayfee=", strprintf("Fee rate (in %s/kB) used to defined dust, the value of an output such that it will cost about 1/3 of its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE))); + strUsage += HelpMessageOpt("-dustrelayfee=", strprintf("Fee rate (in %s/kB) used to defined dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE))); } strUsage += HelpMessageOpt("-bytespersigop", strprintf(_("Equivalent bytes per sigop in transactions for relay and mining (default: %u)"), DEFAULT_BYTES_PER_SIGOP)); strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER)); diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 9f2d623e769..605e3e06968 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -19,16 +19,18 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) { // "Dust" is defined in terms of dustRelayFee, // which has units satoshis-per-kilobyte. - // If you'd pay more than 1/3 in fees + // If you'd pay more in fees than the value of the output // to spend something, then we consider it dust. // A typical spendable non-segwit txout is 34 bytes big, and will // need a CTxIn of at least 148 bytes to spend: // so dust is a spendable txout less than - // 546*dustRelayFee/1000 (in satoshis). + // 182*dustRelayFee/1000 (in satoshis). + // 546 satoshis at the default rate of 3000 sat/kB. // A typical spendable segwit txout is 31 bytes big, and will // need a CTxIn of at least 67 bytes to spend: // so dust is a spendable txout less than - // 294*dustRelayFee/1000 (in satoshis). + // 98*dustRelayFee/1000 (in satoshis). + // 294 satoshis at the default rate of 3000 sat/kB. if (txout.scriptPubKey.IsUnspendable()) return 0; @@ -44,7 +46,7 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above } - return 3 * dustRelayFeeIn.GetFee(nSize); + return dustRelayFeeIn.GetFee(nSize); } bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) diff --git a/src/policy/policy.h b/src/policy/policy.h index 2c2ea9d5b85..c06820f84e6 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -40,12 +40,12 @@ static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS = 100; static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80; /** The maximum size of a standard witnessScript */ static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600; -/** Min feerate for defining dust. Historically this has been the same as the +/** Min feerate for defining dust. Historically this has been based on the * minRelayTxFee, however changing the dust limit changes which transactions are * standard and should be done with care and ideally rarely. It makes sense to * only increase the dust limit after prior releases were already not creating * outputs below the new threshold */ -static const unsigned int DUST_RELAY_TX_FEE = 1000; +static const unsigned int DUST_RELAY_TX_FEE = 3000; /** * Standard script verification flags that standard transactions will comply * with. However scripts violating these flags may still be present in valid diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 39f9f586041..6654634bf13 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -692,7 +692,7 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) BOOST_CHECK(IsStandardTx(t, reason)); // Check dust with default relay fee: - CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000 * 3; + CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000; BOOST_CHECK_EQUAL(nDustThreshold, 546); // dust: t.vout[0].nValue = nDustThreshold - 1; @@ -702,13 +702,13 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) BOOST_CHECK(IsStandardTx(t, reason)); // Check dust with odd relay fee to verify rounding: - // nDustThreshold = 182 * 1234 / 1000 * 3 - dustRelayFee = CFeeRate(1234); + // nDustThreshold = 182 * 3702 / 1000 + dustRelayFee = CFeeRate(3702); // dust: - t.vout[0].nValue = 672 - 1; + t.vout[0].nValue = 673 - 1; BOOST_CHECK(!IsStandardTx(t, reason)); // not dust: - t.vout[0].nValue = 672; + t.vout[0].nValue = 673; BOOST_CHECK(IsStandardTx(t, reason)); dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE); From a70d025366bfd242567ef4ecdb911eaf4907a6cb Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 10 Jul 2017 11:43:17 -0400 Subject: [PATCH 093/148] fixup some rpc param counting for rpc help --- src/wallet/rpcwallet.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ee8c7548fc6..eeaeebaa3e4 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -205,7 +205,7 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 1) + if (request.fHelp || request.params.size() > 0) throw std::runtime_error( "getrawchangeaddress\n" "\nReturns a new Bitcoin address, for receiving change.\n" @@ -484,7 +484,7 @@ UniValue listaddressgroupings(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp) + if (request.fHelp || request.params.size() != 0) throw std::runtime_error( "listaddressgroupings\n" "\nLists groups of addresses which have had their common ownership\n" @@ -1730,7 +1730,7 @@ UniValue listsinceblock(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp) + if (request.fHelp || request.params.size() > 3) throw std::runtime_error( "listsinceblock ( \"blockhash\" target_confirmations include_watchonly)\n" "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n" @@ -2672,7 +2672,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( "fundrawtransaction \"hexstring\" ( options )\n" "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n" From 999ef2073aa2b4aebfbe9bea6f9b12da52b8b2cb Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 10 Jul 2017 11:43:41 -0400 Subject: [PATCH 094/148] importmulti options are optional --- src/wallet/rpcdump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 9f42b1f2661..e9705f51354 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1028,7 +1028,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) // clang-format off if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2) throw std::runtime_error( - "importmulti \"requests\" \"options\"\n\n" + "importmulti \"requests\" ( \"options\" )\n\n" "Import addresses/scripts (with private or public keys, redeem script (P2SH)), rescanning all addresses in one-shot-only (rescan can be disabled via options).\n\n" "Arguments:\n" "1. requests (array, required) Data to be imported\n" From 4dc1915bceacb94446454428da676772290b8c48 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 10 Jul 2017 11:44:39 -0400 Subject: [PATCH 095/148] check for null values in rpc args and handle appropriately --- src/rpc/blockchain.cpp | 22 +++++++++++----------- src/rpc/mining.cpp | 6 +++--- src/rpc/net.cpp | 2 +- src/rpc/rawtransaction.cpp | 6 +++--- src/wallet/rpcdump.cpp | 16 ++++++++-------- src/wallet/rpcwallet.cpp | 40 ++++++++++++++++++++-------------------- 6 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 6178a1c7ab1..d65e107e3c4 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -210,7 +210,7 @@ UniValue waitfornewblock(const JSONRPCRequest& request) + HelpExampleRpc("waitfornewblock", "1000") ); int timeout = 0; - if (request.params.size() > 0) + if (!request.params[0].isNull()) timeout = request.params[0].get_int(); CUpdatedBlock block; @@ -252,7 +252,7 @@ UniValue waitforblock(const JSONRPCRequest& request) uint256 hash = uint256S(request.params[0].get_str()); - if (request.params.size() > 1) + if (!request.params[1].isNull()) timeout = request.params[1].get_int(); CUpdatedBlock block; @@ -295,7 +295,7 @@ UniValue waitforblockheight(const JSONRPCRequest& request) int height = request.params[0].get_int(); - if (request.params.size() > 1) + if (!request.params[1].isNull()) timeout = request.params[1].get_int(); CUpdatedBlock block; @@ -434,7 +434,7 @@ UniValue getrawmempool(const JSONRPCRequest& request) ); bool fVerbose = false; - if (request.params.size() > 0) + if (!request.params[0].isNull()) fVerbose = request.params[0].get_bool(); return mempoolToJSON(fVerbose); @@ -467,7 +467,7 @@ UniValue getmempoolancestors(const JSONRPCRequest& request) } bool fVerbose = false; - if (request.params.size() > 1) + if (!request.params[1].isNull()) fVerbose = request.params[1].get_bool(); uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -531,7 +531,7 @@ UniValue getmempooldescendants(const JSONRPCRequest& request) } bool fVerbose = false; - if (request.params.size() > 1) + if (!request.params[1].isNull()) fVerbose = request.params[1].get_bool(); uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -666,7 +666,7 @@ UniValue getblockheader(const JSONRPCRequest& request) uint256 hash(uint256S(strHash)); bool fVerbose = true; - if (request.params.size() > 1) + if (!request.params[1].isNull()) fVerbose = request.params[1].get_bool(); if (mapBlockIndex.count(hash) == 0) @@ -741,7 +741,7 @@ UniValue getblock(const JSONRPCRequest& request) uint256 hash(uint256S(strHash)); int verbosity = 1; - if (request.params.size() > 1) { + if (!request.params[1].isNull()) { if(request.params[1].isNum()) verbosity = request.params[1].get_int(); else @@ -984,7 +984,7 @@ UniValue gettxout(const JSONRPCRequest& request) int n = request.params[1].get_int(); COutPoint out(hash, n); bool fMempool = true; - if (request.params.size() > 2) + if (!request.params[2].isNull()) fMempool = request.params[2].get_bool(); Coin coin; @@ -1037,9 +1037,9 @@ UniValue verifychain(const JSONRPCRequest& request) LOCK(cs_main); - if (request.params.size() > 0) + if (!request.params[0].isNull()) nCheckLevel = request.params[0].get_int(); - if (request.params.size() > 1) + if (!request.params[1].isNull()) nCheckDepth = request.params[1].get_int(); return CVerifyDB().VerifyDB(Params(), pcoinsTip, nCheckLevel, nCheckDepth); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index b8c94d32ecf..26f4378718f 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -101,7 +101,7 @@ UniValue getnetworkhashps(const JSONRPCRequest& request) ); LOCK(cs_main); - return GetNetworkHashPS(request.params.size() > 0 ? request.params[0].get_int() : 120, request.params.size() > 1 ? request.params[1].get_int() : -1); + return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1); } UniValue generateBlocks(std::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) @@ -171,7 +171,7 @@ UniValue generatetoaddress(const JSONRPCRequest& request) int nGenerate = request.params[0].get_int(); uint64_t nMaxTries = 1000000; - if (request.params.size() > 2) { + if (!request.params[2].isNull()) { nMaxTries = request.params[2].get_int(); } @@ -373,7 +373,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) UniValue lpval = NullUniValue; std::set setClientRules; int64_t nMaxVersionPreVB = -1; - if (request.params.size() > 0) + if (!request.params[0].isNull()) { const UniValue& oparam = request.params[0].get_obj(); const UniValue& modeval = find_value(oparam, "mode"); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index ed452fcb021..fde0b27a338 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -310,7 +310,7 @@ UniValue getaddednodeinfo(const JSONRPCRequest& request) std::vector vInfo = g_connman->GetAddedNodeInfo(); - if (request.params.size() == 1) { + if (request.params.size() == 1 && !request.params[0].isNull()) { bool found = false; for (const AddedNodeInfo& info : vInfo) { if (info.strAddedNode == request.params[0].get_str()) { diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index b878624df87..185bc7fd3d6 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -137,7 +137,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request) // Accept either a bool (true) or a num (>=1) to indicate verbose output. bool fVerbose = false; - if (request.params.size() > 1) { + if (!request.params[1].isNull()) { if (request.params[1].isNum()) { if (request.params[1].get_int() != 0) { fVerbose = true; @@ -211,7 +211,7 @@ UniValue gettxoutproof(const JSONRPCRequest& request) CBlockIndex* pblockindex = NULL; uint256 hashBlock; - if (request.params.size() > 1) + if (!request.params[1].isNull()) { hashBlock = uint256S(request.params[1].get_str()); if (!mapBlockIndex.count(hashBlock)) @@ -412,7 +412,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) } } - if (request.params.size() > 3 && rbfOptIn != SignalsOptInRBF(rawTx)) { + if (!request.params[3].isNull() && rbfOptIn != SignalsOptInRBF(rawTx)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number(s) contradict replaceable option"); } diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index e9705f51354..5abf32480a8 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -106,12 +106,12 @@ UniValue importprivkey(const JSONRPCRequest& request) std::string strSecret = request.params[0].get_str(); std::string strLabel = ""; - if (request.params.size() > 1) + if (!request.params[1].isNull()) strLabel = request.params[1].get_str(); // Whether to perform rescan after import bool fRescan = true; - if (request.params.size() > 2) + if (!request.params[2].isNull()) fRescan = request.params[2].get_bool(); if (fRescan && fPruneMode) @@ -245,12 +245,12 @@ UniValue importaddress(const JSONRPCRequest& request) std::string strLabel = ""; - if (request.params.size() > 1) + if (!request.params[1].isNull()) strLabel = request.params[1].get_str(); // Whether to perform rescan after import bool fRescan = true; - if (request.params.size() > 2) + if (!request.params[2].isNull()) fRescan = request.params[2].get_bool(); if (fRescan && fPruneMode) @@ -258,7 +258,7 @@ UniValue importaddress(const JSONRPCRequest& request) // Whether to import a p2sh version, too bool fP2SH = false; - if (request.params.size() > 3) + if (!request.params[3].isNull()) fP2SH = request.params[3].get_bool(); LOCK2(cs_main, pwallet->cs_wallet); @@ -410,12 +410,12 @@ UniValue importpubkey(const JSONRPCRequest& request) std::string strLabel = ""; - if (request.params.size() > 1) + if (!request.params[1].isNull()) strLabel = request.params[1].get_str(); // Whether to perform rescan after import bool fRescan = true; - if (request.params.size() > 2) + if (!request.params[2].isNull()) fRescan = request.params[2].get_bool(); if (fRescan && fPruneMode) @@ -1071,7 +1071,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) //Default options bool fRescan = true; - if (mainRequest.params.size() > 1) { + if (!mainRequest.params[1].isNull()) { const UniValue& options = mainRequest.params[1]; if (options.exists("rescan")) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index eeaeebaa3e4..55f4abd7a38 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -134,7 +134,7 @@ UniValue getnewaddress(const JSONRPCRequest& request) // Parse the account first so we don't generate a key if there's an error std::string strAccount; - if (request.params.size() > 0) + if (!request.params[0].isNull()) strAccount = AccountFromValue(request.params[0]); if (!pwallet->IsLocked()) { @@ -629,7 +629,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request) // Minimum confirmations int nMinDepth = 1; - if (request.params.size() > 1) + if (!request.params[1].isNull()) nMinDepth = request.params[1].get_int(); // Tally @@ -680,7 +680,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request) // Minimum confirmations int nMinDepth = 1; - if (request.params.size() > 1) + if (!request.params[1].isNull()) nMinDepth = request.params[1].get_int(); // Get the set of pub keys assigned to account @@ -757,10 +757,10 @@ UniValue getbalance(const JSONRPCRequest& request) const std::string* account = account_param != "*" ? &account_param : nullptr; int nMinDepth = 1; - if (request.params.size() > 1) + if (!request.params[1].isNull()) nMinDepth = request.params[1].get_int(); isminefilter filter = ISMINE_SPENDABLE; - if(request.params.size() > 2) + if(!request.params[2].isNull()) if(request.params[2].get_bool()) filter = filter | ISMINE_WATCH_ONLY; @@ -963,7 +963,7 @@ UniValue sendmany(const JSONRPCRequest& request) std::string strAccount = AccountFromValue(request.params[0]); UniValue sendTo = request.params[1].get_obj(); int nMinDepth = 1; - if (request.params.size() > 2) + if (!request.params[2].isNull()) nMinDepth = request.params[2].get_int(); CWalletTx wtx; @@ -1210,16 +1210,16 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA { // Minimum confirmations int nMinDepth = 1; - if (params.size() > 0) + if (!params[0].isNull()) nMinDepth = params[0].get_int(); // Whether to include empty accounts bool fIncludeEmpty = false; - if (params.size() > 1) + if (!params[1].isNull()) fIncludeEmpty = params[1].get_bool(); isminefilter filter = ISMINE_SPENDABLE; - if(params.size() > 2) + if(!params[2].isNull()) if(params[2].get_bool()) filter = filter | ISMINE_WATCH_ONLY; @@ -1581,16 +1581,16 @@ UniValue listtransactions(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); std::string strAccount = "*"; - if (request.params.size() > 0) + if (!request.params[0].isNull()) strAccount = request.params[0].get_str(); int nCount = 10; - if (request.params.size() > 1) + if (!request.params[1].isNull()) nCount = request.params[1].get_int(); int nFrom = 0; - if (request.params.size() > 2) + if (!request.params[2].isNull()) nFrom = request.params[2].get_int(); isminefilter filter = ISMINE_SPENDABLE; - if(request.params.size() > 3) + if(!request.params[3].isNull()) if(request.params[3].get_bool()) filter = filter | ISMINE_WATCH_ONLY; @@ -1777,7 +1777,7 @@ UniValue listsinceblock(const JSONRPCRequest& request) int target_confirms = 1; isminefilter filter = ISMINE_SPENDABLE; - if (request.params.size() > 0) + if (!request.params[0].isNull()) { uint256 blockId; @@ -1796,7 +1796,7 @@ UniValue listsinceblock(const JSONRPCRequest& request) } } - if (request.params.size() > 1) + if (!request.params[1].isNull()) { target_confirms = request.params[1].get_int(); @@ -1888,7 +1888,7 @@ UniValue gettransaction(const JSONRPCRequest& request) hash.SetHex(request.params[0].get_str()); isminefilter filter = ISMINE_SPENDABLE; - if(request.params.size() > 1) + if(!request.params[1].isNull()) if(request.params[1].get_bool()) filter = filter | ISMINE_WATCH_ONLY; @@ -2010,7 +2010,7 @@ UniValue keypoolrefill(const JSONRPCRequest& request) // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool unsigned int kpSize = 0; - if (request.params.size() > 0) { + if (!request.params[0].isNull()) { if (request.params[0].get_int() < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size."); kpSize = (unsigned int)request.params[0].get_int(); @@ -2603,7 +2603,7 @@ UniValue listunspent(const JSONRPCRequest& request) CAmount nMinimumSumAmount = MAX_MONEY; uint64_t nMaximumCount = 0; - if (request.params.size() > 4) { + if (!request.params[4].isNull()) { const UniValue& options = request.params[4].get_obj(); if (options.exists("minimumAmount")) @@ -2736,7 +2736,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) UniValue subtractFeeFromOutputs; std::set setSubtractFeeFromOutputs; - if (request.params.size() > 1) { + if (!request.params[1].isNull()) { if (request.params[1].type() == UniValue::VBOOL) { // backward compatibility bool only fallback coinControl.fAllowWatchOnly = request.params[1].get_bool(); @@ -2904,7 +2904,7 @@ UniValue bumpfee(const JSONRPCRequest& request) CAmount totalFee = 0; CCoinControl coin_control; coin_control.signalRbf = true; - if (request.params.size() > 1) { + if (!request.params[1].isNull()) { UniValue options = request.params[1]; RPCTypeCheckObj(options, { From dba485d65168794d8be39bd5e8de8777e7085434 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 15 Jul 2017 10:46:06 +0200 Subject: [PATCH 096/148] init: Factor out AppInitLockDataDirectory Alternative to #10818, alternative solution to #10815. After this change: All the AppInit steps before and inclusive AppInitLockDataDirectory must not have Shutdown() called in case of failure. Only when AppInitMain fails, Shutdown should be called. Changes the GUI and bitcoind code to consistently do this. --- src/bitcoind.cpp | 7 +++++- src/init.cpp | 12 ++++++++--- src/init.h | 16 +++++++++----- src/qt/bitcoin.cpp | 62 ++++++++++++++++++++++++++++++++++++------------------ 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 374678310c6..f3844e9d479 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -159,7 +159,12 @@ bool AppInit(int argc, char* argv[]) return false; #endif // HAVE_DECL_DAEMON } - + // Lock data directory after daemonization + if (!AppInitLockDataDirectory()) + { + // If locking the data directory failed, exit immediately + exit(EXIT_FAILURE); + } fRet = AppInitMain(threadGroup, scheduler); } catch (const std::exception& e) { diff --git a/src/init.cpp b/src/init.cpp index 1e85642019c..d9b98be739d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1170,13 +1170,13 @@ bool AppInitSanityChecks() return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME))); // Probe the data directory lock to give an early error message, if possible + // We cannot hold the data directory lock here, as the forking for daemon() hasn't yet happened, + // and a fork will cause weird behavior to it. return LockDataDirectory(true); } -bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) +bool AppInitLockDataDirectory() { - const CChainParams& chainparams = Params(); - // ********************************************************* Step 4a: application initialization // After daemonization get the data directory lock again and hold on to it until exit // This creates a slight window for a race condition to happen, however this condition is harmless: it // will at most make us exit without printing a message to console. @@ -1184,7 +1184,13 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) // Detailed error printed inside LockDataDirectory return false; } + return true; +} +bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) +{ + const CChainParams& chainparams = Params(); + // ********************************************************* Step 4a: application initialization #ifndef WIN32 CreatePidFile(GetPidFile(), getpid()); #endif diff --git a/src/init.h b/src/init.h index 82227943747..a0a824738cf 100644 --- a/src/init.h +++ b/src/init.h @@ -27,27 +27,33 @@ void InitLogging(); void InitParameterInteraction(); /** Initialize bitcoin core: Basic context setup. - * @note This can be done before daemonization. + * @note This can be done before daemonization. Do not call Shutdown() if this function fails. * @pre Parameters should be parsed and config file should be read. */ bool AppInitBasicSetup(); /** * Initialization: parameter interaction. - * @note This can be done before daemonization. + * @note This can be done before daemonization. Do not call Shutdown() if this function fails. * @pre Parameters should be parsed and config file should be read, AppInitBasicSetup should have been called. */ bool AppInitParameterInteraction(); /** * Initialization sanity checks: ecc init, sanity checks, dir lock. - * @note This can be done before daemonization. + * @note This can be done before daemonization. Do not call Shutdown() if this function fails. * @pre Parameters should be parsed and config file should be read, AppInitParameterInteraction should have been called. */ bool AppInitSanityChecks(); /** - * Bitcoin core main initialization. - * @note This should only be done after daemonization. + * Lock bitcoin core data directory. + * @note This should only be done after daemonization. Do not call Shutdown() if this function fails. * @pre Parameters should be parsed and config file should be read, AppInitSanityChecks should have been called. */ +bool AppInitLockDataDirectory(); +/** + * Bitcoin core main initialization. + * @note This should only be done after daemonization. Call Shutdown() if this function fails. + * @pre Parameters should be parsed and config file should be read, AppInitLockDataDirectory should have been called. + */ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler); /** The help message mode determines what help message to show */ diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 8a745cadce7..4a4116c6702 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -178,6 +178,10 @@ class BitcoinCore: public QObject Q_OBJECT public: explicit BitcoinCore(); + /** Basic initialization, before starting initialization/shutdown thread. + * Return true on success. + */ + static bool baseInitialize(); public Q_SLOTS: void initialize(); @@ -270,26 +274,32 @@ void BitcoinCore::handleRunawayException(const std::exception *e) Q_EMIT runawayException(QString::fromStdString(GetWarnings("gui"))); } +bool BitcoinCore::baseInitialize() +{ + if (!AppInitBasicSetup()) + { + return false; + } + if (!AppInitParameterInteraction()) + { + return false; + } + if (!AppInitSanityChecks()) + { + return false; + } + if (!AppInitLockDataDirectory()) + { + return false; + } + return true; +} + void BitcoinCore::initialize() { try { qDebug() << __func__ << ": Running initialization in thread"; - if (!AppInitBasicSetup()) - { - Q_EMIT initializeResult(false); - return; - } - if (!AppInitParameterInteraction()) - { - Q_EMIT initializeResult(false); - return; - } - if (!AppInitSanityChecks()) - { - Q_EMIT initializeResult(false); - return; - } bool rv = AppInitMain(threadGroup, scheduler); Q_EMIT initializeResult(rv); } catch (const std::exception& e) { @@ -689,16 +699,26 @@ int main(int argc, char *argv[]) if (GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !GetBoolArg("-min", false)) app.createSplashScreen(networkStyle.data()); + int rv = EXIT_SUCCESS; try { app.createWindow(networkStyle.data()); - app.requestInitialize(); + // Perform base initialization before spinning up initialization/shutdown thread + // This is acceptable because this function only contains steps that are quick to execute, + // so the GUI thread won't be held up. + if (BitcoinCore::baseInitialize()) { + app.requestInitialize(); #if defined(Q_OS_WIN) && QT_VERSION >= 0x050000 - WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId()); + WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId()); #endif - app.exec(); - app.requestShutdown(); - app.exec(); + app.exec(); + app.requestShutdown(); + app.exec(); + rv = app.getReturnValue(); + } else { + // A dialog with detailed error will have been shown by InitError() + rv = EXIT_FAILURE; + } } catch (const std::exception& e) { PrintExceptionContinue(&e, "Runaway exception"); app.handleRunawayException(QString::fromStdString(GetWarnings("gui"))); @@ -706,6 +726,6 @@ int main(int argc, char *argv[]) PrintExceptionContinue(NULL, "Runaway exception"); app.handleRunawayException(QString::fromStdString(GetWarnings("gui"))); } - return app.getReturnValue(); + return rv; } #endif // BITCOIN_QT_TEST From 30d8f3a18e7d927459e409a38ee1c0d1ddf054ad Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sat, 15 Jul 2017 01:00:30 +0000 Subject: [PATCH 097/148] Pushdown walletdb though CWallet::AddKeyPubKey to avoid flushes. This prevents the wallet from being flushed between each and every key during top-up. This results in a >10x speed-up for the top-up. --- src/wallet/wallet.cpp | 35 ++++++++++++++++++++++++++++------- src/wallet/wallet.h | 1 + 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b3b3c1c10a3..d8c1dd94fcb 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -106,8 +106,9 @@ CPubKey CWallet::GenerateNewKey(CWalletDB &walletdb, bool internal) } // Compressed public keys were introduced in version 0.6.0 - if (fCompressed) + if (fCompressed) { SetMinVersion(FEATURE_COMPRPUBKEY); + } CPubKey pubkey = secret.GetPubKey(); assert(secret.VerifyPubKey(pubkey)); @@ -115,8 +116,9 @@ CPubKey CWallet::GenerateNewKey(CWalletDB &walletdb, bool internal) mapKeyMetadata[pubkey.GetID()] = metadata; UpdateTimeFirstKey(nCreationTime); - if (!AddKeyPubKey(secret, pubkey)) + if (!AddKeyPubKeyWithDB(walletdb, secret, pubkey)) { throw std::runtime_error(std::string(__func__) + ": AddKey failed"); + } return pubkey; } @@ -166,29 +168,48 @@ void CWallet::DeriveNewChildKey(CWalletDB &walletdb, CKeyMetadata& metadata, CKe throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); } -bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) +bool CWallet::AddKeyPubKeyWithDB(CWalletDB &walletdb, const CKey& secret, const CPubKey &pubkey) { AssertLockHeld(cs_wallet); // mapKeyMetadata - if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey)) + + // CCryptoKeyStore has no concept of wallet databases, but calls AddCryptedKey + // which is overridden below. To avoid flushes, the database handle is + // tunneled through to it. + bool needsDB = !pwalletdbEncryption; + if (needsDB) { + pwalletdbEncryption = &walletdb; + } + if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey)) { + if (needsDB) pwalletdbEncryption = NULL; return false; + } + if (needsDB) pwalletdbEncryption = NULL; // check if we need to remove from watch-only CScript script; script = GetScriptForDestination(pubkey.GetID()); - if (HaveWatchOnly(script)) + if (HaveWatchOnly(script)) { RemoveWatchOnly(script); + } script = GetScriptForRawPubKey(pubkey); - if (HaveWatchOnly(script)) + if (HaveWatchOnly(script)) { RemoveWatchOnly(script); + } if (!IsCrypted()) { - return CWalletDB(*dbw).WriteKey(pubkey, + return walletdb.WriteKey(pubkey, secret.GetPrivKey(), mapKeyMetadata[pubkey.GetID()]); } return true; } +bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) +{ + CWalletDB walletdb(*dbw); + return CWallet::AddKeyPubKeyWithDB(walletdb, secret, pubkey); +} + bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index e91a6effd3c..0bf6ccf722e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -869,6 +869,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface CPubKey GenerateNewKey(CWalletDB& walletdb, bool internal = false); //! Adds a key to the store, and saves it to disk. bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override; + bool AddKeyPubKeyWithDB(CWalletDB &walletdb,const CKey& key, const CPubKey &pubkey); //! Adds a key to the store, without saving it to disk (used by LoadWallet) bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); } //! Load metadata (used by LoadWallet) From 41dc1635878766e4a810e6a7c57637d079fced64 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Sat, 15 Jul 2017 01:09:10 +0000 Subject: [PATCH 098/148] Increase wallet default keypool size to 1000. --- src/wallet/wallet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0bf6ccf722e..9e687c4bfd0 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -40,7 +40,7 @@ extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; extern bool fWalletRbf; -static const unsigned int DEFAULT_KEYPOOL_SIZE = 100; +static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000; //! -paytxfee default static const CAmount DEFAULT_TRANSACTION_FEE = 0; //! -fallbackfee default From b0e8e2de8408cbaed9d70914c67b4c9f11397cb7 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Mon, 17 Jul 2017 08:16:36 +0000 Subject: [PATCH 099/148] Print one log message per keypool top-up, not one per key. --- src/wallet/wallet.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d8c1dd94fcb..5db13ef02ff 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3213,7 +3213,9 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) } else { setExternalKeyPool.insert(nEnd); } - LogPrintf("keypool added key %d, size=%u (%u internal), new key is %s\n", nEnd, setInternalKeyPool.size() + setExternalKeyPool.size(), setInternalKeyPool.size(), internal ? "internal" : "external"); + } + if (missingInternal + missingExternal > 0) { + LogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size(), setInternalKeyPool.size()); } } return true; From 439c4e8ad5871f59d87ae2ab77fe01aa6fe41414 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 29 Jun 2017 13:57:33 -0400 Subject: [PATCH 100/148] Improve api to estimatesmartfee Change parameter for conservative estimates to be an estimate_mode string. Change to never return a -1 for failure but to instead omit the feerate and return an error string. Throw JSONRPC error on invalid nblocks parameter. --- src/policy/fees.cpp | 19 ++++++++----------- src/rpc/client.cpp | 1 - src/rpc/mining.cpp | 50 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 0f186fa8457..73cc0b4a5e7 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -839,20 +839,20 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation EstimationResult tempResult; // Return failure if trying to analyze a target we're not tracking - if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms()) - return CFeeRate(0); + if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms()) { + return CFeeRate(0); // error conditon + } // It's not possible to get reasonable estimates for confTarget of 1 - if (confTarget == 1) - confTarget = 2; + if (confTarget == 1) confTarget = 2; unsigned int maxUsableEstimate = MaxUsableEstimate(); - if (maxUsableEstimate <= 1) - return CFeeRate(0); - if ((unsigned int)confTarget > maxUsableEstimate) { confTarget = maxUsableEstimate; } + if (feeCalc) feeCalc->returnedTarget = confTarget; + + if (confTarget <= 1) return CFeeRate(0); // error conditon assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints /** true is passed to estimateCombined fee for target/2 and target so @@ -899,10 +899,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation } } - if (feeCalc) feeCalc->returnedTarget = confTarget; - - if (median < 0) - return CFeeRate(0); + if (median < 0) return CFeeRate(0); // error conditon return CFeeRate(median); } diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 775ad4b6c9a..1ab19561242 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -114,7 +114,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getrawmempool", 0, "verbose" }, { "estimatefee", 0, "nblocks" }, { "estimatesmartfee", 0, "nblocks" }, - { "estimatesmartfee", 1, "conservative" }, { "estimaterawfee", 0, "nblocks" }, { "estimaterawfee", 1, "threshold" }, { "prioritisetransaction", 1, "dummy" }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index b8c94d32ecf..caad788591f 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -806,42 +806,62 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( - "estimatesmartfee nblocks (conservative)\n" + "estimatesmartfee nblocks (\"estimate_mode\")\n" "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" "confirmation within nblocks blocks if possible and return the number of blocks\n" "for which the estimate is valid. Uses virtual transaction size as defined\n" "in BIP 141 (witness data is discounted).\n" "\nArguments:\n" - "1. nblocks (numeric)\n" - "2. conservative (bool, optional, default=true) Whether to return a more conservative estimate which\n" - " also satisfies a longer history. A conservative estimate potentially returns a higher\n" - " feerate and is more likely to be sufficient for the desired target, but is not as\n" - " responsive to short term drops in the prevailing fee market\n" + "1. nblocks (numeric) Confirmation target in blocks (1 - 1008)\n" + "2. \"estimate_mode\" (string, optional, default=CONSERVATIVE) The fee estimate mode.\n" + " Whether to return a more conservative estimate which also satisfies\n" + " a longer history. A conservative estimate potentially returns a\n" + " higher feerate and is more likely to be sufficient for the desired\n" + " target, but is not as responsive to short term drops in the\n" + " prevailing fee market. Must be one of:\n" + " \"UNSET\" (defaults to CONSERVATIVE)\n" + " \"ECONOMICAL\"\n" + " \"CONSERVATIVE\"\n" "\nResult:\n" "{\n" - " \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n" + " \"feerate\" : x.x, (numeric, optional) estimate fee-per-kilobyte (in BTC)\n" + " \"errors\": [ str... ] (json array of strings, optional) Errors encountered during processing\n" " \"blocks\" : n (numeric) block number where estimate was found\n" "}\n" "\n" - "A negative value is returned if not enough transactions and blocks\n" + "The request target will be clamped between 2 and the highest target\n" + "fee estimation is able to return based on how long it has been running.\n" + "An error is returned if not enough transactions and blocks\n" "have been observed to make an estimate for any number of blocks.\n" "\nExample:\n" + HelpExampleCli("estimatesmartfee", "6") ); - RPCTypeCheck(request.params, {UniValue::VNUM}); - + RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR}); + RPCTypeCheckArgument(request.params[0], UniValue::VNUM); int nBlocks = request.params[0].get_int(); + if (nBlocks < 1 || (unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid nblocks"); + } bool conservative = true; if (request.params.size() > 1 && !request.params[1].isNull()) { - RPCTypeCheckArgument(request.params[1], UniValue::VBOOL); - conservative = request.params[1].get_bool(); + FeeEstimateMode fee_mode; + if (!FeeModeFromString(request.params[1].get_str(), fee_mode)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); + } + if (fee_mode == FeeEstimateMode::ECONOMICAL) conservative = false; } UniValue result(UniValue::VOBJ); + UniValue errors(UniValue::VARR); FeeCalculation feeCalc; CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocks, &feeCalc, conservative); - result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK()))); + if (feeRate != CFeeRate(0)) { + result.push_back(Pair("feerate", ValueFromAmount(feeRate.GetFeePerK()))); + } else { + errors.push_back("Insufficient data or no feerate found"); + result.push_back(Pair("errors", errors)); + } result.push_back(Pair("blocks", feeCalc.returnedTarget)); return result; } @@ -889,7 +909,7 @@ UniValue estimaterawfee(const JSONRPCRequest& request) + HelpExampleCli("estimaterawfee", "6 0.9") ); - RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM, UniValue::VNUM}, true); + RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); int nBlocks = request.params[0].get_int(); if (nBlocks < 1 || (unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE)) { @@ -963,7 +983,7 @@ static const CRPCCommand commands[] = { "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} }, { "util", "estimatefee", &estimatefee, true, {"nblocks"} }, - { "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks", "conservative"} }, + { "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks", "estimate_mode"} }, { "hidden", "estimaterawfee", &estimaterawfee, true, {"nblocks", "threshold"} }, }; From 06bcdb8da64502a64df03f3c89fbc6ccb72cd349 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 12 Jul 2017 15:10:16 -0400 Subject: [PATCH 101/148] Convert named argument from nblocks to conf_target in estimatesmartfee and estimaterawfee. Also reuse existing bounds checking. --- src/rpc/mining.cpp | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index caad788591f..4fd632dfc55 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -806,13 +806,13 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( - "estimatesmartfee nblocks (\"estimate_mode\")\n" + "estimatesmartfee conf_target (\"estimate_mode\")\n" "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" - "confirmation within nblocks blocks if possible and return the number of blocks\n" + "confirmation within conf_target blocks if possible and return the number of blocks\n" "for which the estimate is valid. Uses virtual transaction size as defined\n" "in BIP 141 (witness data is discounted).\n" "\nArguments:\n" - "1. nblocks (numeric) Confirmation target in blocks (1 - 1008)\n" + "1. conf_target (numeric) Confirmation target in blocks (1 - 1008)\n" "2. \"estimate_mode\" (string, optional, default=CONSERVATIVE) The fee estimate mode.\n" " Whether to return a more conservative estimate which also satisfies\n" " a longer history. A conservative estimate potentially returns a\n" @@ -839,10 +839,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR}); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); - int nBlocks = request.params[0].get_int(); - if (nBlocks < 1 || (unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid nblocks"); - } + unsigned int conf_target = ParseConfirmTarget(request.params[0]); bool conservative = true; if (request.params.size() > 1 && !request.params[1].isNull()) { FeeEstimateMode fee_mode; @@ -855,7 +852,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) UniValue result(UniValue::VOBJ); UniValue errors(UniValue::VARR); FeeCalculation feeCalc; - CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocks, &feeCalc, conservative); + CFeeRate feeRate = ::feeEstimator.estimateSmartFee(conf_target, &feeCalc, conservative); if (feeRate != CFeeRate(0)) { result.push_back(Pair("feerate", ValueFromAmount(feeRate.GetFeePerK()))); } else { @@ -870,18 +867,18 @@ UniValue estimaterawfee(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( - "estimaterawfee nblocks (threshold)\n" + "estimaterawfee conf_target (threshold)\n" "\nWARNING: This interface is unstable and may disappear or change!\n" "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n" " implementation of fee estimation. The parameters it can be called with\n" " and the results it returns will change if the internal implementation changes.\n" "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" - "confirmation within nblocks blocks if possible. Uses virtual transaction size as defined\n" - "in BIP 141 (witness data is discounted).\n" + "confirmation within conf_target blocks if possible. Uses virtual transaction size as\n" + "defined in BIP 141 (witness data is discounted).\n" "\nArguments:\n" - "1. nblocks (numeric) Confirmation target in blocks (1 - 1008)\n" + "1. conf_target (numeric) Confirmation target in blocks (1 - 1008)\n" "2. threshold (numeric, optional) The proportion of transactions in a given feerate range that must have been\n" - " confirmed within nblocks in order to consider those feerates as high enough and proceed to check\n" + " confirmed within conf_target in order to consider those feerates as high enough and proceed to check\n" " lower buckets. Default: 0.95\n" "\nResult:\n" "{\n" @@ -911,10 +908,7 @@ UniValue estimaterawfee(const JSONRPCRequest& request) RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); - int nBlocks = request.params[0].get_int(); - if (nBlocks < 1 || (unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid nblocks"); - } + unsigned int conf_target = ParseConfirmTarget(request.params[0]); double threshold = 0.95; if (!request.params[1].isNull()) { threshold = request.params[1].get_real(); @@ -930,9 +924,9 @@ UniValue estimaterawfee(const JSONRPCRequest& request) EstimationResult buckets; // Only output results for horizons which track the target - if ((unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(horizon)) continue; + if (conf_target > ::feeEstimator.HighestTargetTracked(horizon)) continue; - feeRate = ::feeEstimator.estimateRawFee(nBlocks, threshold, horizon, &buckets); + feeRate = ::feeEstimator.estimateRawFee(conf_target, threshold, horizon, &buckets); UniValue horizon_result(UniValue::VOBJ); UniValue errors(UniValue::VARR); UniValue passbucket(UniValue::VOBJ); @@ -983,9 +977,9 @@ static const CRPCCommand commands[] = { "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} }, { "util", "estimatefee", &estimatefee, true, {"nblocks"} }, - { "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks", "estimate_mode"} }, + { "util", "estimatesmartfee", &estimatesmartfee, true, {"conf_target", "estimate_mode"} }, - { "hidden", "estimaterawfee", &estimaterawfee, true, {"nblocks", "threshold"} }, + { "hidden", "estimaterawfee", &estimaterawfee, true, {"conf_target", "threshold"} }, }; void RegisterMiningRPCCommands(CRPCTable &t) From 31e07203bd98d69be476cbff105ad659b4efa862 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 13 Jul 2017 17:06:27 +0200 Subject: [PATCH 102/148] Add wallet endpoint support to bitcoin-cli (-usewallet) --- src/bitcoin-cli.cpp | 16 +++++++++++++++- src/httpserver.cpp | 11 +++++++++++ src/httpserver.h | 2 ++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 8b48c7f8e42..c2bc15584f0 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -46,6 +46,7 @@ std::string HelpMessageCli() strUsage += HelpMessageOpt("-rpcpassword=", _("Password for JSON-RPC connections")); strUsage += HelpMessageOpt("-rpcclienttimeout=", strprintf(_("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT)); strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)")); + strUsage += HelpMessageOpt("-usewallet=", _("Send RPC for non-default wallet on RPC server (argument is wallet filename in bitcoind directory, required if bitcoind/-Qt runs with multiple wallets)")); return strUsage; } @@ -241,7 +242,20 @@ UniValue CallRPC(const std::string& strMethod, const UniValue& params) assert(output_buffer); evbuffer_add(output_buffer, strRequest.data(), strRequest.size()); - int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, "/"); + // check if we should use a special wallet endpoint + std::string endpoint = "/"; + std::string walletName = GetArg("-usewallet", ""); + if (!walletName.empty()) { + char *encodedURI = evhttp_uriencode(walletName.c_str(), walletName.size(), false); + if (encodedURI) { + endpoint = "/wallet/"+ std::string(encodedURI); + free(encodedURI); + } + else { + throw CConnectionFailed("uri-encode failed"); + } + } + int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, endpoint.c_str()); req.release(); // ownership moved to evcon in above call if (r != 0) { throw CConnectionFailed("send http request failed"); diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 290a2efca2b..ba012554006 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -666,3 +666,14 @@ void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch) } } +std::string urlDecode(const std::string &urlEncoded) { + std::string res; + if (!urlEncoded.empty()) { + char *decoded = evhttp_uridecode(urlEncoded.c_str(), false, NULL); + if (decoded) { + res = std::string(decoded); + free(decoded); + } + } + return res; +} diff --git a/src/httpserver.h b/src/httpserver.h index 9df56e5fc55..3e434bf0a0b 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -148,4 +148,6 @@ class HTTPEvent struct event* ev; }; +std::string urlDecode(const std::string &urlEncoded); + #endif // BITCOIN_HTTPSERVER_H From 32c9710c50b7e9255c81c7083cbfdfddc813b01f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 7 Jul 2017 16:03:24 +0200 Subject: [PATCH 103/148] Fix test_bitcoin circular dependency issue --- src/Makefile.test.include | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 90504ad52df..6415b3d2e33 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -96,12 +96,13 @@ endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) -test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \ - $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) -test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_test_bitcoin_LDADD = if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) endif +test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \ + $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) +test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static From 76603b132513266065235d686b82aaa6a2968303 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Mon, 17 Jul 2017 12:10:23 +0200 Subject: [PATCH 104/148] Select wallet based on the given endpoint --- src/wallet/rpcwallet.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ee8c7548fc6..ef96742a3ca 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -9,6 +9,7 @@ #include "consensus/validation.h" #include "core_io.h" #include "init.h" +#include "httpserver.h" #include "validation.h" #include "net.h" #include "policy/feerate.h" @@ -30,10 +31,21 @@ #include +static const std::string WALLET_ENDPOINT_BASE = "/wallet/"; + CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request) { - // TODO: Some way to access secondary wallets - return vpwallets.empty() ? nullptr : vpwallets[0]; + if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) { + // wallet endpoint was used + std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size())); + for (CWalletRef pwallet : ::vpwallets) { + if (pwallet->GetName() == requestedWallet) { + return pwallet; + } + } + throw JSONRPCError(RPC_INVALID_PARAMETER, "Requested wallet does not exist or is not loaded"); + } + return ::vpwallets.size() == 1 || (request.fHelp && ::vpwallets.size() > 0) ? ::vpwallets[0] : nullptr; } std::string HelpRequiringPassphrase(CWallet * const pwallet) From 979d0b8a6533de58b6352666d90fff33841db63d Mon Sep 17 00:00:00 2001 From: John Newbery Date: Thu, 13 Jul 2017 10:53:42 -0400 Subject: [PATCH 105/148] [tests] [wallet] Add wallet endpoint support to authproxy --- test/functional/test_framework/authproxy.py | 3 +++ test/functional/test_framework/coverage.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py index dfcc524313a..b3671cbdc51 100644 --- a/test/functional/test_framework/authproxy.py +++ b/test/functional/test_framework/authproxy.py @@ -191,3 +191,6 @@ def _get_response(self): else: log.debug("<-- [%.6f] %s"%(elapsed,responsedata)) return response + + def __truediv__(self, relative_uri): + return AuthServiceProxy("{}/{}".format(self.__service_url, relative_uri), self._service_name, connection=self.__conn) diff --git a/test/functional/test_framework/coverage.py b/test/functional/test_framework/coverage.py index 3f87ef91f61..227b1a17afb 100644 --- a/test/functional/test_framework/coverage.py +++ b/test/functional/test_framework/coverage.py @@ -56,6 +56,8 @@ def __call__(self, *args, **kwargs): def url(self): return self.auth_service_proxy_instance.url + def __truediv__(self, relative_uri): + return AuthServiceProxyWrapper(self.auth_service_proxy_instance / relative_uri) def get_filename(dirname, n_node): """ From 6b9faf747003995417d6a66fad64d2537c371092 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 13 Jul 2017 17:49:46 +0200 Subject: [PATCH 106/148] [QA] add basic multiwallet test --- test/functional/multiwallet.py | 47 ++++++++++++++++++++++++++++++++++++++++++ test/functional/test_runner.py | 1 + 2 files changed, 48 insertions(+) create mode 100755 test/functional/multiwallet.py diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py new file mode 100755 index 00000000000..2b4dd2d3e7d --- /dev/null +++ b/test/functional/multiwallet.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 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 multiwallet.""" +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + +class MultiWalletTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 + self.extra_args = [['-wallet=w1', '-wallet=w2', '-wallet=w3']] + + def run_test(self): + w1 = self.nodes[0] / "wallet/w1" + w1.generate(1) + + #accessing wallet RPC without using wallet endpoint fails + assert_raises_jsonrpc(-32601, "Method not found", self.nodes[0].getwalletinfo) + + #check w1 wallet balance + walletinfo = w1.getwalletinfo() + assert_equal(walletinfo['immature_balance'], 50) + + #check w1 wallet balance + w2 = self.nodes[0] / "wallet/w2" + walletinfo = w2.getwalletinfo() + assert_equal(walletinfo['immature_balance'], 0) + + w3 = self.nodes[0] / "wallet/w3" + + w1.generate(101) + assert_equal(w1.getbalance(), 100) + assert_equal(w2.getbalance(), 0) + assert_equal(w3.getbalance(), 0) + + w1.sendtoaddress(w2.getnewaddress(), 1) + w1.sendtoaddress(w3.getnewaddress(), 2) + w1.generate(1) + assert_equal(w2.getbalance(), 1) + assert_equal(w3.getbalance(), 2) + +if __name__ == '__main__': + MultiWalletTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index b7bc6e841b0..51577589fe0 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -63,6 +63,7 @@ 'segwit.py', # vv Tests less than 2m vv 'wallet.py', + 'multiwallet.py', 'wallet-accounts.py', 'p2p-segwit.py', 'wallet-dump.py', From 1fc8c3de0cff2971cc1f9903bfc3d03a982f2fab Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 11 Jul 2017 12:15:02 -0400 Subject: [PATCH 107/148] No longer ever reuse keypool indexes This fixes an issue where you could reserve a keypool entry, then top up the keypool, writing out a new key at the given index, then return they key from the pool. This isnt likely to cause issues, but given there is no reason to ever re-use keypool indexes (they're 64 bits...), best to avoid it alltogether. --- src/wallet/wallet.cpp | 14 +++++--------- src/wallet/wallet.h | 5 ++++- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6f1894d4307..53175025890 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3211,21 +3211,17 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) internal = true; } - if (!setInternalKeyPool.empty()) { - nEnd = *(setInternalKeyPool.rbegin()) + 1; - } - if (!setExternalKeyPool.empty()) { - nEnd = std::max(nEnd, *(setExternalKeyPool.rbegin()) + 1); - } + assert(m_max_keypool_index < std::numeric_limits::max()); // How in the hell did you use so many keys? + int64_t index = ++m_max_keypool_index; - if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey(walletdb, internal), internal))) { + if (!walletdb.WritePool(index, CKeyPool(GenerateNewKey(walletdb, internal), internal))) { throw std::runtime_error(std::string(__func__) + ": writing generated key failed"); } if (internal) { - setInternalKeyPool.insert(nEnd); + setInternalKeyPool.insert(index); } else { - setExternalKeyPool.insert(nEnd); + setExternalKeyPool.insert(index); } } if (missingInternal + missingExternal > 0) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 06937566b0f..574fd8710d3 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -701,6 +701,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::set setInternalKeyPool; std::set setExternalKeyPool; + int64_t m_max_keypool_index; int64_t nTimeFirstKey; @@ -743,13 +744,14 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface } } - void LoadKeyPool(int nIndex, const CKeyPool &keypool) + void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) { if (keypool.fInternal) { setInternalKeyPool.insert(nIndex); } else { setExternalKeyPool.insert(nIndex); } + m_max_keypool_index = std::max(m_max_keypool_index, nIndex); // If no metadata exists yet, create a default with the pool key's // creation time. Note that this may be overwritten by actually @@ -795,6 +797,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface nAccountingEntryNumber = 0; nNextResend = 0; nLastResend = 0; + m_max_keypool_index = 0; nTimeFirstKey = 0; fBroadcastTransactions = false; nRelockTime = 0; From 095b9174645f5b855dd5946c99cea4f4ffb5a034 Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Mon, 17 Jul 2017 17:00:00 +0000 Subject: [PATCH 108/148] Avoid using sizes on non-fixed-width types to derive protocol constants. Thanks to awemany for pointing this out. --- src/validation.cpp | 7 ++++--- src/wallet/wallet.cpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index d7d880d24f5..6c9f76d2156 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -20,6 +20,7 @@ #include "init.h" #include "policy/fees.h" #include "policy/policy.h" +#include "policy/rbf.h" #include "pow.h" #include "primitives/block.h" #include "primitives/transaction.h" @@ -488,9 +489,9 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool if (!setConflicts.count(ptxConflicting->GetHash())) { // Allow opt-out of transaction replacement by setting - // nSequence >= maxint-1 on all inputs. + // nSequence > MAX_BIP125_RBF_SEQUENCE (SEQUENCE_FINAL-2) on all inputs. // - // maxint-1 is picked to still allow use of nLockTime by + // SEQUENCE_FINAL-1 is picked to still allow use of nLockTime by // non-replaceable transactions. All inputs rather than just one // is for the sake of multi-party protocols, where we don't // want a single party to be able to disable replacement. @@ -504,7 +505,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool { for (const CTxIn &_txin : ptxConflicting->vin) { - if (_txin.nSequence < std::numeric_limits::max()-1) + if (_txin.nSequence <= MAX_BIP125_RBF_SEQUENCE) { fReplacementOptOut = false; break; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6f1894d4307..ea0493cd0bf 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2723,7 +2723,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // to avoid conflicting with other possible uses of nSequence, // and in the spirit of "smallest possible change from prior // behavior." - const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (std::numeric_limits::max() - 1); + const uint32_t nSequence = coin_control.signalRbf ? MAX_BIP125_RBF_SEQUENCE : (CTxIn::SEQUENCE_FINAL - 1); for (const auto& coin : setCoins) txNew.vin.push_back(CTxIn(coin.outpoint,CScript(), nSequence)); From 077d01f2fcc305809f084ccc34badc531ae2f30a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 17 Jul 2017 13:14:53 -0400 Subject: [PATCH 109/148] random: only use getentropy on openbsd --- src/random.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/random.cpp b/src/random.cpp index 3226abb69e3..b308e8f4a1d 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -227,10 +227,12 @@ void GetOSRand(unsigned char *ent32) RandFailure(); } } -#elif defined(HAVE_GETENTROPY) +#elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__) /* On OpenBSD this can return up to 256 bytes of entropy, will return an * error if more are requested. * The call cannot return less than the requested number of bytes. + getentropy is explicitly limited to openbsd here, as a similar (but not + the same) function may exist on other platforms via glibc. */ if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { RandFailure(); From f4d00e63f7951469c840edede3f675d07249f62a Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Thu, 6 Jul 2017 14:00:46 -0400 Subject: [PATCH 110/148] Add a discard_rate Any change output which would be dust at the discard_rate you are willing to discard completely and add to fee (as well as continuing to pay the fee that would have been needed for creating the change). --- src/wallet/wallet.cpp | 31 +++++++++++++++++++++++++++++-- src/wallet/wallet.h | 3 +++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 13da7bb2c2f..e230ee0eb0e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -57,6 +57,8 @@ CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE); */ CFeeRate CWallet::fallbackFee = CFeeRate(DEFAULT_FALLBACK_FEE); +CFeeRate CWallet::m_discard_rate = CFeeRate(DEFAULT_DISCARD_FEE); + const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); /** @defgroup mapWallet @@ -2501,6 +2503,17 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC return true; } +static CFeeRate GetDiscardRate(const CBlockPolicyEstimator& estimator) +{ + unsigned int highest_target = estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); + CFeeRate discard_rate = estimator.estimateSmartFee(highest_target, nullptr /* FeeCalculation */, false /* conservative */); + // Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate + discard_rate = (discard_rate == CFeeRate(0)) ? CWallet::m_discard_rate : std::min(discard_rate, CWallet::m_discard_rate); + // Discard rate must be at least dustRelayFee + discard_rate = std::max(discard_rate, ::dustRelayFee); + return discard_rate; +} + bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign) { @@ -2600,6 +2613,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT CTxOut change_prototype_txout(0, scriptChange); size_t change_prototype_size = GetSerializeSize(change_prototype_txout, SER_DISK, 0); + CFeeRate discard_rate = GetDiscardRate(::feeEstimator); nFeeRet = 0; bool pick_new_inputs = true; CAmount nValueIn = 0; @@ -2667,7 +2681,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // Never create dust outputs; if we would, just // add the dust to the fee. - if (IsDust(newTxOut, ::dustRelayFee)) + if (IsDust(newTxOut, discard_rate)) { nChangePosInOut = -1; nFeeRet += nChange; @@ -2747,7 +2761,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // (because of reduced tx size) and so we should add a // change output. Only try this once. CAmount fee_needed_for_change = GetMinimumFee(change_prototype_size, coin_control, ::mempool, ::feeEstimator, nullptr); - CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, ::dustRelayFee); + CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, discard_rate); CAmount max_excess_fee = fee_needed_for_change + minimum_value_for_change; if (nFeeRet > nFeeNeeded + max_excess_fee && nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) { pick_new_inputs = false; @@ -3788,6 +3802,9 @@ std::string CWallet::GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), DEFAULT_KEYPOOL_SIZE)); strUsage += HelpMessageOpt("-fallbackfee=", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"), CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE))); + strUsage += HelpMessageOpt("-discardfee=", strprintf(_("The fee rate (in %s/kB) used to discard change (to fee) if it would be dust at this fee rate (default: %s) " + "Note: We will always discard up to the dust relay fee and a discard fee above that is limited by the longest target fee estimate"), + CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE))); strUsage += HelpMessageOpt("-mintxfee=", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"), CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE))); strUsage += HelpMessageOpt("-paytxfee=", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"), @@ -4113,6 +4130,16 @@ bool CWallet::ParameterInteraction() _("This is the transaction fee you may pay when fee estimates are not available.")); CWallet::fallbackFee = CFeeRate(nFeePerK); } + if (IsArgSet("-discardfee")) + { + CAmount nFeePerK = 0; + if (!ParseMoney(GetArg("-discardfee", ""), nFeePerK)) + return InitError(strprintf(_("Invalid amount for -discardfee=: '%s'"), GetArg("-discardfee", ""))); + if (nFeePerK > HIGH_TX_FEE_PER_KB) + InitWarning(AmountHighWarn("-discardfee") + " " + + _("This is the transaction fee you may discard if change is smaller than dust at this level")); + CWallet::m_discard_rate = CFeeRate(nFeePerK); + } if (IsArgSet("-paytxfee")) { CAmount nFeePerK = 0; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b716e46a7d8..a7fef8a8025 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -45,6 +45,8 @@ static const unsigned int DEFAULT_KEYPOOL_SIZE = 100; static const CAmount DEFAULT_TRANSACTION_FEE = 0; //! -fallbackfee default static const CAmount DEFAULT_FALLBACK_FEE = 20000; +//! -m_discard_rate default +static const CAmount DEFAULT_DISCARD_FEE = 10000; //! -mintxfee default static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000; //! minimum recommended increment for BIP 125 replacement txs @@ -965,6 +967,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface static CFeeRate minTxFee; static CFeeRate fallbackFee; + static CFeeRate m_discard_rate; /** * Estimate the minimum fee considering user set parameters * and the required fee From 99c7fc39a5359fda8503e053f9da676c6684efd7 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 11 Jul 2017 20:59:46 -0400 Subject: [PATCH 111/148] Prevent user from specifying conflicting parameters to fundrawtx estimate_mode/conf_target both are overridden by feeRate, so should not be specified together with feeRate. --- src/wallet/rpcwallet.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ee8c7548fc6..079b2ce7898 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2795,9 +2795,15 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) coinControl.signalRbf = options["replaceable"].get_bool(); } if (options.exists("conf_target")) { + if (options.exists("feeRate")) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate"); + } coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"]); } if (options.exists("estimate_mode")) { + if (options.exists("feeRate")) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate"); + } if (!FeeModeFromString(options["estimate_mode"].get_str(), coinControl.m_fee_mode)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter"); } From 35aff432175b437529200f8a3fcc44001b6569ad Mon Sep 17 00:00:00 2001 From: practicalswift Date: Tue, 18 Jul 2017 14:02:15 +0200 Subject: [PATCH 112/148] Remove unused variable int64_t nEnd Last use of nEnd removed in commit 1fc8c3de0cff2971cc1f9903bfc3d03a982f2fab. --- src/wallet/wallet.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 53175025890..458c54774fb 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3206,7 +3206,6 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) CWalletDB walletdb(*dbw); for (int64_t i = missingInternal + missingExternal; i--;) { - int64_t nEnd = 1; if (i < missingInternal) { internal = true; } From 5a6671c4ca85947b59d03a4f9f0f24412a8f9cf7 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Tue, 18 Jul 2017 14:02:42 +0200 Subject: [PATCH 113/148] =?UTF-8?q?Fix=20typo:=20"conditon"=20=E2=86=92=20?= =?UTF-8?q?"condition"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Typo introduced in commit 439c4e8ad5871f59d87ae2ab77fe01aa6fe41414. --- src/policy/fees.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 73cc0b4a5e7..b9476407cf1 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -840,7 +840,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation // Return failure if trying to analyze a target we're not tracking if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms()) { - return CFeeRate(0); // error conditon + return CFeeRate(0); // error condition } // It's not possible to get reasonable estimates for confTarget of 1 @@ -852,7 +852,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation } if (feeCalc) feeCalc->returnedTarget = confTarget; - if (confTarget <= 1) return CFeeRate(0); // error conditon + if (confTarget <= 1) return CFeeRate(0); // error condition assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints /** true is passed to estimateCombined fee for target/2 and target so @@ -899,7 +899,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation } } - if (median < 0) return CFeeRate(0); // error conditon + if (median < 0) return CFeeRate(0); // error condition return CFeeRate(median); } From e0d459264fa9330eea99d33208fbddb8c8362be4 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Tue, 18 Jul 2017 15:11:18 +0200 Subject: [PATCH 114/148] Avoid redundant redeclaration of GetWarnings(const string&) std::string GetWarnings(const std::string& strFor) is declared in warnings.h and defined in warnings.cpp. --- src/qt/clientmodel.cpp | 1 + src/rpc/mining.cpp | 1 + src/rpc/misc.cpp | 1 + src/rpc/net.cpp | 2 +- src/validation.h | 8 -------- src/warnings.h | 7 +++++++ 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 33f4535ee22..52ce11cefd2 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -18,6 +18,7 @@ #include "txmempool.h" #include "ui_interface.h" #include "util.h" +#include "warnings.h" #include diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 4fd632dfc55..daca32d2511 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -24,6 +24,7 @@ #include "util.h" #include "utilstrencodings.h" #include "validationinterface.h" +#include "warnings.h" #include #include diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index fcbbe1ceed0..3c4f071fcf0 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -21,6 +21,7 @@ #include "wallet/wallet.h" #include "wallet/walletdb.h" #endif +#include "warnings.h" #include #ifdef HAVE_MALLOC_INFO diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index ed452fcb021..090d9e448e8 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -18,7 +18,7 @@ #include "util.h" #include "utilstrencodings.h" #include "version.h" - +#include "warnings.h" #include diff --git a/src/validation.h b/src/validation.h index a9f995abb88..95c8e5b93e3 100644 --- a/src/validation.h +++ b/src/validation.h @@ -268,14 +268,6 @@ void UnloadBlockIndex(); void ThreadScriptCheck(); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(); -/** Format a string that describes several potential problems detected by the core. - * strFor can have three values: - * - "rpc": get critical warnings, which should put the client in safe mode if non-empty - * - "statusbar": get all warnings - * - "gui": get all warnings, translated (where possible) for GUI - * This function only returns the highest priority warning of the set selected by strFor. - */ -std::string GetWarnings(const std::string& strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ bool GetTransaction(const uint256 &hash, CTransactionRef &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ diff --git a/src/warnings.h b/src/warnings.h index a7aa6574264..fd0ca539423 100644 --- a/src/warnings.h +++ b/src/warnings.h @@ -14,6 +14,13 @@ void SetfLargeWorkForkFound(bool flag); bool GetfLargeWorkForkFound(); void SetfLargeWorkInvalidChainFound(bool flag); bool GetfLargeWorkInvalidChainFound(); +/** Format a string that describes several potential problems detected by the core. + * strFor can have three values: + * - "rpc": get critical warnings, which should put the client in safe mode if non-empty + * - "statusbar": get all warnings + * - "gui": get all warnings, translated (where possible) for GUI + * This function only returns the highest priority warning of the set selected by strFor. + */ std::string GetWarnings(const std::string& strFor); static const bool DEFAULT_TESTSAFEMODE = false; From cf82a9e704f56d245cf512d76ba9d0e6b178f3b0 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 10 Jul 2017 14:29:06 -0400 Subject: [PATCH 115/148] Do not allow users to get keys from keypool without reserving them fundrawtransaction allows users to add a change output and then not have it removed from keypool. While it would be nice to have users follow the normal CreateTransaction/CommitTransaction process we use internally, there isnt much benefit in exposing this option, especially with HD wallets, while there is ample room for users to misunderstand or misuse this option. This could be particularly nasty in some use-cases (especially pre-HD-split) - eg a user might fundrawtransaction, then call getnewaddress, hand out the address for someone to pay them, then sendrawtransaction. This may result in the user thinking they have received payment, even though it was really just their own change! This could obviously result in needless key-reuse. --- src/wallet/rpcwallet.cpp | 9 ++------- src/wallet/wallet.cpp | 12 +++++++----- src/wallet/wallet.h | 2 +- test/functional/fundrawtransaction.py | 17 +++-------------- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ee8c7548fc6..26fcfea95ce 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2693,7 +2693,6 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) " \"changePosition\" (numeric, optional, default random) The index of the change output\n" " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n" " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n" - " \"reserveChangeKey\" (boolean, optional, default true) Reserves the change output key from the keypool\n" " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (" + CURRENCY_UNIT + " per KB)\n" " \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n" " The fee will be equally deducted from the amount of each specified output.\n" @@ -2732,7 +2731,6 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) CCoinControl coinControl; int changePosition = -1; bool lockUnspents = false; - bool reserveChangeKey = true; UniValue subtractFeeFromOutputs; std::set setSubtractFeeFromOutputs; @@ -2752,7 +2750,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) {"changePosition", UniValueType(UniValue::VNUM)}, {"includeWatching", UniValueType(UniValue::VBOOL)}, {"lockUnspents", UniValueType(UniValue::VBOOL)}, - {"reserveChangeKey", UniValueType(UniValue::VBOOL)}, + {"reserveChangeKey", UniValueType(UniValue::VBOOL)}, // DEPRECATED (and ignored), should be removed in 0.16 or so. {"feeRate", UniValueType()}, // will be checked below {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)}, {"replaceable", UniValueType(UniValue::VBOOL)}, @@ -2779,9 +2777,6 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) if (options.exists("lockUnspents")) lockUnspents = options["lockUnspents"].get_bool(); - if (options.exists("reserveChangeKey")) - reserveChangeKey = options["reserveChangeKey"].get_bool(); - if (options.exists("feeRate")) { coinControl.m_feerate = CFeeRate(AmountFromValue(options["feeRate"])); @@ -2830,7 +2825,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) CAmount nFeeOut; std::string strFailReason; - if (!pwallet->FundTransaction(tx, nFeeOut, changePosition, strFailReason, lockUnspents, setSubtractFeeFromOutputs, coinControl, reserveChangeKey)) { + if (!pwallet->FundTransaction(tx, nFeeOut, changePosition, strFailReason, lockUnspents, setSubtractFeeFromOutputs, coinControl)) { throw JSONRPCError(RPC_WALLET_ERROR, strFailReason); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 53175025890..c56fd05d7ed 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2471,7 +2471,7 @@ bool CWallet::SignTransaction(CMutableTransaction &tx) return true; } -bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set& setSubtractFeeFromOutputs, CCoinControl coinControl, bool keepReserveKey) +bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set& setSubtractFeeFromOutputs, CCoinControl coinControl) { std::vector vecSend; @@ -2493,8 +2493,13 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, coinControl, false)) { return false; } - if (nChangePosInOut != -1) + + if (nChangePosInOut != -1) { tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.tx->vout[nChangePosInOut]); + // we dont have the normal Create/Commit cycle, and dont want to risk reusing change, + // so just remove the key from the keypool here. + reservekey.KeepKey(); + } // Copy output sizes from new transaction; they may have had the fee subtracted from them for (unsigned int idx = 0; idx < tx.vout.size(); idx++) @@ -2515,9 +2520,6 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC } } - // optionally keep the change output key - if (keepReserveKey) - reservekey.KeepKey(); return true; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 574fd8710d3..bf09b040f6d 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -949,7 +949,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Insert additional inputs into the transaction by * calling CreateTransaction(); */ - bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set& setSubtractFeeFromOutputs, CCoinControl, bool keepReserveKey = true); + bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set& setSubtractFeeFromOutputs, CCoinControl); bool SignTransaction(CMutableTransaction& tx); /** diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index 0baab6d01cf..e52e773918b 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -636,20 +636,9 @@ def run_test(self): assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate) assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) - ############################# - # Test address reuse option # - ############################# - - result3 = self.nodes[3].fundrawtransaction(rawtx, {"reserveChangeKey": False}) - res_dec = self.nodes[0].decoderawtransaction(result3["hex"]) - changeaddress = "" - for out in res_dec['vout']: - if out['value'] > 1.0: - changeaddress += out['scriptPubKey']['addresses'][0] - assert(changeaddress != "") - nextaddr = self.nodes[3].getrawchangeaddress() - # frt should not have removed the key from the keypool - assert(changeaddress == nextaddr) + ################################ + # Test no address reuse occurs # + ################################ result3 = self.nodes[3].fundrawtransaction(rawtx) res_dec = self.nodes[0].decoderawtransaction(result3["hex"]) From 6b4f231f5f0f88690488c4da20ea1c180dbc4b19 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Fri, 9 Jun 2017 22:38:06 -0700 Subject: [PATCH 116/148] Move transaction combining from signrawtransaction to new RPC Create a combinerawtransaction RPC which accepts a json array of hex raw transactions to combine them into one transaction. Signrawtransaction is changed to no longer combine transactions and only accept one transaction at a time. --- src/rpc/client.cpp | 1 + src/rpc/rawtransaction.cpp | 135 ++++++++++++++++++++++++--------- test/functional/rawtransactions.py | 57 +++++++++++++- test/functional/signrawtransactions.py | 16 ---- 4 files changed, 154 insertions(+), 55 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 775ad4b6c9a..d82e85f825d 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -95,6 +95,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "signrawtransaction", 1, "prevtxs" }, { "signrawtransaction", 2, "privkeys" }, { "sendrawtransaction", 1, "allowhighfees" }, + { "combinerawtransaction", 0, "txs" }, { "fundrawtransaction", 1, "options" }, { "gettxout", 1, "n" }, { "gettxout", 2, "include_mempool" }, diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index b878624df87..10886fea9fe 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -554,6 +554,93 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std:: vErrorsRet.push_back(entry); } +UniValue combinerawtransaction(const JSONRPCRequest& request) +{ + + if (request.fHelp || request.params.size() != 1) + throw std::runtime_error( + "combinerawtransaction [\"hexstring\",...]\n" + "\nCombine multiple partially signed transactions into one transaction.\n" + "The combined transaction may be another partially signed transaction or a \n" + "fully signed transaction." + + "\nArguments:\n" + "1. \"txs\" (string) A json array of hex strings of partially signed transactions\n" + " [\n" + " \"hexstring\" (string) A transaction hash\n" + " ,...\n" + " ]\n" + + "\nResult:\n" + "\"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n" + + "\nExamples:\n" + + HelpExampleCli("combinerawtransaction", "[\"myhex1\", \"myhex2\", \"myhex3\"]") + ); + + + UniValue txs = request.params[0].get_array(); + std::vector txVariants(txs.size()); + + for (unsigned int idx = 0; idx < txs.size(); idx++) { + if (!DecodeHexTx(txVariants[idx], txs[idx].get_str(), true)) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed for tx %d", idx)); + } + } + + if (txVariants.empty()) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transactions"); + } + + // mergedTx will end up with all the signatures; it + // starts as a clone of the rawtx: + CMutableTransaction mergedTx(txVariants[0]); + + // Fetch previous transactions (inputs): + CCoinsView viewDummy; + CCoinsViewCache view(&viewDummy); + { + LOCK(cs_main); + LOCK(mempool.cs); + CCoinsViewCache &viewChain = *pcoinsTip; + CCoinsViewMemPool viewMempool(&viewChain, mempool); + view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view + + for (const CTxIn& txin : mergedTx.vin) { + view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail. + } + + view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long + } + + // Use CTransaction for the constant parts of the + // transaction to avoid rehashing. + const CTransaction txConst(mergedTx); + // Sign what we can: + for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { + CTxIn& txin = mergedTx.vin[i]; + const Coin& coin = view.AccessCoin(txin.prevout); + if (coin.IsSpent()) { + throw JSONRPCError(RPC_VERIFY_ERROR, "Input not found or already spent"); + } + const CScript& prevPubKey = coin.out.scriptPubKey; + const CAmount& amount = coin.out.nValue; + + SignatureData sigdata; + + // ... and merge in other signatures: + for (const CMutableTransaction& txv : txVariants) { + if (txv.vin.size() > i) { + sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i)); + } + } + + UpdateTransaction(mergedTx, i, sigdata); + } + + return EncodeHexTx(mergedTx); +} + UniValue signrawtransaction(const JSONRPCRequest& request) { #ifdef ENABLE_WALLET @@ -626,26 +713,9 @@ UniValue signrawtransaction(const JSONRPCRequest& request) #endif RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true); - std::vector txData(ParseHexV(request.params[0], "argument 1")); - CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); - std::vector txVariants; - while (!ssData.empty()) { - try { - CMutableTransaction tx; - ssData >> tx; - txVariants.push_back(tx); - } - catch (const std::exception&) { - throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); - } - } - - if (txVariants.empty()) - throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction"); - - // mergedTx will end up with all the signatures; it - // starts as a clone of the rawtx: - CMutableTransaction mergedTx(txVariants[0]); + CMutableTransaction mtx; + if (!DecodeHexTx(mtx, request.params[0].get_str(), true)) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); // Fetch previous transactions (inputs): CCoinsView viewDummy; @@ -656,7 +726,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) CCoinsViewMemPool viewMempool(&viewChain, mempool); view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view - for (const CTxIn& txin : mergedTx.vin) { + for (const CTxIn& txin : mtx.vin) { view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail. } @@ -781,10 +851,10 @@ UniValue signrawtransaction(const JSONRPCRequest& request) // Use CTransaction for the constant parts of the // transaction to avoid rehashing. - const CTransaction txConst(mergedTx); + const CTransaction txConst(mtx); // Sign what we can: - for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { - CTxIn& txin = mergedTx.vin[i]; + for (unsigned int i = 0; i < mtx.vin.size(); i++) { + CTxIn& txin = mtx.vin[i]; const Coin& coin = view.AccessCoin(txin.prevout); if (coin.IsSpent()) { TxInErrorToJSON(txin, vErrors, "Input not found or already spent"); @@ -795,17 +865,11 @@ UniValue signrawtransaction(const JSONRPCRequest& request) SignatureData sigdata; // Only sign SIGHASH_SINGLE if there's a corresponding output: - if (!fHashSingle || (i < mergedTx.vout.size())) - ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata); + if (!fHashSingle || (i < mtx.vout.size())) + ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mtx, i, amount, nHashType), prevPubKey, sigdata); + sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(mtx, i)); - // ... and merge in other signatures: - for (const CMutableTransaction& txv : txVariants) { - if (txv.vin.size() > i) { - sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i)); - } - } - - UpdateTransaction(mergedTx, i, sigdata); + UpdateTransaction(mtx, i, sigdata); ScriptError serror = SCRIPT_ERR_OK; if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) { @@ -815,7 +879,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) bool fComplete = vErrors.empty(); UniValue result(UniValue::VOBJ); - result.push_back(Pair("hex", EncodeHexTx(mergedTx))); + result.push_back(Pair("hex", EncodeHexTx(mtx))); result.push_back(Pair("complete", fComplete)); if (!vErrors.empty()) { result.push_back(Pair("errors", vErrors)); @@ -905,6 +969,7 @@ static const CRPCCommand commands[] = { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, {"hexstring"} }, { "rawtransactions", "decodescript", &decodescript, true, {"hexstring"} }, { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, {"hexstring","allowhighfees"} }, + { "rawtransactions", "combinerawtransaction", &combinerawtransaction, true, {"txs"} }, { "rawtransactions", "signrawtransaction", &signrawtransaction, false, {"hexstring","prevtxs","privkeys","sighashtype"} }, /* uses wallet if enabled */ { "blockchain", "gettxoutproof", &gettxoutproof, true, {"txids", "blockhash"} }, diff --git a/test/functional/rawtransactions.py b/test/functional/rawtransactions.py index 35debf9cab5..6272fc69b78 100755 --- a/test/functional/rawtransactions.py +++ b/test/functional/rawtransactions.py @@ -114,7 +114,7 @@ def run_test(self): rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned = self.nodes[1].signrawtransaction(rawTx, inputs) assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx - + rawTxSigned = self.nodes[2].signrawtransaction(rawTx, inputs) assert_equal(rawTxSigned['complete'], True) #node2 can sign the tx compl., own two of three keys self.nodes[2].sendrawtransaction(rawTxSigned['hex']) @@ -124,6 +124,55 @@ def run_test(self): self.sync_all() assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx + # 2of2 test for combining transactions + bal = self.nodes[2].getbalance() + addr1 = self.nodes[1].getnewaddress() + addr2 = self.nodes[2].getnewaddress() + + addr1Obj = self.nodes[1].validateaddress(addr1) + addr2Obj = self.nodes[2].validateaddress(addr2) + + self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) + mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) + mSigObjValid = self.nodes[2].validateaddress(mSigObj) + + txId = self.nodes[0].sendtoaddress(mSigObj, 2.2) + decTx = self.nodes[0].gettransaction(txId) + rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex']) + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + assert_equal(self.nodes[2].getbalance(), bal) # the funds of a 2of2 multisig tx should not be marked as spendable + + txDetails = self.nodes[0].gettransaction(txId, True) + rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex']) + vout = False + for outpoint in rawTx2['vout']: + if outpoint['value'] == Decimal('2.20000000'): + vout = outpoint + break + + bal = self.nodes[0].getbalance() + inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex']}] + outputs = { self.nodes[0].getnewaddress() : 2.19 } + rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs) + rawTxPartialSigned1 = self.nodes[1].signrawtransaction(rawTx2, inputs) + self.log.info(rawTxPartialSigned1) + assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx + + rawTxPartialSigned2 = self.nodes[2].signrawtransaction(rawTx2, inputs) + self.log.info(rawTxPartialSigned2) + assert_equal(rawTxPartialSigned2['complete'], False) #node2 only has one key, can't comp. sign the tx + rawTxComb = self.nodes[2].combinerawtransaction([rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']]) + self.log.info(rawTxComb) + self.nodes[2].sendrawtransaction(rawTxComb) + rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb) + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx + # getrawtransaction tests # 1. valid parameters - only supply txid txHash = rawTx["hash"] @@ -156,17 +205,17 @@ def run_test(self): rawtx = self.nodes[0].createrawtransaction(inputs, outputs) decrawtx= self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['vin'][0]['sequence'], 1000) - + # 9. invalid parameters - sequence number out of range inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : -1}] outputs = { self.nodes[0].getnewaddress() : 1 } assert_raises_jsonrpc(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs) - + # 10. invalid parameters - sequence number out of range inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967296}] outputs = { self.nodes[0].getnewaddress() : 1 } assert_raises_jsonrpc(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs) - + inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967294}] outputs = { self.nodes[0].getnewaddress() : 1 } rawtx = self.nodes[0].createrawtransaction(inputs, outputs) diff --git a/test/functional/signrawtransactions.py b/test/functional/signrawtransactions.py index 437905e764f..415727268a3 100755 --- a/test/functional/signrawtransactions.py +++ b/test/functional/signrawtransactions.py @@ -43,22 +43,6 @@ def successful_signing_test(self): # 2) No script verification error occurred assert 'errors' not in rawTxSigned - # Check that signrawtransaction doesn't blow up on garbage merge attempts - dummyTxInconsistent = self.nodes[0].createrawtransaction([inputs[0]], outputs) - rawTxUnsigned = self.nodes[0].signrawtransaction(rawTx + dummyTxInconsistent, inputs) - - assert 'complete' in rawTxUnsigned - assert_equal(rawTxUnsigned['complete'], False) - - # Check that signrawtransaction properly merges unsigned and signed txn, even with garbage in the middle - rawTxSigned2 = self.nodes[0].signrawtransaction(rawTxUnsigned["hex"] + dummyTxInconsistent + rawTxSigned["hex"], inputs) - - assert 'complete' in rawTxSigned2 - assert_equal(rawTxSigned2['complete'], True) - - assert 'errors' not in rawTxSigned2 - - def script_verification_error_test(self): """Create and sign a raw transaction with valid (vin 0), invalid (vin 1) and one missing (vin 2) input script. From 1c9b8187567b915adc1050ffb1b64ecac93c4ad3 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Mon, 17 Jul 2017 15:31:29 -0700 Subject: [PATCH 117/148] getinfo deprecation warning --- src/rpc/misc.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index fcbbe1ceed0..8a0d45f30fe 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -50,6 +50,7 @@ UniValue getinfo(const JSONRPCRequest& request) "\nDEPRECATED. Returns an object containing various state info.\n" "\nResult:\n" "{\n" + " \"deprecation-warning\": \"...\" (string) warning that the getinfo command is deprecated and will be removed in 0.16\n" " \"version\": xxxxx, (numeric) the server version\n" " \"protocolversion\": xxxxx, (numeric) the protocol version\n" " \"walletversion\": xxxxx, (numeric) the wallet version\n" @@ -57,7 +58,7 @@ UniValue getinfo(const JSONRPCRequest& request) " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" " \"timeoffset\": xxxxx, (numeric) the time offset\n" " \"connections\": xxxxx, (numeric) the number of connections\n" - " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n" + " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n" " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" " \"testnet\": true|false, (boolean) if the server is using testnet or not\n" " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n" @@ -65,7 +66,7 @@ UniValue getinfo(const JSONRPCRequest& request) " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n" " \"relayfee\": x.xxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n" - " \"errors\": \"...\" (string) any error messages\n" + " \"errors\": \"...\" (string) any error messages\n" "}\n" "\nExamples:\n" + HelpExampleCli("getinfo", "") @@ -84,6 +85,8 @@ UniValue getinfo(const JSONRPCRequest& request) GetProxy(NET_IPV4, proxy); UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("deprecation-warning", "WARNING: getinfo is deprecated and will be fully removed in 0.16." + " Projects should transition to using getblockchaininfo, getnetworkinfo, and getwalletinfo before upgrading to 0.16")); obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("protocolversion", PROTOCOL_VERSION)); #ifdef ENABLE_WALLET From 2264236da05fadd9d7d3c103882df8ebecc01b6b Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Wed, 19 Jul 2017 15:44:20 -0400 Subject: [PATCH 118/148] Rename -usewallet to -rpcwallet --- src/bitcoin-cli.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index c2bc15584f0..445b9d8e89a 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -46,7 +46,7 @@ std::string HelpMessageCli() strUsage += HelpMessageOpt("-rpcpassword=", _("Password for JSON-RPC connections")); strUsage += HelpMessageOpt("-rpcclienttimeout=", strprintf(_("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT)); strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)")); - strUsage += HelpMessageOpt("-usewallet=", _("Send RPC for non-default wallet on RPC server (argument is wallet filename in bitcoind directory, required if bitcoind/-Qt runs with multiple wallets)")); + strUsage += HelpMessageOpt("-rpcwallet=", _("Send RPC for non-default wallet on RPC server (argument is wallet filename in bitcoind directory, required if bitcoind/-Qt runs with multiple wallets)")); return strUsage; } @@ -244,7 +244,7 @@ UniValue CallRPC(const std::string& strMethod, const UniValue& params) // check if we should use a special wallet endpoint std::string endpoint = "/"; - std::string walletName = GetArg("-usewallet", ""); + std::string walletName = GetArg("-rpcwallet", ""); if (!walletName.empty()) { char *encodedURI = evhttp_uriencode(walletName.c_str(), walletName.size(), false); if (encodedURI) { From a5ecaf1490be8d01ac6806785157230d30f77061 Mon Sep 17 00:00:00 2001 From: "Steven D. Lander" Date: Wed, 19 Jul 2017 16:50:26 -0400 Subject: [PATCH 119/148] Fix misspellings and remove safety verbiage --- src/wallet/rpcwallet.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 867ccd42444..7c0c91dc5c2 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -587,7 +587,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request) + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") + "\nThe amount including unconfirmed transactions, zero confirmations\n" + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 0") + - "\nThe amount with at least 6 confirmation, very safe\n" + "\nThe amount with at least 6 confirmations\n" + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 6") + "\nAs a json rpc call\n" + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6") @@ -647,7 +647,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request) + HelpExampleCli("getreceivedbyaccount", "\"\"") + "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n" + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") + - "\nThe amount with at least 6 confirmation, very safe\n" + "\nThe amount with at least 6 confirmations\n" + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") + "\nAs a json rpc call\n" + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6") @@ -719,7 +719,7 @@ UniValue getbalance(const JSONRPCRequest& request) "\nExamples:\n" "\nThe total amount in the wallet\n" + HelpExampleCli("getbalance", "") + - "\nThe total amount in the wallet at least 5 blocks confirmed\n" + "\nThe total amount in the wallet at least 6 blocks confirmed\n" + HelpExampleCli("getbalance", "\"*\" 6") + "\nAs a json rpc call\n" + HelpExampleRpc("getbalance", "\"*\", 6") @@ -2008,7 +2008,7 @@ UniValue walletpassphrase(const JSONRPCRequest& request) "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n" "time that overrides the old one.\n" "\nExamples:\n" - "\nunlock the wallet for 60 seconds\n" + "\nUnlock the wallet for 60 seconds\n" + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") + "\nLock the wallet again (before 60 seconds)\n" + HelpExampleCli("walletlock", "") + @@ -2163,11 +2163,11 @@ UniValue encryptwallet(const JSONRPCRequest& request) "\nArguments:\n" "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n" "\nExamples:\n" - "\nEncrypt you wallet\n" + "\nEncrypt your wallet\n" + HelpExampleCli("encryptwallet", "\"my pass phrase\"") + "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n" + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") + - "\nNow we can so something like sign\n" + "\nNow we can do something like sign\n" + HelpExampleCli("signmessage", "\"address\" \"test message\"") + "\nNow lock the wallet again by removing the passphrase\n" + HelpExampleCli("walletlock", "") + From 4d50f38fe05374342b4b55953d188fd50d422663 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 13 Jul 2017 17:10:26 -0700 Subject: [PATCH 120/148] Support multi-block SHA256 transforms Extracted from a patch by Wladimir van der Laan. --- src/crypto/sha256.cpp | 177 +++++++++++++++++++++++++------------------------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 5b9f00a0a2d..45ee93d4719 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -43,88 +43,91 @@ void inline Initialize(uint32_t* s) s[7] = 0x5be0cd19ul; } -/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ -void Transform(uint32_t* s, const unsigned char* chunk) +/** Perform a number of SHA-256 transformations, processing 64-byte chunks. */ +void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) { - uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; - uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - - Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); - Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12)); - Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16)); - Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20)); - Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24)); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28)); - Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32)); - Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36)); - Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40)); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44)); - Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48)); - Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52)); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56)); - Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60)); - - Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); - - s[0] += a; - s[1] += b; - s[2] += c; - s[3] += d; - s[4] += e; - s[5] += f; - s[6] += g; - s[7] += h; + while (blocks--) { + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); + Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12)); + Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16)); + Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20)); + Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24)); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28)); + Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32)); + Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36)); + Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40)); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44)); + Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48)); + Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52)); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56)); + Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60)); + + Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; + chunk += 64; + } } } // namespace sha256 @@ -147,14 +150,14 @@ CSHA256& CSHA256::Write(const unsigned char* data, size_t len) memcpy(buf + bufsize, data, 64 - bufsize); bytes += 64 - bufsize; data += 64 - bufsize; - sha256::Transform(s, buf); + sha256::Transform(s, buf, 1); bufsize = 0; } - while (end >= data + 64) { - // Process full chunks directly from the source. - sha256::Transform(s, data); - bytes += 64; - data += 64; + if (end - data >= 64) { + size_t blocks = (end - data) / 64; + sha256::Transform(s, data, blocks); + data += 64 * blocks; + bytes += 64 * blocks; } if (end > data) { // Fill the buffer with what remains. From 2991c91d88f3d17ac6b38bddfa6f1b6b8d835c0f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 13 Jul 2017 23:26:04 -0700 Subject: [PATCH 121/148] Add SHA256 dispatcher --- src/bench/bench_bitcoin.cpp | 2 ++ src/crypto/sha256.cpp | 13 +++++++++++-- src/crypto/sha256.h | 6 ++++++ src/init.cpp | 2 ++ src/test/test_bitcoin.cpp | 2 ++ 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp index 226861aa7f7..37fd772435e 100644 --- a/src/bench/bench_bitcoin.cpp +++ b/src/bench/bench_bitcoin.cpp @@ -4,6 +4,7 @@ #include "bench.h" +#include "crypto/sha256.h" #include "key.h" #include "validation.h" #include "util.h" @@ -12,6 +13,7 @@ int main(int argc, char** argv) { + SHA256AutoDetect(); RandomInit(); ECC_Start(); SetupEnvironment(); diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 45ee93d4719..3649dc4be0d 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -8,6 +8,8 @@ #include +#include + // Internal implementation code. namespace { @@ -131,8 +133,15 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) } } // namespace sha256 + +void (*Transform)(uint32_t*, const unsigned char*, size_t) = sha256::Transform; + } // namespace +std::string SHA256AutoDetect() +{ + return "standard"; +} ////// SHA-256 @@ -150,12 +159,12 @@ CSHA256& CSHA256::Write(const unsigned char* data, size_t len) memcpy(buf + bufsize, data, 64 - bufsize); bytes += 64 - bufsize; data += 64 - bufsize; - sha256::Transform(s, buf, 1); + Transform(s, buf, 1); bufsize = 0; } if (end - data >= 64) { size_t blocks = (end - data) / 64; - sha256::Transform(s, data, blocks); + Transform(s, data, blocks); data += 64 * blocks; bytes += 64 * blocks; } diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index 127e62a228f..aa4f3972cc7 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -7,6 +7,7 @@ #include #include +#include /** A hasher class for SHA-256. */ class CSHA256 @@ -25,4 +26,9 @@ class CSHA256 CSHA256& Reset(); }; +/** Autodetect the best available SHA256 implementation. + * Returns the name of the implementation. + */ +std::string SHA256AutoDetect(); + #endif // BITCOIN_CRYPTO_SHA256_H diff --git a/src/init.cpp b/src/init.cpp index 1e85642019c..b16653624ca 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1161,6 +1161,8 @@ bool AppInitSanityChecks() // ********************************************************* Step 4: sanity checks // Initialize elliptic curve code + std::string sha256_algo = SHA256AutoDetect(); + LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo); RandomInit(); ECC_Start(); globalVerifyHandle.reset(new ECCVerifyHandle()); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 3ba81ed17b5..0dd51a4908f 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -7,6 +7,7 @@ #include "chainparams.h" #include "consensus/consensus.h" #include "consensus/validation.h" +#include "crypto/sha256.h" #include "fs.h" #include "key.h" #include "validation.h" @@ -33,6 +34,7 @@ extern void noui_connect(); BasicTestingSetup::BasicTestingSetup(const std::string& chainName) { + SHA256AutoDetect(); RandomInit(); ECC_Start(); SetupEnvironment(); From c1ccb15b0e847eb95623f9d25dc522aa02dbdbe8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 13 Jul 2017 23:33:11 -0700 Subject: [PATCH 122/148] Add SSE4 based SHA256 --- src/Makefile.am | 1 + src/crypto/sha256.cpp | 18 +- src/crypto/sha256_sse4.cpp | 1506 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1523 insertions(+), 2 deletions(-) create mode 100644 src/crypto/sha256_sse4.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 06b09404a76..35bfeb466c1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -263,6 +263,7 @@ crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha1.cpp \ crypto/sha1.h \ crypto/sha256.cpp \ + crypto/sha256_sse4.cpp \ crypto/sha256.h \ crypto/sha512.cpp \ crypto/sha512.h diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 3649dc4be0d..4ecf5090397 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -3,13 +3,19 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "crypto/sha256.h" - #include "crypto/common.h" #include - #include +#if defined(__x86_64__) || defined(__amd64__) +#include +namespace sha256_sse4 +{ +void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks); +} +#endif + // Internal implementation code. namespace { @@ -140,6 +146,14 @@ void (*Transform)(uint32_t*, const unsigned char*, size_t) = sha256::Transform; std::string SHA256AutoDetect() { +#if defined(__x86_64__) || defined(__amd64__) + uint32_t eax, ebx, ecx, edx; + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) { + Transform = sha256_sse4::Transform; + return "sse4"; + } +#endif + return "standard"; } diff --git a/src/crypto/sha256_sse4.cpp b/src/crypto/sha256_sse4.cpp new file mode 100644 index 00000000000..89f529a3abc --- /dev/null +++ b/src/crypto/sha256_sse4.cpp @@ -0,0 +1,1506 @@ +// Copyright (c) 2017 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 is a translation to GCC extended asm syntax from YASM code by Intel +// (available at the bottom of this file). + +#include +#include + +#if defined(__x86_64__) || defined(__amd64__) + +namespace sha256_sse4 +{ +void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) +{ + static const uint32_t K256 alignas(16) [] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, + }; + static const uint32_t FLIP_MASK alignas(16) [] = {0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f}; + static const uint32_t SHUF_00BA alignas(16) [] = {0x03020100, 0x0b0a0908, 0xffffffff, 0xffffffff}; + static const uint32_t SHUF_DC00 alignas(16) [] = {0xffffffff, 0xffffffff, 0x03020100, 0x0b0a0908}; + uint32_t a, b, c, d, f, g, h, y0, y1, y2; + uint64_t tbl; + uint64_t inp_end, inp; + uint32_t xfer alignas(16) [4]; + + __asm__ __volatile__( + "shl $0x6,%2;" + "je Ldone_hash_%=;" + "add %1,%2;" + "mov %2,%14;" + "mov (%0),%3;" + "mov 0x4(%0),%4;" + "mov 0x8(%0),%5;" + "mov 0xc(%0),%6;" + "mov 0x10(%0),%k2;" + "mov 0x14(%0),%7;" + "mov 0x18(%0),%8;" + "mov 0x1c(%0),%9;" + "movdqa %18,%%xmm12;" + "movdqa %19,%%xmm10;" + "movdqa %20,%%xmm11;" + + "Lloop0_%=:" + "lea %17,%13;" + "movdqu (%1),%%xmm4;" + "pshufb %%xmm12,%%xmm4;" + "movdqu 0x10(%1),%%xmm5;" + "pshufb %%xmm12,%%xmm5;" + "movdqu 0x20(%1),%%xmm6;" + "pshufb %%xmm12,%%xmm6;" + "movdqu 0x30(%1),%%xmm7;" + "pshufb %%xmm12,%%xmm7;" + "mov %1,%15;" + "mov $3,%1;" + + "Lloop1_%=:" + "movdqa 0x0(%13),%%xmm9;" + "paddd %%xmm4,%%xmm9;" + "movdqa %%xmm9,%16;" + "movdqa %%xmm7,%%xmm0;" + "mov %k2,%10;" + "ror $0xe,%10;" + "mov %3,%11;" + "palignr $0x4,%%xmm6,%%xmm0;" + "ror $0x9,%11;" + "xor %k2,%10;" + "mov %7,%12;" + "ror $0x5,%10;" + "movdqa %%xmm5,%%xmm1;" + "xor %3,%11;" + "xor %8,%12;" + "paddd %%xmm4,%%xmm0;" + "xor %k2,%10;" + "and %k2,%12;" + "ror $0xb,%11;" + "palignr $0x4,%%xmm4,%%xmm1;" + "xor %3,%11;" + "ror $0x6,%10;" + "xor %8,%12;" + "movdqa %%xmm1,%%xmm2;" + "ror $0x2,%11;" + "add %10,%12;" + "add %16,%12;" + "movdqa %%xmm1,%%xmm3;" + "mov %3,%10;" + "add %12,%9;" + "mov %3,%12;" + "pslld $0x19,%%xmm1;" + "or %5,%10;" + "add %9,%6;" + "and %5,%12;" + "psrld $0x7,%%xmm2;" + "and %4,%10;" + "add %11,%9;" + "por %%xmm2,%%xmm1;" + "or %12,%10;" + "add %10,%9;" + "movdqa %%xmm3,%%xmm2;" + "mov %6,%10;" + "mov %9,%11;" + "movdqa %%xmm3,%%xmm8;" + "ror $0xe,%10;" + "xor %6,%10;" + "mov %k2,%12;" + "ror $0x9,%11;" + "pslld $0xe,%%xmm3;" + "xor %9,%11;" + "ror $0x5,%10;" + "xor %7,%12;" + "psrld $0x12,%%xmm2;" + "ror $0xb,%11;" + "xor %6,%10;" + "and %6,%12;" + "ror $0x6,%10;" + "pxor %%xmm3,%%xmm1;" + "xor %9,%11;" + "xor %7,%12;" + "psrld $0x3,%%xmm8;" + "add %10,%12;" + "add 4+%16,%12;" + "ror $0x2,%11;" + "pxor %%xmm2,%%xmm1;" + "mov %9,%10;" + "add %12,%8;" + "mov %9,%12;" + "pxor %%xmm8,%%xmm1;" + "or %4,%10;" + "add %8,%5;" + "and %4,%12;" + "pshufd $0xfa,%%xmm7,%%xmm2;" + "and %3,%10;" + "add %11,%8;" + "paddd %%xmm1,%%xmm0;" + "or %12,%10;" + "add %10,%8;" + "movdqa %%xmm2,%%xmm3;" + "mov %5,%10;" + "mov %8,%11;" + "ror $0xe,%10;" + "movdqa %%xmm2,%%xmm8;" + "xor %5,%10;" + "ror $0x9,%11;" + "mov %6,%12;" + "xor %8,%11;" + "ror $0x5,%10;" + "psrlq $0x11,%%xmm2;" + "xor %k2,%12;" + "psrlq $0x13,%%xmm3;" + "xor %5,%10;" + "and %5,%12;" + "psrld $0xa,%%xmm8;" + "ror $0xb,%11;" + "xor %8,%11;" + "xor %k2,%12;" + "ror $0x6,%10;" + "pxor %%xmm3,%%xmm2;" + "add %10,%12;" + "ror $0x2,%11;" + "add 8+%16,%12;" + "pxor %%xmm2,%%xmm8;" + "mov %8,%10;" + "add %12,%7;" + "mov %8,%12;" + "pshufb %%xmm10,%%xmm8;" + "or %3,%10;" + "add %7,%4;" + "and %3,%12;" + "paddd %%xmm8,%%xmm0;" + "and %9,%10;" + "add %11,%7;" + "pshufd $0x50,%%xmm0,%%xmm2;" + "or %12,%10;" + "add %10,%7;" + "movdqa %%xmm2,%%xmm3;" + "mov %4,%10;" + "ror $0xe,%10;" + "mov %7,%11;" + "movdqa %%xmm2,%%xmm4;" + "ror $0x9,%11;" + "xor %4,%10;" + "mov %5,%12;" + "ror $0x5,%10;" + "psrlq $0x11,%%xmm2;" + "xor %7,%11;" + "xor %6,%12;" + "psrlq $0x13,%%xmm3;" + "xor %4,%10;" + "and %4,%12;" + "ror $0xb,%11;" + "psrld $0xa,%%xmm4;" + "xor %7,%11;" + "ror $0x6,%10;" + "xor %6,%12;" + "pxor %%xmm3,%%xmm2;" + "ror $0x2,%11;" + "add %10,%12;" + "add 12+%16,%12;" + "pxor %%xmm2,%%xmm4;" + "mov %7,%10;" + "add %12,%k2;" + "mov %7,%12;" + "pshufb %%xmm11,%%xmm4;" + "or %9,%10;" + "add %k2,%3;" + "and %9,%12;" + "paddd %%xmm0,%%xmm4;" + "and %8,%10;" + "add %11,%k2;" + "or %12,%10;" + "add %10,%k2;" + "movdqa 0x10(%13),%%xmm9;" + "paddd %%xmm5,%%xmm9;" + "movdqa %%xmm9,%16;" + "movdqa %%xmm4,%%xmm0;" + "mov %3,%10;" + "ror $0xe,%10;" + "mov %k2,%11;" + "palignr $0x4,%%xmm7,%%xmm0;" + "ror $0x9,%11;" + "xor %3,%10;" + "mov %4,%12;" + "ror $0x5,%10;" + "movdqa %%xmm6,%%xmm1;" + "xor %k2,%11;" + "xor %5,%12;" + "paddd %%xmm5,%%xmm0;" + "xor %3,%10;" + "and %3,%12;" + "ror $0xb,%11;" + "palignr $0x4,%%xmm5,%%xmm1;" + "xor %k2,%11;" + "ror $0x6,%10;" + "xor %5,%12;" + "movdqa %%xmm1,%%xmm2;" + "ror $0x2,%11;" + "add %10,%12;" + "add %16,%12;" + "movdqa %%xmm1,%%xmm3;" + "mov %k2,%10;" + "add %12,%6;" + "mov %k2,%12;" + "pslld $0x19,%%xmm1;" + "or %8,%10;" + "add %6,%9;" + "and %8,%12;" + "psrld $0x7,%%xmm2;" + "and %7,%10;" + "add %11,%6;" + "por %%xmm2,%%xmm1;" + "or %12,%10;" + "add %10,%6;" + "movdqa %%xmm3,%%xmm2;" + "mov %9,%10;" + "mov %6,%11;" + "movdqa %%xmm3,%%xmm8;" + "ror $0xe,%10;" + "xor %9,%10;" + "mov %3,%12;" + "ror $0x9,%11;" + "pslld $0xe,%%xmm3;" + "xor %6,%11;" + "ror $0x5,%10;" + "xor %4,%12;" + "psrld $0x12,%%xmm2;" + "ror $0xb,%11;" + "xor %9,%10;" + "and %9,%12;" + "ror $0x6,%10;" + "pxor %%xmm3,%%xmm1;" + "xor %6,%11;" + "xor %4,%12;" + "psrld $0x3,%%xmm8;" + "add %10,%12;" + "add 4+%16,%12;" + "ror $0x2,%11;" + "pxor %%xmm2,%%xmm1;" + "mov %6,%10;" + "add %12,%5;" + "mov %6,%12;" + "pxor %%xmm8,%%xmm1;" + "or %7,%10;" + "add %5,%8;" + "and %7,%12;" + "pshufd $0xfa,%%xmm4,%%xmm2;" + "and %k2,%10;" + "add %11,%5;" + "paddd %%xmm1,%%xmm0;" + "or %12,%10;" + "add %10,%5;" + "movdqa %%xmm2,%%xmm3;" + "mov %8,%10;" + "mov %5,%11;" + "ror $0xe,%10;" + "movdqa %%xmm2,%%xmm8;" + "xor %8,%10;" + "ror $0x9,%11;" + "mov %9,%12;" + "xor %5,%11;" + "ror $0x5,%10;" + "psrlq $0x11,%%xmm2;" + "xor %3,%12;" + "psrlq $0x13,%%xmm3;" + "xor %8,%10;" + "and %8,%12;" + "psrld $0xa,%%xmm8;" + "ror $0xb,%11;" + "xor %5,%11;" + "xor %3,%12;" + "ror $0x6,%10;" + "pxor %%xmm3,%%xmm2;" + "add %10,%12;" + "ror $0x2,%11;" + "add 8+%16,%12;" + "pxor %%xmm2,%%xmm8;" + "mov %5,%10;" + "add %12,%4;" + "mov %5,%12;" + "pshufb %%xmm10,%%xmm8;" + "or %k2,%10;" + "add %4,%7;" + "and %k2,%12;" + "paddd %%xmm8,%%xmm0;" + "and %6,%10;" + "add %11,%4;" + "pshufd $0x50,%%xmm0,%%xmm2;" + "or %12,%10;" + "add %10,%4;" + "movdqa %%xmm2,%%xmm3;" + "mov %7,%10;" + "ror $0xe,%10;" + "mov %4,%11;" + "movdqa %%xmm2,%%xmm5;" + "ror $0x9,%11;" + "xor %7,%10;" + "mov %8,%12;" + "ror $0x5,%10;" + "psrlq $0x11,%%xmm2;" + "xor %4,%11;" + "xor %9,%12;" + "psrlq $0x13,%%xmm3;" + "xor %7,%10;" + "and %7,%12;" + "ror $0xb,%11;" + "psrld $0xa,%%xmm5;" + "xor %4,%11;" + "ror $0x6,%10;" + "xor %9,%12;" + "pxor %%xmm3,%%xmm2;" + "ror $0x2,%11;" + "add %10,%12;" + "add 12+%16,%12;" + "pxor %%xmm2,%%xmm5;" + "mov %4,%10;" + "add %12,%3;" + "mov %4,%12;" + "pshufb %%xmm11,%%xmm5;" + "or %6,%10;" + "add %3,%k2;" + "and %6,%12;" + "paddd %%xmm0,%%xmm5;" + "and %5,%10;" + "add %11,%3;" + "or %12,%10;" + "add %10,%3;" + "movdqa 0x20(%13),%%xmm9;" + "paddd %%xmm6,%%xmm9;" + "movdqa %%xmm9,%16;" + "movdqa %%xmm5,%%xmm0;" + "mov %k2,%10;" + "ror $0xe,%10;" + "mov %3,%11;" + "palignr $0x4,%%xmm4,%%xmm0;" + "ror $0x9,%11;" + "xor %k2,%10;" + "mov %7,%12;" + "ror $0x5,%10;" + "movdqa %%xmm7,%%xmm1;" + "xor %3,%11;" + "xor %8,%12;" + "paddd %%xmm6,%%xmm0;" + "xor %k2,%10;" + "and %k2,%12;" + "ror $0xb,%11;" + "palignr $0x4,%%xmm6,%%xmm1;" + "xor %3,%11;" + "ror $0x6,%10;" + "xor %8,%12;" + "movdqa %%xmm1,%%xmm2;" + "ror $0x2,%11;" + "add %10,%12;" + "add %16,%12;" + "movdqa %%xmm1,%%xmm3;" + "mov %3,%10;" + "add %12,%9;" + "mov %3,%12;" + "pslld $0x19,%%xmm1;" + "or %5,%10;" + "add %9,%6;" + "and %5,%12;" + "psrld $0x7,%%xmm2;" + "and %4,%10;" + "add %11,%9;" + "por %%xmm2,%%xmm1;" + "or %12,%10;" + "add %10,%9;" + "movdqa %%xmm3,%%xmm2;" + "mov %6,%10;" + "mov %9,%11;" + "movdqa %%xmm3,%%xmm8;" + "ror $0xe,%10;" + "xor %6,%10;" + "mov %k2,%12;" + "ror $0x9,%11;" + "pslld $0xe,%%xmm3;" + "xor %9,%11;" + "ror $0x5,%10;" + "xor %7,%12;" + "psrld $0x12,%%xmm2;" + "ror $0xb,%11;" + "xor %6,%10;" + "and %6,%12;" + "ror $0x6,%10;" + "pxor %%xmm3,%%xmm1;" + "xor %9,%11;" + "xor %7,%12;" + "psrld $0x3,%%xmm8;" + "add %10,%12;" + "add 4+%16,%12;" + "ror $0x2,%11;" + "pxor %%xmm2,%%xmm1;" + "mov %9,%10;" + "add %12,%8;" + "mov %9,%12;" + "pxor %%xmm8,%%xmm1;" + "or %4,%10;" + "add %8,%5;" + "and %4,%12;" + "pshufd $0xfa,%%xmm5,%%xmm2;" + "and %3,%10;" + "add %11,%8;" + "paddd %%xmm1,%%xmm0;" + "or %12,%10;" + "add %10,%8;" + "movdqa %%xmm2,%%xmm3;" + "mov %5,%10;" + "mov %8,%11;" + "ror $0xe,%10;" + "movdqa %%xmm2,%%xmm8;" + "xor %5,%10;" + "ror $0x9,%11;" + "mov %6,%12;" + "xor %8,%11;" + "ror $0x5,%10;" + "psrlq $0x11,%%xmm2;" + "xor %k2,%12;" + "psrlq $0x13,%%xmm3;" + "xor %5,%10;" + "and %5,%12;" + "psrld $0xa,%%xmm8;" + "ror $0xb,%11;" + "xor %8,%11;" + "xor %k2,%12;" + "ror $0x6,%10;" + "pxor %%xmm3,%%xmm2;" + "add %10,%12;" + "ror $0x2,%11;" + "add 8+%16,%12;" + "pxor %%xmm2,%%xmm8;" + "mov %8,%10;" + "add %12,%7;" + "mov %8,%12;" + "pshufb %%xmm10,%%xmm8;" + "or %3,%10;" + "add %7,%4;" + "and %3,%12;" + "paddd %%xmm8,%%xmm0;" + "and %9,%10;" + "add %11,%7;" + "pshufd $0x50,%%xmm0,%%xmm2;" + "or %12,%10;" + "add %10,%7;" + "movdqa %%xmm2,%%xmm3;" + "mov %4,%10;" + "ror $0xe,%10;" + "mov %7,%11;" + "movdqa %%xmm2,%%xmm6;" + "ror $0x9,%11;" + "xor %4,%10;" + "mov %5,%12;" + "ror $0x5,%10;" + "psrlq $0x11,%%xmm2;" + "xor %7,%11;" + "xor %6,%12;" + "psrlq $0x13,%%xmm3;" + "xor %4,%10;" + "and %4,%12;" + "ror $0xb,%11;" + "psrld $0xa,%%xmm6;" + "xor %7,%11;" + "ror $0x6,%10;" + "xor %6,%12;" + "pxor %%xmm3,%%xmm2;" + "ror $0x2,%11;" + "add %10,%12;" + "add 12+%16,%12;" + "pxor %%xmm2,%%xmm6;" + "mov %7,%10;" + "add %12,%k2;" + "mov %7,%12;" + "pshufb %%xmm11,%%xmm6;" + "or %9,%10;" + "add %k2,%3;" + "and %9,%12;" + "paddd %%xmm0,%%xmm6;" + "and %8,%10;" + "add %11,%k2;" + "or %12,%10;" + "add %10,%k2;" + "movdqa 0x30(%13),%%xmm9;" + "paddd %%xmm7,%%xmm9;" + "movdqa %%xmm9,%16;" + "add $0x40,%13;" + "movdqa %%xmm6,%%xmm0;" + "mov %3,%10;" + "ror $0xe,%10;" + "mov %k2,%11;" + "palignr $0x4,%%xmm5,%%xmm0;" + "ror $0x9,%11;" + "xor %3,%10;" + "mov %4,%12;" + "ror $0x5,%10;" + "movdqa %%xmm4,%%xmm1;" + "xor %k2,%11;" + "xor %5,%12;" + "paddd %%xmm7,%%xmm0;" + "xor %3,%10;" + "and %3,%12;" + "ror $0xb,%11;" + "palignr $0x4,%%xmm7,%%xmm1;" + "xor %k2,%11;" + "ror $0x6,%10;" + "xor %5,%12;" + "movdqa %%xmm1,%%xmm2;" + "ror $0x2,%11;" + "add %10,%12;" + "add %16,%12;" + "movdqa %%xmm1,%%xmm3;" + "mov %k2,%10;" + "add %12,%6;" + "mov %k2,%12;" + "pslld $0x19,%%xmm1;" + "or %8,%10;" + "add %6,%9;" + "and %8,%12;" + "psrld $0x7,%%xmm2;" + "and %7,%10;" + "add %11,%6;" + "por %%xmm2,%%xmm1;" + "or %12,%10;" + "add %10,%6;" + "movdqa %%xmm3,%%xmm2;" + "mov %9,%10;" + "mov %6,%11;" + "movdqa %%xmm3,%%xmm8;" + "ror $0xe,%10;" + "xor %9,%10;" + "mov %3,%12;" + "ror $0x9,%11;" + "pslld $0xe,%%xmm3;" + "xor %6,%11;" + "ror $0x5,%10;" + "xor %4,%12;" + "psrld $0x12,%%xmm2;" + "ror $0xb,%11;" + "xor %9,%10;" + "and %9,%12;" + "ror $0x6,%10;" + "pxor %%xmm3,%%xmm1;" + "xor %6,%11;" + "xor %4,%12;" + "psrld $0x3,%%xmm8;" + "add %10,%12;" + "add 4+%16,%12;" + "ror $0x2,%11;" + "pxor %%xmm2,%%xmm1;" + "mov %6,%10;" + "add %12,%5;" + "mov %6,%12;" + "pxor %%xmm8,%%xmm1;" + "or %7,%10;" + "add %5,%8;" + "and %7,%12;" + "pshufd $0xfa,%%xmm6,%%xmm2;" + "and %k2,%10;" + "add %11,%5;" + "paddd %%xmm1,%%xmm0;" + "or %12,%10;" + "add %10,%5;" + "movdqa %%xmm2,%%xmm3;" + "mov %8,%10;" + "mov %5,%11;" + "ror $0xe,%10;" + "movdqa %%xmm2,%%xmm8;" + "xor %8,%10;" + "ror $0x9,%11;" + "mov %9,%12;" + "xor %5,%11;" + "ror $0x5,%10;" + "psrlq $0x11,%%xmm2;" + "xor %3,%12;" + "psrlq $0x13,%%xmm3;" + "xor %8,%10;" + "and %8,%12;" + "psrld $0xa,%%xmm8;" + "ror $0xb,%11;" + "xor %5,%11;" + "xor %3,%12;" + "ror $0x6,%10;" + "pxor %%xmm3,%%xmm2;" + "add %10,%12;" + "ror $0x2,%11;" + "add 8+%16,%12;" + "pxor %%xmm2,%%xmm8;" + "mov %5,%10;" + "add %12,%4;" + "mov %5,%12;" + "pshufb %%xmm10,%%xmm8;" + "or %k2,%10;" + "add %4,%7;" + "and %k2,%12;" + "paddd %%xmm8,%%xmm0;" + "and %6,%10;" + "add %11,%4;" + "pshufd $0x50,%%xmm0,%%xmm2;" + "or %12,%10;" + "add %10,%4;" + "movdqa %%xmm2,%%xmm3;" + "mov %7,%10;" + "ror $0xe,%10;" + "mov %4,%11;" + "movdqa %%xmm2,%%xmm7;" + "ror $0x9,%11;" + "xor %7,%10;" + "mov %8,%12;" + "ror $0x5,%10;" + "psrlq $0x11,%%xmm2;" + "xor %4,%11;" + "xor %9,%12;" + "psrlq $0x13,%%xmm3;" + "xor %7,%10;" + "and %7,%12;" + "ror $0xb,%11;" + "psrld $0xa,%%xmm7;" + "xor %4,%11;" + "ror $0x6,%10;" + "xor %9,%12;" + "pxor %%xmm3,%%xmm2;" + "ror $0x2,%11;" + "add %10,%12;" + "add 12+%16,%12;" + "pxor %%xmm2,%%xmm7;" + "mov %4,%10;" + "add %12,%3;" + "mov %4,%12;" + "pshufb %%xmm11,%%xmm7;" + "or %6,%10;" + "add %3,%k2;" + "and %6,%12;" + "paddd %%xmm0,%%xmm7;" + "and %5,%10;" + "add %11,%3;" + "or %12,%10;" + "add %10,%3;" + "sub $0x1,%1;" + "jne Lloop1_%=;" + "mov $0x2,%1;" + + "Lloop2_%=:" + "paddd 0x0(%13),%%xmm4;" + "movdqa %%xmm4,%16;" + "mov %k2,%10;" + "ror $0xe,%10;" + "mov %3,%11;" + "xor %k2,%10;" + "ror $0x9,%11;" + "mov %7,%12;" + "xor %3,%11;" + "ror $0x5,%10;" + "xor %8,%12;" + "xor %k2,%10;" + "ror $0xb,%11;" + "and %k2,%12;" + "xor %3,%11;" + "ror $0x6,%10;" + "xor %8,%12;" + "add %10,%12;" + "ror $0x2,%11;" + "add %16,%12;" + "mov %3,%10;" + "add %12,%9;" + "mov %3,%12;" + "or %5,%10;" + "add %9,%6;" + "and %5,%12;" + "and %4,%10;" + "add %11,%9;" + "or %12,%10;" + "add %10,%9;" + "mov %6,%10;" + "ror $0xe,%10;" + "mov %9,%11;" + "xor %6,%10;" + "ror $0x9,%11;" + "mov %k2,%12;" + "xor %9,%11;" + "ror $0x5,%10;" + "xor %7,%12;" + "xor %6,%10;" + "ror $0xb,%11;" + "and %6,%12;" + "xor %9,%11;" + "ror $0x6,%10;" + "xor %7,%12;" + "add %10,%12;" + "ror $0x2,%11;" + "add 4+%16,%12;" + "mov %9,%10;" + "add %12,%8;" + "mov %9,%12;" + "or %4,%10;" + "add %8,%5;" + "and %4,%12;" + "and %3,%10;" + "add %11,%8;" + "or %12,%10;" + "add %10,%8;" + "mov %5,%10;" + "ror $0xe,%10;" + "mov %8,%11;" + "xor %5,%10;" + "ror $0x9,%11;" + "mov %6,%12;" + "xor %8,%11;" + "ror $0x5,%10;" + "xor %k2,%12;" + "xor %5,%10;" + "ror $0xb,%11;" + "and %5,%12;" + "xor %8,%11;" + "ror $0x6,%10;" + "xor %k2,%12;" + "add %10,%12;" + "ror $0x2,%11;" + "add 8+%16,%12;" + "mov %8,%10;" + "add %12,%7;" + "mov %8,%12;" + "or %3,%10;" + "add %7,%4;" + "and %3,%12;" + "and %9,%10;" + "add %11,%7;" + "or %12,%10;" + "add %10,%7;" + "mov %4,%10;" + "ror $0xe,%10;" + "mov %7,%11;" + "xor %4,%10;" + "ror $0x9,%11;" + "mov %5,%12;" + "xor %7,%11;" + "ror $0x5,%10;" + "xor %6,%12;" + "xor %4,%10;" + "ror $0xb,%11;" + "and %4,%12;" + "xor %7,%11;" + "ror $0x6,%10;" + "xor %6,%12;" + "add %10,%12;" + "ror $0x2,%11;" + "add 12+%16,%12;" + "mov %7,%10;" + "add %12,%k2;" + "mov %7,%12;" + "or %9,%10;" + "add %k2,%3;" + "and %9,%12;" + "and %8,%10;" + "add %11,%k2;" + "or %12,%10;" + "add %10,%k2;" + "paddd 0x10(%13),%%xmm5;" + "movdqa %%xmm5,%16;" + "add $0x20,%13;" + "mov %3,%10;" + "ror $0xe,%10;" + "mov %k2,%11;" + "xor %3,%10;" + "ror $0x9,%11;" + "mov %4,%12;" + "xor %k2,%11;" + "ror $0x5,%10;" + "xor %5,%12;" + "xor %3,%10;" + "ror $0xb,%11;" + "and %3,%12;" + "xor %k2,%11;" + "ror $0x6,%10;" + "xor %5,%12;" + "add %10,%12;" + "ror $0x2,%11;" + "add %16,%12;" + "mov %k2,%10;" + "add %12,%6;" + "mov %k2,%12;" + "or %8,%10;" + "add %6,%9;" + "and %8,%12;" + "and %7,%10;" + "add %11,%6;" + "or %12,%10;" + "add %10,%6;" + "mov %9,%10;" + "ror $0xe,%10;" + "mov %6,%11;" + "xor %9,%10;" + "ror $0x9,%11;" + "mov %3,%12;" + "xor %6,%11;" + "ror $0x5,%10;" + "xor %4,%12;" + "xor %9,%10;" + "ror $0xb,%11;" + "and %9,%12;" + "xor %6,%11;" + "ror $0x6,%10;" + "xor %4,%12;" + "add %10,%12;" + "ror $0x2,%11;" + "add 4+%16,%12;" + "mov %6,%10;" + "add %12,%5;" + "mov %6,%12;" + "or %7,%10;" + "add %5,%8;" + "and %7,%12;" + "and %k2,%10;" + "add %11,%5;" + "or %12,%10;" + "add %10,%5;" + "mov %8,%10;" + "ror $0xe,%10;" + "mov %5,%11;" + "xor %8,%10;" + "ror $0x9,%11;" + "mov %9,%12;" + "xor %5,%11;" + "ror $0x5,%10;" + "xor %3,%12;" + "xor %8,%10;" + "ror $0xb,%11;" + "and %8,%12;" + "xor %5,%11;" + "ror $0x6,%10;" + "xor %3,%12;" + "add %10,%12;" + "ror $0x2,%11;" + "add 8+%16,%12;" + "mov %5,%10;" + "add %12,%4;" + "mov %5,%12;" + "or %k2,%10;" + "add %4,%7;" + "and %k2,%12;" + "and %6,%10;" + "add %11,%4;" + "or %12,%10;" + "add %10,%4;" + "mov %7,%10;" + "ror $0xe,%10;" + "mov %4,%11;" + "xor %7,%10;" + "ror $0x9,%11;" + "mov %8,%12;" + "xor %4,%11;" + "ror $0x5,%10;" + "xor %9,%12;" + "xor %7,%10;" + "ror $0xb,%11;" + "and %7,%12;" + "xor %4,%11;" + "ror $0x6,%10;" + "xor %9,%12;" + "add %10,%12;" + "ror $0x2,%11;" + "add 12+%16,%12;" + "mov %4,%10;" + "add %12,%3;" + "mov %4,%12;" + "or %6,%10;" + "add %3,%k2;" + "and %6,%12;" + "and %5,%10;" + "add %11,%3;" + "or %12,%10;" + "add %10,%3;" + "movdqa %%xmm6,%%xmm4;" + "movdqa %%xmm7,%%xmm5;" + "sub $0x1,%1;" + "jne Lloop2_%=;" + "add (%0),%3;" + "mov %3,(%0);" + "add 0x4(%0),%4;" + "mov %4,0x4(%0);" + "add 0x8(%0),%5;" + "mov %5,0x8(%0);" + "add 0xc(%0),%6;" + "mov %6,0xc(%0);" + "add 0x10(%0),%k2;" + "mov %k2,0x10(%0);" + "add 0x14(%0),%7;" + "mov %7,0x14(%0);" + "add 0x18(%0),%8;" + "mov %8,0x18(%0);" + "add 0x1c(%0),%9;" + "mov %9,0x1c(%0);" + "mov %15,%1;" + "add $0x40,%1;" + "cmp %14,%1;" + "jne Lloop0_%=;" + + "Ldone_hash_%=:" + + : "+r"(s), "+r"(chunk), "+r"(blocks), "=r"(a), "=r"(b), "=r"(c), "=r"(d), /* e = chunk */ "=r"(f), "=r"(g), "=r"(h), "=r"(y0), "=r"(y1), "=r"(y2), "=r"(tbl), "+m"(inp_end), "+m"(inp), "+m"(xfer) + : "m"(K256), "m"(FLIP_MASK), "m"(SHUF_00BA), "m"(SHUF_DC00) + : "cc", "memory", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12" + ); +} +} + +/* +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright (c) 2012, Intel Corporation +; +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are +; met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the +; distribution. +; +; * Neither the name of the Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived from +; this software without specific prior written permission. +; +; +; THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY +; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR +; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Example YASM command lines: +; Windows: yasm -Xvc -f x64 -rnasm -pnasm -o sha256_sse4.obj -g cv8 sha256_sse4.asm +; Linux: yasm -f x64 -f elf64 -X gnu -g dwarf2 -D LINUX -o sha256_sse4.o sha256_sse4.asm +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; This code is described in an Intel White-Paper: +; "Fast SHA-256 Implementations on Intel Architecture Processors" +; +; To find it, surf to http://www.intel.com/p/en_US/embedded +; and search for that title. +; The paper is expected to be released roughly at the end of April, 2012 +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; This code schedules 1 blocks at a time, with 4 lanes per block +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +%define MOVDQ movdqu ;; assume buffers not aligned + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Define Macros + +; addm [mem], reg +; Add reg to mem using reg-mem add and store +%macro addm 2 + add %2, %1 + mov %1, %2 +%endm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; COPY_XMM_AND_BSWAP xmm, [mem], byte_flip_mask +; Load xmm with mem and byte swap each dword +%macro COPY_XMM_AND_BSWAP 3 + MOVDQ %1, %2 + pshufb %1, %3 +%endmacro + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +%define X0 xmm4 +%define X1 xmm5 +%define X2 xmm6 +%define X3 xmm7 + +%define XTMP0 xmm0 +%define XTMP1 xmm1 +%define XTMP2 xmm2 +%define XTMP3 xmm3 +%define XTMP4 xmm8 +%define XFER xmm9 + +%define SHUF_00BA xmm10 ; shuffle xBxA -> 00BA +%define SHUF_DC00 xmm11 ; shuffle xDxC -> DC00 +%define BYTE_FLIP_MASK xmm12 + +%ifdef LINUX +%define NUM_BLKS rdx ; 3rd arg +%define CTX rsi ; 2nd arg +%define INP rdi ; 1st arg + +%define SRND rdi ; clobbers INP +%define c ecx +%define d r8d +%define e edx +%else +%define NUM_BLKS r8 ; 3rd arg +%define CTX rdx ; 2nd arg +%define INP rcx ; 1st arg + +%define SRND rcx ; clobbers INP +%define c edi +%define d esi +%define e r8d + +%endif +%define TBL rbp +%define a eax +%define b ebx + +%define f r9d +%define g r10d +%define h r11d + +%define y0 r13d +%define y1 r14d +%define y2 r15d + + + +_INP_END_SIZE equ 8 +_INP_SIZE equ 8 +_XFER_SIZE equ 8 +%ifdef LINUX +_XMM_SAVE_SIZE equ 0 +%else +_XMM_SAVE_SIZE equ 7*16 +%endif +; STACK_SIZE plus pushes must be an odd multiple of 8 +_ALIGN_SIZE equ 8 + +_INP_END equ 0 +_INP equ _INP_END + _INP_END_SIZE +_XFER equ _INP + _INP_SIZE +_XMM_SAVE equ _XFER + _XFER_SIZE + _ALIGN_SIZE +STACK_SIZE equ _XMM_SAVE + _XMM_SAVE_SIZE + +; rotate_Xs +; Rotate values of symbols X0...X3 +%macro rotate_Xs 0 +%xdefine X_ X0 +%xdefine X0 X1 +%xdefine X1 X2 +%xdefine X2 X3 +%xdefine X3 X_ +%endm + +; ROTATE_ARGS +; Rotate values of symbols a...h +%macro ROTATE_ARGS 0 +%xdefine TMP_ h +%xdefine h g +%xdefine g f +%xdefine f e +%xdefine e d +%xdefine d c +%xdefine c b +%xdefine b a +%xdefine a TMP_ +%endm + +%macro FOUR_ROUNDS_AND_SCHED 0 + ;; compute s0 four at a time and s1 two at a time + ;; compute W[-16] + W[-7] 4 at a time + movdqa XTMP0, X3 + mov y0, e ; y0 = e + ror y0, (25-11) ; y0 = e >> (25-11) + mov y1, a ; y1 = a + palignr XTMP0, X2, 4 ; XTMP0 = W[-7] + ror y1, (22-13) ; y1 = a >> (22-13) + xor y0, e ; y0 = e ^ (e >> (25-11)) + mov y2, f ; y2 = f + ror y0, (11-6) ; y0 = (e >> (11-6)) ^ (e >> (25-6)) + movdqa XTMP1, X1 + xor y1, a ; y1 = a ^ (a >> (22-13) + xor y2, g ; y2 = f^g + paddd XTMP0, X0 ; XTMP0 = W[-7] + W[-16] + xor y0, e ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) + and y2, e ; y2 = (f^g)&e + ror y1, (13-2) ; y1 = (a >> (13-2)) ^ (a >> (22-2)) + ;; compute s0 + palignr XTMP1, X0, 4 ; XTMP1 = W[-15] + xor y1, a ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) + ror y0, 6 ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) + xor y2, g ; y2 = CH = ((f^g)&e)^g + movdqa XTMP2, XTMP1 ; XTMP2 = W[-15] + ror y1, 2 ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) + add y2, y0 ; y2 = S1 + CH + add y2, [rsp + _XFER + 0*4] ; y2 = k + w + S1 + CH + movdqa XTMP3, XTMP1 ; XTMP3 = W[-15] + mov y0, a ; y0 = a + add h, y2 ; h = h + S1 + CH + k + w + mov y2, a ; y2 = a + pslld XTMP1, (32-7) + or y0, c ; y0 = a|c + add d, h ; d = d + h + S1 + CH + k + w + and y2, c ; y2 = a&c + psrld XTMP2, 7 + and y0, b ; y0 = (a|c)&b + add h, y1 ; h = h + S1 + CH + k + w + S0 + por XTMP1, XTMP2 ; XTMP1 = W[-15] ror 7 + or y0, y2 ; y0 = MAJ = (a|c)&b)|(a&c) + add h, y0 ; h = h + S1 + CH + k + w + S0 + MAJ + +ROTATE_ARGS + movdqa XTMP2, XTMP3 ; XTMP2 = W[-15] + mov y0, e ; y0 = e + mov y1, a ; y1 = a + movdqa XTMP4, XTMP3 ; XTMP4 = W[-15] + ror y0, (25-11) ; y0 = e >> (25-11) + xor y0, e ; y0 = e ^ (e >> (25-11)) + mov y2, f ; y2 = f + ror y1, (22-13) ; y1 = a >> (22-13) + pslld XTMP3, (32-18) + xor y1, a ; y1 = a ^ (a >> (22-13) + ror y0, (11-6) ; y0 = (e >> (11-6)) ^ (e >> (25-6)) + xor y2, g ; y2 = f^g + psrld XTMP2, 18 + ror y1, (13-2) ; y1 = (a >> (13-2)) ^ (a >> (22-2)) + xor y0, e ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) + and y2, e ; y2 = (f^g)&e + ror y0, 6 ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) + pxor XTMP1, XTMP3 + xor y1, a ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) + xor y2, g ; y2 = CH = ((f^g)&e)^g + psrld XTMP4, 3 ; XTMP4 = W[-15] >> 3 + add y2, y0 ; y2 = S1 + CH + add y2, [rsp + _XFER + 1*4] ; y2 = k + w + S1 + CH + ror y1, 2 ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) + pxor XTMP1, XTMP2 ; XTMP1 = W[-15] ror 7 ^ W[-15] ror 18 + mov y0, a ; y0 = a + add h, y2 ; h = h + S1 + CH + k + w + mov y2, a ; y2 = a + pxor XTMP1, XTMP4 ; XTMP1 = s0 + or y0, c ; y0 = a|c + add d, h ; d = d + h + S1 + CH + k + w + and y2, c ; y2 = a&c + ;; compute low s1 + pshufd XTMP2, X3, 11111010b ; XTMP2 = W[-2] {BBAA} + and y0, b ; y0 = (a|c)&b + add h, y1 ; h = h + S1 + CH + k + w + S0 + paddd XTMP0, XTMP1 ; XTMP0 = W[-16] + W[-7] + s0 + or y0, y2 ; y0 = MAJ = (a|c)&b)|(a&c) + add h, y0 ; h = h + S1 + CH + k + w + S0 + MAJ + +ROTATE_ARGS + movdqa XTMP3, XTMP2 ; XTMP3 = W[-2] {BBAA} + mov y0, e ; y0 = e + mov y1, a ; y1 = a + ror y0, (25-11) ; y0 = e >> (25-11) + movdqa XTMP4, XTMP2 ; XTMP4 = W[-2] {BBAA} + xor y0, e ; y0 = e ^ (e >> (25-11)) + ror y1, (22-13) ; y1 = a >> (22-13) + mov y2, f ; y2 = f + xor y1, a ; y1 = a ^ (a >> (22-13) + ror y0, (11-6) ; y0 = (e >> (11-6)) ^ (e >> (25-6)) + psrlq XTMP2, 17 ; XTMP2 = W[-2] ror 17 {xBxA} + xor y2, g ; y2 = f^g + psrlq XTMP3, 19 ; XTMP3 = W[-2] ror 19 {xBxA} + xor y0, e ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) + and y2, e ; y2 = (f^g)&e + psrld XTMP4, 10 ; XTMP4 = W[-2] >> 10 {BBAA} + ror y1, (13-2) ; y1 = (a >> (13-2)) ^ (a >> (22-2)) + xor y1, a ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) + xor y2, g ; y2 = CH = ((f^g)&e)^g + ror y0, 6 ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) + pxor XTMP2, XTMP3 + add y2, y0 ; y2 = S1 + CH + ror y1, 2 ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) + add y2, [rsp + _XFER + 2*4] ; y2 = k + w + S1 + CH + pxor XTMP4, XTMP2 ; XTMP4 = s1 {xBxA} + mov y0, a ; y0 = a + add h, y2 ; h = h + S1 + CH + k + w + mov y2, a ; y2 = a + pshufb XTMP4, SHUF_00BA ; XTMP4 = s1 {00BA} + or y0, c ; y0 = a|c + add d, h ; d = d + h + S1 + CH + k + w + and y2, c ; y2 = a&c + paddd XTMP0, XTMP4 ; XTMP0 = {..., ..., W[1], W[0]} + and y0, b ; y0 = (a|c)&b + add h, y1 ; h = h + S1 + CH + k + w + S0 + ;; compute high s1 + pshufd XTMP2, XTMP0, 01010000b ; XTMP2 = W[-2] {DDCC} + or y0, y2 ; y0 = MAJ = (a|c)&b)|(a&c) + add h, y0 ; h = h + S1 + CH + k + w + S0 + MAJ + +ROTATE_ARGS + movdqa XTMP3, XTMP2 ; XTMP3 = W[-2] {DDCC} + mov y0, e ; y0 = e + ror y0, (25-11) ; y0 = e >> (25-11) + mov y1, a ; y1 = a + movdqa X0, XTMP2 ; X0 = W[-2] {DDCC} + ror y1, (22-13) ; y1 = a >> (22-13) + xor y0, e ; y0 = e ^ (e >> (25-11)) + mov y2, f ; y2 = f + ror y0, (11-6) ; y0 = (e >> (11-6)) ^ (e >> (25-6)) + psrlq XTMP2, 17 ; XTMP2 = W[-2] ror 17 {xDxC} + xor y1, a ; y1 = a ^ (a >> (22-13) + xor y2, g ; y2 = f^g + psrlq XTMP3, 19 ; XTMP3 = W[-2] ror 19 {xDxC} + xor y0, e ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) + and y2, e ; y2 = (f^g)&e + ror y1, (13-2) ; y1 = (a >> (13-2)) ^ (a >> (22-2)) + psrld X0, 10 ; X0 = W[-2] >> 10 {DDCC} + xor y1, a ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) + ror y0, 6 ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) + xor y2, g ; y2 = CH = ((f^g)&e)^g + pxor XTMP2, XTMP3 + ror y1, 2 ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) + add y2, y0 ; y2 = S1 + CH + add y2, [rsp + _XFER + 3*4] ; y2 = k + w + S1 + CH + pxor X0, XTMP2 ; X0 = s1 {xDxC} + mov y0, a ; y0 = a + add h, y2 ; h = h + S1 + CH + k + w + mov y2, a ; y2 = a + pshufb X0, SHUF_DC00 ; X0 = s1 {DC00} + or y0, c ; y0 = a|c + add d, h ; d = d + h + S1 + CH + k + w + and y2, c ; y2 = a&c + paddd X0, XTMP0 ; X0 = {W[3], W[2], W[1], W[0]} + and y0, b ; y0 = (a|c)&b + add h, y1 ; h = h + S1 + CH + k + w + S0 + or y0, y2 ; y0 = MAJ = (a|c)&b)|(a&c) + add h, y0 ; h = h + S1 + CH + k + w + S0 + MAJ + +ROTATE_ARGS +rotate_Xs +%endm + +;; input is [rsp + _XFER + %1 * 4] +%macro DO_ROUND 1 + mov y0, e ; y0 = e + ror y0, (25-11) ; y0 = e >> (25-11) + mov y1, a ; y1 = a + xor y0, e ; y0 = e ^ (e >> (25-11)) + ror y1, (22-13) ; y1 = a >> (22-13) + mov y2, f ; y2 = f + xor y1, a ; y1 = a ^ (a >> (22-13) + ror y0, (11-6) ; y0 = (e >> (11-6)) ^ (e >> (25-6)) + xor y2, g ; y2 = f^g + xor y0, e ; y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) + ror y1, (13-2) ; y1 = (a >> (13-2)) ^ (a >> (22-2)) + and y2, e ; y2 = (f^g)&e + xor y1, a ; y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) + ror y0, 6 ; y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) + xor y2, g ; y2 = CH = ((f^g)&e)^g + add y2, y0 ; y2 = S1 + CH + ror y1, 2 ; y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) + add y2, [rsp + _XFER + %1 * 4] ; y2 = k + w + S1 + CH + mov y0, a ; y0 = a + add h, y2 ; h = h + S1 + CH + k + w + mov y2, a ; y2 = a + or y0, c ; y0 = a|c + add d, h ; d = d + h + S1 + CH + k + w + and y2, c ; y2 = a&c + and y0, b ; y0 = (a|c)&b + add h, y1 ; h = h + S1 + CH + k + w + S0 + or y0, y2 ; y0 = MAJ = (a|c)&b)|(a&c) + add h, y0 ; h = h + S1 + CH + k + w + S0 + MAJ + ROTATE_ARGS +%endm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; void sha256_sse4(void *input_data, UINT32 digest[8], UINT64 num_blks) +;; arg 1 : pointer to input data +;; arg 2 : pointer to digest +;; arg 3 : Num blocks +section .text +global sha256_sse4 +align 32 +sha256_sse4: + push rbx +%ifndef LINUX + push rsi + push rdi +%endif + push rbp + push r13 + push r14 + push r15 + + sub rsp,STACK_SIZE +%ifndef LINUX + movdqa [rsp + _XMM_SAVE + 0*16],xmm6 + movdqa [rsp + _XMM_SAVE + 1*16],xmm7 + movdqa [rsp + _XMM_SAVE + 2*16],xmm8 + movdqa [rsp + _XMM_SAVE + 3*16],xmm9 + movdqa [rsp + _XMM_SAVE + 4*16],xmm10 + movdqa [rsp + _XMM_SAVE + 5*16],xmm11 + movdqa [rsp + _XMM_SAVE + 6*16],xmm12 +%endif + + shl NUM_BLKS, 6 ; convert to bytes + jz done_hash + add NUM_BLKS, INP ; pointer to end of data + mov [rsp + _INP_END], NUM_BLKS + + ;; load initial digest + mov a,[4*0 + CTX] + mov b,[4*1 + CTX] + mov c,[4*2 + CTX] + mov d,[4*3 + CTX] + mov e,[4*4 + CTX] + mov f,[4*5 + CTX] + mov g,[4*6 + CTX] + mov h,[4*7 + CTX] + + movdqa BYTE_FLIP_MASK, [PSHUFFLE_BYTE_FLIP_MASK wrt rip] + movdqa SHUF_00BA, [_SHUF_00BA wrt rip] + movdqa SHUF_DC00, [_SHUF_DC00 wrt rip] + +loop0: + lea TBL,[K256 wrt rip] + + ;; byte swap first 16 dwords + COPY_XMM_AND_BSWAP X0, [INP + 0*16], BYTE_FLIP_MASK + COPY_XMM_AND_BSWAP X1, [INP + 1*16], BYTE_FLIP_MASK + COPY_XMM_AND_BSWAP X2, [INP + 2*16], BYTE_FLIP_MASK + COPY_XMM_AND_BSWAP X3, [INP + 3*16], BYTE_FLIP_MASK + + mov [rsp + _INP], INP + + ;; schedule 48 input dwords, by doing 3 rounds of 16 each + mov SRND, 3 +align 16 +loop1: + movdqa XFER, [TBL + 0*16] + paddd XFER, X0 + movdqa [rsp + _XFER], XFER + FOUR_ROUNDS_AND_SCHED + + movdqa XFER, [TBL + 1*16] + paddd XFER, X0 + movdqa [rsp + _XFER], XFER + FOUR_ROUNDS_AND_SCHED + + movdqa XFER, [TBL + 2*16] + paddd XFER, X0 + movdqa [rsp + _XFER], XFER + FOUR_ROUNDS_AND_SCHED + + movdqa XFER, [TBL + 3*16] + paddd XFER, X0 + movdqa [rsp + _XFER], XFER + add TBL, 4*16 + FOUR_ROUNDS_AND_SCHED + + sub SRND, 1 + jne loop1 + + mov SRND, 2 +loop2: + paddd X0, [TBL + 0*16] + movdqa [rsp + _XFER], X0 + DO_ROUND 0 + DO_ROUND 1 + DO_ROUND 2 + DO_ROUND 3 + paddd X1, [TBL + 1*16] + movdqa [rsp + _XFER], X1 + add TBL, 2*16 + DO_ROUND 0 + DO_ROUND 1 + DO_ROUND 2 + DO_ROUND 3 + + movdqa X0, X2 + movdqa X1, X3 + + sub SRND, 1 + jne loop2 + + addm [4*0 + CTX],a + addm [4*1 + CTX],b + addm [4*2 + CTX],c + addm [4*3 + CTX],d + addm [4*4 + CTX],e + addm [4*5 + CTX],f + addm [4*6 + CTX],g + addm [4*7 + CTX],h + + mov INP, [rsp + _INP] + add INP, 64 + cmp INP, [rsp + _INP_END] + jne loop0 + +done_hash: +%ifndef LINUX + movdqa xmm6,[rsp + _XMM_SAVE + 0*16] + movdqa xmm7,[rsp + _XMM_SAVE + 1*16] + movdqa xmm8,[rsp + _XMM_SAVE + 2*16] + movdqa xmm9,[rsp + _XMM_SAVE + 3*16] + movdqa xmm10,[rsp + _XMM_SAVE + 4*16] + movdqa xmm11,[rsp + _XMM_SAVE + 5*16] + movdqa xmm12,[rsp + _XMM_SAVE + 6*16] +%endif + + add rsp, STACK_SIZE + + pop r15 + pop r14 + pop r13 + pop rbp +%ifndef LINUX + pop rdi + pop rsi +%endif + pop rbx + + ret + + +section .data +align 64 +K256: + dd 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + dd 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + dd 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + dd 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + dd 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + dd 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + dd 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + dd 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + dd 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + dd 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + dd 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + dd 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + dd 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + dd 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + dd 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + dd 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + +PSHUFFLE_BYTE_FLIP_MASK: ddq 0x0c0d0e0f08090a0b0405060700010203 + +; shuffle xBxA -> 00BA +_SHUF_00BA: ddq 0xFFFFFFFFFFFFFFFF0b0a090803020100 + +; shuffle xDxC -> DC00 +_SHUF_DC00: ddq 0x0b0a090803020100FFFFFFFFFFFFFFFF +*/ + +#endif From fa9be909c945c3689591590ac19504aa53154c2f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 16 Jul 2017 11:30:27 -0700 Subject: [PATCH 123/148] Add selftest for SHA256 transform --- src/crypto/sha256.cpp | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 4ecf5090397..25f4eabd4c2 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -5,6 +5,7 @@ #include "crypto/sha256.h" #include "crypto/common.h" +#include #include #include @@ -140,7 +141,36 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) } // namespace sha256 -void (*Transform)(uint32_t*, const unsigned char*, size_t) = sha256::Transform; +typedef void (*TransformType)(uint32_t*, const unsigned char*, size_t); + +bool SelfTest(TransformType tr) { + static const unsigned char in1[65] = {0, 0x80}; + static const unsigned char in2[129] = { + 0, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 + }; + static const uint32_t init[8] = {0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul}; + static const uint32_t out1[8] = {0xe3b0c442ul, 0x98fc1c14ul, 0x9afbf4c8ul, 0x996fb924ul, 0x27ae41e4ul, 0x649b934cul, 0xa495991bul, 0x7852b855ul}; + static const uint32_t out2[8] = {0xce4153b0ul, 0x147c2a86ul, 0x3ed4298eul, 0xe0676bc8ul, 0x79fc77a1ul, 0x2abe1f49ul, 0xb2b055dful, 0x1069523eul}; + uint32_t buf[8]; + memcpy(buf, init, sizeof(buf)); + // Process nothing, and check we remain in the initial state. + tr(buf, nullptr, 0); + if (memcmp(buf, init, sizeof(buf))) return false; + // Process the padded empty string (unaligned) + tr(buf, in1 + 1, 1); + if (memcmp(buf, out1, sizeof(buf))) return false; + // Process 64 spaces (unaligned) + memcpy(buf, init, sizeof(buf)); + tr(buf, in2 + 1, 2); + if (memcmp(buf, out2, sizeof(buf))) return false; + return true; +} + +TransformType Transform = sha256::Transform; } // namespace @@ -150,10 +180,12 @@ std::string SHA256AutoDetect() uint32_t eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) { Transform = sha256_sse4::Transform; + assert(SelfTest(Transform)); return "sse4"; } #endif + assert(SelfTest(Transform)); return "standard"; } From 6b8d872e5e2dd68a5229ec55f5261dae34ff9bdb Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 18 Jul 2017 01:06:11 -0700 Subject: [PATCH 124/148] Protect SSE4 code behind a compile-time flag --- configure.ac | 11 +++++++++++ src/Makefile.am | 5 ++++- src/crypto/sha256.cpp | 4 +++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 835dcdbf570..aea5d7160c7 100644 --- a/configure.ac +++ b/configure.ac @@ -177,6 +177,16 @@ AC_ARG_ENABLE([glibc-back-compat], [use_glibc_compat=$enableval], [use_glibc_compat=no]) +AC_ARG_ENABLE([experimental-asm], + [AS_HELP_STRING([--enable-experimental-asm], + [Enable experimental assembly routines (default is no)])], + [experimental_asm=$enableval], + [experimental_asm=no]) + +if test "x$experimental_asm" = xyes; then + AC_DEFINE(EXPERIMENTAL_ASM, 1, [Define this symbol to build in experimental assembly routines]) +fi + AC_ARG_WITH([system-univalue], [AS_HELP_STRING([--with-system-univalue], [Build with system UniValue (default is no)])], @@ -1162,6 +1172,7 @@ AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes]) AM_CONDITIONAL([ENABLE_HWCRC32],[test x$enable_hwcrc32 = xyes]) +AM_CONDITIONAL([EXPERIMENTAL_ASM],[test x$experimental_asm = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) diff --git a/src/Makefile.am b/src/Makefile.am index 35bfeb466c1..f7abab482e9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -263,11 +263,14 @@ crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha1.cpp \ crypto/sha1.h \ crypto/sha256.cpp \ - crypto/sha256_sse4.cpp \ crypto/sha256.h \ crypto/sha512.cpp \ crypto/sha512.h +if EXPERIMENTAL_ASM +crypto_libbitcoin_crypto_a_SOURCES += crypto/sha256_sse4.cpp +endif + # consensus: shared between all executables that validate any consensus rules. libbitcoin_consensus_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_consensus_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 25f4eabd4c2..15d6db90c24 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -10,12 +10,14 @@ #include #if defined(__x86_64__) || defined(__amd64__) +#if defined(EXPERIMENTAL_ASM) #include namespace sha256_sse4 { void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks); } #endif +#endif // Internal implementation code. namespace @@ -176,7 +178,7 @@ TransformType Transform = sha256::Transform; std::string SHA256AutoDetect() { -#if defined(__x86_64__) || defined(__amd64__) +#if defined(EXPERIMENTAL_ASM) && (defined(__x86_64__) || defined(__amd64__)) uint32_t eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) { Transform = sha256_sse4::Transform; From 97375727b8f3b7d26c7c813630a6139005b5c5c9 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 18 Jul 2017 20:19:47 +0200 Subject: [PATCH 125/148] [Qt] Use wallet 0 in rpc console if running with multiple wallets --- src/qt/rpcconsole.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index ec0580b81c2..232068bf45c 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -25,6 +25,7 @@ #ifdef ENABLE_WALLET #include +#include #endif #include @@ -301,6 +302,14 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & JSONRPCRequest req; req.params = RPCConvertValues(stack.back()[0], std::vector(stack.back().begin() + 1, stack.back().end())); req.strMethod = stack.back()[0]; +#ifdef ENABLE_WALLET + // TODO: Move this logic to WalletModel + if (!vpwallets.empty()) { + // in Qt, use always the wallet with index 0 when running with multiple wallets + QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(vpwallets[0]->GetName())); + req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length()); + } +#endif lastResult = tableRPC.execute(req); } From 09eacee6b2844edf4f804e77180489cf31383143 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Thu, 15 Jun 2017 13:49:38 -0400 Subject: [PATCH 126/148] [wallet] fix comment for CWallet::Verify() --- src/wallet/wallet.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index bcd7e4b4eed..7ef2e6f1d8e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1066,7 +1066,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface //! Flush wallet (bitdb flush) void Flush(bool shutdown=false); - //! Verify the wallet database and perform salvage if required + //! Responsible for reading and validating the -wallet arguments and verifying the wallet database. + // This function will perform salvage on the wallet if requested, as long as only one wallet is + // being loaded (CWallet::ParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet). static bool Verify(); /** From 4a057152d2635e5a4cff8fd654087fee044efef6 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Thu, 15 Jun 2017 11:45:08 -0400 Subject: [PATCH 127/148] [wallet] [rpc] print wallet name in getwalletinfo --- src/wallet/rpcwallet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4275a9181d6..030f203d26a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2447,6 +2447,7 @@ UniValue getwalletinfo(const JSONRPCRequest& request) "Returns an object containing various wallet state info.\n" "\nResult:\n" "{\n" + " \"walletname\": xxxxx, (string) the wallet name\n" " \"walletversion\": xxxxx, (numeric) the wallet version\n" " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n" " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n" @@ -2469,6 +2470,7 @@ UniValue getwalletinfo(const JSONRPCRequest& request) UniValue obj(UniValue::VOBJ); size_t kpExternalSize = pwallet->KeypoolCountExternalKeys(); + obj.push_back(Pair("walletname", pwallet->GetName())); obj.push_back(Pair("walletversion", pwallet->GetVersion())); obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance()))); obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance()))); From 9508761ed69a30f4af24fbc9274176056431abfb Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 27 Jun 2017 09:46:55 -0400 Subject: [PATCH 128/148] [wallet] [rpc] Add listwallets RPC This commit adds a listwallets RPC, which lists the names of the currently loaded wallets. This command intentionally shows no information about the wallet other then the name. Information on individual wallets can be obtained using the getwalletinfo RPC. --- src/wallet/rpcwallet.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 030f203d26a..2b7b4085eea 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2491,6 +2491,39 @@ UniValue getwalletinfo(const JSONRPCRequest& request) return obj; } +UniValue listwallets(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() != 0) + throw std::runtime_error( + "listwallets\n" + "Returns a list of currently loaded wallets.\n" + "For full information on the wallet, use \"getwalletinfo\"\n" + "\nResult:\n" + "[ (json array of strings)\n" + " \"walletname\" (string) the wallet name\n" + " ...\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("listwallets", "") + + HelpExampleRpc("listwallets", "") + ); + + UniValue obj(UniValue::VARR); + + for (CWalletRef pwallet : vpwallets) { + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + LOCK(pwallet->cs_wallet); + + obj.push_back(pwallet->GetName()); + } + + return obj; +} + UniValue resendwallettransactions(const JSONRPCRequest& request) { CWallet * const pwallet = GetWalletForJSONRPCRequest(request); @@ -3087,6 +3120,7 @@ static const CRPCCommand commands[] = { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} }, { "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} }, { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe","query_options"} }, + { "wallet", "listwallets", &listwallets, true, {} }, { "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} }, { "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} }, { "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} }, From 3707fcd94e6251384235d16faafc975853d49e3d Mon Sep 17 00:00:00 2001 From: John Newbery Date: Thu, 15 Jun 2017 09:05:32 -0400 Subject: [PATCH 129/148] [wallet] [tests] Add listwallets to multiwallet test --- test/functional/multiwallet.py | 31 +++++++++++++++++++++---------- test/functional/test_runner.py | 1 + 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py index 2b4dd2d3e7d..f0929a8e28f 100755 --- a/test/functional/multiwallet.py +++ b/test/functional/multiwallet.py @@ -2,9 +2,12 @@ # Copyright (c) 2017 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 multiwallet.""" +"""Test multiwallet. + +Verify that a bitcoind node can load multiple wallet files +""" from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import assert_equal, assert_raises_jsonrpc class MultiWalletTest(BitcoinTestFramework): @@ -18,20 +21,28 @@ def run_test(self): w1 = self.nodes[0] / "wallet/w1" w1.generate(1) - #accessing wallet RPC without using wallet endpoint fails + # accessing wallet RPC without using wallet endpoint fails assert_raises_jsonrpc(-32601, "Method not found", self.nodes[0].getwalletinfo) - #check w1 wallet balance - walletinfo = w1.getwalletinfo() - assert_equal(walletinfo['immature_balance'], 50) + # check w1 wallet balance + w1_info = w1.getwalletinfo() + assert_equal(w1_info['immature_balance'], 50) + w1_name = w1_info['walletname'] + assert_equal(w1_name, "w1") - #check w1 wallet balance + # check w1 wallet balance w2 = self.nodes[0] / "wallet/w2" - walletinfo = w2.getwalletinfo() - assert_equal(walletinfo['immature_balance'], 0) + w2_info = w2.getwalletinfo() + assert_equal(w2_info['immature_balance'], 0) + w2_name = w2_info['walletname'] + assert_equal(w2_name, "w2") w3 = self.nodes[0] / "wallet/w3" - + w3_name = w3.getwalletinfo()['walletname'] + assert_equal(w3_name, "w3") + + assert_equal({"w1", "w2", "w3"}, {w1_name, w2_name, w3_name}) + w1.generate(101) assert_equal(w1.getbalance(), 100) assert_equal(w2.getbalance(), 0) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 51577589fe0..c158eaa34e0 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -89,6 +89,7 @@ 'mempool_spendcoinbase.py', 'mempool_reorg.py', 'mempool_persist.py', + 'multiwallet.py', 'httpbasics.py', 'multi_rpc.py', 'proxy_test.py', From 6adc3a37324caa07015368bfe8529e1964366eef Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 20 Jul 2017 23:23:57 +0200 Subject: [PATCH 130/148] qt: Periodic translations update Tree-SHA512: 6f2548776007ebe172d43fd26673c62d0db34af815fcf4451cb293f19c0d8cf84a6761dc2636ffb5a906074d70988b3cd805e21b2471de5eb1697fadc82d0205 --- src/qt/bitcoinstrings.cpp | 10 + src/qt/locale/bitcoin_af.ts | 106 +++- src/qt/locale/bitcoin_af_ZA.ts | 64 ++ src/qt/locale/bitcoin_ar.ts | 30 +- src/qt/locale/bitcoin_bg.ts | 24 + src/qt/locale/bitcoin_ca_ES.ts | 30 +- src/qt/locale/bitcoin_da.ts | 6 +- src/qt/locale/bitcoin_de.ts | 120 +++- src/qt/locale/bitcoin_el_GR.ts | 274 +++++++- src/qt/locale/bitcoin_en.ts | 133 ++-- src/qt/locale/bitcoin_eo.ts | 122 +++- src/qt/locale/bitcoin_es.ts | 132 +++- src/qt/locale/bitcoin_es_ES.ts | 92 ++- src/qt/locale/bitcoin_et_EE.ts | 32 + src/qt/locale/bitcoin_fa.ts | 128 ++++ src/qt/locale/bitcoin_fa_IR.ts | 458 ++++++++++++-- src/qt/locale/bitcoin_fi.ts | 378 ++++++++++- src/qt/locale/bitcoin_fr.ts | 26 +- src/qt/locale/bitcoin_fr_FR.ts | 394 +++++++++++- src/qt/locale/bitcoin_he.ts | 1248 +++++++++++++++++++++++++++++++++++- src/qt/locale/bitcoin_hu.ts | 28 + src/qt/locale/bitcoin_id_ID.ts | 434 ++++++++++++- src/qt/locale/bitcoin_it.ts | 1028 +++++++++++++++++++++++++++++- src/qt/locale/bitcoin_it_IT.ts | 20 + src/qt/locale/bitcoin_ka.ts | 8 + src/qt/locale/bitcoin_ko_KR.ts | 1020 +++++++++++++++++++++++++++--- src/qt/locale/bitcoin_ms_MY.ts | 338 +++++++++- src/qt/locale/bitcoin_nb.ts | 540 +++++++++++++++- src/qt/locale/bitcoin_ne.ts | 76 +++ src/qt/locale/bitcoin_nl.ts | 304 ++++++++- src/qt/locale/bitcoin_pl.ts | 162 ++++- src/qt/locale/bitcoin_pt_BR.ts | 6 +- src/qt/locale/bitcoin_pt_PT.ts | 848 ++++++++++++++++++++++++- src/qt/locale/bitcoin_ru.ts | 20 + src/qt/locale/bitcoin_ru_RU.ts | 12 +- src/qt/locale/bitcoin_sk.ts | 1358 ++++++++++++++++++++++++++++++++++++++-- src/qt/locale/bitcoin_sv.ts | 888 +++++++++++++++++++++++++- src/qt/locale/bitcoin_tr.ts | 6 +- src/qt/locale/bitcoin_uk.ts | 98 ++- src/qt/locale/bitcoin_ur_PK.ts | 24 + src/qt/locale/bitcoin_vi_VN.ts | 20 + src/qt/locale/bitcoin_zh_CN.ts | 8 + src/qt/locale/bitcoin_zh_HK.ts | 382 ++++++++++- 43 files changed, 10974 insertions(+), 461 deletions(-) diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index b3d2cf1d55c..f99c46ecf5c 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -170,11 +170,19 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "rebuild the block database if you are sure that your computer's date and " "time are correct"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"The fee rate (in %s/kB) used to discard change (to fee) if it would be dust " +"at this fee rate (default: %s) Note: We will always discard up to the dust " +"relay fee and a discard fee above that is limited by the longest target fee " +"estimate"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "The transaction amount is too small to send after the fee has been deducted"), QT_TRANSLATE_NOOP("bitcoin-core", "" "This is a pre-release test build - use at your own risk - do not use for " "mining or merchant applications"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"This is the transaction fee you may discard if change is smaller than dust " +"at this level"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "This is the transaction fee you may pay when fee estimates are not available."), QT_TRANSLATE_NOOP("bitcoin-core", "" "This product includes software developed by the OpenSSL Project for use in " @@ -305,6 +313,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -onion address or hostname: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address or hostname: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -%s=: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -discardfee=: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -fallbackfee=: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=: '%s' (must be at least %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid characters in -wallet filename"), @@ -375,6 +384,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Tor control port password (default: empty)"), QT_TRANSLATE_NOOP("bitcoin-core", "Tor control port to use if onion listening enabled (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction amount too small"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction amounts must not be negative"), +QT_TRANSLATE_NOOP("bitcoin-core", "Transaction fee and change calculation failed"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction has too long of a mempool chain"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction must have at least one recipient"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large for fee policy"), diff --git a/src/qt/locale/bitcoin_af.ts b/src/qt/locale/bitcoin_af.ts index 9726987b63b..250fc6b5a25 100644 --- a/src/qt/locale/bitcoin_af.ts +++ b/src/qt/locale/bitcoin_af.ts @@ -74,6 +74,10 @@ &Dupliseer Adres + Copy &Label + Kopieer &Etiket + + &Edit &Verander @@ -200,6 +204,14 @@ U het die verkeerde wagwoord ingetik. + Wallet decryption failed + Beursie-dekripsie het misluk + + + Wallet passphrase was successfully changed. + Beursie wagwoordfrase is suksesvol verander. + + Warning: The Caps Lock key is on! WAARSKUWING: Outomatiese Kapitalisering is aktief op u sleutelbord! @@ -207,6 +219,10 @@ BanTableModel + IP/Netmask + IP/Netmasker + + Banned Until Verban tot @@ -214,6 +230,10 @@ BitcoinGUI + Sign &message... + Teken &boodskap... + + Synchronizing with network... Netwerk-sinkronisasie... @@ -294,6 +314,18 @@ Oop & URI... + Click to disable network activity. + Kliek om netwerkaktiwiteit af te skakel. + + + Network activity disabled. + Netwerkaktiwiteit gedeaktiveer. + + + Click to enable network activity again. + Kliek om netwerkaktiwiteit weer aan te skakel. + + Reindexing blocks on disk... Besig met herindeksering van blokke op hardeskyf... @@ -310,6 +342,14 @@ Verander die wagwoord wat ek vir kodifikasie van my beursie gebruik + &Debug window + &Ontfout venster + + + Open debugging and diagnostic console + Maak ontfouting en diagnostiese konsole oop + + Bitcoin Bitcoin @@ -473,16 +513,48 @@ Bevestig + yes + ja + + + no + nee + + + Can vary +/- %1 satoshi(s) per input. + Kan verskil met +/- %1 satoshi(s) per invoer. + + (no label) (geen etiket) - + + change from %1 (%2) + verander van %1 (%2) + + + (change) + (verander) + + EditAddressDialog Edit Address Wysig Adres + + &Label + &Etiket + + + &Address + &Adres + + + Could not unlock wallet. + Kon beursie nie oopsluit nie. + FreespaceChecker @@ -525,6 +597,10 @@ Welkom by %1. + Error: Specified data directory "%1" cannot be created. + Fout: Gespesifiseerde dataleêr "%1" kon nie geskep word nie. + + Error Fout @@ -562,10 +638,30 @@ Alle kliëntopsies na verstek terugstel. + &Network + &Netwerk + + + W&allet + B&eursie + + Expert Kenner + Enable coin &control features + Bemagtig munt &beheer funksies. + + + &Port: + &Poort: + + + IPv4 + IPv4 + + IPv6 IPv6 @@ -574,6 +670,14 @@ Tor + &OK + &OK + + + &Cancel + &Kanselleer + + default verstek diff --git a/src/qt/locale/bitcoin_af_ZA.ts b/src/qt/locale/bitcoin_af_ZA.ts index 1679482c771..432e8c3faf8 100644 --- a/src/qt/locale/bitcoin_af_ZA.ts +++ b/src/qt/locale/bitcoin_af_ZA.ts @@ -6,6 +6,10 @@ Skep 'n nuwe adres + &New + &Nuwe + + Copy the currently selected address to the system clipboard Maak 'n kopie van die huidige adres na die stelsel klipbord @@ -18,6 +22,14 @@ Verwyder die huidiglik gekieste address van die lys + Export the data in the current tab to a file + Voer inligting uit van die huidige blad na n lêer + + + &Export + &Uitvoer + + &Delete &Verwyder @@ -25,6 +37,42 @@ Choose the address to send coins to Kies die address na wie die muntstukke gestuur moet word + + C&hoose + K&ies + + + Sending addresses + Stuur adresse + + + Receiving addresses + Ontvang adresse + + + &Copy Address + &Kopie adres + + + Copy &Label + Kopie &Etiket + + + &Edit + &Wysig + + + Export Address List + Voer adres lys uit + + + Comma separated file (*.csv) + Koma geskeide lêers (*.csv) + + + Exporting Failed + Uitvoering Misluk + AddressTableModel @@ -661,6 +709,10 @@ Kopieer bedrag + Comma separated file (*.csv) + Koma geskeide lêers (*.csv) + + Date Datum @@ -681,6 +733,10 @@ ID + Exporting Failed + Uitvoering Misluk + + Range: Reeks: @@ -704,6 +760,14 @@ WalletView + + &Export + &Uitvoer + + + Export the data in the current tab to a file + Voer inligting uit van die huidige blad na n lêer + bitcoin-core diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts index 9b865f29bff..68c69038fd4 100644 --- a/src/qt/locale/bitcoin_ar.ts +++ b/src/qt/locale/bitcoin_ar.ts @@ -314,6 +314,18 @@ افتح &URI... + Click to disable network activity. + اضغط لإلغاء تفعيل الشبكه + + + Network activity disabled. + تم إلغاء تفعيل الشبكه + + + Click to enable network activity again. + اضغط لتفعيل الشبكه مره أخرى + + Reindexing blocks on disk... إعادة الفهرسة الكتل على القرص ... @@ -509,7 +521,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> المحفظة <b>مشفرة</b> و <b>مقفلة</b> حاليا - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + خطأ فادح حدث . لا يمكن اتمام بيتكوين بامان سيتم الخروج + + CoinControlDialog @@ -609,6 +625,10 @@ نسخ بعد الرسوم + Copy bytes + نسخ البايتات + + Copy change نسخ التعديل @@ -796,6 +816,10 @@ نمودج + Unknown... + غير معرف + + Hide إخفاء @@ -1363,6 +1387,10 @@ نسخ بعد الرسوم + Copy bytes + نسخ البايتات + + Copy change نسخ التعديل diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts index c5716983043..37b7f8532a3 100644 --- a/src/qt/locale/bitcoin_bg.ts +++ b/src/qt/locale/bitcoin_bg.ts @@ -314,6 +314,18 @@ Отвори &URI... + Click to disable network activity. + Натиснете за деактивиране на мрежата + + + Network activity disabled. + Мрежата деактивирана + + + Click to enable network activity again. + Натиснете за повторно активиране на мрежата + + Reindexing blocks on disk... Повторно индексиране на блоковете на диска... @@ -458,6 +470,10 @@ %1 клиент + Connecting to peers... + Свързване с пиъри + + Catching up... Зарежда блокове... @@ -795,6 +811,10 @@ Добре дошли в %1. + As this is the first time the program is launched, you can choose where %1 will store its data. + Програмата се стартира за първи път вие може да изберете къде %1 ще се запаметят данните. + + Use the default data directory Използване на директория по подразбиране @@ -818,6 +838,10 @@ Време на последния блок + calculating... + Изчисляване... + + Hide Скрий diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts index 8cbb57bd353..2dd724c442a 100644 --- a/src/qt/locale/bitcoin_ca_ES.ts +++ b/src/qt/locale/bitcoin_ca_ES.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Feu clic dret per a editar l'adreça o l'etiqueta + Feu clic dret per a editar l'adreça o l'etiquetaccn Create a new address @@ -878,6 +878,10 @@ Formulari + Unknown... + Desconegut... + + Last block time Últim temps de bloc @@ -1382,7 +1386,11 @@ QObject::QObject - + + Error: %1 + Avís: %1 + + QRImageWidget @@ -2338,6 +2346,10 @@ %1/fora de línia + abandoned + abandonada + + %1/unconfirmed %1/sense confirmar @@ -2468,7 +2480,11 @@ This pane shows a detailed description of the transaction Aquest panell mostra una descripció detallada de la transacció - + + Details for %1 + Detalls per %1 + + TransactionTableModel @@ -2659,6 +2675,10 @@ Copia la transacció crua + Copy full transaction details + Copia els detalls complets de la transacció + + Edit label Editar etiqueta @@ -3142,6 +3162,10 @@ Avís + Warning: unknown new rules activated (versionbit %i) + Avís: regles noves desconegudes activades (versionbit %i) + + Zapping all transactions from wallet... Se suprimeixen totes les transaccions del moneder... diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index 54ef4a2bdf5..bc3fcb278e6 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Højreklik for at redigere adresse eller mærke + Højreklik for at redigere adresse eller mærkat Create a new address @@ -604,7 +604,7 @@ Received with label - Modtaget med mærke + Modtaget med mærkat Received with address @@ -3123,7 +3123,7 @@ Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB) - Reducér pladskravene ved at beskære (slette, "prune") gamle blokke. Dette tillader pruneblockchain-RPC'en at blive kaldt for at slette specifikke blokke, og det aktiverer automatisk beskæring af gamle blokke, hvis en målstørrelse i MiB er angivet. Denne tilstand er ikke kompatibel med -txindex og -rescan. Advarsel: Fortrydelse af denne indstilling kræver download af hele blokkæden igen. (standard: 0 = slå beskæring af blokke fra, 1 = tillad manuel beskæring via RPC, >%u = beskær automatisk blokfiler for at bliver under den angivne målstørrelse i MiB) + Reducér pladskravene ved at beskære (slette, “prune”) gamle blokke. Dette tillader pruneblockchain-RPC'en at blive kaldt for at slette specifikke blokke, og det aktiverer automatisk beskæring af gamle blokke, hvis en målstørrelse i MiB er angivet. Denne tilstand er ikke kompatibel med -txindex og -rescan. Advarsel: Fortrydelse af denne indstilling kræver download af hele blokkæden igen. (standard: 0 = slå beskæring af blokke fra, 1 = tillad manuel beskæring via RPC, >%u = beskær automatisk blokfiler for at bliver under den angivne målstørrelse i MiB) Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s) diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index af79d477363..c3d440c1a40 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -79,7 +79,7 @@ &Edit - &Editieren + B&earbeiten Export Address List @@ -133,7 +133,7 @@ Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. - Geben Sie die neue Passphrase für die Wallet ein.<br>Bitte benutzen Sie eine Passphrase bestehend aus <b>zehn oder mehr zufälligen Zeichen</b> oder <b>acht oder mehr Wörtern</b>. + Geben Sie die neue Passphrase für die Brieftasche ein.<br>Bitte benutzen Sie eine Passphrase bestehend aus <b>zehn oder mehr zufälligen Zeichen</b> oder <b>acht oder mehr Wörtern</b>. Encrypt wallet @@ -141,7 +141,7 @@ This operation needs your wallet passphrase to unlock the wallet. - Dieser Vorgang benötigt ihre Passphrase, um die Wallet zu entsperren. + Dieser Vorgang benötigt ihre Passphrase, um die Brieftasche zu entsperren. Unlock wallet @@ -149,11 +149,11 @@ This operation needs your wallet passphrase to decrypt the wallet. - Dieser Vorgang benötigt Ihre Passphrase, um die Wallet zu entschlüsseln. + Dieser Vorgang benötigt Ihre Passphrase, um die Brieftasche zu entschlüsseln. Decrypt wallet - Wallet entschlüsseln + Brieftasche entschlüsseln Change passphrase @@ -161,39 +161,39 @@ Enter the old passphrase and new passphrase to the wallet. - Geben Sie die alte und neue Wallet-Passphrase ein. + Geben Sie die alte und neue Brieftschen-Passphrase ein. Confirm wallet encryption - Wallet-Verschlüsselung bestätigen + Brieftaschen-Verschlüsselung bestätigen Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - Warnung: Wenn Sie Ihre Wallet verschlüsseln und Ihre Passphrase verlieren, werden Sie <b>alle Ihre Bitcoins verlieren</b>! + Warnung: Wenn Sie Ihre Brieftasche verschlüsseln und Ihre Passphrase verlieren, werden Sie <b>alle Ihre Bitcoins verlieren</b>! Are you sure you wish to encrypt your wallet? - Sind Sie sich sicher, dass Sie Ihre Wallet verschlüsseln möchten? + Sind Sie sich sicher, dass Sie Ihre Brieftasche verschlüsseln möchten? Wallet encrypted - Wallet verschlüsselt + Brieftasche verschlüsselt %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. - %1 wird jetzt beendet, um den Verschlüsselungsprozess abzuschließen. Bitte beachten Sie, dass die Wallet-Verschlüsselung nicht vollständig vor Diebstahl Ihrer Bitcoins durch Schadprogramme schützt, die Ihren Computer befällt. + %1 wird jetzt beendet, um den Verschlüsselungsprozess abzuschließen. Bitte beachten Sie, dass die Brieftaschen-Verschlüsselung nicht vollständig vor Diebstahl Ihrer Bitcoins durch Schadprogramme schützt, die Ihren Computer befällt. IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. - WICHTIG: Alle vorherigen Wallet-Sicherungen sollten durch die neu erzeugte, verschlüsselte Wallet ersetzt werden. Aus Sicherheitsgründen werden vorherige Sicherungen der unverschlüsselten Wallet nutzlos, sobald Sie die neue, verschlüsselte Wallet verwenden. + WICHTIG: Alle vorherigen Brieftaschen-Sicherungen sollten durch die neu erzeugte, verschlüsselte Brieftasche ersetzt werden. Aus Sicherheitsgründen werden vorherige Sicherungen der unverschlüsselten Brieftasche nutzlos, sobald Sie die neue, verschlüsselte Brieftasche verwenden. Wallet encryption failed - Wallet-Verschlüsselung fehlgeschlagen + Brieftaschen-Verschlüsselung fehlgeschlagen Wallet encryption failed due to an internal error. Your wallet was not encrypted. - Die Wallet-Verschlüsselung ist aufgrund eines internen Fehlers fehlgeschlagen. Ihre Wallet wurde nicht verschlüsselt. + Die Brieftaschen-Verschlüsselung ist aufgrund eines internen Fehlers fehlgeschlagen. Ihre Brieftasche wurde nicht verschlüsselt. The supplied passphrases do not match. @@ -201,19 +201,19 @@ Wallet unlock failed - Wallet-Entsperrung fehlgeschlagen + Brieftaschen-Entsperrung fehlgeschlagen The passphrase entered for the wallet decryption was incorrect. - Die eingegebene Passphrase zur Wallet-Entschlüsselung war nicht korrekt. + Die eingegebene Passphrase zur Brieftaschen-Entschlüsselung war nicht korrekt. Wallet decryption failed - Wallet-Entschlüsselung fehlgeschlagen + Brieftaschen-Entschlüsselung fehlgeschlagen Wallet passphrase was successfully changed. - Die Wallet-Passphrase wurde erfolgreich geändert. + Die Brieftaschen-Passphrase wurde erfolgreich geändert. Warning: The Caps Lock key is on! @@ -439,7 +439,7 @@ Indexing blocks on disk... - Reindiziere Blöcke auf Datenträger... + Indiziere Blöcke auf Datenträger... Processing blocks on disk... @@ -636,7 +636,7 @@ Copy transaction ID - Transaktionskennung kopieren + Transaktions-ID kopieren Lock unspent @@ -660,7 +660,7 @@ Copy bytes - Byte kopieren + Bytes kopieren Copy dust @@ -751,7 +751,7 @@ Could not unlock wallet. - Wallet konnte nicht entsperrt werden. + Brieftasche konnte nicht entsperrt werden. New key generation failed. @@ -817,7 +817,7 @@ Set language, for example "de_DE" (default: system locale) - Sprache einstellen, zum Beispiel "de_DE" (default: system locale) + Sprache einstellen, zum Beispiel "de_DE" (Standard: Systemgebietsschema) Start minimized @@ -825,7 +825,7 @@ Set SSL root certificates for payment request (default: -system-) - SSL-Wurzelzertifikate für Zahlungsanforderungen festlegen (Standard: -system-) + SSL-Wurzelzertifikate für Zahlungsanforderungen festlegen (Standard: Systemstandard) Show splash screen on startup (default: %u) @@ -886,6 +886,14 @@ Formular + Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below. + Neueste Transaktionen werden eventuell noch nicht angezeigt, daher könnte Ihr Kontostand veraltet sein. Er wird korrigiert, sobald Ihr Wallet die Synchronisation mit dem Bitcoin-Netzwerk erfolgreich abgeschlossen. Details dazu finden sich weiter unten. + + + Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network. + Versuche, Bitcoins aus noch nicht angezeigten Transaktionen auszugeben, werden vom Netzwerk nicht akzeptiert. + + Number of blocks left Anzahl verbleibender Blöcke @@ -2201,6 +2209,10 @@ Bestätige benutzerdefinierte Wechselgeld-Adresse + The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure? + Die ausgewählte Wechselgeld-Adresse ist nicht Bestandteil dieses Wallets. Einige oder alle Mittel aus Ihrem Wallet könnten an diese Adresse gesendet werden. Wollen Sie das wirklich? + + (no label) (keine Bezeichnung) @@ -2998,6 +3010,10 @@ Eingehende Verbindungen annehmen (Standard: 1, wenn nicht -proxy oder -connect/-noconnect) + Connect only to the specified node(s); -noconnect or -connect=0 alone to disable automatic connections + Verbindungen nur zu spezifizierten Node(s); verwenden Sie -noconnect oder -connect=0 alleine um automatische Verbindungen zu deaktivieren + + Distributed under the MIT software license, see the accompanying file %s or %s Veröffentlicht unter der MIT-Softwarelizenz, siehe beiligende Datei %s oder %s. @@ -3074,8 +3090,12 @@ Befehl ausführen wenn sich eine Wallet-Transaktion verändert (%s im Befehl wird durch die Transaktions-ID ersetzt) - Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) - Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + Extra transactions to keep in memory for compact block reconstructions (default: %u) + Zusätzliche Transaktionen für kompakten Block-Nachbau im Speicher vorhalten (default: %u) + + + If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s) + Sofern dieser Block Bestandteil der Blockchain ist, nehme an das er und seine Vorgänger gültig sind und überspringe ggf. dessen Skriptverifikation (0 um alle zu verifizieren, default: %s, testnet: %s) Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) @@ -3090,6 +3110,14 @@ Wenn sie %s nützlich finden, sind Helfer sehr gern gesehen. Besuchen Sie %s um mehr über das Softwareprojekt zu erfahren. + Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB) + Speicherplatzanforderung durch Kürzen (Pruning) alter Blöcke reduzieren. Dies erlaubt das Aufrufen des sogenannten Pruneblockchain RPC zum Löschen spezifischer Blöcke und und aktiviert das automatische Pruning alter Blöcke, sofern eine Zielgröße in MIB angegeben wird. Dieser Modus ist nicht mit -txindex und -resacan kompatibel. Warnung: Das Rücksetzen dieser Einstellung erfordert das erneute Herunterladen der gesamten Blockchain. (Standard: 0 = deaktiviert das Pruning, 1 = erlaubt manuelles Pruning via RPC, >%u = automatisches Pruning der Blockdateien, um angegebene Maximalgröße nicht zu überschreiten) + + + Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s) + Niedrigste Gebühr (in %s/kB) für Transaktionen einstellen, die bei der Blockerzeugung berücksichtigt werden sollen. (default: %s) + + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Maximale Anzahl an Skript-Verifizierungs-Threads festlegen (%u bis %d, 0 = automatisch, <0 = so viele Kerne frei lassen, Standard: %d) @@ -3114,6 +3142,10 @@ Benutzername und gehashtes Passwort für JSON-RPC Verbindungen. Das Feld <userpw> kommt im Format: <USERNAME>:<SALT>$<HASH>. Ein kanonisches Pythonskript ist in share/rpcuser inbegriffen. Der client benutzt wie gehabt, die rpcuser/rpcpassword Parameter. Diese Option kann mehrere Male spezifiziert werden + Wallet will not create transactions that violate mempool chain limits (default: %u) + Das Wallet erzeugt keine Transaktionen, die das Mempool Chain Limit überschreiten (Standardeinstellung: %u) + + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. Warnung: Das Netzwerk scheint nicht vollständig übereinzustimmen! Einige Miner scheinen Probleme zu haben. @@ -3154,6 +3186,10 @@ Kann Adresse in -%s nicht auflösen: '%s' + Chain selection options: + Chain Auswahloptionen: + + Change index out of range Position des Wechselgelds außerhalb des Bereichs @@ -3222,6 +3258,10 @@ Fehler beim Laden von %s: Das Wallet benötigt eine neuere Version von %s + Error loading %s: You can't disable HD on a already existing HD wallet + Fehler beim Laden von %s: Sie können die hierarchisch deterministische Schlüsselgeneration (HD) für eine bereits existierende HD-Brieftasche nicht deaktivieren + + Error loading block database Fehler beim Laden der Blockdatenbank @@ -3303,7 +3343,7 @@ Rebuild chain state from the currently indexed blocks - Blockkettenindex aus aktuellen Dateien blk000??.dat wiederaufbauen + Blockkettenzustand aus aktuelle indizierten Blöcken wiederaufbauen Rewinding blocks... @@ -3435,7 +3475,7 @@ Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start - Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + Verwende hierarchisch deterministische Schlüsselgenerierung (HD) nach BIP32. Funktioniert nur bei der Erstellung (erster Start) von einer Brieftasche. Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway @@ -3646,6 +3686,10 @@ Adressen von Gegenstellen via DNS-Namensauflösung finden, falls zu wenige Adressen verfügbar sind (Standard: 1, außer bei -connect/-noconnect) + Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d) + Setzt die Serialisierung von Rohtransaktionen oder Block Hex-Daten auf non-verbose mode, nicht-Segwit(0) oder Segwit(1) (default: %d) + + Support filtering of blocks and transaction with bloom filters (default: %u) Unterstütze Blöcke und Transaktionen mit Bloomfiltern zu filtern (default: %u) @@ -3706,6 +3750,10 @@ Ungültige Adresse in -proxy: '%s' + Keypool ran out, please call keypoolrefill first + Der Keypool ist erschöpft. Bitte rufen Sie zunächst keypoolrefill auf. + + Listen for JSON-RPC connections on <port> (default: %u or testnet: %u) <port> nach JSON-RPC-Verbindungen abhören (Standard: %u oder Testnetz: %u) @@ -3774,6 +3822,14 @@ Unbestätigtes Wechselgeld darf beim Senden von Transaktionen ausgegeben werden (Standard: %u) + Starting network threads... + Netzwerk-Threads werden gestartet... + + + The wallet will avoid paying less than the minimum relay fee. + Das Wallet verhindert Zahlungen, die die Mindesttransaktionsgebühr nicht berücksichtigen. + + This is the minimum transaction fee you pay on every transaction. Dies ist die minimale Gebühr die beim Senden einer Transaktion fällig wird. @@ -3790,6 +3846,14 @@ Transaktionsbeträge dürfen nicht negativ sein. + Transaction has too long of a mempool chain + Die Speicherpoolkette der Transaktion ist zu lang. + + + Transaction must have at least one recipient + Die Transaktion muss mindestens einen Empfänger enthalten. + + Unknown network specified in -onlynet: '%s' Unbekannter Netztyp in -onlynet angegeben: '%s' diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts index 0390a378e77..2bbc1546a5a 100644 --- a/src/qt/locale/bitcoin_el_GR.ts +++ b/src/qt/locale/bitcoin_el_GR.ts @@ -41,10 +41,66 @@ &Delete &Διαγραφή + + Choose the address to send coins to + Επιλέξτε διεύθυνση αποστολής των νομισμάτων σας + + + Choose the address to receive coins with + Επιλέξτε διεύθυνση παραλαβής νομισμάτων + + + C&hoose + Ε&πιλογή + + + Sending addresses + Διευθύνσεις αποστολής + + + Receiving addresses + Διευθύνσεις λήψης + + + &Copy Address + &Αντιγραφή Διεύθυνσης + + + Copy &Label + Αντιγραφή&Ετικέτα + + + &Edit + &Διόρθωση + + + Export Address List + Εξαγωγή Λίστας Διεύθυνσεων + + + Comma separated file (*.csv) + Αρχείο οριοθετημένο με κόμματα (*.csv) + + + Exporting Failed + Αποτυχία Εξαγωγής + AddressTableModel - + + Label + Ετικέτα + + + Address + Διεύθυνση + + + (no label) + (χωρίς ετικέτα) + + AskPassphraseDialog @@ -63,6 +119,22 @@ Repeat new passphrase Επανέλαβε τον νέο κωδικό πρόσβασης + + Encrypt wallet + Κρυπτογράφηση πορτοφολιού + + + Unlock wallet + Ξεκλειδωσε το πορτοφολι + + + Change passphrase + Αλλάξτε Φράση Πρόσβασης + + + Wallet unlock failed + Το Ξεκλείδωμα του Πορτοφολιού Απέτυχε + BanTableModel @@ -394,6 +466,26 @@ Confirmed Επικυρωμένες + + Copy address + Αντιγραφή διεύθυνσης + + + Copy label + Αντιγραφή ετικέτας + + + Copy amount + Αντιγραφή ποσού + + + Copy transaction ID + Αντιγραφή ταυτότητας συναλλαγής + + + (no label) + (χωρίς ετικέτα) + EditAddressDialog @@ -417,6 +509,18 @@ &Address &Διεύθυνση + + New receiving address + Νέα Διεύθυνση Λήψης + + + New sending address + Νέα Διεύθυνση Αποστολής + + + Edit receiving address + Διόρθωση Διεύθυνσης Λήψης + FreespaceChecker @@ -1064,7 +1168,15 @@ Remove Αφαίρεση - + + Copy label + Αντιγραφή ετικέτας + + + Copy amount + Αντιγραφή ποσού + + ReceiveRequestDialog @@ -1083,9 +1195,29 @@ &Save Image... &Αποθήκευση εικόνας... + + Address + Διεύθυνση + + + Label + Ετικέτα + RecentRequestsTableModel + + Date + Ημερομήνια + + + Label + Ετικέτα + + + (no label) + (χωρίς ετικέτα) + SendCoinsDialog @@ -1209,7 +1341,15 @@ S&end Αποστολη - + + Copy amount + Αντιγραφή ποσού + + + (no label) + (χωρίς ετικέτα) + + SendCoinsEntry @@ -1374,6 +1514,70 @@ TransactionDesc + + Open until %1 + Ανοιχτό μέχρι %1 + + + %1/offline + %1/αποσυνδεδεμένο + + + 0/unconfirmed, %1 + 0/ανεπιβεβαίωτο, %1 + + + Date + Ημερομηνία + + + Source + Πηγή + + + Generated + Παράχθηκε + + + From + Από + + + unknown + Άγνωστο + + + To + Προς + + + own address + δική σας διεύθυνση + + + watch-only + παρακολούθηση-μόνο + + + label + ετικέτα + + + Credit + Πίστωση + + + not accepted + μη έγκυρο + + + Total credit + Συνολική πίστωση + + + Transaction fee + Κόστος συναλλαγής + TransactionDescDialog @@ -1384,9 +1588,73 @@ TransactionTableModel + + Date + Ημερομήνια + + + Label + Ετικέτα + + + Open until %1 + Ανοιχτό μέχρι %1 + + + watch-only + παρακολούθηση-μόνο + + + (no label) + (χωρίς ετικέτα) + TransactionView + + Copy address + Αντιγραφή διεύθυνσης + + + Copy label + Αντιγραφή ετικέτας + + + Copy amount + Αντιγραφή ποσού + + + Copy transaction ID + Αντιγραφή ταυτότητας συναλλαγής + + + Copy raw transaction + Αντιγραφή ανεπεξέργαστης συναλλαγής + + + Edit label + Επεξεργασία ετικέτας + + + Comma separated file (*.csv) + Αρχείο οριοθετημένο με κόμματα (*.csv) + + + Date + Ημερομήνια + + + Label + Ετικέτα + + + Address + Διεύθυνση + + + Exporting Failed + Αποτυχία Εξαγωγής + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index 91830750671..4b6f242eb79 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -690,7 +690,7 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> - + A fatal error occurred. Bitcoin can no longer continue safely and will quit. @@ -864,7 +864,7 @@ - + Can vary +/- %1 satoshi(s) per input. @@ -1915,7 +1915,7 @@ - + %1 didn't yet exit safely... @@ -1923,7 +1923,7 @@ QObject::QObject - + Error: Specified data directory "%1" does not exist. @@ -2598,7 +2598,7 @@ SendCoinsDialog - + Send Coins Send Coins @@ -2729,17 +2729,7 @@ - - normal - - - - - fast - - - - + Request Replace-By-Fee @@ -2764,7 +2754,7 @@ - + Dust: @@ -2774,7 +2764,7 @@ - + Clear &All Clear &All @@ -2794,7 +2784,7 @@ S&end - + Copy quantity @@ -2829,7 +2819,12 @@ - + + %1 (%2 blocks) + + + + @@ -2911,21 +2906,13 @@ Payment request expired. - - - %n block(s) - - %n block - %n blocks - - - + Pay only the required fee of %1 - + Estimated to begin confirmation within %n block(s). Estimated to begin confirmation within %n block. @@ -2933,7 +2920,7 @@ - + Warning: Invalid Bitcoin address @@ -3070,7 +3057,7 @@ SendConfirmationDialog - + Yes @@ -3905,12 +3892,12 @@ WalletModel - + Send Coins Send Coins - + Fee bump error @@ -4003,7 +3990,7 @@ bitcoin-core - + Options: Options: @@ -4013,22 +4000,22 @@ Specify data directory - + Connect to a node to retrieve peer addresses, and disconnect Connect to a node to retrieve peer addresses, and disconnect - + Specify your own public address Specify your own public address - + Accept command line and JSON-RPC commands Accept command line and JSON-RPC commands - + Distributed under the MIT software license, see the accompanying file %s or %s @@ -4053,7 +4040,7 @@ - + Error: A fatal internal error occurred, see debug.log for details @@ -4063,7 +4050,7 @@ - + Pruning blockstore... @@ -4073,12 +4060,12 @@ Run in the background as a daemon and accept commands - + Unable to start HTTP server. See debug log for details. - + Bitcoin Core Bitcoin Core @@ -4183,11 +4170,21 @@ + + The fee rate (in %s/kB) used to discard change (to fee) if it would be dust at this fee rate (default: %s) Note: We will always discard up to the dust relay fee and a discard fee above that is limited by the longest target fee estimate + + + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications + + This is the transaction fee you may discard if change is smaller than dust at this level + + + Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate. @@ -4419,6 +4416,11 @@ + Invalid amount for -discardfee=<amount>: '%s' + + + + Invalid amount for -fallbackfee=<amount>: '%s' @@ -4518,7 +4520,12 @@ - + + Transaction fee and change calculation failed + + + + Unable to bind to %s on this computer. %s is probably already running. @@ -4588,7 +4595,7 @@ - + Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times @@ -4643,12 +4650,12 @@ - + The transaction amount is too small to send after the fee has been deducted - + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start @@ -4718,7 +4725,7 @@ - + Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s) @@ -4803,7 +4810,7 @@ Transaction amount too small - + Transaction too large for fee policy @@ -4858,22 +4865,22 @@ - + Password for JSON-RPC connections Password for JSON-RPC connections - + Execute command when the best block changes (%s in cmd is replaced by block hash) Execute command when the best block changes (%s in cmd is replaced by block hash) - + Allow DNS lookups for -addnode, -seednode and -connect Allow DNS lookups for -addnode, -seednode and -connect - + (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) @@ -4948,7 +4955,7 @@ - + This is the transaction fee you may pay when fee estimates are not available. @@ -5023,7 +5030,7 @@ - + Keypool ran out, please call keypoolrefill first @@ -5143,7 +5150,7 @@ - + Transaction has too long of a mempool chain @@ -5158,27 +5165,27 @@ Unknown network specified in -onlynet: '%s' - + Insufficient funds Insufficient funds - + Loading block index... Loading block index... - + Add a node to connect to and attempt to keep the connection open Add a node to connect to and attempt to keep the connection open - + Loading wallet... Loading wallet... - + Cannot downgrade wallet Cannot downgrade wallet @@ -5188,12 +5195,12 @@ Cannot write default address - + Rescanning... Rescanning... - + Done loading Done loading diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts index b4ed5e7fd50..16c584c4b10 100644 --- a/src/qt/locale/bitcoin_eo.ts +++ b/src/qt/locale/bitcoin_eo.ts @@ -41,10 +41,78 @@ &Delete &Forigi - + + Choose the address to send coins to + Elekti la adreson por sendi monerojn + + + Choose the address to receive coins with + Elekti la adreson ricevi monerojn kun + + + C&hoose + &Elekti + + + Sending addresses + Sendaj adresoj + + + Receiving addresses + Ricevaj adresoj + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Jen viaj Bitmon-adresoj por sendi pagojn. Zorge kontrolu la sumon kaj la alsendan adreson antaŭ ol sendi. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Jen viaj bitmonaj adresoj por ricevi pagojn. Estas konsilinde uzi apartan ricevan adreson por ĉiu transakcio. + + + &Copy Address + &Kopii Adreson + + + Copy &Label + Kopii &Etikedon + + + &Edit + &Redakti + + + Export Address List + Eksporti Adresliston + + + Comma separated file (*.csv) + Perkome disigita dosiero (*.csv) + + + Exporting Failed + ekspotado malsukcesinta + + + There was an error trying to save the address list to %1. Please try again. + Okazis eraron dum konservo de adreslisto al %1. Bonvolu provi denove. + + AddressTableModel - + + Label + Etikedo + + + Address + Adreso + + + (no label) + (neniu etikedo) + + AskPassphraseDialog @@ -386,6 +454,10 @@ Confirmed Konfirmita + + (no label) + (neniu etikedo) + EditAddressDialog @@ -934,9 +1006,25 @@ &Save Image... &Konservi Bildon... + + Address + Adreso + + + Label + Etikedo + RecentRequestsTableModel + + Label + Etikedo + + + (no label) + (neniu etikedo) + SendCoinsDialog @@ -1016,7 +1104,11 @@ S&end Ŝendi - + + (no label) + (neniu etikedo) + + SendCoinsEntry @@ -1179,9 +1271,33 @@ TransactionTableModel + + Label + Etikedo + + + (no label) + (neniu etikedo) + TransactionView + + Comma separated file (*.csv) + Perkome disigita dosiero (*.csv) + + + Label + Etikedo + + + Address + Adreso + + + Exporting Failed + ekspotado malsukcesinta + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index fc71bf841be..1cac03951c6 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -486,6 +486,10 @@ %1 cliente + Connecting to peers... + Conectando a pares... + + Catching up... Actualizando... @@ -891,7 +895,7 @@ Number of blocks left - Número de bloques dejados + Número de bloques restantes Unknown... @@ -1722,7 +1726,7 @@ WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramification of a command. - ADVERTENCIA: Los estafadores han sido activados, diciéndoles a los usuarios que escriban comandos aquí, robando el contenido de sus monederos. No utilice esta consola sin entender completamente la repercusión de un comando. + ADVERTENCIA: Hay estafadores activos diciendo a los usuarios que escriban comandos aquí y robando el contenido de sus monederos. No utilice esta consola sin entender completamente la repercusión de un comando. Network activity disabled @@ -2473,6 +2477,10 @@ TransactionDesc + + Open for %n more block(s) + Abrir para %n bloque másAbrir para %n bloques más + Open until %1 Abierto hasta %1 @@ -2517,6 +2525,10 @@ , has not been successfully broadcast yet , no ha sido emitido con éxito aún + + , broadcast through %n node(s) + , transmitir a través de %n nodo, transmitir a través de %n nodos + Date Fecha @@ -2557,6 +2569,10 @@ Credit Credito + + matures in %n more block(s) + disponible en %n bloque másdisponible en %n bloques más + not accepted no aceptada @@ -2594,6 +2610,10 @@ Identificador de transacción (ID) + Transaction total size + Tamaño total de transacción + + Output index Indice de salida @@ -2655,6 +2675,10 @@ Label Etiqueta + + Open for %n more block(s) + Abrir para %n bloque másAbrir para %n bloques más + Open until %1 Abierto hasta %1 @@ -2988,6 +3012,18 @@ + Accept connections from outside (default: 1 if no -proxy or -connect/-noconnect) + Aceptar conexiones desde el exterior (predeterminado: 1 si no -proxy o -connect/-desconectar) + + + Connect only to the specified node(s); -noconnect or -connect=0 alone to disable automatic connections + Conectar sólo al nodo(s) especificado; -no conectar or -conectar=solo 0 para deshabilitar conexiones automáticas + + + Distributed under the MIT software license, see the accompanying file %s or %s + Distribuido bajo la licencia de software MIT, vea el archivo adjunto %s o %s + + If <category> is not supplied or if <category> = 1, output all debugging information. Si <category> no es proporcionado o si <category> =1, muestra toda la información de depuración. @@ -3065,6 +3101,14 @@ Ejecutar comando cuando una transacción del monedero cambia (%s en cmd se remplazará por TxID) + Extra transactions to keep in memory for compact block reconstructions (default: %u) + Transacciones extra a mantener en la memoria para reconstrucciones de bloque compacto (predeterminado: %u) + + + If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s) + Si este bloque está en la cadena asuma que sus predecesores y él son válidos y potencialmente se saltan su script de verificación (0 para verificar todo, predeterminado: %s, testnet: %s) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) Ajuste máximo permitido del tiempo offset medio de pares. La perspectiva local de tiempo se verá influenciada por los pares anteriores y posteriores a esta cantidad. (Por defecto: %u segundos) @@ -3081,6 +3125,14 @@ Contribuya si encuentra %s de utilidad. Visite %s para mas información acerca del programa. + Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB) + Reducir los requerimientos de almacenamiento habilitando la poda (eliminación) de los bloques viejos. Esto permite que la cadena de bloqueo RPC sea llamada para eliminar bloques específicos, y habilita la poda automática de bloques viejos si se provee el tamaño de un objetivo en MiB. Este modo es incompatible con -txindex and -rescan. Precaución: Revertir este ajuste requiere volver a descargar la cadena de bloqueo completa. (predefinido: 0 = deshabilita bloques de poda, 1 = permite la poda manual mediante RPC, >%u = elimina automáticamente los archivos de bloqueo para permanecer bajo el tamaño del objetivo especificado en MiB) + + + Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s) + Establecer la tasa más baja (en %s/kB) por transacciones para incluirse en la creación de bloque. (predeterminado: %s) + + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Establecer el número de hilos (threads) de verificación de scripts (entre %u y %d, 0 = automático, <0 = dejar libres ese número de núcleos; predeterminado: %d) @@ -3089,6 +3141,10 @@ La base de datos de bloques contiene un bloque que parece ser del futuro. Esto puede ser porque la fecha y hora de tu ordenador están mal ajustados. Reconstruye la base de datos de bloques solo si estas seguro de que la fecha y hora de tu ordenador estan ajustados correctamente. + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications + Esta es una versión de prueba prelanzada - utilícelo a su propio riesgo - no lo utilice para aplicaciones de minería o comerciales + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain No es posible reconstruir la base de datos a un estado anterior. Debe descargar de nuevo la cadena de bloques. @@ -3097,6 +3153,22 @@ Utiliza UPnP para asignar el puerto de escucha (predeterminado: 1 cuando esta escuchando sin -proxy) + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times + Nombre de usuario y contraseña numerada para conexiones JSON-RPC. El campo <userpw> viene en el formato: <USERNAME>:<SALT>$<HASH>. Un script canónico de python está incluído en compartir/usuario rpc. Entonces el cliente se conecta normalmente utilizando la pareja de argumentos usuario rpc=<USERNAME>/contraseña rpc=<PASSWORD>. Esta opción puede ser especificada múltiples veces + + + Wallet will not create transactions that violate mempool chain limits (default: %u) + El monedero no creará transacciones que violen los límites de la cadena mempool (predeterminado: %u) + + + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. + Advertencia: ¡La red no parece coincidir del todo! Algunos mineros parecen estar experimentando problemas. + + + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. + Advertencia: ¡No parecemos estar del todo con nuestros pares! Puede que necesite actualizarse, o puede que otros nodos necesiten actualizarse. + + You need to rebuild the database using -reindex-chainstate to change -txindex Necesita reconstruir la base de datos usando -reindex-chainstate para cambiar -txindex @@ -3129,6 +3201,10 @@ No se puede resolver -%s direccion: '%s' + Chain selection options: + Opciones de selección en cadena: + + Change index out of range Cambio de indice fuera de rango @@ -3325,6 +3401,10 @@ Usar UPnP para asignar el puerto de escucha (predeterminado:: %u) + Use the test chain + Utilice la cadena de prueba + + User Agent comment (%s) contains unsafe characters. El comentario del Agente de Usuario (%s) contiene caracteres inseguros. @@ -3619,6 +3699,10 @@ Mostrar depuración (por defecto: %u, proporcionar <category> es opcional) + Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect/-noconnect) + Preguntar por direcciones pares al buscar DNS, si baja en las direcciones (predeterminado: 1 a menos que -connect/-noconnect) + + Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d) https://www.transifex.com/joyful-world/breaking-english/ Establecer la serialización de las transacciones sin procesar o el bloque hex devuelto en non-verbose mode, non-segwit(O) o segwit(1) (default: %d) @@ -3628,6 +3712,14 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d Admite filtrado de bloques, y transacciones con filtros Bloom. Reduce la carga de red. ( por defecto :%u) + This is the transaction fee you may pay when fee estimates are not available. + Esta es la tarifa de cuota que debe pagar cuando las estimaciones de tarifas no estén disponibles. + + + This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. + Este producto incluye software desarrollado por el Proyecto OpenSSL para utilizarlo en el juego de herramientas OpenSSL %s y software criptográfico escrito por Eric Young y software UPnP escrito por Thomas Bernard. + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. La longitud total de la cadena de versión de red ( %i ) supera la longitud máxima ( %i ) . Reducir el número o tamaño de uacomments . @@ -3660,6 +3752,10 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d Los pares de listas blancas que se conectan desde la dirección IP dada (por ejemplo, 1.2.3.4) o la red marcada CIDR (por ejemplo, 1.2.3.0/24). Se puede especificar varias veces. + %s is set very high! + ¡%s se establece muy alto! + + (default: %s) (predeterminado: %s) @@ -3680,6 +3776,10 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d Dirección -proxy inválida: '%s' + Keypool ran out, please call keypoolrefill first + Keypool se ha agotado, llame a keypoolrefill primero + + Listen for JSON-RPC connections on <port> (default: %u or testnet: %u) Escuchar conexiones JSON-RPC en <puerto> (predeterminado: %u o testnet: %u) @@ -3716,6 +3816,10 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d Relay non-P2SH multisig (default: %u) + Send transactions with full-RBF opt-in enabled (default: %u) + Enviar transacciones con full-RBF opt-in habilitado (predeterminado: %u) + + Set key pool size to <n> (default: %u) Ajustar el número de claves en reserva <n> (predeterminado: %u) @@ -3748,10 +3852,34 @@ Establecer la serialización de las transacciones sin procesar o el bloque hex d Iniciando funciones de red... + The wallet will avoid paying less than the minimum relay fee. + El monedero evitará pagar menos que la cuota de retransmisión mínima. + + + This is the minimum transaction fee you pay on every transaction. + Esta es la tarifa mínima de transacción que usted paga en cada transacción. + + + This is the transaction fee you will pay if you send a transaction. + Esta es la cuota de transacción que pagará si envía una transacción. + + Threshold for disconnecting misbehaving peers (default: %u) Umbral para la desconexión de pares con mal comportamiento (predeterminado: %u) + Transaction amounts must not be negative + Las cantidades de transacción no deben ser negativa + + + Transaction has too long of a mempool chain + La transacción tiene demasiado tiempo de una cadena de mempool + + + Transaction must have at least one recipient + La transacción debe de tener al menos un receptor + + Unknown network specified in -onlynet: '%s' La red especificada en -onlynet '%s' es desconocida diff --git a/src/qt/locale/bitcoin_es_ES.ts b/src/qt/locale/bitcoin_es_ES.ts index 7865483183d..e0ddf7d530f 100644 --- a/src/qt/locale/bitcoin_es_ES.ts +++ b/src/qt/locale/bitcoin_es_ES.ts @@ -318,6 +318,22 @@ Abrir &URI... + Click to disable network activity. + Haz click para desactivar la actividad de red. + + + Network activity disabled. + Actividad de red desactivada. + + + Click to enable network activity again. + Haz click para reactivar la actividad de red. + + + Syncing Headers (%1%)... + Sincronizando cabeceras (%1%)... + + Reindexing blocks on disk... Reindexando bloques en disco... @@ -470,6 +486,10 @@ %1 cliente + Connecting to peers... + Conectando a pares... + + Catching up... Actualizando... @@ -519,7 +539,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> El monedero está <b>cifrado</b> y actualmente <b>bloqueado</b> - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + Ha ocurrido un error fatal. Bitcoin no puede continuar de manera segura y se cerrará. + + CoinControlDialog @@ -854,14 +878,42 @@ Formulario + Number of blocks left + Número de bloques restantes + + + Unknown... + Desconocido... + + Last block time Hora del último bloque + Progress + Progreso + + + Progress increase per hour + Incremento del progreso por hora + + + calculating... + calculando... + + + Estimated time left until synced + Tiempo estimado restante hasta sincronización completa + + Hide Ocultar - + + Unknown. Syncing Headers (%1)... + Desconocido. Sincronizando cabeceras (%1)... + + OpenURIDialog @@ -1296,7 +1348,15 @@ Node/Service Nodo/Servicio - + + NodeId + NodeId + + + Ping + Ping + + QObject @@ -1339,9 +1399,17 @@ %1 and %2 %1 y %2 - + + %1 didn't yet exit safely... + %1 aún no ha salido de manera segura... + + QObject::QObject + + Error: Specified data directory "%1" does not exist. + Error: directorio especificado "%1" no existe. + QRImageWidget @@ -1712,6 +1780,10 @@ Eliminar + Copy URI + Copiar URL + + Copy label Copiar capa @@ -1937,6 +2009,10 @@ Polvo: + Confirmation time target: + Tiempo objetivo de confirmación: + + Clear &All Vaciar &todo @@ -3483,6 +3559,10 @@ Aviso: fichero de monedero corrupto, datos recuperados! Original %s guardado como %s en %s; si su balance de transacciones es incorrecto, debe restaurar desde una copia de seguridad. + %s is set very high! + %s es demasiado alto! + + (default: %s) (predeterminado: %s) @@ -3539,6 +3619,10 @@ Relay non-P2SH multisig (default: %u) + Send transactions with full-RBF opt-in enabled (default: %u) + Enviar transaciones con RBF-completo opt-in activado (default: %u) + + Set key pool size to <n> (default: %u) Ajustar el número de claves en reserva <n> (predeterminado: %u) diff --git a/src/qt/locale/bitcoin_et_EE.ts b/src/qt/locale/bitcoin_et_EE.ts index d96ffa42f5b..9b0c9083815 100644 --- a/src/qt/locale/bitcoin_et_EE.ts +++ b/src/qt/locale/bitcoin_et_EE.ts @@ -88,6 +88,10 @@ Sisestatud paroolid ei kattu. + Wallet unlock failed + Rahakoti lahtilukustamine ebaõnnestus + + Wallet decryption failed Rahakoti dekrüpteerimine ebaõnnestus @@ -110,6 +114,14 @@ &Ülevaade + Quit application + Välju rakendusest + + + &Options... + &Valikud... + + Open &URI... Ava &URI... @@ -126,14 +138,30 @@ Rahakott + &Send + &Saada + + + &Show / Hide + &Näita / Peida + + &File &Fail + &Settings + &Seaded + + &Help &Abi + &Command-line options + &Käsurea valikud + + %1 behind %1 ajast maas @@ -204,6 +232,10 @@ EditAddressDialog + &Address + &Aadress + + New key generation failed. Uue võtme genereerimine ebaõnnestus. diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts index c9cfad0f2a5..c9aa1b56249 100644 --- a/src/qt/locale/bitcoin_fa.ts +++ b/src/qt/locale/bitcoin_fa.ts @@ -62,6 +62,14 @@ آدرس های گیرنده + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + اینها آدرس های شما برای فرستادن پرداخت هاست. همیشه قبل از فرستادن سکه ها مقدار و آدرس دریافت کننده را چک کنید. + + + &Copy Address + کپی کردن آدرس + + Copy &Label کپی و برچسب‌&گذاری @@ -69,6 +77,14 @@ &Edit &ویرایش + + Export Address List + صدور لیست آدرس ها + + + Exporting Failed + صدور موفق نبود + AddressTableModel @@ -108,14 +124,30 @@ رمزنگاری کیف پول + This operation needs your wallet passphrase to unlock the wallet. + این عملیات نیاز به عبارت کیف پول شما برای بازگشایی کیف پول دارد + + Unlock wallet باز کردن قفل کیف پول + This operation needs your wallet passphrase to decrypt the wallet. + این عملیات نیاز به عبارت کیف پول شما برای رمزگشایی کیف پول دارد. + + Decrypt wallet رمزگشایی کیف پول + Change passphrase + تغییر گذرواژه + + + Enter the old passphrase and new passphrase to the wallet. + عبارت کهنه و جدید کیف پول را وارد کنید. + + Confirm wallet encryption تأیید رمزنگاری کیف پول @@ -250,6 +282,18 @@ باز کردن &آدرس + Click to disable network activity. + برای غیر فعال کردن فعالیت شبکه کلیک کنید. + + + Network activity disabled. + فعالیت شبکه غیر فعال شد. + + + Click to enable network activity again. + برای فعال کردن دوباره فعالیت شبکه کلیک کنید. + + Reindexing blocks on disk... بازنشانی بلوک‌ها روی دیسک... @@ -507,6 +551,10 @@ تأیید شده + Copy address + کپی ادرس + + Copy label کپی برچسب @@ -531,6 +579,18 @@ کپی تعداد + Copy fee + رونوشت کارمزد + + + Copy bytes + کپی کردن بایت ها + + + Copy change + کپی کردن تغییر + + (%1 locked) (%1 قفل شده) @@ -698,10 +758,30 @@ فرم + Unknown... + مشخص نیست + + Last block time زمان آخرین بلوک + Progress + پیشروی + + + Progress increase per hour + پیشروی در هر ساعت بیشتر میشود + + + calculating... + در حال محاسبه... + + + Estimated time left until synced + زمان تخمینی تا سینک شدن + + Hide پنهان کردن @@ -921,6 +1001,10 @@ PaymentServer + + Invalid payment request. + درخواست پرداخت نامعتبر. + PeerTableModel @@ -1085,6 +1169,10 @@ در: + Out: + خروجی: + + Debug log file فایلِ لاگِ اشکال زدایی @@ -1093,6 +1181,26 @@ پاکسازی کنسول + 1 &hour + 1 ساعت + + + 1 &day + 1 روز + + + 1 &week + 1 هفته + + + 1 &year + 1 سال + + + Ban for + محدود شده برای + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. دکمه‌های بالا و پایین برای پیمایش تاریخچه و <b>Ctrl-L</b> برای پاک کردن صفحه. @@ -1329,6 +1437,18 @@ کپی مقدار + Copy fee + رونوشت کارمزد + + + Copy bytes + کپی کردن بایت ها + + + Copy change + کپی کردن تغییر + + (no label) (بدون برچسب) @@ -1515,6 +1635,10 @@ TransactionView + Copy address + کپی ادرس + + Copy label کپی برچسب @@ -1534,6 +1658,10 @@ Address آدرس + + Exporting Failed + صدور موفق نبود + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_fa_IR.ts b/src/qt/locale/bitcoin_fa_IR.ts index 1e829aff9eb..b0acc67b920 100644 --- a/src/qt/locale/bitcoin_fa_IR.ts +++ b/src/qt/locale/bitcoin_fa_IR.ts @@ -2,8 +2,12 @@ AddressBookPage + Right-click to edit address or label + برای ویرایش آدرس یا برچسب روی آن راست کلیک کنید + + Create a new address - گشایش حسابی جدید + گشایش حساب جدید &New @@ -37,9 +41,65 @@ &Delete حذف + + Choose the address to send coins to + آدرس برای ارسال کوین‌ها را انتخاب کنید + + + Choose the address to receive coins with + انتخاب آدرس جهت دریافت سکه‌ها با آن + + + C&hoose + انتخاب + + + Sending addresses + آدرس‌های فرستنده + + + Receiving addresses + آدرس‌های گیرنده + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + اینها آدرس‌های بیتکوین شما برای ارسال وجوه هستند. همیشه قبل از ارسال، مقدار و آدرس گیرنده را بررسی کنید. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + اینها آدرس‌های بیتکوین شما برای دریافت وجوه هستند. توصیه می‌شود برای هر دریافت از یک آدرس جدید استفاده کنید. + + + &Copy Address + کپی آدرس + + + Copy &Label + کپی برچسب + + + &Edit + ویرایش + + + Export Address List + از فهرست آدرس خروجی گرفته شود + + + Exporting Failed + گرفتن خروجی به مشکل خورد + AddressTableModel + + Label + برچسب + + + Address + آدرس + AskPassphraseDialog @@ -59,6 +119,26 @@ Repeat new passphrase رمز/پَس فرِیز را دوباره وارد کنید + + Encrypt wallet + رمزگذاری کیف پول + + + Decrypt wallet + رمزگشایی کیف پول + + + Change passphrase + تغییر رمزعبور + + + Confirm wallet encryption + تایید رمزگذاری کیف پول + + + Wallet encrypted + کیف پول رمزگذاری شده است + BanTableModel @@ -75,7 +155,7 @@ &Overview - و بازبینی + بازبینی Show general overview of wallet @@ -83,7 +163,7 @@ &Transactions - و تراکنش + تراکنش Browse transaction history @@ -99,7 +179,7 @@ About &Qt - درباره و Qt + درباره Qt Show information about Qt @@ -107,15 +187,15 @@ &Options... - و انتخابها + انتخاب ها &Encrypt Wallet... - و رمزگذاری wallet + رمزگذاری کیف پول &Backup Wallet... - و گرفتن نسخه پیشتیبان از wallet + تهیه نسخه پشتیبان از کیف پول &Change Passphrase... @@ -126,16 +206,28 @@ دریافت آدرس ها + Send coins to a Bitcoin address + ارسال کوین به آدرس بیت کوین + + Backup wallet to another location گرفتن نسخه پیشتیبان در آدرسی دیگر Change the passphrase used for wallet encryption - رمز مربوط به رمزگذاریِ wallet را تغییر دهید + رمز عبور مربوط به رمزگذاریِ کیف پول را تغییر دهید + + + &Debug window + پنجره دیباگ + + + &Verify message... + تایید پیام Bitcoin - bitcoin + بیت کوین Wallet @@ -143,23 +235,23 @@ &Send - و ارسال + ارسال &Show / Hide - &نمایش/ عدم نمایش و + نمایش/ عدم نمایش &File - و فایل + فایل &Settings - و تنظیمات + تنظیمات &Help - و راهنما + راهنما Tabs toolbar @@ -171,7 +263,7 @@ Up to date - روزآمد + به روز Catching up... @@ -179,7 +271,7 @@ Sent transaction - ارسال تراکنش + تراکنش ارسالی Incoming transaction @@ -197,21 +289,85 @@ CoinControlDialog + Coin Selection + انتخاب کوین + + + Quantity: + مقدار + + Amount: میزان وجه: + Fee: + هزینه + + + Change: + تغییر + + + (un)select all + (عدم)انتخاب همه + + Amount میزان + Received with label + دریافت شده با برچسب + + + Received with address + دریافت شده با آدرس + + Date تاریخ + Confirmations + تاییدیه + + Confirmed تایید شده + + Copy address + کپی آدرس + + + Copy label + کپی برچسب + + + Copy amount + کپی مقدار + + + Copy transaction ID + کپی شناسه تراکنش + + + Copy quantity + کپی مقدار + + + Copy fee + کپی هزینه + + + yes + بله + + + no + خیر + EditAddressDialog @@ -221,15 +377,35 @@ &Label - و برچسب + برچسب &Address - حساب& + آدرس + + + New receiving address + آدرس دریافتی جدید + + + New sending address + آدرس ارسالی جدید + + + Edit receiving address + ویرایش آدرس دریافتی + + + Edit sending address + ویرایش آدرس ارسالی FreespaceChecker + + name + نام + HelpMessageDialog @@ -245,6 +421,10 @@ Intro + Welcome + خوش آمدید + + Error خطا @@ -255,6 +435,18 @@ Form فرم + + Unknown... + ناشناس... + + + calculating... + در حال محاسبه... + + + Hide + پنهان کردن + OpenURIDialog @@ -263,7 +455,15 @@ OptionsDialog Options - انتخاب/آپشن + گزینه ها + + + MB + مگابایت + + + &Reset Options + تنظیم مجدد گزینه ها &Network @@ -274,12 +474,24 @@ کیف پول + &Port: + پورت: + + + &Window + پنجره + + + &Display + نمایش + + &OK - و تایید + تایید &Cancel - و رد + لغو default @@ -296,6 +508,26 @@ The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. اطلاعات نمایش داده شده ممکن است روزآمد نباشد. wallet شما به صورت خودکار بعد از برقراری اتصال با شبکه bitcoin به روز می شود اما این فرایند هنوز تکمیل نشده است. + + Available: + در دسترس: + + + Pending: + در حال انتظار: + + + Total: + کل: + + + Spendable: + قابل مصرف: + + + Recent transactions + تراکنش های اخیر + PaymentServer @@ -347,22 +579,46 @@ &Label: - و برچسب + برچسب: &Message: پیام: - + + Remove + حذف + + + Copy label + کپی برچسب + + + Copy amount + کپی مقدار + + ReceiveRequestDialog Copy &Address کپی آدرس + + Address + آدرس + + + Label + برچسب + RecentRequestsTableModel + + Label + برچسب + SendCoinsDialog @@ -375,14 +631,34 @@ وجوه ناکافی + Quantity: + مقدار + + Amount: میزان وجه: + Fee: + هزینه + + + Change: + تغییر + + + Hide + پنهان کردن + + Send to multiple recipients at once ارسال همزمان به گیرنده های متعدد + Clear &All + پاک کردن همه + + Balance: مانده حساب: @@ -394,32 +670,36 @@ S&end و ارسال + + Copy quantity + کپی مقدار + + + Copy amount + کپی مقدار + + + Copy fee + کپی هزینه + SendCoinsEntry A&mount: - و میزان وجه + میزان وجه Pay &To: - پرداخت و به چه کسی + پرداخت به: &Label: - و برچسب - - - Alt+A - Alt و A + برچسب: Paste address from clipboard - آدرس را بر کلیپ بورد کپی کنید - - - Alt+P - Alt و P + استفاده از آدرس کلیپ بورد Message: @@ -448,23 +728,39 @@ SignVerifyMessageDialog &Sign Message - و امضای پیام - - - Alt+A - Alt و A + امضای پیام Paste address from clipboard آدرس را بر کلیپ بورد کپی کنید - Alt+P - Alt و P + Enter the message you want to sign here + پیامی که می خواهید امضا کنید را اینجا وارد کنید + + + Signature + امضا Sign &Message - و امضای پیام + امضای پیام + + + Clear &All + پاک کردن همه + + + &Verify Message + تایید پیام + + + Verify &Message + تایید پیام + + + The entered address is invalid. + آدرس وارد شده نامعتبر است. @@ -479,6 +775,26 @@ TransactionDesc + + Status + وضعیت + + + Source + منبع + + + Generated + تولید شده + + + From + از + + + To + به + TransactionDescDialog @@ -489,9 +805,65 @@ TransactionTableModel + + Label + برچسب + + + Unconfirmed + تایید نشده + + + Received from + دریافت شده از + + + Sent to + ارسال شده به + + + Mined + استخراج شده + TransactionView + + Sent to + ارسال شده به + + + Mined + استخراج شده + + + Copy address + کپی آدرس + + + Copy label + کپی برچسب + + + Copy amount + کپی مقدار + + + Copy transaction ID + کپی شناسه تراکنش + + + Label + برچسب + + + Address + آدرس + + + Exporting Failed + گرفتن خروجی به مشکل خورد + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts index ef76abc098e..38f0e1444cb 100644 --- a/src/qt/locale/bitcoin_fi.ts +++ b/src/qt/locale/bitcoin_fi.ts @@ -41,10 +41,66 @@ &Delete &Poista + + Choose the address to send coins to + Valitse osoite johon kolikot lähetetään + + + Choose the address to receive coins with + Valitse osoite kolikoiden vastaanottamiseen + + + C&hoose + V&alitse + + + Sending addresses + Lähetysosoitteet + + + Receiving addresses + Vastaanotto-osoitteet + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Nämä ovat Bitcoin-osoitteesi maksujen lähettämistä varten. Tarkista aina määrä ja vastaanotto-osoite ennen kolikoiden lähettämistä. + + + &Copy Address + &Kopioi osoite + + + Copy &Label + Kopioi &nimike + + + &Edit + &Muokkaa + + + Export Address List + Vie osoitelista + + + Exporting Failed + Vienti epäonnistui + AddressTableModel - + + Label + Nimike + + + Address + Osoite + + + (no label) + (ei nimikettä) + + AskPassphraseDialog @@ -63,7 +119,55 @@ Repeat new passphrase Toista uusi tunnuslause - + + Encrypt wallet + Salaa lompakko + + + Unlock wallet + Avaa lompakko + + + Decrypt wallet + Pura lompakon salaus + + + Change passphrase + Vaihda salasana + + + Confirm wallet encryption + Vahvista lompakon salaaminen + + + Are you sure you wish to encrypt your wallet? + Oletko varma, että haluat salata lompakkosi? + + + Wallet encrypted + Lompakko salattiin + + + Wallet encryption failed + Lompakon salaus epäonnistui + + + Wallet unlock failed + Lompakon lukituksen avaaminen epäonnistui + + + Wallet decryption failed + Lompakon salauksen purkaminen epäonnistui + + + Wallet passphrase was successfully changed. + Lompakon salasana vaihdettiin onnistuneesti. + + + Warning: The Caps Lock key is on! + Varoitus: Caps Lock-painike on päällä! + + BanTableModel @@ -162,6 +266,18 @@ Avaa &URI... + Click to disable network activity. + Paina poistaaksesi verkkoyhteysilmaisin käytöstä. + + + Network activity disabled. + Verkkoyhteysmittari pois käytöstä + + + Click to enable network activity again. + Paina ottaaksesi verkkoyhteysilmaisin uudelleen käyttöön. + + Reindexing blocks on disk... Ladataan lohkoindeksiä... @@ -314,6 +430,10 @@ %1-asiakas + Connecting to peers... + Yhdistetään vertaisiin... + + Catching up... Saavutetaan verkkoa... @@ -434,7 +554,75 @@ Confirmed Vahvistettu - + + Copy address + Kopioi osoite + + + Copy label + Kopioi nimike + + + Copy amount + Kopioi määrä + + + Copy transaction ID + Kopioi transaktion ID + + + Lock unspent + Lukitse käyttämättömät + + + Unlock unspent + Avaa käyttämättömien lukitus + + + Copy quantity + Kopioi kappalemäärä + + + Copy fee + Kopioi rahansiirtokulu + + + Copy after fee + Kopioi rahansiirtokulun jälkeen + + + Copy bytes + Kopioi tavut + + + Copy dust + Kopioi tomu + + + Copy change + Kopioi vaihtorahat + + + (%1 locked) + (%1 lukittu) + + + yes + kyllä + + + no + ei + + + (no label) + (ei nimikettä) + + + (change) + (vaihtoraha) + + EditAddressDialog @@ -457,7 +645,19 @@ &Address &Osoite - + + New receiving address + Uusi vastaanotto-osoite + + + New sending address + Uusi lähetysosoite + + + New key generation failed. + Uuden avaimen luonti epäonnistui. + + FreespaceChecker @@ -586,10 +786,30 @@ Lomake + Unknown... + Tunnistamaton.. + + Last block time Viimeisimmän lohkon aika + Progress + Tila + + + Progress increase per hour + Edistymisen kasvu tunnissa + + + calculating... + lasketaan.. + + + Estimated time left until synced + Arvioitu jäljellä oleva aika, kunnes synkronoitu + + Hide Piilota @@ -928,7 +1148,11 @@ Node/Service Noodi/Palvelu - + + Ping + Vasteaika + + QObject @@ -974,9 +1198,17 @@ QObject::QObject - + + Error: %1 + Virhe: %1 + + QRImageWidget + + Save QR Code + Tallenna QR-koodi + RPCConsole @@ -1137,6 +1369,10 @@ Yhteyskokeilun odotus + Min Ping + Pienin vasteaika + + Time Offset Ajan poikkeama @@ -1197,6 +1433,10 @@ 1 &vuosi + Welcome to the %1 RPC console. + Tervetuloa %1 RPC-konsoliin. + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Ylös- ja alas-nuolet selaavat historiaa ja <b>Ctrl-L</b> tyhjentää ruudun. @@ -1323,7 +1563,15 @@ Remove Poista - + + Copy label + Kopioi nimike + + + Copy amount + Kopioi määrä + + ReceiveRequestDialog @@ -1342,6 +1590,22 @@ &Save Image... &Tallenna kuva + + Address + Osoite + + + Amount + Määrä + + + Label + Nimike + + + Message + Viesti + RecentRequestsTableModel @@ -1349,7 +1613,23 @@ Date Aika - + + Label + Nimike + + + Message + Viesti + + + (no label) + (ei nimikettä) + + + Requested + Pyydetty + + SendCoinsDialog @@ -1484,7 +1764,43 @@ S&end &Lähetä - + + Copy quantity + Kopioi kappalemäärä + + + Copy amount + Kopioi määrä + + + Copy fee + Kopioi rahansiirtokulu + + + Copy after fee + Kopioi rahansiirtokulun jälkeen + + + Copy bytes + Kopioi tavut + + + Copy dust + Kopioi tomu + + + Copy change + Kopioi vaihtorahat + + + or + tai + + + (no label) + (ei nimikettä) + + SendCoinsEntry @@ -1677,6 +1993,14 @@ Date Aika + + Message + Viesti + + + Amount + Määrä + TransactionDescDialog @@ -1691,13 +2015,49 @@ Date Aika + + Label + Nimike + + + (no label) + (ei nimikettä) + TransactionView + Copy address + Kopioi osoite + + + Copy label + Kopioi nimike + + + Copy amount + Kopioi määrä + + + Copy transaction ID + Kopioi transaktion ID + + Date Aika + + Label + Nimike + + + Address + Osoite + + + Exporting Failed + Vienti epäonnistui + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts index 21800231596..830e6bb05f1 100644 --- a/src/qt/locale/bitcoin_fr.ts +++ b/src/qt/locale/bitcoin_fr.ts @@ -887,7 +887,7 @@ Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below. - Les transactions récentes ne sont peut-être pas encore visibles, et par conséquent, le solde de votre porte-monnaie est peut-être erroné. Cette information sera juste une fois que votre porte-monnaie aura fini de se synchroniser avec le réseau Bitcoin, tel que décrit ci-dessous. + Les transactions récentes ne sont peut-être pas encore visibles et par conséquent le solde de votre porte-monnaie est peut-être erroné. Cette information sera juste quand votre porte-monnaie aura fini de se synchroniser avec le réseau Bitcoin, comme décrit ci-dessous. Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network. @@ -903,7 +903,7 @@ Last block time - Horodatage du dernier bloc + Estampille temporelle du dernier bloc Progress @@ -1009,7 +1009,7 @@ Active command-line options that override above options: - Options actives de ligne de commande qui annulent les options ci-dessus : + Options de ligne de commande actives qui remplacent les options ci-dessus : Reset all client options to default. @@ -1081,7 +1081,7 @@ Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. - S'affiche, si le mandataire SOCKS5 par défaut fourni est utilisé pour atteindre les pairs par ce type de réseau. + Indique si le mandataire SOCKS5 par défaut fourni est utilisé pour atteindre des pairs par ce type de réseau. IPv4 @@ -1366,7 +1366,7 @@ NodeId - NodeId + ID de nœud Ping @@ -1646,7 +1646,7 @@ Last block time - Horodatage du dernier bloc + Estampille temporelle du dernier bloc &Open @@ -2178,7 +2178,7 @@ The transaction was rejected with the following reason: %1 - La transaction a été rejetée pour la raison suivante: %1 + La transaction a été rejetée pour la raison suivante : %1 A fee higher than %1 is considered an absurdly high fee. @@ -3623,7 +3623,7 @@ Whether to operate in a blocks only mode (default: %u) - Faut-il fonctionner en mode blocs seulement (par défaut : %u) + Fonctionner ou non en mode blocs seulement (par défaut : %u) Zapping all transactions from wallet... @@ -3643,7 +3643,7 @@ Allow DNS lookups for -addnode, -seednode and -connect - Autoriser les recherches DNS pour -addnode, -seednode et -connect + Autoriser les consultations DNS pour -addnode, -seednode et -connect Loading addresses... @@ -3691,7 +3691,7 @@ Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect/-noconnect) - Requête d'adresses de paires par recherche DNS, si il y a peu d'adresses (par défaut : 1 sauf si -connect/-noconnect) + Requête d'adresses de paires par consultation DNS, si il y a peu d'adresses (par défaut : 1 sauf si -connect/-noconnect) Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d) @@ -3751,7 +3751,7 @@ Always query for peer addresses via DNS lookup (default: %u) - Toujours demander les adresses des pairs par recherche DNS (par défaut : %u) + Toujours demander les adresses des pairs par consultation DNS (par défaut : %u) How many blocks to check at startup (default: %u, 0 = all) @@ -3795,7 +3795,7 @@ Prepend debug output with timestamp (default: %u) - Ajouter l'horodatage au début de la sortie de débogage (par défaut : %u) + Ajouter l'estampille temporelle au début de la sortie de débogage (par défaut : %u) Relay and mine data carrier transactions (default: %u) @@ -3807,7 +3807,7 @@ Send transactions with full-RBF opt-in enabled (default: %u) - Envoyer des transactions avec « RBF opt-in » complet activé (par défaut : %u) + Envoyer les transactions avec « full-RBF opt-in » activé (par défaut : %u) Set key pool size to <n> (default: %u) diff --git a/src/qt/locale/bitcoin_fr_FR.ts b/src/qt/locale/bitcoin_fr_FR.ts index 4d02aa5114d..c10cdf95a2f 100644 --- a/src/qt/locale/bitcoin_fr_FR.ts +++ b/src/qt/locale/bitcoin_fr_FR.ts @@ -15,7 +15,7 @@ Copy the currently selected address to the system clipboard - Copier l'adresse surlignée dans votre presse-papiers + Copier l'adresse sélectionnée dans le presse-papiers &Copy @@ -41,10 +41,62 @@ &Delete &Supprimer + + Choose the address to send coins to + Choisissez une adresse où envoyer les bitcoins + + + Choose the address to receive coins with + Choisissez une adresse où recevoir les bitcoins + + + C&hoose + C&hoisir + + + Sending addresses + Adresses d'envoi + + + Receiving addresses + Adresses de réception + + + Copy &Label + Copier &Étiquette + + + &Edit + &Éditer + + + Export Address List + Exporter la liste d'adresses + + + Comma separated file (*.csv) + Valeurs séparées par des virgules (*.csv) + + + Exporting Failed + Échec de l'export + AddressTableModel - + + Label + Étiquette + + + Address + Adresse + + + (no label) + (aucune étiquette) + + AskPassphraseDialog @@ -63,6 +115,26 @@ Repeat new passphrase Répétez la phrase de passe + + Encrypt wallet + Chiffrer le porte-monnaie + + + Unlock wallet + Déverrouiller le porte-monnaie + + + Decrypt wallet + Décrypter le porte-monnaie + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Attention : Si vous chiffrez votre portefeuille et que vous perdez votre mot de passe vous <b> PERDREZ TOUS VOS BITCOINS</b> ! + + + Wallet encrypted + Portefeuille chiffré + BanTableModel @@ -79,7 +151,7 @@ BitcoinGUI Sign &message... - Signer &message... + Signer un &message... Synchronizing with network... @@ -364,7 +436,7 @@ Fee: - Frais: + Frais : Dust: @@ -414,6 +486,50 @@ Confirmed Confirmée + + Copy address + Copier l'adresse + + + Copy label + Copier l'étiquette + + + Copy amount + Copier le montant + + + Copy transaction ID + Copier l'ID de transaction + + + Copy quantity + Copier la quantité + + + Copy fee + Copier les frais + + + Copy after fee + Copier après les frais + + + Copy bytes + Copier les octets + + + yes + oui + + + no + non + + + (no label) + (aucune étiquette) + EditAddressDialog @@ -797,6 +913,14 @@ QRImageWidget + + &Copy Image + &Copier image + + + Save QR Code + Sauvegarder QR code + RPCConsole @@ -1055,7 +1179,15 @@ Remove Retirer - + + Copy label + Copier l'étiquette + + + Copy amount + Copier le montant + + ReceiveRequestDialog @@ -1074,9 +1206,45 @@ &Save Image... &Sauvegarder image + + URI + URI + + + Address + Adresse + + + Amount + Montant + + + Label + Étiquette + + + Message + Message + RecentRequestsTableModel + + Date + Date + + + Label + Étiquette + + + Message + Message + + + (no label) + (aucune étiquette) + SendCoinsDialog @@ -1180,7 +1348,35 @@ S&end E&voyer - + + Copy quantity + Copier la quantité + + + Copy amount + Copier le montant + + + Copy fee + Copier les frais + + + Copy after fee + Copier après les frais + + + Copy bytes + Copier les octets + + + or + ou + + + (no label) + (aucune étiquette) + + SendCoinsEntry @@ -1234,7 +1430,11 @@ SendConfirmationDialog - + + Yes + Oui + + ShutdownWindow @@ -1305,7 +1505,87 @@ TransactionDesc - + + Status + État + + + Date + Date + + + Source + Source + + + Generated + Généré + + + From + De + + + unknown + inconnu + + + To + Á + + + own address + Votre adresse + + + watch-only + Lecture uniquement + + + label + Étiquette + + + Credit + Crédit + + + Debit + Débit + + + Total debit + Débit total + + + Total credit + Crédit total + + + Net amount + Montant net + + + Message + Message + + + Comment + Commentaire + + + Amount + Montant + + + true + vrai + + + false + faux + + TransactionDescDialog @@ -1315,10 +1595,106 @@ TransactionTableModel + + Date + Date + + + Type + Type + + + Label + Étiquette + + + watch-only + Lecture uniquement + + + (no label) + (aucune étiquette) + TransactionView - + + All + Toutes + + + Today + Aujourd'hui + + + This week + Cette semaine + + + This month + Ce mois + + + Last month + Mois dernier + + + This year + Cette année + + + Other + Autres + + + Copy address + Copier l'adresse + + + Copy label + Copier l'étiquette + + + Copy amount + Copier le montant + + + Copy transaction ID + Copier l'ID de transaction + + + Comma separated file (*.csv) + Valeurs séparées par des virgules (*.csv) + + + Date + Date + + + Type + Type + + + Label + Étiquette + + + Address + Adresse + + + ID + ID + + + Exporting Failed + Échec de l'export + + + to + à + + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts index 78ef446ff1b..82be81e9219 100644 --- a/src/qt/locale/bitcoin_he.ts +++ b/src/qt/locale/bitcoin_he.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - לחץ מקש ימני כדי לערוך כתובת או תווית + יש ללחוץ עם הכפתור הימני כדי לערוך כתובת או תווית Create a new address @@ -43,15 +43,15 @@ Choose the address to send coins to - בחר את הכתובת אליה תרצה לשלוח את המטבעות + נא לבחור את הכתובת אליה ברצונך לשלוח את המטבעות Choose the address to receive coins with - בחר את הכתובת בה תקבל את המטבעות + נא לבחור את הכתובת לקבלת המטבעות C&hoose - בחר + &בחירה Sending addresses @@ -59,27 +59,35 @@ Receiving addresses - מקבל כתובות + כתובות לקבלה These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - אלה הם כתובות הביטקוין שלך לשליחת תשלומים. חשוב לבדוק את הכמות של הכתובות המקבלות לפני שליחת מטבעות + אלו הן כתובות הביטקוין שלך לשליחת תשלומים. חשוב לבדוק את כמות הכתובות המקבלות לפני שליחת מטבעות. These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - אלה הן כתובות הביטקוין שלך לקבלת תשלומים. מומלץ להשתמש בכתובת חדשה לכל העברה. + אלו הן כתובות הביטקוין שלך לקבלת תשלומים. מומלץ להשתמש בכתובת חדשה לכל העברה. &Copy Address - &העתק כתובת + ה&עתקת כתובת Copy &Label - העתק &תוית + העתקת &תוית &Edit - &ערוך + &עריכה + + + Export Address List + יצוא רשימת הכתובות + + + Comma separated file (*.csv) + קובץ מופרד בפסיקים (‎*.csv) Exporting Failed @@ -94,7 +102,7 @@ AddressTableModel Label - תוית + תווית Address @@ -123,10 +131,102 @@ Repeat new passphrase נא לחזור על מילת הצופן החדשה - + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + נא להזין את מילת הצופן לארנק.<br/>נא להשתמש במילת צופן המורכבת מ<b>עשרה או יותר תווים אקראיים</b>, או <b>שמונה מילים ומעלה</b>. + + + Encrypt wallet + הצפנת הארנק + + + This operation needs your wallet passphrase to unlock the wallet. + פעולה זו דורשת את מילת הצופן של הארנק שלך כדי לשחרר את הארנק. + + + Unlock wallet + שחרור הארנק + + + This operation needs your wallet passphrase to decrypt the wallet. + פעולה זו דורשת את מילת הצופן של הארנק שלך כדי לפענח את הארנק. + + + Decrypt wallet + פענוח הארנק + + + Change passphrase + החלפת מילת הצופן + + + Enter the old passphrase and new passphrase to the wallet. + נא להזין את מילת הצופן הישנה וחדשה לארנק + + + Confirm wallet encryption + אימות הצפנת הארנק + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + אזהרה: איבוד מילת הצופן לאחר הצפנת הארנק עשויה לגרום לכך <b>שכל הביטקוינים שלך יאבדו</b>! + + + Are you sure you wish to encrypt your wallet? + להצפין את הארנק? + + + Wallet encrypted + הארנק מוצפן + + + %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + %1 ייסגר כעת כדי לסיים את תהליך ההצפנה. נא לשים לב כי הצפנת הארנק שלך לא יכול להגן על הביטקוינים שלך מפני גניבה או נוזקה שתוקפת את מחשבך. + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + חשוב: כל הגיבויים הקודמים שערכת לארנק שלך אמורים להתחלף עם קובץ הארנק המוצפן שנוצר כרגע. מטעמי אבטחה, הגיבויים הקודמים של קובץ הארנק שאינו מוגן הופכים לחסרי תועלת ברגע התחלת השימוש בארנק החדש והמוצפן. + + + Wallet encryption failed + הצפנת הארנק נכשלה + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + הצפנת הארנק נכשלה עקב תקלה פנימית. הארנק שלך לא הוצפן. + + + The supplied passphrases do not match. + מילות הצופן שסופקו אינן תואמות. + + + Wallet unlock failed + שחרור האנרק נכשל + + + The passphrase entered for the wallet decryption was incorrect. + מילת הצופן שהוזנה לצורך פענוח הארנק שגויה. + + + Wallet decryption failed + פענוח הארנק נכשל + + + Wallet passphrase was successfully changed. + מילת הצופן של הארנק הוחלפה בהצלחה. + + + Warning: The Caps Lock key is on! + אזהרה: מקש ה־Caps Lock פעיל! + + BanTableModel + IP/Netmask + IP/מסכת רשת + + Banned Until חסום עד @@ -190,6 +290,10 @@ &אפשרויות… + Modify configuration options for %1 + שינוי אפשרויות התצורה עבור %1 + + &Encrypt Wallet... ה&צפנת הארנק… @@ -214,6 +318,22 @@ פתיחת &כתובת משאב… + Click to disable network activity. + יש ללחוץ כדי לנטרל פעילות רשת. + + + Network activity disabled. + פעילות הרשת נוטרלה. + + + Click to enable network activity again. + יש ללחוץ כדי להפעיל את פעילות הרשת מחדש. + + + Syncing Headers (%1%)... + הכותרות מתעדכנות (%1%)... + + Reindexing blocks on disk... המקטעים נוספים למפתח בכונן… @@ -313,6 +433,10 @@ &Command-line options אפשרויות &שורת הפקודה + + %n active connection(s) to Bitcoin network + חיבור אחד פעיל לרשת ביטקוין%n חיבורים פעילים לרשת ביטקוין + Processing blocks on disk... מעבד בלוקים על הדיסק... @@ -346,10 +470,52 @@ עדכני + Show the %1 help message to get a list with possible Bitcoin command-line options + יש להציג את הודעת העזרה של %1 כדי להציג רשימה עם אפשרויות שורת פקודה לביטקוין + + + %1 client + לקוח %1 + + + Connecting to peers... + מתבצעת התחברות לעמיתים… + + Catching up... מתבצע עדכון… + Date: %1 + + תאריך: %1 + + + + Amount: %1 + + כמות: %1 + + + + Type: %1 + + סוג: %1 + + + + Label: %1 + + תווית: %1 + + + + Address: %1 + + כתובת: %1 + + + Sent transaction העברת שליחה @@ -365,7 +531,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> הארנק <b>מוצפן</b> ו<b>נעול</b> כרגע - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + אירעה שגיאה חמורה. אין אפשרות להשתמש עוד בביטקוין באופן מאובטח והיישום ייסגר. + + CoinControlDialog @@ -437,6 +607,70 @@ מאושר + Copy address + העתקת הכתובת + + + Copy label + העתקת התווית + + + Copy amount + העתקת הסכום + + + Copy transaction ID + העתקת מזהה ההעברה + + + Lock unspent + נעילת יתרה + + + Unlock unspent + פתיחת יתרה + + + Copy quantity + העתקת הכמות + + + Copy fee + העתקת העמלה + + + Copy after fee + העתקה אחרי העמלה + + + Copy bytes + העתקת בתים + + + Copy dust + העתקת אבק + + + Copy change + העתקת השינוי + + + yes + כן + + + no + לא + + + This label turns red if any recipient receives an amount smaller than the current dust threshold. + תווית זו הופכת לאדומה אם מישהו מהנמענים מקבל סכום נמוך יותר מסף האבק הנוכחי. + + + Can vary +/- %1 satoshi(s) per input. + יכול להשתנות במגמה של +/- %1 סנטושי לקלט. + + (no label) (ללא תוית) @@ -463,7 +697,39 @@ &Address &כתובת - + + New receiving address + כתובת קבלה חדשה + + + New sending address + כתובת שליחה חדשה + + + Edit receiving address + עריכת כתובת הקבלה + + + Edit sending address + עריכת כתובת השליחה + + + The entered address "%1" is not a valid Bitcoin address. + הכתובת שהוקלדה „%1” היא אינה כתובת ביטקוין תקנית. + + + The entered address "%1" is already in the address book. + הכתובת שהוקלדה „%1” כבר נמצאת בספר הכתובות. + + + Could not unlock wallet. + לא ניתן לשחרר את הארנק. + + + New key generation failed. + יצירת המפתח החדש נכשלה. + + FreespaceChecker @@ -498,6 +764,10 @@ (%1-סיביות) + About %1 + על אודות %1 + + Command-line options אפשרויות שורת פקודה @@ -514,10 +784,22 @@ אפשרויות ממשק + Choose data directory on startup (default: %u) + נא לבחור תיקיית נתונים עם הפתיחה (בררת מחדל: %u) + + + Set language, for example "de_DE" (default: system locale) + הגדרת השפה, לדוגמה „he_IL” (בררת מחדל: שפת העמרכת) + + Start minimized התחל ממוזער + Set SSL root certificates for payment request (default: -system-) + הגדרת אישורי בסיס SSL לבקשות תשלומים (בררת מחדל: -מערכת-) + + Show splash screen on startup (default: %u) הצג מסך פתיחה בעת הפעלה (ברירת מחדל: %u) @@ -537,6 +819,10 @@ ברוך הבא ל %1. + As this is the first time the program is launched, you can choose where %1 will store its data. + כיוון שזו ההפעלה הראשונה של התכנית, ניתן לבחור היכן יאוחסן המידע של %1. + + Use the default data directory שימוש בבררת המחדל של תיקיית הנתונים. @@ -560,14 +846,42 @@ טופס + Number of blocks left + מספר מקטעים שנותרו + + + Unknown... + לא ידוע... + + Last block time זמן המקטע האחרון + Progress + התקדמות + + + Progress increase per hour + התקדמות לפי שעה + + + calculating... + נערך חישוב… + + + Estimated time left until synced + הזמן המוערך שנותר עד הסנכרון + + Hide הסתר - + + Unknown. Syncing Headers (%1)... + לא ידוע. הכותרות מתעדכנות (%1)… + + OpenURIDialog @@ -586,7 +900,11 @@ Select payment request file בחירת קובץ בקשת תשלום - + + Select payment request file to open + בחירת קובץ בקשת תשלום לפתיחה + + OptionsDialog @@ -598,6 +916,14 @@ &ראשי + Automatically start %1 after logging in to the system. + להפעיל את %1 אוטומטית לאחר הכניסה למערכת. + + + &Start %1 on system login + ה&פעלת %1 עם הכניסה למערכת + + Size of &database cache גודל מ&טמון מסד הנתונים @@ -706,6 +1032,14 @@ &חלון + &Hide the icon from the system tray. + ה&סתרת הסמל ממגש המערכת. + + + Hide tray icon + הסתרת הסמל במגש המערכת + + Show only a tray icon after minimizing the window. הצג סמל מגש בלבד לאחר מזעור החלון. @@ -726,6 +1060,10 @@ &שפת מנשק המשתמש: + The user interface language can be set here. This setting will take effect after restarting %1. + ניתן להגדיר כאן את שפת מנשק המשתמש. הגדרה זו תיכנס לתוקף לאחר הפעלה של %1 מחדש. + + &Unit to show amounts in: י&חידת מידה להצגת כמויות: @@ -762,6 +1100,10 @@ נדרשת הפעלה מחדש של הלקוח כדי להפעיל את השינויים. + Client will be shut down. Do you want to proceed? + הלקוח יכבה. להמשיך? + + This change would require a client restart. שינוי זה ידרוש הפעלה מחדש של תכנית הלקוח. @@ -847,7 +1189,71 @@ PaymentServer - + + Payment request error + שגיאת בקשת תשלום + + + Cannot start bitcoin: click-to-pay handler + לא ניתן להפעיל את המקשר bitcoin: click-to-pay + + + URI handling + טיפול בכתובות + + + Invalid payment address %1 + כתובת תשלום שגויה %1 + + + Payment request rejected + בקשת התשלום נדחתה + + + Payment request network doesn't match client network. + רשת בקשת התשלום אינה תואמת לרשת הלקוח. + + + Payment request expired. + בקשת התשלום פגה. + + + Payment request is not initialized. + בקשת התשלום לא הופעלה. + + + Unverified payment requests to custom payment scripts are unsupported. + בקשות תשלום לתסריטי תשלום מותאמים אישית שלא עברו וידוא אינן נתמכות. + + + Invalid payment request. + בקשת תשלום שגויה. + + + Refund from %1 + זיכוי מאת %1 + + + Error communicating with %1: %2 + שגיאה בעת יצירת קשר עם %1:‏ %2 + + + Payment request cannot be parsed! + לא ניתן לפענח את בקשת התשלום! + + + Bad response from server %1 + תגובה שגויה מהשרת %1 + + + Network request error + שגיאת בקשת רשת + + + Payment acknowledged + התשלום אושר + + PeerTableModel @@ -893,17 +1299,73 @@ %1 ms %1 מילישניות + + %n second(s) + שנייה אחת%n שניות + + + %n minute(s) + דקה אחת%n דקות + + + %n hour(s) + שעה אחת%n שעות + + + %n day(s) + יום אחד%n ימים + + + %n week(s) + שבוע אחד%n שבועות + %1 and %2 %1 ו%2 - + + %n year(s) + שנה אחת%n שנים + + + %1 didn't yet exit safely... + הסגירה של %1 לא הושלמה בהצלחה עדיין… + + QObject::QObject - + + Error: Specified data directory "%1" does not exist. + שגיאה: תיקיית הנתונים שצוינה „%1” אינה קיימת. + + + Error: Cannot parse configuration file: %1. Only use key=value syntax. + שגיאה: לא ניתן לפענח את התצורה: %1. יש להשתמש אך ורק בתחביר מפתח=ערך. + + + Error: %1 + שגיאה: %1 + + QRImageWidget - + + &Save Image... + &שמירת תמונה… + + + &Copy Image + העתקת ת&מונה + + + Save QR Code + שמירת קוד QR + + + PNG Image (*.png) + תמונת PNG (‏‎*.png) + + RPCConsole @@ -1007,6 +1469,10 @@ בלוק התחלה + Synced Headers + כותרות עדכניות + + Synced Blocks בלוקים מסונכרנים @@ -1107,6 +1573,22 @@ 1 & שנה + &Disconnect + &ניתוק + + + Ban for + חסימה למשך + + + &Unban + &שחרור חסימה + + + Welcome to the %1 RPC console. + ברוך בואך למסוף ה־RPC של %1. + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. יש להשתמש בחצים למעלה ולמטה כדי לנווט בהיסטוריה, וב־<b>Ctrl-L</b> כדי לנקות את המסך. @@ -1115,6 +1597,10 @@ ניתן להקליד <b>help</b> לקבלת סקירה של הפקודות הזמינות. + Network activity disabled + פעילות הרשת נוטרלה + + %1 B %1 ב׳ @@ -1229,8 +1715,24 @@ Remove הסרה - - + + Copy URI + העתקת כתובת + + + Copy label + העתקת התווית + + + Copy message + העתקת הודעה + + + Copy amount + העתקת הסכום + + + ReceiveRequestDialog QR Code @@ -1249,24 +1751,64 @@ &שמירת תמונה… + Request payment to %1 + בקשת תשלום אל %1 + + + Payment information + פרטי תשלום + + + URI + כתובת + + Address כתובת + Amount + סכום + + Label תוית + + Message + הודעה + + + Resulting URI too long, try to reduce the text for label / message. + הכתובת שנוצרה ארוכה מדי, כדאי לנסות לקצר את הטקסט של התווית / הודעה. + RecentRequestsTableModel + Date + תאריך + + Label תוית + Message + הודעה + + (no label) (ללא תוית) + + (no message) + (אין הודעה) + + + (no amount requested) + (לא התבקש סכום) + SendCoinsDialog @@ -1331,6 +1873,10 @@ בחר... + collapse fee-settings + צמצום הגדרות עמלה + + per kilobyte עבור קילו-בית @@ -1391,6 +1937,110 @@ &שליחה + Copy quantity + העתקת הכמות + + + Copy amount + העתקת הסכום + + + Copy fee + העתקת העמלה + + + Copy after fee + העתקה אחרי העמלה + + + Copy bytes + העתקת בתים + + + Copy dust + העתקת אבק + + + Copy change + העתקת השינוי + + + Are you sure you want to send? + לשלוח? + + + added as transaction fee + נוספה עמלת העברה + + + Total Amount %1 + סכום כולל %1 + + + or + או + + + Confirm send coins + אימות שליחת מטבעות + + + The recipient address is not valid. Please recheck. + כתובת הנמען שגויה. נא לבדוק שוב. + + + The amount to pay must be larger than 0. + הסכום לתשלום צריך להיות גדול מ־0. + + + The amount exceeds your balance. + הסכום חורג מהמאזן שלך. + + + Duplicate address found: addresses should only be used once each. + נמצאה כתובת כפולה: יש להשתמש בכל כתובת פעם אחת בלבד. + + + Transaction creation failed! + יצירת ההעברה נכשלה! + + + The transaction was rejected with the following reason: %1 + ההעברה נדחתה מהסיבות הבאות: %1 + + + A fee higher than %1 is considered an absurdly high fee. + עמלה מעל לסכום של %1 נחשבת לעמלה גבוהה באופן מוגזם. + + + Payment request expired. + בקשת התשלום פגה. + + + %n block(s) + מקטע אחד%n מקטעים + + + Pay only the required fee of %1 + תשלום של העמלה הנדרשת בלבד על סך %1 + + + Warning: Invalid Bitcoin address + אזהרה: כתובת ביטקיון שגויה + + + Warning: Unknown change address + אזהרה: כתובת החלפה בלתי ידועה + + + Confirm custom change address + אימות כתובת החלפה בהתאמה אישית + + + The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure? + הכתובת שבחרת עבור ההחלפה אינה חלק מארנק זה. כל ההסכום שבארנק שלך עשוי להישלח לכתובת זו. מקובל עליך? + + (no label) (ללא תוית) @@ -1438,6 +2088,14 @@ הסרת רשומה זו + The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally. + העמלה תנוכה מהסכום שנשלח. הנמען יקבל פחות ביטקוינים ממה שהזנת בשדה הסכום. אם נבחרו מספר נמענים, העמלה תחולק באופן שווה. + + + S&ubtract fee from amount + ה&חסרת העמלה מהסכום + + Message: הודעה: @@ -1461,10 +2119,18 @@ Memo: תזכורת: - + + Enter a label for this address to add it to your address book + נא להזין תווית לכתובת זו כדי להוסיף אותה לספר הכתובות שלך + + SendConfirmationDialog - + + Yes + כן + + ShutdownWindow @@ -1550,7 +2216,59 @@ Reset all verify message fields איפוס כל שדות אימות ההודעה - + + Click "Sign Message" to generate signature + יש ללחוץ על „חתימת ההודעה“ כדי לייצר חתימה + + + The entered address is invalid. + הכתובת שהוזנה שגויה. + + + Please check the address and try again. + נא לבדוק את הכתובת ולנסות שוב. + + + The entered address does not refer to a key. + הכתובת שהוזנה לא מתייחסת למפתח. + + + Wallet unlock was cancelled. + שחרור הארנק בוטל. + + + Private key for the entered address is not available. + המפתח הפרטי לכתובת שהוכנסה אינו זמין. + + + Message signing failed. + חתימת ההודעה נכשלה. + + + Message signed. + ההודעה נחתמה. + + + The signature could not be decoded. + לא ניתן לפענח את החתימה. + + + Please check the signature and try again. + נא לבדוק את החתימה ולנסות שוב. + + + The signature did not match the message digest. + החתימה לא תואמת את תקציר ההודעה. + + + Message verification failed. + וידוא ההודעה נכשל. + + + Message verified. + ההודעה עברה וידוא. + + SplashScreen @@ -1567,28 +2285,304 @@ TransactionDesc - + + in memory pool + במאגר הזיכרון + + + not in memory pool + לא במאגר הזיכרון + + + abandoned + ננטש + + + Status + מצב + + + Date + תאריך + + + Source + מקור + + + From + מאת + + + unknown + לא ידוע + + + To + אל + + + own address + כתובת עצמית + + + watch-only + צפייה בלבד + + + label + תווית + + + Credit + אשראי + + + Debit + חיוב + + + Total debit + חיוב כולל + + + Total credit + אשראי כול + + + Transaction fee + עמלת העברה + + + Net amount + סכום נטו + + + Message + הודעה + + + Comment + הערה + + + Transaction ID + מזהה העברה + + + Transaction total size + גודל ההעברה הכללי + + + Output index + מפתח פלט + + + Debug information + פרטי ניפוי שגיאות + + + Transaction + העברה + + + Inputs + אמצעי קלט + + + Amount + סכום + + + true + אמת + + + false + שקר + + TransactionDescDialog This pane shows a detailed description of the transaction חלונית זו מציגה תיאור מפורט של ההעברה - + + Details for %1 + פרטים עבור %1 + + TransactionTableModel + Date + תאריך + + + Type + סוג + + Label תוית + Abandoned + ננטש + + + Received with + התקבל עם + + + Received from + התקבל מאת + + + Sent to + נשלח אל + + + Payment to yourself + תשלום לעצמך + + + Mined + נכרו + + + watch-only + צפייה בלבד + + + (n/a) + (לא זמין) + + (no label) (ללא תוית) + + Type of transaction. + סוג ההעברה. + TransactionView + All + הכול + + + Today + היום + + + This week + השבוע + + + This month + החודש + + + Last month + חודש שעבר + + + This year + השנה הזאת + + + Range... + טווח… + + + Received with + התקבל עם + + + Sent to + נשלח אל + + + To yourself + לעצמך + + + Mined + נכרו + + + Other + אחר + + + Enter address or label to search + נא להזין כתובת או תווית לחיפוש + + + Min amount + סכום מזערי + + + Abandon transaction + נטישת העברה + + + Copy address + העתקת הכתובת + + + Copy label + העתקת התווית + + + Copy amount + העתקת הסכום + + + Copy transaction ID + העתקת מזהה ההעברה + + + Copy raw transaction + העתקת העברה גולמית + + + Copy full transaction details + העתקת פרטי ההעברה המלאים + + + Edit label + עריכת תווית + + + Show transaction details + הצגת פרטי העברה + + + Export Transaction History + יצוא היסטוריית העברה + + + Comma separated file (*.csv) + קובץ מופרד בפסיקים (‎*.csv) + + + Watch-only + צפייה בלבד + + + Date + תאריך + + + Type + סוג + + Label תוית @@ -1597,10 +2591,34 @@ כתובת + ID + מזהה + + Exporting Failed יצוא נכשל - + + There was an error trying to save the transaction history to %1. + אירעה שגיאה בעת ניסיון שמירת היסטוריית ההעברות אל %1. + + + Exporting Successful + הייצוא נכשל + + + The transaction history was successfully saved to %1. + היסטוריית ההעברות נשמרה בהצלחה אל %1. + + + Range: + טווח: + + + to + עד + + UnitDisplayStatusBarControl @@ -1610,13 +2628,53 @@ WalletFrame - + + No wallet has been loaded. + לא נטען ארנק. + + WalletModel - + + Send Coins + שליחת מטבעות + + WalletView - + + &Export + &יצוא + + + Export the data in the current tab to a file + יצוא הנתונים בלשונית הנוכחית לקובץ + + + Backup Wallet + גיבוי הארנק + + + Wallet Data (*.dat) + נתוני ארנק (‎*.dat) + + + Backup Failed + הגיבוי נכשל + + + There was an error trying to save the wallet data to %1. + אירעה שגיאה בעת הניסיון לשמור את נתוני הארנק אל %1. + + + Backup Successful + הגיבוי הצליח + + + The wallet data was successfully saved to %1. + נתוני הארנק נשמרו בהצלחה אל %1. + + bitcoin-core @@ -1640,6 +2698,10 @@ קבלת פקודות משורת הפקודה ומ־JSON-RPC + Accept connections from outside (default: 1 if no -proxy or -connect/-noconnect) + קבלת חיבורים מבחוץ (בררת מחדל: 1 אם לא במצב ‎-proxy או ‎-connect/-noconnet) + + Error: A fatal internal error occurred, see debug.log for details שגיאה: סניה קלמה קריטית פנימית קרטה, פנה ל debug.log לפרטים @@ -1668,14 +2730,38 @@ ביצוע פקודה כאשר העברה בארנק משתנה (%s ב־cmd יוחלף ב־TxID) + Use UPnP to map the listening port (default: 1 when listening and no -proxy) + שימוש ב־UPnP כדי למפות את הפתחה להאזנה (בררת מחדל: 1 בעת האזנה ובלי ‎-proxy) + + + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. + אזהרה: נראה כי הרשת אינה מסכימה באופן מלא! חלק מהכורים חווים תקלות. + + + You need to rebuild the database using -reindex-chainstate to change -txindex + עליך לבנות מחדש את מסד הנתונים בעזרת ‎-reindex-chainstate כדי לשנות את ‎-txindex + + + -maxmempool must be at least %d MB + ‎-maxmempool חייב להיות לפחות %d מ״ב + + <category> can be: <קטגוריה> יכולה להיות: + Append comment to the user agent string + הוספת הערה למחרוזת סוכן המשתמש + + Block creation options: אפשרויות יצירת מקטע: + Chain selection options: + אפשרויות בחירת שרשרת: + + Change index out of range אינדקס העודף מחוץ לתחום @@ -1684,6 +2770,10 @@ הגדרות חיבור: + Copyright (C) %i-%i + כל הזכויות שמורות (C) %i-‏%i + + Corrupted block database detected התגלה מסד נתוני מקטעים לא תקין @@ -1740,6 +2830,14 @@ כתובת onion- שגויה: '%s' + Invalid amount for -%s=<amount>: '%s' + סכום שגוי עבור ‎-%s=<amount>:‏ '%s' + + + Invalid amount for -fallbackfee=<amount>: '%s' + סכום שגוי עבור ‎-fallbackfee=<amount>:‏ '%s' + + Loading banlist... טוען רשימת חסומים... @@ -1752,6 +2850,10 @@ תמיד להתחבר למפרקים ברשת <net>‏ (ipv4,‏ ipv6 או onion) + Print this help message and exit + להדפיס הודעת עזרה זו ולצאת + + Print version and exit הדפס גירסא וצא @@ -1784,6 +2886,10 @@ אפשרות דיבוג/בדיקת ארנק: + Wallet needed to be rewritten: restart %s to complete + יש לכתוב את הארנק מחדש: יש להפעיל את %s כדי להמשיך + + Wallet options: אפשרויות הארנק: @@ -1796,6 +2902,10 @@ סכום העברה נמוך מדי לשליחה אחרי גביית העמלה + (default: %u) + (בררת מחדל: %u) + + Connect through SOCKS5 proxy התחברות דרך מתווך SOCKS5 @@ -1892,14 +3002,90 @@ הכתובות בטעינה… + Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported. + המשתנה ‎-socks נמצא אך אין בו תמיכה עוד. הגדרת גרסת SOCKS אינה אפשרית עוד, קיימת תמיכה רק ב־SOCKS5. + + (default: %s) (ברירת מחדל: %s) + Always query for peer addresses via DNS lookup (default: %u) + תמיד לתשאל את כתובת העמיתים באמצעות חיפוש DNS (בררת מחדל: %u) + + + How many blocks to check at startup (default: %u, 0 = all) + כמה מקטעים לבדוק עם ההפעלה (בררת מחדל: %u,‏ 0 = הכול) + + + Include IP addresses in debug output (default: %u) + לכלול את כתובת ה־IP בפלט ניפוי השגיאות (בררת מחדל: %u) + + Invalid -proxy address: '%s' כתובת ‎-proxy לא תקינה: '%s' + Listen for JSON-RPC connections on <port> (default: %u or testnet: %u) + האזנה לחיבורי JSON-RPC דרך <port> (בררת מחדל: %u או ברשת הבדיקה: %u) + + + Listen for connections on <port> (default: %u or testnet: %u) + האזנה לחיבורים על גבי <port> (בררת מחדל: %u או לרשת הבדיקה: %u) + + + Maintain at most <n> connections to peers (default: %u) + לשמור על <n> חיבורים לעמיתים לכל היותר (בררת מחדל: %u) + + + Make the wallet broadcast transactions + להגדיר את הארנק להפצת העברות + + + Set key pool size to <n> (default: %u) + הגדרת גודל מאגר המפתחות לכדי <n> (בררת מחדל: %u) + + + Set maximum BIP141 block weight (default: %d) + הגדרת משקל מרבי למקטע BIP141 (בררת מחדל: %d) + + + Specify configuration file (default: %s) + הגדרת קובץ תצורה (בררת מחדל: %s) + + + Specify connection timeout in milliseconds (minimum: 1, default: %d) + ציון תפוגת זמן ההמתנה לחיבור במילישניות (מינימום: 1, בררת מחדל: %d) + + + Specify pid file (default: %s) + ציון קובץ pid (בררת מחדל: %s) + + + Starting network threads... + תהליכי הרשת מופעלים… + + + This is the minimum transaction fee you pay on every transaction. + זו עמלת ההעברה המזערית שתיגבה מכל העברה שלך. + + + This is the transaction fee you will pay if you send a transaction. + זו עמלת ההעברה שתיגבה ממך במידה של שליחת העברה. + + + Threshold for disconnecting misbehaving peers (default: %u) + סף לניתוק עמיתים סוררים (בררת מחדל: %u) + + + Transaction amounts must not be negative + סכומי ההעברה לא יכולים להיות שליליים + + + Transaction must have at least one recipient + להעברה חייב להיות לפחות נמען אחד + + Unknown network specified in -onlynet: '%s' רשת לא ידועה צוינה דרך ‎-onlynet:‏ '%s' diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts index 28270e8c2e1..5c98319c6bd 100644 --- a/src/qt/locale/bitcoin_hu.ts +++ b/src/qt/locale/bitcoin_hu.ts @@ -41,9 +41,17 @@ &Delete &Törlés + + &Copy Address + &Cím másolása + AddressTableModel + + Label + Címke + AskPassphraseDialog @@ -63,6 +71,10 @@ Repeat new passphrase Új jelszó újra + + Decrypt wallet + Tárca dekódolása + BanTableModel @@ -1078,9 +1090,17 @@ &Save Image... &Kép mentése + + Label + Címke + RecentRequestsTableModel + + Label + Címke + SendCoinsDialog @@ -1331,9 +1351,17 @@ TransactionTableModel + + Label + Címke + TransactionView + + Label + Címke + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts index fd77f07cd85..89ec216ab3d 100644 --- a/src/qt/locale/bitcoin_id_ID.ts +++ b/src/qt/locale/bitcoin_id_ID.ts @@ -41,10 +41,74 @@ &Delete &Hapus + + Choose the address to send coins to + Pilih alamat untuk mengirim koin + + + Choose the address to receive coins with + Piih alamat untuk menerima koin + + + C&hoose + &Pilih + + + Sending addresses + Alamat-alamat pengirim + + + Receiving addresses + Alamat-alamat penerima + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Ini adalah alamat- alamat Bitcoin Anda untuk mengirimkan pembayaran. Selalu periksa jumlah dan alamat penerima sebelum mengirimkan koin. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Ini adalah alamat- alamat Bitcoin Anda untuk menerima pembayaran. Dianjurkan untuk menggunakan alamat penerima yang baru setiap melakukan transaksi. + + + &Copy Address + &Salin Alamat + + + Copy &Label + Salin& Label + + + &Edit + &Ubah + + + Export Address List + Ekspor Daftar Alamat + + + Comma separated file (*.csv) + File yang berformat(*.csv) + + + Exporting Failed + Mengekspor Gagal + AddressTableModel - + + Label + Label + + + Address + Alamat + + + (no label) + (tidak ada label) + + AskPassphraseDialog @@ -63,7 +127,95 @@ Repeat new passphrase Ulangi kata kunci baru - + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Masukan kata sandi baru ke dompet.<br/>Mohon gunakan kata sandi <b>sepuluh karakter acak atau lebih</b>, atau <b> delapan atau lebih beberapa kata </​​b>. + + + Encrypt wallet + Enkripsi dompet + + + This operation needs your wallet passphrase to unlock the wallet. + Operasi ini memerlukan kata sandi dompet Anda untuk membuka dompet. + + + Unlock wallet + Buka dompet + + + This operation needs your wallet passphrase to decrypt the wallet. + Operasi ini memerlukan kata sandi dompet Anda untuk mendekripsikan dompet. + + + Decrypt wallet + Dekripsi dompet + + + Change passphrase + Ganti kata sandi + + + Enter the old passphrase and new passphrase to the wallet. + Masukkan kata sandi lama dan kata sandi baru ke dompet. + + + Confirm wallet encryption + Konfirmasi pengenkripsian dompet + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Peringatan: Jika Anda enkripsi dompet Anda dan lupa kata sandi anda, Anda akan <b>KEHILANGAN SEMUA BITCOIN ANDA</b>! + + + Are you sure you wish to encrypt your wallet? + Apakah Anda yakin ingin enkripsi dompet Anda? + + + Wallet encrypted + Dompet terenkripsi + + + %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + %1 sekarang akan ditutup untuk menyelesaikan proses enkripsi. Ingatlah bahwa mengenkripsi dompet Anda tidak dapat sepenuhnya melindungi komputer Anda dari pencurian malware yang menginfeksi komputer Anda. + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + PENTING: Backup sebelumnya yang Anda buat dari file dompet Anda harus diganti dengan file dompet terenkripsi yang baru dibuat. Demi keamanan, backup file dompet sebelumnya yang tidak dienkripsi sebelumnya akan menjadi tidak berguna begitu Anda mulai menggunakan dompet terenkripsi yang baru. + + + Wallet encryption failed + Pengenkripsian dompet gagal + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Pengenkripsian dompet gagal karena kesalahan internal. Dompet Anda tidak dienkripsi. + + + The supplied passphrases do not match. + Kata sandi yang dimasukkan tidak cocok. + + + Wallet unlock failed + Membuka dompet gagal + + + The passphrase entered for the wallet decryption was incorrect. + Kata sandi yang dimasukkan untuk dekripsi dompet salah. + + + Wallet decryption failed + Dekripsi dompet gagal + + + Wallet passphrase was successfully changed. + Kata sandi berhasil diganti. + + + Warning: The Caps Lock key is on! + Peringatan: Tombol Caps Lock aktif! + + BanTableModel @@ -114,6 +266,14 @@ Keluar dari aplikasi + &About %1 + &Tentang%1 + + + Show information about %1 + Tampilkan informasi perihal %1 + + About &Qt Mengenai &Qt @@ -126,6 +286,10 @@ &Pilihan... + Modify configuration options for %1 + Pengubahan opsi konfigurasi untuk %1 + + &Encrypt Wallet... &Enkripsi Dompet... @@ -150,6 +314,22 @@ Buka &URI + Click to disable network activity. + Klik untuk menonaktifkan aktivitas jaringan. + + + Network activity disabled. + Aktivitas jaringan dinonaktifkan. + + + Click to enable network activity again. + Klik untuk mengaktifkan aktivitas jaringan lagi. + + + Syncing Headers (%1%)... + Menyinkronkan Header (%1%) ... + + Reindexing blocks on disk... Mengindex ulang blok di dalam disk... @@ -253,6 +433,14 @@ %n active connection(s) to Bitcoin network %n koneksi aktif ke jaringan Bitcoin + + Indexing blocks on disk... + Pengindeksan blok pada disk ... + + + Processing blocks on disk... + Memproses blok pada disk ... + Processed %n block(s) of transaction history. %n blok dari riwayat transaksi diproses. @@ -286,6 +474,18 @@ Terbaru + Show the %1 help message to get a list with possible Bitcoin command-line options + Tampilkan %1 pesan bantuan untuk mendapatkan daftar opsi baris perintah Bitcoin yang memungkinkan + + + %1 client + %1 klien + + + Connecting to peers... + Menghubungkan ke peer... + + Catching up... Menyusul... @@ -328,6 +528,14 @@ Transaksi diterima + HD key generation is <b>enabled</b> + Pembuatan kunci HD <b>diaktifkan</b> + + + HD key generation is <b>disabled</b> + Pembuatan kunci HD <b>dinonaktifkan</b> + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> Dompet saat ini <b>terenkripsi</b> dan <b>terbuka</b> @@ -335,7 +543,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> Dompet saat ini <b>terenkripsi</b> dan <b>terkunci</b> - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + Terjadi Kesalahan Fatal. Bitcoin Tidak Dapat Melanjutkan Dengan Aman Dan Akan Keluar + + CoinControlDialog @@ -406,6 +618,70 @@ Confirmed Terkonfirmasi + + Copy address + Salin alamat + + + Copy label + Salin label + + + Copy amount + Salin Jumlah + + + Copy transaction ID + Salain ID Transaksi + + + Lock unspent + Kunci Yang Tidak Digunakan + + + Unlock unspent + Buka Kunci Yang Tidak Digunakan + + + Copy quantity + Salin Kuantitas + + + Copy fee + Salin biaya + + + Copy after fee + Salin Setelah Upah + + + Copy bytes + Salin bytes + + + Copy dust + Salin jumlah yang lebih kecil + + + Copy change + Salin Perubahan + + + (%1 locked) + (%1 terkunci) + + + yes + Ya + + + no + Tidak + + + (no label) + (tidak ada label) + EditAddressDialog @@ -429,7 +705,39 @@ &Address &Alamat - + + New receiving address + Alamat penerima baru + + + New sending address + Alamat pengirim baru + + + Edit receiving address + Ubah alamat penerima + + + Edit sending address + Ubah alamat pengirim + + + The entered address "%1" is not a valid Bitcoin address. + Alamat yang dimasukkan "%1" bukanlah alamat Bitcoin yang valid. + + + The entered address "%1" is already in the address book. + Alamat yang dimasukkan "%1" sudah ada di dalam buku alamat. + + + Could not unlock wallet. + Tidak dapat membuka dompet. + + + New key generation failed. + Pembuatan kunci baru gagal. + + FreespaceChecker @@ -464,6 +772,10 @@ (%1-bit) + About %1 + Tentang %1 + + Command-line options Pilihan Command-line @@ -499,7 +811,11 @@ Show splash screen on startup (default: %u) Tampilkan layar kilat saat memulai (default: %u) - + + Reset all settings changed in the GUI + Hapus semua pengaturan pada GUI. + + Intro @@ -507,6 +823,14 @@ Selamat Datang + Welcome to %1. + Selamat Datang ke %1. + + + As this is the first time the program is launched, you can choose where %1 will store its data. + Karena ini adalah pertama kalinya program dijalankan, Anda dapat memilih lokasi %1 akan menyimpan data. + + Use the default data directory Gunakan direktori data default. @@ -1065,7 +1389,15 @@ Remove Menghapus - + + Copy label + Salin label + + + Copy amount + Salin Jumlah + + ReceiveRequestDialog @@ -1085,12 +1417,28 @@ &Simpan Gambaran... + Address + Alamat + + Amount Jumlah + + Label + Label + RecentRequestsTableModel + + Label + Label + + + (no label) + (tidak ada label) + SendCoinsDialog @@ -1194,7 +1542,39 @@ S&end K&irim - + + Copy quantity + Salin Kuantitas + + + Copy amount + Salin Jumlah + + + Copy fee + Salin biaya + + + Copy after fee + Salin Setelah Upah + + + Copy bytes + Salin bytes + + + Copy dust + Salin dust + + + Copy change + Salin Perubahan + + + (no label) + (tidak ada label) + + SendCoinsEntry @@ -1357,9 +1737,49 @@ TransactionTableModel + + Label + Label + + + (no label) + (tidak ada label) + TransactionView + + Copy address + Salin alamat + + + Copy label + Salin label + + + Copy amount + Salin Jumlah + + + Copy transaction ID + Salain ID Transaksi + + + Comma separated file (*.csv) + Berkas yang berformat(*.csv) + + + Label + Label + + + Address + Alamat + + + Exporting Failed + Mengekspor Gagal + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts index 9f2c7626de0..d38459c6ff8 100644 --- a/src/qt/locale/bitcoin_it.ts +++ b/src/qt/locale/bitcoin_it.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Fare clic con il tasto destro del mouse per modificare l'indirizzo o l'etichettadefault + Tasto destro per modificare l'indirizzo o l'etichetta Create a new address @@ -180,10 +180,22 @@ Portamonete cifrato + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANTE: qualsiasi backup del file portamonete effettuato in precedenza dovrà essere sostituito con il file del portamonete cifrato appena generato. Per ragioni di sicurezza, i precedenti backup del file del portamonete non cifrato diventeranno inservibili non appena si inizierà ad utilizzare il nuovo portamonete cifrato. + + Wallet encryption failed Il processo di crittografia del tuo portafogli è fallito + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Crittaggio fallito a causa di un errore interno. Il portamonete non è stato crittato. + + + The supplied passphrases do not match. + Le frasi di accesso non corrispondono. + + Wallet unlock failed Sbloccaggio del portafoglio fallito @@ -191,7 +203,19 @@ The passphrase entered for the wallet decryption was incorrect. La frase inserita per decrittografare il tuo portafoglio è incorretta - + + Wallet decryption failed + Decrittazione del portamonete fallita. + + + Wallet passphrase was successfully changed. + La frase di accesso al portamonete è stata cambiata con successo. + + + Warning: The Caps Lock key is on! + Attenzione: è attivo il tasto blocco maiuscole ! + + BanTableModel @@ -290,6 +314,22 @@ Apri &URI... + Click to disable network activity. + Clicca per disattivare la rete. + + + Network activity disabled. + Attività di rete disabilitata + + + Click to enable network activity again. + Clicca per abilitare nuovamente l'attività di rete + + + Syncing Headers (%1%)... + Sincronizzazione Headers (%1%)... + + Reindexing blocks on disk... Re-indicizzazione blocchi su disco... @@ -442,6 +482,10 @@ %1 client + Connecting to peers... + Connessione ai peers + + Catching up... In aggiornamento... @@ -484,6 +528,14 @@ Transazione ricevuta + HD key generation is <b>enabled</b> + La creazione della chiave HD è <b>abilitata</b> + + + HD key generation is <b>disabled</b> + La creazione della chiave HD è <b>disabilitata</b> + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> Il portamonete è <b>cifrato</b> ed attualmente <b>sbloccato</b> @@ -491,7 +543,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> Il portamonete è <b>cifrato</b> ed attualmente <b>bloccato</b> - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + Si è verificato un errore critico. Bitcoin non può più funzionare in maniera sicura e verrà chiuso. + + CoinControlDialog @@ -563,10 +619,86 @@ Confermato + Copy address + Copia indirizzo + + + Copy label + Copia etichetta + + + Copy amount + Copia l'importo + + + Copy transaction ID + Copia l'ID transazione + + + Lock unspent + Bloccare non spesi + + + Unlock unspent + Sbloccare non spesi + + + Copy quantity + Copia quantità + + + Copy fee + Copia commissione + + + Copy after fee + Copia dopo commissione + + + Copy bytes + Copia byte + + + Copy dust + Copia trascurabile + + + Copy change + Copia resto + + + (%1 locked) + (%1 bloccato) + + + yes + + + + no + no + + + This label turns red if any recipient receives an amount smaller than the current dust threshold. + Questa etichetta diventerà rossa se uno qualsiasi dei destinatari riceverà un importo inferiore alla corrente soglia minima per la movimentazione della valuta. + + + Can vary +/- %1 satoshi(s) per input. + Può variare di +/- %1 satoshi per input. + + (no label) (nessuna etichetta) - + + change from %1 (%2) + cambio da %1 (%2) + + + (change) + (resto) + + EditAddressDialog @@ -589,7 +721,39 @@ &Address &Indirizzo - + + New receiving address + Nuovo indirizzo di ricezione + + + New sending address + Nuovo indirizzo d'invio + + + Edit receiving address + Modifica indirizzo di ricezione + + + Edit sending address + Modifica indirizzo d'invio + + + The entered address "%1" is not a valid Bitcoin address. + L'indirizzo inserito "%1" non è un indirizzo bitcoin valido. + + + The entered address "%1" is already in the address book. + L'indirizzo inserito "%1" è già in rubrica. + + + Could not unlock wallet. + Impossibile sbloccare il portamonete. + + + New key generation failed. + Generazione della nuova chiave non riuscita. + + FreespaceChecker @@ -703,6 +867,10 @@ Errore + %n GB of free space available + GB di spazio libero disponibile%n GB di spazio disponibile + + (of %n GB needed) (di %nGB richiesti)(%n GB richiesti) @@ -714,14 +882,42 @@ Modulo + Number of blocks left + Numero di blocchi mancanti + + + Unknown... + Sconosciuto... + + Last block time Ora del blocco più recente + Progress + Progresso + + + Progress increase per hour + Aumento dei progressi per ogni ora + + + calculating... + calcolando... + + + Estimated time left until synced + Tempo stimato al completamento della sincronizzazione. + + Hide Nascondi - + + Unknown. Syncing Headers (%1)... + Sconosciuto. Sincronizzazione Headers (%1)... + + OpenURIDialog @@ -740,7 +936,11 @@ Select payment request file Seleziona il file di richiesta di pagamento - + + Select payment request file to open + Seleziona il file di richiesta di pagamento da aprire + + OptionsDialog @@ -1054,7 +1254,95 @@ Per specificare più URL separarli con una barra verticale "|". PaymentServer - + + Payment request error + Errore di richiesta di pagamento + + + Cannot start bitcoin: click-to-pay handler + Impossibile avviare bitcoin: gestore click-to-pay + + + URI handling + Gestione URI + + + Payment request fetch URL is invalid: %1 + URL di recupero della Richiesta di pagamento non valido: %1 + + + Invalid payment address %1 + Indirizzo di pagamento non valido %1 + + + URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. + Impossibile interpretare l'URI! I parametri dell'URI o l'indirizzo Bitcoin potrebbero non essere corretti. + + + Payment request file handling + Gestione del file di richiesta del pagamento + + + Payment request file cannot be read! This can be caused by an invalid payment request file. + Impossibile leggere il file della richiesta di pagamento! Il file della richiesta di pagamento potrebbe non essere valido + + + Payment request rejected + Richiesta di pagamento respinta + + + Payment request network doesn't match client network. + La rete della richiesta di pagamento non corrisponde alla rete del client. + + + Payment request expired. + Richiesta di pagamento scaduta. + + + Payment request is not initialized. + La richiesta di pagamento non è stata inizializzata. + + + Unverified payment requests to custom payment scripts are unsupported. + Le richieste di pagamento non verificate verso script di pagamento personalizzati non sono supportate. + + + Invalid payment request. + Richiesta di pagamento invalida + + + Requested payment amount of %1 is too small (considered dust). + L'importo di pagamento di %1 richiesto è troppo basso (considerato come trascurabile). + + + Refund from %1 + Rimborso da %1 + + + Payment request %1 is too large (%2 bytes, allowed %3 bytes). + La richiesta di pagamento %1 è troppo grande (%2 bytes, consentiti %3 bytes) + + + Error communicating with %1: %2 + Errore di comunicazione con %1: %2 + + + Payment request cannot be parsed! + La richiesta di pagamento non può essere processata! + + + Bad response from server %1 + Risposta errata da parte del server %1 + + + Network request error + Errore di richiesta di rete + + + Payment acknowledged + Pagamento riconosciuto + + PeerTableModel @@ -1065,7 +1353,11 @@ Per specificare più URL separarli con una barra verticale "|". Node/Service Nodo/Servizio - + + Ping + Ping + + QObject @@ -1104,17 +1396,65 @@ Per specificare più URL separarli con una barra verticale "|". %1 ms %1 ms + + %n second(s) + %n secondo%n secondi + + + %n minute(s) + %n minuto%n minuti + + + %n hour(s) + %n ora%n ore + + + %n day(s) + %n giorno%n giorni + + + %n week(s) + %n settimana%n settimane + %1 and %2 %1 e %2 - + + %n year(s) + %n anno%n anni + + + %1 didn't yet exit safely... + %1 non è ancora stato chiuso in modo sicuro + + QObject::QObject - + + Error: %1 + Errore: %1 + + QRImageWidget - + + &Save Image... + &Salva immagine + + + &Copy Image + &Copia immagine + + + Save QR Code + Salva codice QR + + + PNG Image (*.png) + Immagine PNG (*.png) + + RPCConsole @@ -1274,6 +1614,10 @@ Per specificare più URL separarli con una barra verticale "|". Attesa ping + Min Ping + Ping Minimo + + Time Offset Scarto Temporale @@ -1334,6 +1678,18 @@ Per specificare più URL separarli con una barra verticale "|". 1 &anno + &Disconnect + &Disconnetti + + + Ban for + Bannato per + + + &Unban + &Sbanna + + Welcome to the %1 RPC console. Benvenuto nella console RPC di %1. @@ -1346,6 +1702,10 @@ Per specificare più URL separarli con una barra verticale "|". Scrivi <b>help</b> per un riassunto dei comandi disponibili. + Network activity disabled + Attività di rete disabilitata + + %1 B %1 B @@ -1464,7 +1824,23 @@ Per specificare più URL separarli con una barra verticale "|". Remove Rimuovi - + + Copy URI + Copia URI + + + Copy label + Copia etichetta + + + Copy message + Copia il messaggio + + + Copy amount + Copia l'importo + + ReceiveRequestDialog @@ -1484,25 +1860,73 @@ Per specificare più URL separarli con una barra verticale "|". &Salva Immagine... + Request payment to %1 + Richiesta di pagamento a %1 + + + Payment information + Informazioni di pagamento + + + URI + URI + + Address Indirizzo + Amount + Importo + + Label Etichetta - + + Message + Messaggio + + + Resulting URI too long, try to reduce the text for label / message. + L'URI risultante è troppo lungo, prova a ridurre il testo nell'etichetta / messaggio. + + + Error encoding URI into QR Code. + Errore nella codifica dell'URI nel codice QR. + + RecentRequestsTableModel + Date + Data + + Label Etichetta + Message + Messaggio + + (no label) (nessuna etichetta) - + + (no message) + (nessun messaggio) + + + (no amount requested) + (nessun importo richiesto) + + + Requested + Richiesto + + SendCoinsDialog @@ -1646,23 +2070,127 @@ Per specificare più URL separarli con una barra verticale "|". &Invia - (no label) - (nessuna etichetta) + Copy quantity + Copia quantità - - - SendCoinsEntry - A&mount: - &Importo: + Copy amount + Copia l'importo - Pay &To: - Paga &a: + Copy fee + Copia commissione - &Label: - &Etichetta: + Copy after fee + Copia dopo commissione + + + Copy bytes + Copia byte + + + Copy dust + Copia trascurabile + + + Copy change + Copia resto + + + %1 to %2 + %1 a %2 + + + Are you sure you want to send? + Sei sicuro di voler inviare? + + + added as transaction fee + Includi il costo della transazione + + + Total Amount %1 + Importo Totale %1 + + + or + o + + + Confirm send coins + Conferma invio coins + + + The recipient address is not valid. Please recheck. + L'indirizzo del destinatario non è valido. Si prega di ricontrollare. + + + The amount to pay must be larger than 0. + L'importo da pagare deve essere maggiore di 0. + + + The amount exceeds your balance. + Non hai abbastanza fondi + + + The total exceeds your balance when the %1 transaction fee is included. + Il totale è superiore al tuo saldo attuale includendo la commissione di %1. + + + Duplicate address found: addresses should only be used once each. + Rilevato un indirizzo duplicato Ciascun indirizzo dovrebbe essere utilizzato una sola volta. + + + Transaction creation failed! + Creazione della transazione fallita! + + + The transaction was rejected with the following reason: %1 + La transazione è stata respinta per il seguente motivo: %1 + + + A fee higher than %1 is considered an absurdly high fee. + Una commissione maggiore di %1 è considerata irragionevolmente elevata. + + + Payment request expired. + Richiesta di pagamento scaduta. + + + %n block(s) + %n blocco%n blocchi + + + Pay only the required fee of %1 + Paga solamente la commissione richiesta di %1 + + + Warning: Invalid Bitcoin address + Attenzione: Indirizzo Bitcoin non valido + + + Warning: Unknown change address + Attenzione: Indirizzo per il resto sconosciuto + + + (no label) + (nessuna etichetta) + + + + SendCoinsEntry + + A&mount: + &Importo: + + + Pay &To: + Paga &a: + + + &Label: + &Etichetta: Choose previously used address @@ -1731,7 +2259,11 @@ Per specificare più URL separarli con una barra verticale "|". SendConfirmationDialog - + + Yes + Si + + ShutdownWindow @@ -1829,7 +2361,59 @@ Per specificare più URL separarli con una barra verticale "|". Reset all verify message fields Reimposta tutti i campi della verifica messaggio - + + Click "Sign Message" to generate signature + Clicca "Firma Messaggio" per generare una firma + + + The entered address is invalid. + L'indirizzo inserito non è valido. + + + Please check the address and try again. + Per favore controlla l'indirizzo e prova di nuovo. + + + The entered address does not refer to a key. + L'indirizzo bitcoin inserito non è associato a nessuna chiave. + + + Wallet unlock was cancelled. + Sblocco del portamonete annullato. + + + Private key for the entered address is not available. + La chiave privata per l'indirizzo inserito non è disponibile. + + + Message signing failed. + Firma messaggio fallita. + + + Message signed. + Messaggio firmato. + + + The signature could not be decoded. + Non è stato possibile decodificare la firma. + + + Please check the signature and try again. + Per favore controlla la firma e prova di nuovo. + + + The signature did not match the message digest. + La firma non corrisponde al digest del messaggio. + + + Message verification failed. + Verifica messaggio fallita. + + + Message verified. + Messaggio verificato. + + SplashScreen @@ -1846,7 +2430,139 @@ Per specificare più URL separarli con una barra verticale "|". TransactionDesc - + + %1/offline + %1/offline + + + 0/unconfirmed, %1 + 0/non confermati, %1 + + + abandoned + abbandonato + + + %1/unconfirmed + %1/non confermato + + + %1 confirmations + %1 conferme + + + Status + Stato + + + , has not been successfully broadcast yet + , non è ancora stata trasmessa con successo + + + Date + Data + + + Source + Sorgente + + + Generated + Generato + + + From + Da + + + unknown + sconosciuto + + + To + A + + + own address + proprio indirizzo + + + watch-only + sola lettura + + + label + etichetta + + + Credit + Credito + + + not accepted + non accettate + + + Debit + Debito + + + Total debit + Debito totale + + + Total credit + Credito totale + + + Transaction fee + Commissione transazione + + + Net amount + Importo netto + + + Message + Messaggio + + + Comment + Commento + + + Transaction ID + ID della transazione + + + Merchant + Commerciante + + + Debug information + Informazione di debug + + + Transaction + Transazione + + + Inputs + Input + + + Amount + Importo + + + true + vero + + + false + falso + + TransactionDescDialog @@ -1857,21 +2573,201 @@ Per specificare più URL separarli con una barra verticale "|". TransactionTableModel + Date + Data + + + Type + Tipo + + Label Etichetta + Offline + Offline + + + Unconfirmed + Non confermata + + + Confirmed (%1 confirmations) + Confermata (%1 conferme) + + + This block was not received by any other nodes and will probably not be accepted! + Questo blocco non è stato ricevuto da alcun altro nodo e probabilmente non sarà accettato! + + + Generated but not accepted + Generati, ma non accettati + + + Received with + Ricevuto tramite + + + Sent to + Inviato a + + + Payment to yourself + Pagamento a te stesso + + + Mined + Ottenuto dal mining + + + watch-only + sola lettura + + + (n/a) + (n/d) + + (no label) (nessuna etichetta) - + + Transaction status. Hover over this field to show number of confirmations. + Stato della transazione. Passare con il mouse su questo campo per visualizzare il numero di conferme. + + + Date and time that the transaction was received. + Data e ora in cui la transazione è stata ricevuta. + + + Type of transaction. + Tipo di transazione. + + + Whether or not a watch-only address is involved in this transaction. + Indica se un indirizzo di sola lettura sia o meno coinvolto in questa transazione. + + + User-defined intent/purpose of the transaction. + Intento/scopo della transazione definito dall'utente. + + + Amount removed from or added to balance. + Importo rimosso o aggiunto al saldo. + + TransactionView + All + Tutti + + + Today + Oggi + + + This week + Questa settimana + + + This month + Questo mese + + + Last month + Il mese scorso + + + This year + Quest'anno + + + Range... + Intervallo... + + + Received with + Ricevuto tramite + + + Sent to + Inviato a + + + To yourself + A te stesso + + + Mined + Ottenuto dal mining + + + Other + Altro + + + Enter address or label to search + Inserisci un indirizzo o un'etichetta da cercare + + + Min amount + Importo minimo + + + Copy address + Copia indirizzo + + + Copy label + Copia etichetta + + + Copy amount + Copia l'importo + + + Copy transaction ID + Copia l'ID transazione + + + Copy raw transaction + Copia la transazione raw + + + Edit label + Modifica l'etichetta + + + Show transaction details + Mostra i dettagli della transazione + + + Export Transaction History + Esporta lo storico delle transazioni + + Comma separated file (*.csv) Testo CSV (*.csv) + Confirmed + Confermato + + + Watch-only + Sola lettura + + + Date + Data + + + Type + Tipo + + Label Etichetta @@ -1880,10 +2776,34 @@ Per specificare più URL separarli con una barra verticale "|". Indirizzo + ID + ID + + Exporting Failed Esportazione Fallita - + + There was an error trying to save the transaction history to %1. + Si è verificato un errore durante il salvataggio dello storico delle transazioni in %1. + + + Exporting Successful + Esportazione Riuscita + + + The transaction history was successfully saved to %1. + Lo storico delle transazioni e' stato salvato con successo in %1. + + + Range: + Intervallo: + + + to + a + + UnitDisplayStatusBarControl @@ -1893,13 +2813,53 @@ Per specificare più URL separarli con una barra verticale "|". WalletFrame - + + No wallet has been loaded. + Non è stato caricato alcun portamonete. + + WalletModel - + + Send Coins + Invia Bitcoin + + WalletView - + + &Export + &Esporta + + + Export the data in the current tab to a file + Esporta su file i dati contenuti nella tabella corrente + + + Backup Wallet + Backup Portamonete + + + Wallet Data (*.dat) + Dati Portamonete (*.dat) + + + Backup Failed + Backup Fallito + + + There was an error trying to save the wallet data to %1. + Si è verificato un errore durante il salvataggio dei dati del portamonete in %1. + + + Backup Successful + Backup eseguito con successo + + + The wallet data was successfully saved to %1. + Il portamonete è stato correttamente salvato in %1. + + bitcoin-core diff --git a/src/qt/locale/bitcoin_it_IT.ts b/src/qt/locale/bitcoin_it_IT.ts index 09d40497fa7..ebb30f13e4b 100644 --- a/src/qt/locale/bitcoin_it_IT.ts +++ b/src/qt/locale/bitcoin_it_IT.ts @@ -41,9 +41,21 @@ &Delete Cancella + + Choose the address to send coins to + Scegli l'indirizzo a cui inviare denaro + + + C&hoose + Scegli + AddressTableModel + + Address + Indirizzo + AskPassphraseDialog @@ -132,6 +144,10 @@ ReceiveRequestDialog + + Address + Indirizzo + RecentRequestsTableModel @@ -168,6 +184,10 @@ TransactionView + + Address + Indirizzo + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts index 14378ebea16..5aa9137753c 100644 --- a/src/qt/locale/bitcoin_ka.ts +++ b/src/qt/locale/bitcoin_ka.ts @@ -37,6 +37,14 @@ &Delete &წაშლა + + Sending addresses + გამმგზავნი მისამართ + + + Receiving addresses + მიმღები მისამართი + AddressTableModel diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts index 9b5c1c077ef..c104bdd0db8 100644 --- a/src/qt/locale/bitcoin_ko_KR.ts +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -318,6 +318,22 @@ &URI 열기... + Click to disable network activity. + 네트워크 활동을 중지하려면 클릭. + + + Network activity disabled. + 네트워크 활동이 정지됨. + + + Click to enable network activity again. + 네트워크 활동을 다시 시작하려면 클릭. + + + Syncing Headers (%1%)... + 헤더 동기화중 (%1%)... + + Reindexing blocks on disk... 디스크에서 블록 다시 색인중... @@ -431,7 +447,7 @@ Processed %n block(s) of transaction history. - %n 블럭 만큼의 거래 기록이 처리됨. + %n 블록 만큼의 거래 기록이 처리됨. %1 behind @@ -470,6 +486,10 @@ %1 클라이언트 + Connecting to peers... + 피어에 연결중... + + Catching up... 블록 따라잡기... @@ -512,14 +532,26 @@ 들어오고 있는 거래 + HD key generation is <b>enabled</b> + HD 키 생성이 <b>활성화되었습니다</b> + + + HD key generation is <b>disabled</b> + HD 키 생성이 <b>비활성화되었습니다</b> + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> - 지갑이 암호화 되었고 현재 차단해제 되었습니다 + 지갑이 <b>암호화</b> 되었고 현재 <b>잠금해제</b> 되었습니다 Wallet is <b>encrypted</b> and currently <b>locked</b> - 지갑이 암호화 되었고 현재 잠겨져 있습니다 + 지갑이 <b>암호화</b> 되었고 현재 <b>잠겨져</b> 있습니다 - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + 치명적인 오류가 발생했습니다. 비트코인을 더이상 안전하게 진행할 수 없어 곧 종료합니다. + + CoinControlDialog @@ -552,7 +584,7 @@ Change: - 체인지: + 잔돈: (un)select all @@ -651,6 +683,10 @@ 아니요 + This label turns red if any recipient receives an amount smaller than the current dust threshold. + 수령인이 현재 더스트 임계값보다 작은 양을 수신하면 이 라벨이 빨간색으로 변합니다. + + Can vary +/- %1 satoshi(s) per input. 입력마다 +/- %1 사토시(s)가 변할 수 있습니다. @@ -816,7 +852,7 @@ %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - %1가 블럭체인의 복사본을 다운로드 저장합니다. 적어도 %2GB의 데이터가 이 폴더에 저장되며 시간이 경과할수록 점차 증가합니다. 그리고 지갑 또한 이 폴더에 저장됩니다. + %1가 블록체인의 복사본을 다운로드 저장합니다. 적어도 %2GB의 데이터가 이 폴더에 저장되며 시간이 경과할수록 점차 증가합니다. 그리고 지갑 또한 이 폴더에 저장됩니다. Use the default data directory @@ -850,14 +886,50 @@ 유형 + Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below. + 최근 거래는 아직 보이지 않을 것입니다, 그러므로 당신의 지갑의 잔액이 틀릴 수도 있습니다. 이 정보는 비트코인 네트워크와 완전한 동기화가 완료되면 아래의 설명과 같이 정확해집니다. + + + Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network. + 아직 표시되지 않은 거래의 영향을 받는 비트코인을 사용하려고 하는 것은 네트워크에서 허가되지 않습니다. + + + Number of blocks left + 남은 블록의 수 + + + Unknown... + 알수없음... + + Last block time - 최종 블럭 시각 + 최종 블록 시각 + + + Progress + 진행 + + + Progress increase per hour + 시간당 진행 증가율 + + + calculating... + 계산중... + + + Estimated time left until synced + 동기화 완료까지 예상 시간 Hide 숨기기 - + + Unknown. Syncing Headers (%1)... + 알수없음. 헤더 동기화중 (%1)... + + OpenURIDialog @@ -929,7 +1001,7 @@ Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. - 서드-파티 URLs (예. 블록 탐색기)는 거래 탭의 컨텍스트 메뉴에 나타납니다. URL의 %s는 트랜잭션 해시값으로 대체됩니다. 여러 URLs는 수직 바 | 에서 나누어 집니다. + 서드-파티 URLs (예. 블록 탐색기)는 거래 탭의 컨텍스트 메뉴에 나타납니다. URL의 %s는 거래 해시값으로 대체됩니다. 여러 URLs는 수직 바 | 에서 나누어 집니다. Third party transaction URLs @@ -969,7 +1041,7 @@ If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. - 검증되지 않은 잔돈 쓰기를 비활성화하면 트랜잭션이 적어도 1회 이상 검증되기 전까지 그 트랜잭션의 거스름돈은 사용할 수 없습니다. 이는 잔액 계산 방법에도 영향을 미칩니다. + 검증되지 않은 잔돈 쓰기를 비활성화하면 거래가 적어도 1회 이상 검증되기 전까지 그 거래의 거스름돈은 사용할 수 없습니다. 이는 잔액 계산 방법에도 영향을 미칩니다. &Spend unconfirmed change @@ -1128,7 +1200,7 @@ Watch-only: - 모니터링 지갑: + 조회전용: Available: @@ -1168,7 +1240,7 @@ Your current balance in watch-only addresses - 모니터링 지갑의 현재 잔액 + 조회전용 주소의 현재 잔액 Spendable: @@ -1180,15 +1252,15 @@ Unconfirmed transactions to watch-only addresses - 모니터링 지갑의 검증되지 않은 트랜잭션 + 조회전용 주소의 검증되지 않은 거래 Mined balance in watch-only addresses that has not yet matured - 모니터링 지갑의 채굴된 잔액 중 숙성되지 않은 것 + 조회전용 주소의 채굴된 잔액 중 숙성되지 않은 것 Current total balance in watch-only addresses - 모니터링 지갑의 현재 잔액 + 조회전용 주소의 현재 잔액 @@ -1199,13 +1271,89 @@ Cannot start bitcoin: click-to-pay handler - 비트코인을 시작할 수 없습니다: 지급제어기를 클릭하시오 + 비트코인을 시작할 수 없습니다: 지급제어기를 클릭하세요 URI handling URI 핸들링 - + + Payment request fetch URL is invalid: %1 + 지불 요청의 URL이 올바르지 않습니다: %1 + + + Invalid payment address %1 + 잘못된 지불 주소입니다 %1 + + + URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. + URI의 파싱에 문제가 발생했습니다. 잘못된 비트코인 주소나 URI 파라미터 구성에 오류가 존재할 수 있습니다. + + + Payment request file handling + 지불이 파일 처리를 요청합니다 + + + Payment request file cannot be read! This can be caused by an invalid payment request file. + 지불 요청 파일을 읽을 수 없습니다. 이것은 잘못된 지불 요청 파일에 의해 발생하는 오류일 수 있습니다. + + + Payment request rejected + 지불 요청이 거부됨 + + + Payment request network doesn't match client network. + 지급 요청 네트워크가 클라이언트 네트워크와 일치되지 않습니다. + + + Payment request expired. + 지불 요청이 만료됨. + + + Payment request is not initialized. + 지불 요청이 초기화 되지 않았습니다. + + + Unverified payment requests to custom payment scripts are unsupported. + 임의로 변경한 결제 스크립트 기반의 지불 요청 양식은 검증되기 전까지는 지원되지 않습니다. + + + Invalid payment request. + 잘못된 지불 요청. + + + Requested payment amount of %1 is too small (considered dust). + 요청한 금액 %1의 양이 너무 적습니다. (스팸성 거래로 간주) + + + Refund from %1 + %1 으로부터의 환불 + + + Payment request %1 is too large (%2 bytes, allowed %3 bytes). + 지불 요청 %1은 너무 큽니다 (%2 바이트, %3 바이트까지 허용됩니다). + + + Error communicating with %1: %2 + %1과 소통하는데 에러: %2 + + + Payment request cannot be parsed! + 지불요청을 파싱할 수 없습니다. + + + Bad response from server %1 + 서버로 부터 잘못된 반응 %1 + + + Network request error + 네트워크 요청 에러 + + + Payment acknowledged + 지불이 승인됨 + + PeerTableModel @@ -1216,7 +1364,15 @@ Node/Service 노드/서비스 - + + NodeId + 노드 ID + + + Ping + + + QObject @@ -1255,17 +1411,73 @@ %1 ms %1 ms + + %n second(s) + %n 초 + + + %n minute(s) + %n 분 + + + %n hour(s) + %n 시간 + + + %n day(s) + &n 일 + + + %n week(s) + %n 주 + %1 and %2 %1 그리고 %2 - + + %n year(s) + %n 년 + + + %1 didn't yet exit safely... + %1가 아직 안전하게 종료되지 않았습니다... + + QObject::QObject - + + Error: Specified data directory "%1" does not exist. + 에러: 지정한 데이터 폴더 "%1"은 존재하지 않습니다. + + + Error: Cannot parse configuration file: %1. Only use key=value syntax. + 에러: 설정파일을 파싱할수 없습니다: %1. key=value syntax만 사용가능합니다. + + + Error: %1 + 에러: %1 + + QRImageWidget - + + &Save Image... + 이미지 저장(&S)... + + + &Copy Image + 이미지 복사(&C) + + + Save QR Code + QR코드 저장 + + + PNG Image (*.png) + PNG 이미지(*.png) + + RPCConsole @@ -1314,11 +1526,11 @@ Block chain - 블럭 체인 + 블록 체인 Current number of blocks - 현재 블럭 수 + 현재 블록 수 Memory Pool @@ -1326,7 +1538,7 @@ Current number of transactions - 현재 트랜잭션 수 + 현재 거래 수 Memory usage @@ -1425,12 +1637,16 @@ Ping 대기 + Min Ping + 최소 핑 + + Time Offset 시간 오프셋 Last block time - 최종 블럭 시각 + 최종 블록 시각 &Open @@ -1485,6 +1701,18 @@ 1년(&Y) + &Disconnect + 접속 끊기(&D) + + + Ban for + 추방 + + + &Unban + 노드 추방 취소(&U) + + Welcome to the %1 RPC console. %1 RPC 콘솔에 오신걸 환영합니다 @@ -1497,6 +1725,14 @@ 사용할 수 있는 명령을 둘러보려면 <b>help</b>를 입력하십시오. + WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramification of a command. + 경고 : 사기꾼이 사용자에게 여기에 명령을 입력하게 하여 지갑 내용을 훔칠수 있다는 사실을 알려드립니다. 명령어를 완전히 이해하지 못한다면 콘솔을 사용하지 마십시오. + + + Network activity disabled + 네트워크 활동이 정지됨. + + %1 B %1 바이트 @@ -1616,10 +1852,18 @@ 삭제 + Copy URI + URI 복사 + + Copy label 라벨 복사 + Copy message + 메시지 복사 + + Copy amount 거래액 복사 @@ -1643,14 +1887,42 @@ 이미지 저장(&S)... + Request payment to %1 + %1에 지불을 요청했습니다 + + + Payment information + 지불 정보 + + + URI + URI + + Address 주소 + Amount + 거래액 + + Label 라벨 - + + Message + 메시지 + + + Resulting URI too long, try to reduce the text for label / message. + URI 결과가 너무 길음, 라벨/메세지의 글을 줄이도록 하세요. + + + Error encoding URI into QR Code. + URI를 QR 코드로 인코딩하는 중 오류가 발생했습니다. + + RecentRequestsTableModel @@ -1662,10 +1934,26 @@ 라벨 + Message + 메시지 + + (no label) (라벨 없음) - + + (no message) + (메세지가 없습니다) + + + (no amount requested) + (요청한 거래액 없음) + + + Requested + 요청됨 + + SendCoinsDialog @@ -1710,7 +1998,7 @@ Change: - 체인지: + 잔돈: If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. @@ -1738,7 +2026,7 @@ If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - 사용자 정의 수수료가 1000사토시로 지정된 경우 트랜잭션의 크기가 250바이트 일 경우 1킬로바이트당 250사토시만 지불되지만 "최소 수수료"에선 1000사토시가 지불됩니다. 1킬로바이트가 넘는 트랜잭션인 경우 어떠한 경우에든 1킬로바이트 기준으로 지불됩니다. + 사용자 정의 수수료가 1000사토시로 지정된 경우 거래의 크기가 250바이트 일 경우 1킬로바이트당 250사토시만 지불되지만 "최소 수수료"에선 1000사토시가 지불됩니다. 1킬로바이트가 넘는 거래인 경우 어떠한 경우에든 1킬로바이트 기준으로 지불됩니다. Hide @@ -1750,11 +2038,11 @@ Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process. - 블록의 용량보다 트랜잭션의 용량이 작은 경우에는 최소한의 수수료만으로도 충분합니다. 그러나 비트코인 네트워크의 처리량보다 더 많은 트랜잭션 요구는 영원히 검증이 안 될 수도 있습니다. + 블록의 용량보다 거래의 용량이 작은 경우에는 최소한의 수수료만으로도 충분합니다. 그러나 비트코인 네트워크의 처리량보다 더 많은 거래 요구는 영원히 검증이 안 될 수도 있습니다. (read the tooltip) - (툴팁을 읽어보세요) + (툴팁을 꼭 읽어보세요) Recommended: @@ -1766,7 +2054,7 @@ (Smart fee not initialized yet. This usually takes a few blocks...) - (Smart fee가 아직 초기화되지 않았습니다. 블록 분석이 완료될 때 까지 기다려주십시오...) + (Smart fee가 아직 초기화 되지 않았습니다. 블록 분석이 완전하게 끝날 때 까지 기다려주십시오...) normal @@ -1793,6 +2081,10 @@ 더스트: + Confirmation time target: + 승인 시간 목표: + + Clear &All 모두 지우기(&A) @@ -1837,6 +2129,94 @@ 잔돈 복사 + %1 to %2 + %1을(를) %2(으)로 + + + Are you sure you want to send? + 정말로 보내시겠습니까? + + + added as transaction fee + 거래 수수료로 추가됨 + + + Total Amount %1 + 총 액수 %1 + + + or + 또는 + + + Confirm send coins + 코인 전송을 확인 + + + The recipient address is not valid. Please recheck. + 수령인 주소가 정확하지 않습니다. 재확인 바랍니다 + + + The amount to pay must be larger than 0. + 지불하는 금액은 0 보다 커야 합니다. + + + The amount exceeds your balance. + 잔고를 초과하였습니다. + + + The total exceeds your balance when the %1 transaction fee is included. + %1 의 거래수수료를 포함하면 잔고를 초과합니다. + + + Duplicate address found: addresses should only be used once each. + 중복된 주소 발견: 한번에 하나의 주소에만 작업할 수 있습니다. + + + Transaction creation failed! + 거래를 생성하는 것을 실패하였습니다! + + + The transaction was rejected with the following reason: %1 + 거래가 다음과 같은 이유로 거부되었습니다: %1 + + + A fee higher than %1 is considered an absurdly high fee. + %1 보다 높은 수수료는 너무 높은 수수료 입니다. + + + Payment request expired. + 지불 요청이 만료됨. + + + %n block(s) + %n 블록 + + + Pay only the required fee of %1 + 오직 %1 만의 수수료를 지불하기 + + + Estimated to begin confirmation within %n block(s). + %n 블록 안에 승인이 시작될 것으로 추정됩니다. + + + Warning: Invalid Bitcoin address + 경고: 잘못된 비트코인주소입니다 + + + Warning: Unknown change address + 경고: 알려지지 않은 주소변경입니다 + + + Confirm custom change address + 맞춤 주소 변경 확인 + + + The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure? + 변경하기 위해 선택한 주소는 이 지갑의 일부가 아닙니다. 지갑에 있는 일부 또는 모든 금액을 이 주소로 보낼 수 있습니다. 확실합니까? + + (no label) (라벨 없음) @@ -1919,10 +2299,18 @@ Memo: 메모: - + + Enter a label for this address to add it to your address book + 주소록에 추가하려면 라벨을 입력하세요 + + SendConfirmationDialog - + + Yes + + + ShutdownWindow @@ -1931,7 +2319,7 @@ Do not shut down the computer until this window disappears. - 창이 사라지기 전까지 컴퓨터를 끄지마시오. + 이 창이 사라지기 전까지 컴퓨터를 끄지 마세요. @@ -2020,7 +2408,59 @@ Reset all verify message fields 모든 검증 메시지 필드 재설정 - + + Click "Sign Message" to generate signature + 서명을 만들려면 "메시지 서명"을 누르십시오 + + + The entered address is invalid. + 입력한 주소가 잘못되었습니다. + + + Please check the address and try again. + 주소를 확인하고 다시 시도하십시오. + + + The entered address does not refer to a key. + 입력한 주소는 키에서 참조하지 않습니다. + + + Wallet unlock was cancelled. + 지갑 잠금 해제를 취소했습니다. + + + Private key for the entered address is not available. + 입력한 주소에 대한 개인키가 없습니다. + + + Message signing failed. + 메시지 서명에 실패했습니다. + + + Message signed. + 메시지를 서명했습니다. + + + The signature could not be decoded. + 서명을 해독할 수 없습니다. + + + Please check the signature and try again. + 서명을 확인하고 다시 시도하십시오. + + + The signature did not match the message digest. + 메시지 다이제스트와 서명이 일치하지 않습니다. + + + Message verification failed. + 메시지 검증에 실패했습니다. + + + Message verified. + 메시지를 검증했습니다. + + SplashScreen @@ -2037,18 +2477,190 @@ TransactionDesc + + Open for %n more block(s) + %n개의 더 많은 블록 열기 + + + Open until %1 + %1 까지 열림 + + + conflicted with a transaction with %1 confirmations + %1 승인이 있는 거래와 충돌 함 + + + %1/offline + %1/오프라인 + + + 0/unconfirmed, %1 + 0/미승인, %1 + + + in memory pool + 메모리 풀 안에 있음 + + + not in memory pool + 메모리 풀 안에 없음 + + + abandoned + 버려진 + + + %1/unconfirmed + %1/미확인 + + + %1 confirmations + %1 확인됨 + + + Status + 상태 + + + , has not been successfully broadcast yet + . 아직 성공적으로 통보하지 않음 + + + , broadcast through %n node(s) + , %n개 노드를 통해 전파 + Date 날짜 - + + Source + 소스 + + + Generated + 생성됨 + + + From + 으로부터 + + + unknown + 알수없음 + + + To + 에게 + + + own address + 자신의 주소 + + + watch-only + 조회전용 + + + label + 라벨 + + + Credit + 입금액 + + + matures in %n more block(s) + %n개의 더 많은 블록을 숙성 + + + not accepted + 허용되지 않음 + + + Debit + 출금액 + + + Total debit + 총 출금액 + + + Total credit + 총 입금액 + + + Transaction fee + 거래 수수료 + + + Net amount + 총 거래액 + + + Message + 메시지 + + + Comment + 설명 + + + Transaction ID + 거래 ID + + + Transaction total size + 거래 총 크기 + + + Output index + 출력 인덱스 + + + Merchant + 상인 + + + Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + 신규 채굴된 코인이 사용되기 위해서는 %1 개의 블록이 경과되어야 합니다. 블록을 생성할 때 블록체인에 추가되도록 네트워크에 전파되는 과정을 거치는데, 블록체인에 포함되지 못하고 실패한다면 해당 블록의 상태는 '미승인'으로 표현되고 비트코인 또한 사용될 수 없습니다. 이 현상은 다른 노드가 비슷한 시간대에 동시에 블록을 생성할 때 종종 발생할 수 있습니다. + + + Debug information + 디버깅 정보 + + + Transaction + 거래 + + + Inputs + 입력 + + + Amount + 거래액 + + + true + + + + false + 거짓 + + TransactionDescDialog This pane shows a detailed description of the transaction 이 창은 거래의 세부내역을 보여줍니다 - + + Details for %1 + %1에 대한 세부 정보 + + TransactionTableModel @@ -2063,22 +2675,138 @@ Label 라벨 + + Open for %n more block(s) + %n개의 더 많은 블록 열기 + + + Open until %1 + %1 까지 열림 + + + Offline + 오프라인 + + + Unconfirmed + 미확인 + + + Abandoned + 버려진 + + + Confirming (%1 of %2 recommended confirmations) + 승인 중 (권장되는 승인 회수 %2 대비 현재 승인 수 %1) + + + Confirmed (%1 confirmations) + 승인됨 (%1 확인됨) + + + Conflicted + 충돌 + + + Immature (%1 confirmations, will be available after %2) + 충분히 숙성되지 않은 상태 (%1 승인, %2 후에 사용 가능합니다) + + + This block was not received by any other nodes and will probably not be accepted! + 이 블록은 다른 노드로부터 받지 않아 허용되지 않을 것임! + + + Generated but not accepted + 생성되었으나 거절됨 + Received with 받은 주소 + Received from + 보낸 주소 + + Sent to 보낸 주소 + Payment to yourself + 자신에게 지불 + + + Mined + 채굴 + + + watch-only + 조회전용 + + + (n/a) + (없음) + + (no label) (라벨 없음) - + + Transaction status. Hover over this field to show number of confirmations. + 거래상황. 마우스를 올리면 검증횟수가 표시됩니다. + + + Date and time that the transaction was received. + 거래가 이루어진 날짜와 시각. + + + Type of transaction. + 거래의 종류. + + + Whether or not a watch-only address is involved in this transaction. + 조회전용 주소가 이 거래에 참여하는지 여부입니다. + + + User-defined intent/purpose of the transaction. + 거래에 대한 사용자 정의 intent/purpose + + + Amount removed from or added to balance. + 변경된 잔고. + + TransactionView + All + 전체 + + + Today + 오늘 + + + This week + 이번주 + + + This month + 이번 달 + + + Last month + 지난 달 + + + This year + 올 해 + + + Range... + 범위... + + Received with 받은 주소 @@ -2087,8 +2815,28 @@ 보낸 주소 + To yourself + 자기거래 + + + Mined + 채굴 + + + Other + 기타 + + + Enter address or label to search + 검색하기 위한 주소 또는 표 입력 + + + Min amount + 최소 거래액 + + Abandon transaction - 버려진 트랜잭션 + 버려진 거래 Copy address @@ -2104,11 +2852,11 @@ Copy transaction ID - 트랜잭션 아이디 복사 + 거래 아이디 복사 Copy raw transaction - 로우 트랜잭션 복사 + 원시 거래 복사 Copy full transaction details @@ -2136,7 +2884,7 @@ Watch-only - 모니터링 지갑 + 조회전용 Date @@ -2262,6 +3010,18 @@ 명령줄과 JSON-RPC 명령 수락 + Accept connections from outside (default: 1 if no -proxy or -connect/-noconnect) + 외부 접속을 승인합니다 (기본값 : -proxy 또는 -connect / -noconnect가 없는 경우 1) + + + Connect only to the specified node(s); -noconnect or -connect=0 alone to disable automatic connections + 지정된 노드에만 연결; 자동 연결을 사용하지 않으려면 -noconnect 또는 -connect=0 을 단독으로 사용하십시오. + + + Distributed under the MIT software license, see the accompanying file %s or %s + MIT 소프트웨어 라이센스에 따라 배포 됨, 첨부 파일 %s 또는 %s을 참조하십시오. + + If <category> is not supplied or if <category> = 1, output all debugging information. <category>가 제공되지 않거나 <category> = 1 인 경우, 모든 디버깅 정보를 출력 @@ -2303,7 +3063,7 @@ The %s developers - %s 코어 개발자 + %s 개발자 A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) @@ -2311,7 +3071,7 @@ Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) - 트랜잭션의 중계를 하지 않더라도 화이트 리스트에 포함된 피어에서 받은 트랜잭션은 중계하기 (기본값: %d) + 거래의 중계를 하지 않더라도 화이트 리스트에 포함된 피어에서 받은 트랜잭션은 중계하기 (기본값: %d) Bind to given address and always listen on it. Use [host]:port notation for IPv6 @@ -2323,7 +3083,7 @@ Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup - 시작시 모든 지갑 트랜잭션을 삭제하고 -rescan을 통하여 블록체인만 복구합니다. + 시작시 모든 지갑 거래를 삭제하고 -rescan을 통하여 블록체인만 복구합니다. Error loading %s: You can't enable HD on a already existing non-HD wallet @@ -2338,8 +3098,16 @@ 지갑 거래가 바뀌면 명령을 실행합니다.(%s 안의 명령어가 TxID로 바뀝니다) - Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s) - 하나의 지갑 트랜잭션에서의 총 수수료(%s)의 최대치; 너무 낮게 설정하면 큰 트랜잭션이 중지 됩니다 (기본값: %s) + Extra transactions to keep in memory for compact block reconstructions (default: %u) + 압축 블록 재구성을 위해 메모리에 보관해야하는 추가 거래 (기본값: %u) + + + If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s) + 이 블록이 체인에 있으면 해당 블록과 그 조상이 유효하며 잠재적으로 스크립트 확인을 건너 뜁니다 (0은 모두 확인, 기본값: %s, testnet: %s) + + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) + 허용 된 최대 중간 피어 시간 오프셋 조정. 시간에 대한 지역적 전망치는 전방 또는 후방의 피어에 의해 영향을 받을 수 있습니다. (기본값: %u 초) Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. @@ -2350,6 +3118,10 @@ %s가 유용하다고 생각한다면 프로젝트에 공헌해주세요. 이 소프트웨어에 대한 보다 자세한 정보는 %s를 방문해주십시오. + Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s) + 블록 생성시 거래가 포함되도록 최저 수수료율을 설정하십시오 (%s/kB 단위). (기본값: %s) + + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) 스크립트 인증 스레드의 갯수 설정 (%u-%d, 0 = 자동, <0 = 지정된 코어 개수만큼 사용 안함, 기본값: %d) @@ -2358,6 +3130,10 @@ 블록 데이터베이스에 미래의 블록이 포함되어 있습니다. 이것은 사용자의 컴퓨터의 날짜와 시간이 올바르게 설정되어 있지 않을때 나타날 수 있습니다. 만약 사용자의 컴퓨터의 날짜와 시간이 올바르다고 확신할 때에만 블록 데이터 베이스의 재구성을 하십시오 + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications + 출시 전의 테스트 빌드 입니다. - 스스로의 책임하에 사용하십시오 - 채굴이나 상업적 용도로 프로그램으로 사용하지 마십시오 + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain 데이터베이스를 포크 전 상태로 돌리지 못했습니다. 블록체인을 다시 다운로드 해주십시오. @@ -2366,8 +3142,24 @@ 리슨(Listen) 포트를 할당하기 위해 UPnP 사용 (기본값: 열려있거나 -proxy 옵션을 사용하지 않을 시 1) + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times + 클라이언트JSON-RPC 연결시 사용자 이름과 해시화된 암호문. <userpw> 필드는 <USERNAME>:<SALT>$<HASH> 포멧으로 구성되어 있습니다. 전형적 파이썬 스크립트에선 share/rpcuser가 포함되어 있습니다. 그런 다음 클라이언트는 rpcuser=<USERNAME>/ rpcpassword=<PASSWORD> 쌍의 인수를 사용하여 정상적으로 연결합니다. 이 옵션은 여러번 지정할 수 있습니다. + + + Wallet will not create transactions that violate mempool chain limits (default: %u) + 지갑은 mempool chain limit (기본값: %u) 을 위반하는 거래를 생성하지 않습니다. + + + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. + 경고 : 모든 네트워크가 동의해야 하나, 일부 채굴자들에게 문제가 있는 것으로 보입니다. + + + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. + 경고: 현재 비트코인 버전이 다른 네트워크 참여자들과 동일하지 않은 것 같습니다. 당신 또는 다른 참여자들이 동일한 비트코인 버전으로 업그레이드 할 필요가 있습니다. + + You need to rebuild the database using -reindex-chainstate to change -txindex - -txindex를 바꾸기 위해서는 -reindex-chainstate를 사용해서 데이터베이스를 재구성해야 합니다. + -txindex를 바꾸기 위해서는 -reindex-chainstate 를 사용해서 데이터베이스를 재구성해야 합니다. %s corrupt, salvage failed @@ -2398,6 +3190,14 @@ %s 주소를 확인할 수 없습니다: '%s' + Chain selection options: + 체인 선택 옵션: + + + Change index out of range + 범위 밖의 인덱스 변경 + + Connection options: 연결 설정 : @@ -2419,7 +3219,7 @@ Do you want to rebuild the block database now? - 블락 데이터베이스를 다시 생성하시겠습니까? + 블록 데이터베이스를 다시 생성하시겠습니까? Enable publish hash block in <address> @@ -2427,19 +3227,19 @@ Enable publish hash transaction in <address> - <address>에 대한 해시 트랙잭션 공개 활성화 + <address>에 대한 해시 거래 공개 활성화 Enable publish raw block in <address> - <address>에 대한 로우 블록 공개 활성화 + <address>에 대한 원시 블록 공개 활성화 Enable publish raw transaction in <address> - <address>에 대한 로우 트랜잭션 공개 활성화 + <address>에 대한 원시 거래 공개 활성화 Enable transaction replacement in the memory pool (default: %u) - 메모리 풀(pool) 내의 트랜잭션 치환(replacement) 활성화 (기본값: %u) + 메모리 풀(pool) 내의 거래 치환(replacement) 활성화 (기본값: %u) Error initializing block database @@ -2507,7 +3307,7 @@ Keep the transaction memory pool below <n> megabytes (default: %u) - 트랜잭션 메모리 풀의 용량을 <n>메가바이트 아래로 유지하기 (기본값: %u) + 거래 메모리 풀의 용량을 <n>메가바이트 아래로 유지하기 (기본값: %u) Loading banlist... @@ -2590,6 +3390,10 @@ 리슨(Listen) 포트를 할당하기 위해 UPnP 사용 (기본값: %u) + Use the test chain + 테스트 체인 사용 + + User Agent comment (%s) contains unsafe characters. 사용자 정의 코멘트 (%s)에 안전하지 못한 글자가 포함되어 있습니다. @@ -2647,7 +3451,7 @@ Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s) - 해당 금액(%s/kB) 보다 적은 수수료는 중계, 채굴, 트랜잭션 생성에서 수수료 면제로 간주됩니다 (기본값: %s) + 해당 금액(%s/kB) 보다 적은 수수료는 중계, 채굴, 거래 생성에서 수수료 면제로 간주됩니다 (기본값: %s) If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) @@ -2655,11 +3459,11 @@ Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions) - 유효하지 않은 금액 -maxtxfee=<amount>: '%s' (트랜잭션이 막히는 상황을 방지하게 위해 적어도 %s 의 중계 수수료를 지정해야 합니다) + 유효하지 않은 금액 -maxtxfee=<amount>: '%s' (거래가 막히는 상황을 방지하게 위해 적어도 %s 의 중계 수수료를 지정해야 합니다) Maximum size of data in data carrier transactions we relay and mine (default: %u) - 중계 및 채굴을 할 때 데이터 운송 트랜잭션에서 데이터의 최대 크기 (기본값: %u) + 중계 및 채굴을 할 때 데이터 운송 거래에서 데이터의 최대 크기 (기본값: %u) Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u) @@ -2674,8 +3478,12 @@ 거래액이 수수료를 지불하기엔 너무 작습니다 + Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start + BIP32 이후에는 계층적 결정성 키 생성 (HD)을 사용하십시오. 지갑 생성/처음 시작 시에만 효과가 있습니다. + + Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway - 화이트리스트에 포함된 피어는 이미 메모리풀에 포함되어 있어도 DoS 추방이 되지 않으며 그들의 트랜잭션이 항상 중계됩니다, 이는 예를 들면 게이트웨이에서 유용합니다. + 화이트리스트에 포함된 피어는 이미 메모리풀에 포함되어 있어도 DoS 추방이 되지 않으며 그들의 거래가 항상 중계됩니다, 이는 예를 들면 게이트웨이에서 유용합니다. You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain @@ -2719,7 +3527,7 @@ Keep at most <n> unconnectable transactions in memory (default: %u) - 최대 <n>개의 연결할 수 없는 트랜잭션을 메모리에 저장 (기본값: %u) + 최대 <n>개의 연결할 수 없는 거래를 메모리에 저장 (기본값: %u) Need to specify a port with -whitebind: '%s' @@ -2739,7 +3547,7 @@ Rescan the block chain for missing wallet transactions on startup - 시작시 누락된 지갑 트랜잭션에 대해 블록 체인을 다시 검색 합니다 + 시작시 누락된 지갑 거래에 대해 블록 체인을 다시 검색 합니다 Send trace/debug info to console instead of debug.log file @@ -2747,7 +3555,7 @@ Send transactions as zero-fee transactions if possible (default: %u) - 가능한 경우 수수료 없이 트랜잭션 보내기 (기본값: %u) + 가능한 경우 수수료 없이 거래 보내기 (기본값: %u) Show all debugging options (usage: --help -help-debug) @@ -2783,7 +3591,7 @@ Transaction too large for fee policy - 수수료 정책에 비해 트랜잭션이 너무 큽니다 + 수수료 정책에 비해 거래가 너무 큽니다 Transaction too large @@ -2823,7 +3631,7 @@ Execute command when the best block changes (%s in cmd is replaced by block hash) - 최고의 블럭이 변하면 명령을 실행(cmd 에 있는 %s 는 블럭 해시에 의해 대체되어 짐) + 최고의 블록이 변하면 명령을 실행 (cmd 에 있는 %s 는 블록 해시에 의해 대체되어 짐) Allow DNS lookups for -addnode, -seednode and -connect @@ -2835,27 +3643,35 @@ (1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data) - (1 = 트랜잭션의 메타 데이터를 유지함 예. 계좌정보 와 지불 요구 정보, 2 = 트랜잭션 메타 데이터 파기) + (1 = 거래의 메타 데이터를 유지함 예. 계좌정보 와 지불 요구 정보, 2 = 거래 메타 데이터 파기) -maxtxfee is set very high! Fees this large could be paid on a single transaction. - -maxtxfee값이 너무 큽니다! 하나의 트랜잭션에 너무 큰 수수료가 지불 됩니다. + -maxtxfee값이 너무 큽니다! 하나의 거래에 너무 큰 수수료가 지불 됩니다. Do not keep transactions in the mempool longer than <n> hours (default: %u) - 메모리 풀에 있는 트랜잭션 기록을 <n>시간 후 부터는 유지하지 않기 (기본값: %u) + 메모리 풀에 있는 거래 기록을 <n>시간 후 부터는 유지하지 않기 (기본값: %u) + + + Equivalent bytes per sigop in transactions for relay and mining (default: %u) + 릴레이 및 마이닝 거래의 sigop 당 동등한 바이트 (기본값: %u) Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) 해당 금액(%s/kB) 보다 적은 수수료는 수수료 면제로 간주됩니다.(기본값: %s) + Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d) + 피어들이 로컬 중계 정책을 위반하더라도 화이트 리스트에 포함된 피어인경우 강제로 중계하기 (기본값: %d) + + How thorough the block verification of -checkblocks is (0-4, default: %u) -checkblocks을 통한 블록 점검 (0-4, 기본값: %u) Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u) - getrawtransaction를 RPC CALL를 통해 완전한 트랜잭션 인덱스 유지 (기본값: %u) + getrawtransaction를 RPC CALL를 통해 완전한 거래 인덱스 유지 (기본값: %u) Number of seconds to keep misbehaving peers from reconnecting (default: %u) @@ -2866,8 +3682,24 @@ 디버그 정보 출력 (기본값: %u, <category> 제공은 선택입니다) + Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect/-noconnect) + 보유한 피어 주소가 적은 경우 DNS 조회를 통해 피어 주소를 요청합니다. (-connect / -noconnect가 아니라면 기본값은 1) + + + Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d) + non-segwit(0) 또는 segwit(1) (기본값: %d) 가 아닌 자세한 정보 표시 모드로 반환 된 원시 거래 또는 블록 hex의 직렬화를 설정합니다. + + Support filtering of blocks and transaction with bloom filters (default: %u) - 블룸필터를 통해 블록과 트랜잭션 필터링 지원 (기본값: %u) + 블룸필터를 통해 블록과 거래 필터링 지원 (기본값: %u) + + + This is the transaction fee you may pay when fee estimates are not available. + 이것은 수수료 견적을 이용할 수 없을 때 지불 할 수 있는 거래 수수료입니다. + + + This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. + 이 제품에는 OpenSSL Project에서 OpenSSL Toolkit %s으로 사용하기 위해 개발 한 소프트웨어와 Eric Young이 작성한 암호화 소프트웨어 및 Thomas Bernard가 작성한 UPnP 소프트웨어가 포함되어 있습니다. Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. @@ -2902,6 +3734,10 @@ 설정된 IP주소 (보기 1.2.3.4) 혹은 CIDR로 작성된 네트워크 (보기 1.2.3.0/24)로 화이트리스트에 포함된 피어에 접속합니다. 이 설정은 복수로 지정 할 수 있습니다. + %s is set very high! + %s가 매우 높게 설정되었습니다! + + (default: %s) (기본값: %s) @@ -2922,6 +3758,10 @@ 잘못된 -proxy 주소입니다: '%s' + Keypool ran out, please call keypoolrefill first + Keypool이 종료되었습니다. 먼저 keypoolrefill을 호출하십시오. + + Listen for JSON-RPC connections on <port> (default: %u or testnet: %u) JSON-RPC 연결을 <port>포트로 받기 (기본값: %u 혹은 테스트넷: %u) @@ -2935,7 +3775,7 @@ Make the wallet broadcast transactions - 지갑 브로드캐스트 트랜잭션을 만들기 + 지갑 브로드캐스트 거래를 만들기 Maximum per-connection receive buffer, <n>*1000 bytes (default: %u) @@ -2951,17 +3791,25 @@ Relay and mine data carrier transactions (default: %u) - 데이터 운송 트랜잭션을 중계 및 채굴 (기본값: %u) + 데이터 운송 거래를 중계 및 채굴 (기본값: %u) Relay non-P2SH multisig (default: %u) 비 P2SH 다중서명을 중계 (기본값: %u) + Send transactions with full-RBF opt-in enabled (default: %u) + full-RBF opt-in이 활성화 된 거래을 전송합니다. (기본값: %u) + + Set key pool size to <n> (default: %u) 키 풀 사이즈를 <n> 로 설정 (기본값: %u) + Set maximum BIP141 block weight (default: %d) + 최대 BIP141 블록 무게 설정 (기본값: %d) + + Set the number of threads to service RPC calls (default: %d) 원격 프로시져 호출 서비스를 위한 쓰레드 개수를 설정 (기본값 : %d) @@ -2979,15 +3827,39 @@ Spend unconfirmed change when sending transactions (default: %u) - 트랜잭션을 보낼 때 검증되지 않은 잔돈 쓰기 (기본값: %u) + 거래를 보낼 때 검증되지 않은 잔돈 쓰기 (기본값: %u) Starting network threads... 네트워크 스레드 시작중... + The wallet will avoid paying less than the minimum relay fee. + 지갑은 최소 중계 수수료보다 적은 금액을 지불하는 것을 피할 것입니다. + + + This is the minimum transaction fee you pay on every transaction. + 이것은 모든 거래에서 지불하는 최소 거래 수수료입니다. + + + This is the transaction fee you will pay if you send a transaction. + 이것은 거래를 보낼 경우 지불 할 거래 수수료입니다. + + Threshold for disconnecting misbehaving peers (default: %u) - 이상행동 네트워크 참여자의 연결을 차단시키기 위한 한계치 (기본값: %u) + 비정상적인 피어의 연결을 차단시키기 위한 임계값 (기본값: %u) + + + Transaction amounts must not be negative + 거래액은 반드시 정수여야합니다. + + + Transaction has too long of a mempool chain + 거래가 너무 긴 mempool 체인을 갖고 있습니다 + + + Transaction must have at least one recipient + 거래에는 최소한 한명의 수령인이 있어야 합니다. Unknown network specified in -onlynet: '%s' @@ -2999,7 +3871,7 @@ Loading block index... - 블럭 인덱스를 불러오는 중... + 블록 인덱스를 불러오는 중... Add a node to connect to and attempt to keep the connection open diff --git a/src/qt/locale/bitcoin_ms_MY.ts b/src/qt/locale/bitcoin_ms_MY.ts index 0108332dd75..7844093e3bb 100644 --- a/src/qt/locale/bitcoin_ms_MY.ts +++ b/src/qt/locale/bitcoin_ms_MY.ts @@ -2,6 +2,10 @@ AddressBookPage + Right-click to edit address or label + Klik-kanan untuk edit alamat ataupun label + + Create a new address Cipta alamat baru @@ -18,6 +22,10 @@ &Salin + C&lose + &Tutup + + Delete the currently selected address from the list Padam alamat semasa yang dipilih dari senaraiyang dipilih dari senarai @@ -34,25 +42,301 @@ Alihkan fail data ke dalam tab semasa &Delete &Padam - + + Choose the address to send coins to + Pilih alamat untuk hantar koin kepada + + + Choose the address to receive coins with + Pilih alamat untuk menerima koin dengan + + + C&hoose + &Pilih + + + Sending addresses + alamat-alamat penghantaran + + + Receiving addresses + alamat-alamat penerimaan + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Ini adalah alamat Bitcoin anda untuk pembayaran. Periksa jumlah dan alamat penerima sebelum membuat penghantaran koin sentiasa. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Ini adalah alamat Bitcoin anda untuk menerima pembayaraan. Anda disyorkan untuk menguna alamat menerima untuk setiap transaksi. + + + &Copy Address + &Salin Aamat + + + Copy &Label + Salin & Label + + + &Edit + &Edit + + + Export Address List + Eskport Senarai Alamat + + + Comma separated file (*.csv) + Fail dibahagi oleh koma(*.csv) + + + Exporting Failed + Mengeksport Gagal + + + There was an error trying to save the address list to %1. Please try again. + Terdapat ralat semasa cubaan menyimpan senarai alamat kepada %1. Sila cuba lagi. + + AddressTableModel - + + Label + Label + + + Address + Alamat + + + (no label) + (tiada label) + + AskPassphraseDialog - + + Passphrase Dialog + Dialog frasa laluan + + + Enter passphrase + memasukkan frasa laluan + + + New passphrase + Frasa laluan baru + + + Repeat new passphrase + Ulangi frasa laluan baru + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Memasukkan frasa laluan baru kepada dompet.<br/>Sila mengunakkan frasa laluan yang<b>mengandungi 10 atau lebih aksara rawak</b>,ataupun<b>lapan atau lebih perkataan.</b> + + + Encrypt wallet + Dompet encrypt + + + This operation needs your wallet passphrase to unlock the wallet. + Operasi ini perlukan frasa laluan dompet anda untuk membuka kunci dompet. + + + Unlock wallet + Membuka kunci dompet + + + This operation needs your wallet passphrase to decrypt the wallet. + Operasi ini memerlukan frasa laluan dompet anda untuk menyahsulit dompet. + + + Decrypt wallet + Menyahsulit dompet + + + Change passphrase + Menukar frasa laluan + + + Enter the old passphrase and new passphrase to the wallet. + Memasukkan frasa laluan lama dan frasa laluan baru untuk. + + + Confirm wallet encryption + Mengesahkan enkripsi dompet + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Amaran: Jika anda enkripkan dompet anda dan hilangkan frasa laluan, anda akan <b>ANDA AKAN HILANGKAN SEMUA BITCOIN ANDA</b>! + + + Are you sure you wish to encrypt your wallet? + Anda pasti untuk membuat enkripsi dompet anda? + + + Wallet encrypted + Dompet dienkripsi + + + %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + %1 akan tutup untuk menyelesaikan proses enkripsi. Ingat bahawa enkripsi tidak boleh melidungi sepenuhnya bitcoins anda daripada dicuri oleh malware yang menjangkiti komputer anda. + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + PENTING: Apa-apa sandaran yang anda buat sebelum ini untuk fail dompet anda hendaklah digantikan dengan fail dompet enkripsi yang dijana baru. Untuk sebab-sebab keselamatan , sandaran fail dompet yang belum dibuat enkripsi sebelum ini akan menjadi tidak berguna secepat anda mula guna dompet enkripsi baru. + + + Wallet encryption failed + Enkripsi dompet gagal + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Enkripsi dompet gagal kerana ralat dalaman. Dompet anda tidak dienkripkan. + + + The supplied passphrases do not match. + Frasa laluan yang dibekalkan tidak sepadan. + + + Wallet unlock failed + Pembukaan kunci dompet gagal + + + The passphrase entered for the wallet decryption was incorrect. + Frasa laluan dimasukki untuk dekripsi dompet adalah tidak betul. + + + Wallet decryption failed + Dekripsi dompet gagal + + + Wallet passphrase was successfully changed. + Frasa laluan dompet berjaya ditukar. + + + Warning: The Caps Lock key is on! + Amaran: Kunci Caps Lock buka! + + BanTableModel - + + IP/Netmask + IP/Netmask + + + Banned Until + Diharamkan sehingga + + BitcoinGUI + Sign &message... + Tandatangan & mesej... + + + Synchronizing with network... + Penyegerakan dengan rangkaian... + + + &Overview + &Gambaran Keseluruhan + + + Node + Nod + + + Show general overview of wallet + Tunjuk gambaran keseluruhan umum dompet + + + &Transactions + &Transaksi + + + Browse transaction history + Menyemak imbas sejarah transaksi + + + E&xit + &Keluar + + + Quit application + Berhenti aplikasi + + + &About %1 + &Mengenai%1 + + + Show information about %1 + Menunjuk informasi mengenai%1 + + + About &Qt + Mengenai &Qt + + + Show information about Qt + Menunjuk informasi megenai Qt + + &Options... Pilihan + + Modify configuration options for %1 + Mengubah suai pilihan konfigurasi untuk %1 + + + &Encrypt Wallet... + &Enkripsi Dompet + + + &Backup Wallet... + &Dompet Sandaran... + + + &Change Passphrase... + &Menukar frasa-laluan + + + &Sending addresses... + &Menghantar frasa-laluan + + + &Receiving addresses... + &Menerima frasa-laluan... + + + Open &URI... + Buka &URI... + + + Reindexing blocks on disk... + Reindexi blok pada cakera... + + + Send coins to a Bitcoin address + Menghantar koin kepada alamat Bitcoin + + + Backup wallet to another location + Wallet sandaran ke lokasi lain + CoinControlDialog + + (no label) + (tiada label) + EditAddressDialog @@ -113,9 +397,25 @@ Alihkan fail data ke dalam tab semasa Copy &Address &Salin Alamat + + Address + Alamat + + + Label + Label + RecentRequestsTableModel + + Label + Label + + + (no label) + (tiada label) + SendCoinsDialog @@ -123,7 +423,11 @@ Alihkan fail data ke dalam tab semasa Balance: Baki - + + (no label) + (tiada label) + + SendCoinsEntry @@ -150,9 +454,33 @@ Alihkan fail data ke dalam tab semasa TransactionTableModel + + Label + Label + + + (no label) + (tiada label) + TransactionView + + Comma separated file (*.csv) + Fail dibahagi oleh koma(*.csv) + + + Label + Label + + + Address + Alamat + + + Exporting Failed + Mengeksport Gagal + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts index 183cbac80aa..14919c440df 100644 --- a/src/qt/locale/bitcoin_nb.ts +++ b/src/qt/locale/bitcoin_nb.ts @@ -41,10 +41,78 @@ &Delete &Slett - + + Choose the address to send coins to + Velg adressen å sende mynter til + + + Choose the address to receive coins with + Velg adressen til å motta mynter med + + + C&hoose + V&elg + + + Sending addresses + Utsendingsadresser + + + Receiving addresses + Mottaksadresser + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Dette er dine Bitcoin-adresser for sending av betalinger. Sjekk alltid beløpet og mottakeradressen før sending av mynter. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Dette er dine Bitcoin-adresser for å sende betalinger med. Det er anbefalt å bruke en ny mottaksadresse for hver transaksjon. + + + &Copy Address + &Kopier Adresse + + + Copy &Label + Kopier &Merkelapp + + + &Edit + &Rediger + + + Export Address List + Eksporter adresseliste + + + Comma separated file (*.csv) + Kommaseparert fil (*.csv) + + + Exporting Failed + Eksportering feilet + + + There was an error trying to save the address list to %1. Please try again. + Det oppstod en feil under lagring av adresselisten til %1. Vennligst prøv på nytt. + + AddressTableModel - + + Label + Merkelapp + + + Address + Adresse + + + (no label) + (ingen merkelapp) + + AskPassphraseDialog @@ -63,7 +131,95 @@ Repeat new passphrase Gjenta ny adgangsfrase - + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Oppgi adgangsfrasen til lommeboken.<br/>Vennligst bruk en adgangsfrase med <b>ti eller flere tilfeldige tegn</b>, eller <b>åtte eller flere ord</b>. + + + Encrypt wallet + Krypter lommebok + + + This operation needs your wallet passphrase to unlock the wallet. + Denne operasjonen krever adgangsfrasen til lommeboken for å låse den opp. + + + Unlock wallet + Lås opp lommebok + + + This operation needs your wallet passphrase to decrypt the wallet. + Denne operasjonen krever adgangsfrasen til lommeboken for å dekryptere den. + + + Decrypt wallet + Dekrypter lommebok + + + Change passphrase + Endre adgangsfrase + + + Enter the old passphrase and new passphrase to the wallet. + Angi den gamle og en ny adgangsfrase til lommeboken. + + + Confirm wallet encryption + Bekreft kryptering av lommebok + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Advarsel: Hvis du krypterer lommeboken og mister adgangsfrasen, så vil du <b>MISTE ALLE DINE BITCOINS</b>! + + + Are you sure you wish to encrypt your wallet? + Er du sikker på at du vil kryptere lommeboken? + + + Wallet encrypted + Lommebok kryptert + + + %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + %1 vil nå lukkes for å fullføre krypteringsprosessen. Husk at kryptering av lommeboken ikke fullt ut kan beskytte dine bitcoins fra å bli stjålet om skadevare infiserer datamaskinen din. + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + VIKTIG: Tidligere sikkerhetskopier av din lommebokfil bør erstattes med den nylig genererte og krypterte filen, da de blir ugyldiggjort av sikkerhetshensyn så snart du begynner å bruke den nye krypterte lommeboken. + + + Wallet encryption failed + Kryptering av lommebok feilet + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Kryptering av lommebok feilet på grunn av en intern feil. Din lommebok ble ikke kryptert. + + + The supplied passphrases do not match. + De angitte adgangsfrasene er ulike. + + + Wallet unlock failed + Opplåsing av lommebok feilet + + + The passphrase entered for the wallet decryption was incorrect. + Adgangsfrasen angitt for dekryptering av lommeboken var feil. + + + Wallet decryption failed + Dekryptering av lommebok feilet + + + Wallet passphrase was successfully changed. + Adgangsfrase for lommebok er endret. + + + Warning: The Caps Lock key is on! + Advarsel: Caps Lock er på! + + BanTableModel @@ -162,6 +318,18 @@ Åpne &URI... + Click to disable network activity. + Klikk for å deaktivere nettverksaktivitet + + + Network activity disabled. + Nettverksaktivitet deaktivert + + + Click to enable network activity again. + Klikk for å aktivere nettverksaktivitet igjen. + + Reindexing blocks on disk... Reindekserer blokker på harddisk... @@ -302,6 +470,10 @@ %1 klient + Connecting to peers... + Kobler til likemannsnettverket... + + Catching up... Laster ned... @@ -351,7 +523,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> Lommeboken er <b>kryptert</b> og for tiden <b>låst</b> - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + En fatal feil har inntruffet. Bitcoin kan ikke lenger trygt fortsette, og må derfor avslutte. + + CoinControlDialog @@ -422,7 +598,59 @@ Confirmed Bekreftet - + + Copy address + Kopier adresse + + + Copy amount + Kopier beløp + + + Copy transaction ID + Kopier transaksjons-ID + + + Copy quantity + Kopier mengde + + + Copy fee + Kopier gebyr + + + Copy change + Kopier veksel + + + (%1 locked) + (%1 låst) + + + yes + ja + + + no + nei + + + Can vary +/- %1 satoshi(s) per input. + Kan variere +/- %1 satoshi(er) per input. + + + (no label) + (ingen merkelapp) + + + change from %1 (%2) + veksel fra %1 (%2) + + + (change) + (veksel) + + EditAddressDialog @@ -445,7 +673,31 @@ &Address &Adresse - + + New receiving address + Ny mottaksadresse + + + New sending address + Ny utsendingsadresse + + + Edit receiving address + Rediger mottaksadresse + + + Edit sending address + Rediger utsendingsadresse + + + Could not unlock wallet. + Kunne ikke låse opp lommebok. + + + New key generation failed. + Generering av ny nøkkel feilet. + + FreespaceChecker @@ -519,7 +771,11 @@ Show splash screen on startup (default: %u) Vis velkomstbilde ved oppstart (default: %u) - + + Reset all settings changed in the GUI + Nullstill alle innstillinger endret i det grafiske brukergrensesnittet + + Intro @@ -562,10 +818,30 @@ Skjema + Unknown... + Ukjent... + + Last block time Tidspunkt for siste blokk + Progress + Fremgang + + + Progress increase per hour + Fremgangen stiger hver time + + + calculating... + kalkulerer... + + + Estimated time left until synced + Estimert gjenstående tid før ferdig synkronisert + + Hide Skjul @@ -736,6 +1012,10 @@ &Vindu + &Hide the icon from the system tray. + &Skjul ikonet fra oppgavelinjen. + + Hide tray icon Skjul søppel ikon @@ -935,17 +1215,61 @@ %1 ms %1 ms + + %n second(s) + %n sekund%n sekunder + + + %n minute(s) + %n minutt%n minutter + + + %n hour(s) + %n time%n timer + + + %n day(s) + %n dag%n dager + + + %n week(s) + %n uke%n uker + %1 and %2 %1 og %2 + + %n year(s) + %n år%n år + QObject::QObject - + + Error: %1 + Feil: %1 + + QRImageWidget - + + &Save Image... + &Lagre bilde... + + + &Copy Image + &Kopier bilde + + + Save QR Code + Lagre QR-kode + + + PNG Image (*.png) + PNG-bilde (*.png) + + RPCConsole @@ -1283,7 +1607,11 @@ Remove Fjern - + + Copy amount + Kopier beløp + + ReceiveRequestDialog @@ -1302,9 +1630,37 @@ &Save Image... &Lagre Bilde... + + Address + Adresse + + + Label + Merkelapp + + + Message + Melding + RecentRequestsTableModel + + Date + Dato + + + Label + Merkelapp + + + Message + Melding + + + (no label) + (ingen merkelapp) + SendCoinsDialog @@ -1448,7 +1804,31 @@ S&end S&end - + + Copy quantity + Kopier mengde + + + Copy amount + Kopier beløp + + + Copy fee + Kopier gebyr + + + Copy change + Kopier veksel + + + or + eller + + + (no label) + (ingen merkelapp) + + SendCoinsEntry @@ -1530,10 +1910,18 @@ SendConfirmationDialog - + + Yes + Ja + + ShutdownWindow + %1 is shutting down... + %1 lukker... + + Do not shut down the computer until this window disappears. Slå ikke av datamaskinen før dette vinduet forsvinner. @@ -1624,6 +2012,14 @@ Reset all verify message fields Tilbakestill alle felter for meldingsverifikasjon + + Message signing failed. + Signering av melding feilet. + + + Message signed. + Melding signert. + SplashScreen @@ -1641,6 +2037,38 @@ TransactionDesc + + Date + Dato + + + From + Fra + + + unknown + ukjent + + + To + Til + + + not accepted + ikke akseptert + + + Message + Melding + + + Comment + Kommentar + + + Transaction ID + Transaksjons-ID + TransactionDescDialog @@ -1651,9 +2079,97 @@ TransactionTableModel + + Date + Dato + + + Label + Merkelapp + + + Offline + Frakoblet + + + Unconfirmed + Ubekreftet + + + Sent to + Sendt til + + + (no label) + (ingen merkelapp) + TransactionView + + All + Alt + + + Today + I dag + + + This week + Denne uka + + + This month + Denne måneden + + + Last month + Forrige måned + + + This year + Dette året + + + Sent to + Sendt til + + + To yourself + Til deg selv + + + Copy address + Kopier adresse + + + Copy amount + Kopier beløp + + + Copy transaction ID + Kopier transaksjons-ID + + + Comma separated file (*.csv) + Kommaseparert fil (*.csv) + + + Date + Dato + + + Label + Merkelapp + + + Address + Adresse + + + Exporting Failed + Eksportering feilet + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_ne.ts b/src/qt/locale/bitcoin_ne.ts index f7fb0e5a6e8..be6e8e03910 100644 --- a/src/qt/locale/bitcoin_ne.ts +++ b/src/qt/locale/bitcoin_ne.ts @@ -41,6 +41,23 @@ &Delete &amp;मेटाउनुहोस् + + C&hoose + छनौट गर्नुहोस्... + + + Sending addresses + पठाउने ठेगानाहरू... + + + Receiving addresses + प्राप्त गर्ने ठेगानाहरू... + + + &Copy Address + ठेगाना कपी गर्नुहोस् + + AddressTableModel @@ -192,6 +209,11 @@ Amount रकम + + Copy address + ठेगाना कपी गर्नुहोस् + + EditAddressDialog @@ -204,6 +226,10 @@ Intro + + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + %1 ले बिटकोइन ब्लक चेनको एउटा प्रतिलिपि डाउनलोड र भण्डारण गर्नेछ । यो निर्देशिकामा कम्तिमा पनि %2GB डाटा भण्डारण गरिनेछ, र यो समयसँगै बढ्नेछ । वालेटलाई पनि यो निर्देशिकामा भण्डारण गरिनेछ । + ModalOverlay @@ -213,6 +239,10 @@ OptionsDialog + + Choose the default subdivision unit to show in the interface and when sending coins. + इन्टरफेसमा र सिक्का पठाउँदा देखिने डिफल्ट उपविभाजन एकाइ चयन गर्नुहोस् । + OverviewPage @@ -281,6 +311,10 @@ Amount रकम + + Enter a Bitcoin address (e.g. %1) + कृपया बिटकोइन ठेगाना प्रवेश गर्नुहोस् (उदाहरण %1) + QObject::QObject @@ -310,14 +344,26 @@ SendCoinsDialog + + Choose... + छनौट गर्नुहोस्... + SendCoinsEntry + Choose previously used address + पहिला प्रयोग गरिएको ठेगाना प्रयोग गर्नुहोस् + + The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally. पठाइँदै गरेको रकमबाट शुल्क कटौती गरिनेछ । प्राप्तकर्ताले तपाईंले रकम क्षेत्रमा प्रवेष गरेको भन्दा थोरै बिटकोइन प्राप्त गर्ने छन् । धेरै प्राप्तकर्ता चयन गरिएको छ भने समान रूपमा शुल्क विभाजित गरिनेछ । + Enter a label for this address to add it to the list of used addresses + यो ठेगानालाई प्रयोग गरिएको ठेगानाको सूचीमा थप्न एउटा लेबल प्रविष्ट गर्नुहोस् + + A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network. बिटकोइनमा संलग्न गरिएको सन्देश: तपाईंको मध्यस्थको लागि कारोबारको साथमा भण्डारण गरिने URI । नोट: यो सन्देश बिटकोइन नेटवर्क मार्फत पठाइने छैन । @@ -334,6 +380,18 @@ You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. आफ्नो ठेगानामा पठाइएको बिटकोइन प्राप्त गर्न सकिन्छ भनेर प्रमाणित गर्न तपाईंले ती ठेगानाले सन्देश/सम्झौताहरूमा हस्ताक्षर गर्न सक्नुहुन्छ । फिसिङ आक्रमणले तपाईंलाई छक्याएर अरूका लागि तपाईंको परिचयमा हस्ताक्षर गराउने प्रयास गर्न सक्ने भएकाले अस्पष्ट वा जथाभावीमा हस्ताक्षर गर्दा ध्यान दिनुहोस् । आफू सहमत भएको पूर्ण विस्तृत-कथनमा मात्र हस्ताक्षर गर्नुहोस् । + + Choose previously used address + पहिला प्रयोग गरिएको ठेगाना प्रयोग गर्नुहोस् + + + Copy the current signature to the system clipboard + वर्तमान हस्ताक्षरलाई प्रणाली क्लिपबोर्डमा कपी गर्नुहोस् + + + Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction! + सन्देश प्रमाणित गर्न, तल दिइएको स्थानमा प्राप्तकर्ता ठेगाना, सन्देश (लाइन ब्रेक, स्पेस, ट्याब, आदि उस्तै गरी कपी गर्ने कुरा सुनिश्चित गर्नुहोस्) र हस्ताक्षर &apos;s प्रविष्ट गर्नुहोस् । बीचमा-मानिसको-आक्रमणबाट बच्न हस्ताक्षर पढ्दा हस्ताक्षर गरिएको सन्देशमा जे छ त्यो भन्दा धेरै कुरामा ध्यान नदिनुहोस् । यो कार्यले हस्ताक्षर गर्ने पक्षले मात्र यो ठेगानाले प्राप्त गर्छ भन्ने कुरा प्रमाणित गर्छ, यसले कुनै पनि कारोबारको प्रेषककर्तालाई प्रमाणित गर्न सक्दैन भन्ने कुरा याद गर्नुहोस्! + SplashScreen @@ -352,6 +410,11 @@ TransactionView + + Copy address + ठेगाना कपी गर्नुहोस् + + UnitDisplayStatusBarControl @@ -364,10 +427,23 @@ WalletView + + &Export + &amp;निर्यात गर्नुहोस् + + + + Export the data in the current tab to a file + वर्तमान ट्याबको डाटालाई फाइलमा निर्यात गर्नुहोस् + bitcoin-core + Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup + वालेटको सबै कारोबार मेटाउनुहोस् र -स्टार्टअपको पुनः स्क्यान मार्फत ब्लकचेनका ती भागहरूलाई मात्र पुनः प्राप्त गर्नुहोस् + + The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct ब्लक डाटाबेसमा भविष्यबाट आए जस्तो देखिने एउटा ब्लक हुन्छ । तपाईंको कम्प्युटरको मिति र समय गलत तरिकाले सेट गरिएकाले यस्तो हुन सक्छ । तपाईं आफ्नो कम्प्युटरको मिति र समय सही छ भनेर पक्का हुनुहुन्छ भने मात्र ब्लक डाटाबेस पुनर्निर्माण गर्नुहोस् । diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts index 2b625b5a078..e523e832810 100644 --- a/src/qt/locale/bitcoin_nl.ts +++ b/src/qt/locale/bitcoin_nl.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Klik met de rechtermuisknop om het adres of label te wijzigen + Rechtermuisklik om het adres of label te wijzigen Create a new address @@ -318,6 +318,22 @@ Open &URI... + Click to disable network activity. + Klik om de netwerkactiviteit te stoppen. + + + Network activity disabled. + Netwerkactiviteit gestopt. + + + Click to enable network activity again. + Klik om de netwerkactiviteit opnieuw te starten. + + + Syncing Headers (%1%)... + Kopteksten synchroniseren (%1%)... + + Reindexing blocks on disk... Bezig met herindexeren van blokken op harde schijf... @@ -470,6 +486,10 @@ %1 client + Connecting to peers... + Gelijke worden verbonden... + + Catching up... Aan het bijwerken... @@ -512,6 +532,14 @@ Binnenkomende transactie + HD key generation is <b>enabled</b> + HD sleutel voortbrenging is <b>ingeschakeld</b> + + + HD key generation is <b>disabled</b> + HD sleutel voortbrenging is <b>uitgeschakeld</b> + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> Portemonnee is <b>versleuteld</b> en momenteel <b>geopend</b> @@ -519,7 +547,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> Portemonnee is <b>versleuteld</b> en momenteel <b>gesloten</b> - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + Een fatale fout heeft zich voorgedaan. Bitcoin kan niet veilig worden verdergezet en wordt afgesloten. + + CoinControlDialog @@ -854,14 +886,50 @@ Vorm + Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below. + Recente transacties zijn mogelijk nog niet zichtbaar. De balans van de geldbeugel is daarom mogelijk niet correct. Deze informatie is correct van zodra de synchronisatie met het Bitcoin-netwerk werd voltooid, zoals onderaan beschreven. + + + Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network. + Poging om bitcoins te besteden die door "nog niet weergegeven" transacties worden beïnvloed, worden niet door het netwerk geaccepteerd. + + + Number of blocks left + Aantal blokken resterend. + + + Unknown... + Onbekend... + + Last block time Tijd laatste blok + Progress + Vooruitgang + + + Progress increase per hour + Vooruitgang per uur + + + calculating... + Berekenen... + + + Estimated time left until synced + Geschatte tijd tot volledig synchroon + + Hide Verbergen - + + Unknown. Syncing Headers (%1)... + Onbekend. Kopteksten synchroniseren (%1%)... + + OpenURIDialog @@ -1296,7 +1364,15 @@ Node/Service Node/Dienst - + + NodeId + Node ID + + + Ping + Ping + + QObject @@ -1335,14 +1411,54 @@ %1 ms %1 ms + + %n second(s) + %n seconde%n seconden + + + %n minute(s) + %n minuut%n minuten + + + %n hour(s) + %n uur%n uren + + + %n day(s) + %n dag%n dagen + + + %n week(s) + %n week%n weken + %1 and %2 %1 en %2 - + + %n year(s) + %n jaar%n jaren + + + %1 didn't yet exit safely... + %1 sloot nog niet veilig af... + + QObject::QObject - + + Error: Specified data directory "%1" does not exist. + Fout: Opgegeven gegevensmap "%1" bestaat niet. + + + Error: Cannot parse configuration file: %1. Only use key=value syntax. + Fout: Kan configuratiebestand niet verwerken: %1. Gebruik enkel de key=value syntax. + + + Error: %1 + Fout: %1 + + QRImageWidget @@ -1521,6 +1637,10 @@ Pingwachttijd + Min Ping + Min Ping + + Time Offset Tijdcompensatie @@ -1581,6 +1701,18 @@ 1 &jaar + &Disconnect + &Verbreek verbinding + + + Ban for + Ban Node voor + + + &Unban + &Maak ban voor Node ongedaan + + Welcome to the %1 RPC console. Welkom bij de %1 RPC-console. @@ -1593,6 +1725,14 @@ Typ <b>help</b> voor een overzicht van de beschikbare opdrachten. + WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramification of a command. + WAARSCHUWING: Er zijn Scammers actief geweest, die gebruikers vragen om hier commando's te typen, waardoor de inhoud van hun portefeuille werd gestolen. Gebruik deze console niet zonder de toedracht van een opdracht volledig te begrijpen. + + + Network activity disabled + Netwerkactiviteit uitgeschakeld + + %1 B %1 B @@ -1712,6 +1852,10 @@ Verwijder + Copy URI + Kopieer URI + + Copy label Kopieer label @@ -1937,6 +2081,10 @@ Stof: + Confirmation time target: + Bevestigingstijddoel: + + Clear &All Verwijder &Alles @@ -2029,6 +2177,10 @@ Transactiecreatie mislukt + The transaction was rejected with the following reason: %1 + De transactie werd afgewezen om de volgende reden: %1 + + A fee higher than %1 is considered an absurdly high fee. Een vergoeding van meer dan %1 wordt beschouwd als een absurd hoge vergoeding. @@ -2036,10 +2188,18 @@ Payment request expired. Betalingsverzoek verlopen. + + %n block(s) + %n blok%n blokken + Pay only the required fee of %1 Betaal alleen de verplichte transactiekosten van %1 + + Estimated to begin confirmation within %n block(s). + Schatting is dat bevestiging begint over %n blok.Schatting is dat bevestiging begint over %n blokken. + Warning: Invalid Bitcoin address Waarschuwing: Ongeldig Bitcoinadres @@ -2049,6 +2209,14 @@ Waarschuwing: Onbekend wisselgeldadres + Confirm custom change address + Bevestig aangepast wisselgeldadres + + + The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure? + Het wisselgeldadres dat u heeft geselecteerd maakt geen deel uit van deze portemonnee. Een deel of zelfs alle geld in uw portemonnee kan mogelijk naar dit adres worden verzonden. Weet je het zeker? + + (no label) (geen label) @@ -2309,6 +2477,10 @@ TransactionDesc + + Open for %n more block(s) + Open voor nog %n blokOpen voor nog %n blokken + Open until %1 Open tot %1 @@ -2393,6 +2565,10 @@ Credit Credit + + matures in %n more block(s) + komt beschikbaar na %n nieuwe blokkomt beschikbaar na %n nieuwe blokken + not accepted niet geaccepteerd @@ -2430,6 +2606,10 @@ Transactie-ID + Transaction total size + Transactie totale grootte + + Output index Output index @@ -2491,6 +2671,10 @@ Label Label + + Open for %n more block(s) + Open voor nog %n blokOpen voor nog %n blokken + Open until %1 Open tot %1 @@ -2822,6 +3006,18 @@ Aanvaard opdrachtregel- en JSON-RPC-opdrachten + Accept connections from outside (default: 1 if no -proxy or -connect/-noconnect) + Accepteer verbindingen van buitenaf (standaard: 1 indien geen -proxy of -connect/-noconnect werd opgegeven) + + + Connect only to the specified node(s); -noconnect or -connect=0 alone to disable automatic connections + Verbind enkel met de opgegeven knooppunt(en); -noconnect of -connect = 0 alleen om automatische verbindingen uit te schakelen + + + Distributed under the MIT software license, see the accompanying file %s or %s + Uitgegeven onder de MIT software licentie, zie het bijgevoegde bestand %s of %s + + If <category> is not supplied or if <category> = 1, output all debugging information. Als er geen <categorie> is opgegeven of als de <categorie> 1 is, laat dan alle debugginginformatie zien. @@ -2898,6 +3094,14 @@ Voer opdracht uit zodra een portemonneetransactie verandert (%s in cmd wordt vervangen door TxID) + Extra transactions to keep in memory for compact block reconstructions (default: %u) + Extra transacties wordt bijgehouden voor compacte blokreconstructie (standaard: %u) + + + If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s) + Als dit blok in de keten staat, gaat het ervan uit dat dit blok en zijn voorouders geldig zijn en mogelijk hun script verificatie overslaan (0 om alles te verifiëren, standaard:%s, testnet:%s) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) Maximum toegestane peer tijd compensatie. Lokaal perspectief van tijd mag worden beinvloed door peers die met deze hoeveelheid voor of achter lopen. (standaard: %u seconden) @@ -2914,6 +3118,14 @@ Gelieve bij te dragen als je %s nuttig vindt. Bezoek %s voor meer informatie over de software. + Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB) + Beperk benodigde opslag door trimmen (verwijderen) van oude blokken in te schakelen. Dit maakt het mogelijk om de pruneblockchain RPC aan te roepen om specifieke blokken te verwijderen, en maakt het automatische trimmen van oude blokken mogelijk wanneer een doelgrootte in MiB is voorzien. Deze modus is niet compatibele met -txindex en -rescan. Waarschuwing: Terugzetten van deze instellingen vereist het opnieuw downloaden van gehele de blokketen. (standaard:0 = uitzetten trimmodus, 1 = manueel trimmen via RPC toestaan, >%u = automatisch blokbestanden trimmen om beneden de gespecificeerde doelgrootte in MiB te blijven) + + + Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s) + Specificeer het laagste tarief (in %s/kB) voor transacties die bij het maken van een blok moeten worden in rekening worden gebracht (standaard: %s) + + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Kies het aantal scriptverificatie processen (%u tot %d, 0 = auto, <0 = laat dit aantal kernen vrij, standaard: %d) @@ -2922,6 +3134,10 @@ De blokdatabase bevat een blok dat lijkt uit de toekomst te komen. Dit kan gebeuren omdat de datum en tijd van uw computer niet goed staat. Herbouw de blokdatabase pas nadat u de datum en tijd van uw computer correct heeft ingesteld. + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications + Dit is een pre-release testversie - gebruik op eigen risico! Gebruik deze niet voor het delven van munten of handelsdoeleinden + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain Niet mogelijk om de databank terug te draaien naar een staat voor de vork. Je zal je blokketen opnieuw moeten downloaden @@ -2930,6 +3146,22 @@ Gebruik UPnP om de luisterende poort te mappen (standaard: 1 als er geluisterd worden en geen -proxy is meegegeven) + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times + Gebruikersnaam en gehasht wachtwoord voor JSON-RPC-verbindingen. De velden <userpw> is in het formaat: <GEBRUIKERSNAAM>:<SALT>$<HASH>. Een kanoniek Pythonscript is inbegrepen in de share/rpcuser. De klant connecteert dan normaal via de rpcuser=<GEBRUIKERSNAAM>/rpcpassword=<PASWOORD> argumenten. Deze optie kan meerdere keren worden meegegeven + + + Wallet will not create transactions that violate mempool chain limits (default: %u) + Portemonnee creëert geen transacties die mempool-ketenlimieten schenden (standaard: %u) + + + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. + Waarschuwing: Het lijkt erop dat het netwerk geen consensus kan vinden! Sommige delvers lijken problemen te ondervinden. + + + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. + Waarschuwing: Het lijkt erop dat we geen consensus kunnen vinden met onze peers! Mogelijk dient u te upgraden, of andere nodes moeten wellicht upgraden. + + You need to rebuild the database using -reindex-chainstate to change -txindex Om -txindex te kunnen veranderen dient u de database opnieuw te bouwen met gebruik van -reindex-chainstate. @@ -2962,6 +3194,10 @@ Kan -%s adres niet herleiden: '%s' + Chain selection options: + Keten selectie opties: + + Change index out of range Wijzigingsindex buiten bereik @@ -3158,6 +3394,10 @@ Gebruik UPnP om de luisterende poort te mappen (standaard: %u) + Use the test chain + Gebruik de test keten + + User Agent comment (%s) contains unsafe characters. User Agentcommentaar (%s) bevat onveilige karakters. @@ -3450,10 +3690,22 @@ Output extra debugginginformatie (standaard: %u, het leveren van <categorie> is optioneel) + Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect/-noconnect) + Query voor peer-adressen via DNS-lookup , indien laag aan adressen (default: 1 unless -connect/-noconnect) + + Support filtering of blocks and transaction with bloom filters (default: %u) Ondersteun filtering van blokken en transacties met bloomfilters (standaard: %u) + This is the transaction fee you may pay when fee estimates are not available. + Dit is de transactiekost die je mogelijk betaald indien geschatte tarief niet beschikbaar is + + + This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. + Dit product bevat software dat ontwikkeld is door het OpenSSL Project voor gebruik in de OpenSSL Toolkit %s en cryptografische software geschreven door Eric Young en UPnP software geschreven door Thomas Bernard. + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. Totale lengte van netwerkversiestring (%i) overschrijdt maximale lengte (%i). Verminder het aantal of grootte van uacomments. @@ -3482,6 +3734,14 @@ Waarschuwing: portomonee bestand is corrupt, data is veiliggesteld! Originele %s is opgeslagen als %s in %s; als uw balans of transacties incorrect zijn dient u een backup terug te zetten. + Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times. + Goedgekeurde peers die verbinden vanaf een bepaald IP adres (vb. 1.2.3.4) of CIDR genoteerd netwerk (vb. 1.2.3.0/24). Kan meerdere keren worden gespecificeerd. + + + %s is set very high! + %s is zeer hoog ingesteld! + + (default: %s) (standaard: %s) @@ -3502,6 +3762,10 @@ Ongeldig -proxy adres: '%s' + Keypool ran out, please call keypoolrefill first + Keypool op geraakt, roep alsjeblieft eerst keypoolrefill functie aan + + Listen for JSON-RPC connections on <port> (default: %u or testnet: %u) Luister naar JSON-RPC-verbindingen op <poort> (standaard: %u of testnet: %u) @@ -3538,6 +3802,10 @@ Geef non-P2SH multisig door (standaard: %u) + Send transactions with full-RBF opt-in enabled (default: %u) + Verstuur transacties met full-RBF opt-in ingeschakeld (standaard: %u) + + Set key pool size to <n> (default: %u) Stel sleutelpoelgrootte in op <n> (standaard: %u) @@ -3570,10 +3838,34 @@ Netwerkthread starten... + The wallet will avoid paying less than the minimum relay fee. + De portemonnee vermijdt minder te betalen dan het minimale relay vergoeding. + + + This is the minimum transaction fee you pay on every transaction. + Dit is het minimum transactietarief dat je betaald op elke transactie. + + + This is the transaction fee you will pay if you send a transaction. + Dit is het transactietarief dat je betaald wanneer je een transactie verstuurt. + + Threshold for disconnecting misbehaving peers (default: %u) Drempel om verbinding te verbreken naar zich misdragende peers (standaard: %u) + Transaction amounts must not be negative + Transactiebedragen moeten positief zijn + + + Transaction has too long of a mempool chain + Transactie heeft een te lange mempoolketen + + + Transaction must have at least one recipient + Transactie moet ten minste één ontvanger hebben + + Unknown network specified in -onlynet: '%s' Onbekend netwerk gespecificeerd in -onlynet: '%s' diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index 46348140700..4d7b8f4442a 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -318,6 +318,22 @@ Otwórz URI... + Click to disable network activity. + Kliknij aby wyłączyć aktywność sieciową. + + + Network activity disabled. + Aktywność sieciowa została wyłączona. + + + Click to enable network activity again. + Kliknij, aby ponownie włączyć aktywności sieciową. + + + Syncing Headers (%1%)... + Synchronizowanie headerów (%1%)... + + Reindexing blocks on disk... Ponowne indeksowanie bloków na dysku... @@ -419,7 +435,7 @@ %n active connection(s) to Bitcoin network - %n aktywnych połączeń do sieci Bitcoin%n aktywnych połączeń do sieci Bitcoin%n aktywnych połączeń do sieci Bitcoin + %n aktywnych połączeń do sieci Bitcoin%n aktywnych połączeń do sieci Bitcoin%n aktywnych połączeń do sieci Bitcoin%n aktywnych połączeń do sieci Bitcoin Indexing blocks on disk... @@ -431,7 +447,7 @@ Processed %n block(s) of transaction history. - Przetworzono %n bloków historii transakcji.Przetworzono %n bloków historii transakcji.Przetworzono %n bloków historii transakcji. + Przetworzono %n bloków historii transakcji.Przetworzono %n bloków historii transakcji.Przetworzono %n bloków historii transakcji.Przetworzono %n bloków historii transakcji. %1 behind @@ -470,6 +486,10 @@ %1 klient + Connecting to peers... + Łączenie z peerami... + + Catching up... Trwa synchronizacja… @@ -519,7 +539,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> Portfel jest <b>zaszyfrowany</b> i obecnie <b>zablokowany</b> - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + Wystąpił krytyczny błąd. Bitcoin nie jest w stanie kontynuować bezpiecznie i zostanie zamknięty. + + CoinControlDialog @@ -710,6 +734,14 @@ Zmień adres wysyłania + The entered address "%1" is not a valid Bitcoin address. + Wprowadzony adres "%1" nie jest prawidłowym adresem Bitcoin. + + + The entered address "%1" is already in the address book. + Wprowadzony adres "%1" znajduje się już w książce adresowej. + + Could not unlock wallet. Nie można było odblokować portfela. @@ -832,11 +864,11 @@ %n GB of free space available - %n GB dostępnego wolnego miejsca%n GB dostępnego wolnego miejsca%n GB dostępnego wolnego miejsca + %n GB dostępnego wolnego miejsca%n GB dostępnego wolnego miejsca%n GB dostępnego wolnego miejsca%n GB dostępnego wolnego miejsca (of %n GB needed) - (z %n GB potrzebnych)(z %n GB potrzebnych)(z %n GB potrzebnych) + (z %n GB potrzebnych)(z %n GB potrzebnych)(z %n GB potrzebnych)(z %n GB potrzebnych) @@ -846,6 +878,10 @@ Formularz + Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below. + Świeże transakcje mogą nie być jeszcze widoczne, a zatem saldo portfela może być nieprawidłowe. Te detale będą poprawne, gdy portfel zakończy synchronizację z siecią bitcoin, zgodnie z poniższym opisem. + + Number of blocks left Pozostało bloków @@ -1230,6 +1266,14 @@ Obsługa URI + Invalid payment address %1 + błędny adres płatności %1 + + + Payment request rejected + Żądanie płatności odrzucone + + Payment request expired. Żądanie płatności upłynęło. @@ -1250,6 +1294,10 @@ Zwrot z %1 + Error communicating with %1: %2 + Błąd komunikacji z %1 : %2 + + Payment request cannot be parsed! Żądanie płatności nie może zostać przetworzone. @@ -1325,11 +1373,11 @@ %n second(s) - %n sekunda%n sekund%n sekund + %n sekunda%n sekund%n sekund%n sekund %n minute(s) - %n minuta%n minut%n minut + %n minuta%n minut%n minut%n minut %1 and %2 @@ -1814,6 +1862,10 @@ (brak wiadomości) + (no amount requested) + (brak kwoty) + + Requested Zażądano @@ -1997,6 +2049,18 @@ %1 do %2 + Are you sure you want to send? + Czy na pewno chcesz wysłać? + + + added as transaction fee + dodano jako opłata transakcyjna + + + Total Amount %1 + Łączna kwota %1 + + or lub @@ -2005,6 +2069,10 @@ Kwota do zapłacenia musi być większa od 0. + The amount exceeds your balance. + Kwota przekracza twoje saldo. + + Transaction creation failed! Utworzenie transakcji nie powiodło się! @@ -2214,6 +2282,14 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Resetuje wszystkie pola weryfikacji wiadomości + The entered address is invalid. + Podany adres jest nieprawidłowy. + + + Please check the address and try again. + Proszę sprawdzić adres i spróbować ponownie. + + Wallet unlock was cancelled. Odblokowanie portfela zostało anulowane. @@ -2229,7 +2305,11 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Message signed. Wiadomość podpisana. - + + Message verified. + Wiadomość zweryfikowana. + + SplashScreen @@ -2247,6 +2327,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw TransactionDesc + abandoned + porzucone + + Date Data @@ -2283,14 +2367,34 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw etykieta + Transaction fee + Opłata transakcyjna + + Message Wiadomość + Transaction + Transakcja + + + Inputs + Wejścia + + Amount Kwota - + + true + prawda + + + false + fałsz + + TransactionDescDialog @@ -2305,6 +2409,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Data + Type + Typ + + Label Etykieta @@ -2392,6 +2500,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Skopiuj ID transakcji + Edit label + Zmień etykietę + + Comma separated file (*.csv) Plik *.CSV (dane rozdzielane przecinkami) @@ -2400,6 +2512,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Data + Type + Typ + + Label Etykieta @@ -2411,7 +2527,15 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw Exporting Failed Eksportowanie nie powiodło się - + + Range: + Zakres: + + + to + do + + UnitDisplayStatusBarControl @@ -2427,7 +2551,23 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw WalletView - + + Backup Wallet + Kopia zapasowa portfela + + + Backup Failed + Nie udało się wykonać kopii zapasowej + + + Backup Successful + Wykonano kopię zapasową + + + The wallet data was successfully saved to %1. + Dane portfela zostały poprawnie zapisane w %1. + + bitcoin-core diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts index 3202587cbd5..59724318bbf 100644 --- a/src/qt/locale/bitcoin_pt_BR.ts +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -51,7 +51,7 @@ C&hoose - Escol&ha + E&scolha Sending addresses @@ -75,7 +75,7 @@ Copy &Label - Copiar rótu&lo + Copiar &rótulo &Edit @@ -87,7 +87,7 @@ Comma separated file (*.csv) - Comma separated file (*.csv) + Arquivo separado por virgula (*.csv) Exporting Failed diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index c97272d4b73..a45bb592397 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -62,6 +62,14 @@ A receber endereços + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Estes são os seus endereços Bitcoin para enviar pagamentos. Verifique sempre o valor e o endereço de envio antes de enviar moedas. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Estes são os seus endereços Bitcoin para receber pagamentos. É recomendado que utilize um endereço novo para cada transacção. + + &Copy Address &Copiar Endereço @@ -172,10 +180,22 @@ Carteira encriptada + %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + %1 irá agora ser fechado para terminar o processo de encriptação. Recorde que a encriptação da sua carteira não protegerá totalmente os seus bitcoins de serem roubados por programas maliciosos que infectem o seu computador. + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANTE: Qualquer cópia de segurança da carteira anterior deverá ser substituída com o novo ficheiro de carteira, agora encriptado. Por razões de segurança, cópias de segurança não encriptadas tornar-se-ão inúteis assim que começar a usar a nova carteira encriptada. + + Wallet encryption failed Encriptação da carteira falhou + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + A encriptação da carteira falhou devido a um erro interno. A carteira não foi encriptada. + + The supplied passphrases do not match. As frases de segurança fornecidas não coincidem. @@ -184,6 +204,10 @@ Desbloqueio da carteira falhou + The passphrase entered for the wallet decryption was incorrect. + A frase de segurança introduzida para a desencriptação da carteira estava incorreta. + + Wallet decryption failed Desencriptação da carteira falhou @@ -306,6 +330,10 @@ Clique para ativar novamente a atividade de rede. + Syncing Headers (%1%)... + A sincronizar cabeçalhos (%1%)... + + Reindexing blocks on disk... A reindexar os blocos no disco... @@ -450,10 +478,18 @@ Atualizado + Show the %1 help message to get a list with possible Bitcoin command-line options + Mostrar a mensagem de ajuda %1 para obter uma lista com possíveis opções a usar na linha de comandos. + + %1 client Cliente %1 + Connecting to peers... + Conectando-se a pares... + + Catching up... Recuperando o atraso... @@ -511,7 +547,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> A carteira está <b>encriptada</b> e atualmente <b>bloqueada</b> - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + Ocorreu um erro fatal. O Bitcoin não pode continuar com segurança e irá fechar. + + CoinControlDialog @@ -623,6 +663,10 @@ Copiar bytes + Copy dust + Copiar poeira + + Copy change Copiar troco @@ -639,6 +683,14 @@ não + This label turns red if any recipient receives an amount smaller than the current dust threshold. + Esta etiqueta fica vermelha se qualquer recipiente receber uma quantia menor que o limite da poeira. + + + Can vary +/- %1 satoshi(s) per input. + Pode variar +/- %1 satoshi(s) por input. + + (no label) (sem etiqueta) @@ -674,6 +726,30 @@ E&ndereço + New receiving address + Novo endereço de depósito + + + New sending address + Novo endereço de envio + + + Edit receiving address + Editar o endereço de depósito + + + Edit sending address + Editar o endereço de envio + + + The entered address "%1" is not a valid Bitcoin address. + O endereço introduzido "%1" não é um endereço bitcoin válido. + + + The entered address "%1" is already in the address book. + O endereço introduzido "%1" já se encontra no livro de endereços. + + Could not unlock wallet. Não foi possível desbloquear a carteira. @@ -771,6 +847,10 @@ Bem-vindo ao %1. + %1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + O %1 irá transferir e armazenar uma cópia da blockchain. Pelo menos %2GB serão armazenados neste diretório, sendo que o valor irá crescer ao longo do tempo. A carteira também será armazenada neste mesmo diretório. + + Use the default data directory Utilizar a pasta de dados predefinida @@ -802,6 +882,14 @@ Formulário + Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below. + Transações recentes podem não ser visíveis por agora, portanto o saldo da sua carteira pode estar incorreto. Esta informação será corrigida quando a sua carteira acabar de sincronizar com a rede, como está explicado em baixo. + + + Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network. + Tentar enviar bitcoins que estão afetadas por transações ainda não exibidas não será aceite pela rede. + + Number of blocks left Número de blocos restantes @@ -818,6 +906,10 @@ Progresso + Progress increase per hour + Aumento horário do progresso + + calculating... a calcular... @@ -1041,6 +1133,10 @@ &Linguagem da interface de utilizador: + The user interface language can be set here. This setting will take effect after restarting %1. + A linguagem da interface do utilizador pode ser definida aqui. Esta definição entrará em efeito após reiniciar %1. + + &Unit to show amounts in: &Unidade para mostrar quantias: @@ -1171,10 +1267,42 @@ Erro do pedido de pagamento + Cannot start bitcoin: click-to-pay handler + Impossível iniciar o controlador de bitcoin: click-to-pay + + + URI handling + Manuseamento de URI + + + Payment request fetch URL is invalid: %1 + O URL do pedido de pagamento é inválido: %1 + + + Invalid payment address %1 + Endereço de pagamento inválido %1 + + + URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. + URI não foi lido correctamente! Isto pode ser causado por um endereço Bitcoin inválido ou por parâmetros URI malformados. + + + Payment request file handling + Controlo de pedidos de pagamento. + + + Payment request file cannot be read! This can be caused by an invalid payment request file. + O ficheiro de pedido de pagamento não pôde ser lido! Isto pode ter sido causado por um ficheiro de pedido de pagamento inválido. + + Payment request rejected Pedido de pagamento rejeitado + Payment request network doesn't match client network. + Rede de requisição de pagamento não corresponde com a rede do cliente. + + Payment request expired. Pedido de pagamento expirado. @@ -1183,18 +1311,46 @@ O pedido de pagamento não foi inicializado. + Unverified payment requests to custom payment scripts are unsupported. + Pedidos de pagamento não-verificados para scripts de pagamento personalizados não são suportados. + + Invalid payment request. Pedido de pagamento inválido. + Requested payment amount of %1 is too small (considered dust). + Quantia solicitada para pagamento de %1 é muito pequena (considerada "pó"). + + Refund from %1 Reembolso de %1 + Payment request %1 is too large (%2 bytes, allowed %3 bytes). + Pedido de pagamento %1 é demasiado grande (%2 bytes, permitido %3 bytes). + + Error communicating with %1: %2 Erro ao comunicar com %1: %2 - + + Payment request cannot be parsed! + O pedido de pagamento não pode ser lido ou processado! + + + Bad response from server %1 + Má resposta do servidor %1 + + + Network request error + Erro de pedido de rede + + + Payment acknowledged + Pagamento confirmado + + PeerTableModel @@ -1205,7 +1361,15 @@ Node/Service Nó/Serviço - + + NodeId + NodeId + + + Ping + Latência + + QObject @@ -1244,17 +1408,73 @@ %1 ms %1 ms + + %n second(s) + %n segundo%n segundos + + + %n minute(s) + %n minuto%n minutos + + + %n hour(s) + %n hora%n horas + + + %n day(s) + %n dia%n dias + + + %n week(s) + %n semana%n semanas + %1 and %2 %1 e %2 - + + %n year(s) + %n anos%n anos + + + %1 didn't yet exit safely... + %1 ainda não foi fechado em segurança... + + QObject::QObject - + + Error: Specified data directory "%1" does not exist. + Erro: Pasta de dados especificada "%1" não existe. + + + Error: Cannot parse configuration file: %1. Only use key=value syntax. + Erro: não é possível analisar o ficheiro de configuração: %1. Utilize apenas a sintaxe key=value. + + + Error: %1 + Erro: %1 + + QRImageWidget - + + &Save Image... + &Guardar Imagem... + + + &Copy Image + &Copiar Imagem + + + Save QR Code + Guardar o código QR + + + PNG Image (*.png) + Imagem PNG (*.png) + + RPCConsole @@ -1282,6 +1502,10 @@ Versão BerkeleyDB em uso + Datadir + Datadir + + Startup time Hora de Arranque @@ -1366,6 +1590,10 @@ Agente Usuário + Open the %1 debug log file from the current data directory. This can take a few seconds for large log files. + Abrir o ficheiro de registo de depuração %1 da pasta de dados actual. Isto pode demorar alguns segundos para ficheiros de registo maiores. + + Decrease font size Diminuir tamanho da letra @@ -1406,6 +1634,10 @@ Espera do Ping + Min Ping + Latência mínima + + Time Offset Fuso Horário @@ -1466,6 +1698,14 @@ 1 &ano + Ban for + Banir para + + + &Unban + &Desbanir + + Welcome to the %1 RPC console. Bem-vindo à consola RPC da %1. @@ -1478,6 +1718,14 @@ Insira <b>help</b> para visualizar os comandos disponíveis. + WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramification of a command. + AVISO: Burlões têm estado ativos, tentando que utilizadores escrevam comandos aqui para lhes roubar as carteiras. Não utilize esta consola sem perceber perfeitamente as ramificações de um comando. + + + Network activity disabled + Atividade de rede desativada + + %1 B %1 B @@ -1597,10 +1845,18 @@ Remover + Copy URI + Copiar URI + + Copy label Copiar etiqueta + Copy message + Copiar mensagem + + Copy amount Copiar valor @@ -1624,6 +1880,18 @@ &Salvar Imagem... + Request payment to %1 + Requisitar Pagamento para %1 + + + Payment information + Informação de Pagamento + + + URI + URI + + Address Endereço @@ -1635,18 +1903,50 @@ Label Etiqueta - + + Message + Mensagem + + + Resulting URI too long, try to reduce the text for label / message. + URI resultante muito longo. Tente reduzir o texto do rótulo / mensagem. + + + Error encoding URI into QR Code. + Erro ao codificar URI em Código QR. + + RecentRequestsTableModel + Date + Data + + Label Etiqueta + Message + Mensagem + + (no label) (sem etiqueta) - + + (no message) + (sem mensagem) + + + (no amount requested) + (sem quantia pedida) + + + Requested + Solicitado + + SendCoinsDialog @@ -1774,6 +2074,10 @@ Lixo: + Confirmation time target: + Tempo de confirmação: + + Clear &All Limpar &Tudo @@ -1810,18 +2114,58 @@ Copiar bytes + Copy dust + Copiar pó + + Copy change Copiar troco + %1 to %2 + %1 para %2 + + + Are you sure you want to send? + Tem a certeza que deseja enviar? + + added as transaction fee adicionado como taxa de transação + Total Amount %1 + Quantia Total %1 + + + or + ou + + + Confirm send coins + Confirme envio de moedas + + + The recipient address is not valid. Please recheck. + O endereço do destinatário é inválido. Por favor, reverifique. + + + The amount to pay must be larger than 0. + O valor a pagar dever maior que 0. + + + The amount exceeds your balance. + O valor excede o seu saldo. + + The total exceeds your balance when the %1 transaction fee is included. O total excede o seu saldo quando a taxa de transação %1 está incluída. + Transaction creation failed! + A criação da transação falhou! + + A fee higher than %1 is considered an absurdly high fee. Uma taxa superior a %1 é considerada uma taxa altamente absurda. @@ -1834,6 +2178,10 @@ Pague apenas a taxa obrigatória de %1 + Warning: Invalid Bitcoin address + Aviso: endereço Bitcoin inválido + + Warning: Unknown change address Aviso: endereço de troco desconhecido @@ -1927,7 +2275,11 @@ SendConfirmationDialog - + + Yes + Sim + + ShutdownWindow @@ -2025,7 +2377,59 @@ Reset all verify message fields Repor todos os campos de verificação de mensagem - + + Click "Sign Message" to generate signature + Clique "Assinar Mensagem" para gerar a assinatura + + + The entered address is invalid. + O endereço introduzido é inválido. + + + Please check the address and try again. + Por favor, verifique o endereço e tente novamente. + + + The entered address does not refer to a key. + O endereço introduzido não refere-se a nenhuma chave. + + + Wallet unlock was cancelled. + O desbloqueio da carteira foi cancelado. + + + Private key for the entered address is not available. + A chave privada para o endereço introduzido não está disponível. + + + Message signing failed. + Assinatura da mensagem falhou. + + + Message signed. + Mensagem assinada. + + + The signature could not be decoded. + Não foi possível descodificar a assinatura. + + + Please check the signature and try again. + Por favor, verifique a assinatura e tente novamente. + + + The signature did not match the message digest. + A assinatura não corresponde com o conteúdo da mensagem. + + + Message verification failed. + Verificação da mensagem falhou. + + + Message verified. + Mensagem verificada. + + SplashScreen @@ -2043,35 +2447,311 @@ TransactionDesc + Open until %1 + Aberto até %1 + + + %1/offline + %1/off-line + + + 0/unconfirmed, %1 + 0/não confirmada, %1 + + + in memory pool + no banco de memória + + + not in memory pool + não está no banco de memória + + + abandoned + abandonada + + + %1/unconfirmed + %1/não confirmada + + + %1 confirmations + %1 confirmações + + + Status + Estado + + + , has not been successfully broadcast yet + , ainda não foi transmitido com sucesso + + + Date + Data + + + Source + Origem + + + Generated + Gerado + + + From + De + + + unknown + desconhecido + + + To + Para + + + own address + endereço próprio + + + watch-only + vigiar apenas + + + label + etiqueta + + + Credit + Crédito + + + not accepted + não aceite + + + Debit + Débito + + + Total debit + Débito total + + + Total credit + Crédito total + + Transaction fee Taxa de transação + Net amount + Valor líquido + + + Message + Mensagem + + + Comment + Comentário + + + Transaction ID + Id. da Transação + + + Transaction total size + Tamanho total da transição + + + Output index + Índex de saída + + + Merchant + Comerciante + + + Debug information + Informação de depuração + + + Transaction + Transação + + + Inputs + Entradas + + Amount Valor - + + true + verdadeiro + + + false + falso + + TransactionDescDialog This pane shows a detailed description of the transaction Esta janela mostra uma descrição detalhada da transação - + + Details for %1 + Detalhes para %1 + + TransactionTableModel + Date + Data + + + Type + Tipo + + Label Etiqueta + Open until %1 + Aberto até %1 + + + Offline + Off-line + + + Unconfirmed + Não confirmado + + + Abandoned + Anbandonada + + + Confirmed (%1 confirmations) + Confirmada (%1 confirmações) + + + Conflicted + Incompatível + + + Generated but not accepted + Gerada mas não aceite + + + Received with + Recebido com + + + Received from + Recebido de + + + Sent to + Enviado para + + + Payment to yourself + Pagamento para si mesmo + + + Mined + Minada + + + watch-only + vigiar apenas + + + (n/a) + (n/d) + + (no label) (sem etiqueta) + + Transaction status. Hover over this field to show number of confirmations. + Estado da transação. Passar o cursor por cima deste campo para mostrar o número de confirmações. + + + Type of transaction. + Tipo de transação. + TransactionView + All + Todas + + + Today + Hoje + + + This week + Esta semana + + + This month + Este mês + + + Last month + Mês passado + + + This year + Este ano + + + Range... + Período... + + + Received with + Recebido com + + + Sent to + Enviado para + + + To yourself + Para si mesmo + + + Mined + Minada + + + Other + Outras + + + Min amount + Valor mín. + + + Abandon transaction + Abandonar transação + + Copy address Copiar endereço @@ -2088,10 +2768,46 @@ Copiar Id. da transação + Copy raw transaction + Copiar transação em bruto + + + Copy full transaction details + Copiar detalhes completos da transação + + + Edit label + Editar etiqueta + + + Show transaction details + Mostrar detalhes da transação + + + Export Transaction History + Exportar Histórico de Transacções + + Comma separated file (*.csv) Ficheiro separado por vírgulas (*.csv) + Confirmed + Confirmada + + + Watch-only + Vigiar apenas + + + Date + Data + + + Type + Tipo + + Label Etiqueta @@ -2100,10 +2816,26 @@ Endereço + ID + Id. + + Exporting Failed Exportação Falhou - + + Exporting Successful + Exportação Bem Sucedida + + + Range: + Período: + + + to + até + + UnitDisplayStatusBarControl @@ -2116,13 +2848,41 @@ WalletModel - + + Send Coins + Enviar Moedas + + WalletView + &Export + &Exportar + + Export the data in the current tab to a file Exportar os dados no separador atual para um ficheiro + + Backup Wallet + Cópia de Segurança da Carteira + + + Wallet Data (*.dat) + Dados da Carteira (*.dat) + + + Backup Failed + Cópia de Segurança Falhou + + + There was an error trying to save the wallet data to %1. + Ocorreu um erro ao tentar guardar os dados da carteira em %1. + + + Backup Successful + Cópia de Segurança Bem Sucedida + bitcoin-core @@ -2187,6 +2947,10 @@ Bitcoin Core + The %s developers + Os programadores de %s + + A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s) Uma percentagem da taxa (em %s/kB) que será utilizada quando a estimativa da taxa tiver dados insuficientes (predefinição: %s) @@ -2219,6 +2983,14 @@ Utilizar UPnP para mapear a porta de escuta (predefinição: 1 quando escutar e sem -proxy) + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. + Aviso: A rede não parece estar completamente de acordo! Parece que alguns mineiros estão com dificuldades técnicas. + + + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. + Aviso: Parecemos não estar de acordo com os nossos pares! Poderá ter que atualizar o seu cliente, ou outros nós poderão ter que atualizar os seus clientes. + + -maxmempool must be at least %d MB - máximo do banco de memória deverá ser pelo menos %d MB @@ -2239,10 +3011,22 @@ Opções da criação de bloco: + Cannot resolve -%s address: '%s' + Não é possível resolver -%s endereço '%s' + + + Chain selection options: + Opções de seleção da cadeia: + + Connection options: Opções de ligação: + Copyright (C) %i-%i + Direitos de Autor (C) %i-%i + + Corrupted block database detected Cadeia de blocos corrompida detectada @@ -2339,6 +3123,10 @@ Manter o banco de memória da transação abaixo de <n> megabytes (predefinição: %u) + Loading banlist... + A carregar a lista de banir... + + Location of the auth cookie (default: data dir) Localização de cookie de autorização (predefinição: diretoria de dados) @@ -2395,6 +3183,10 @@ Utilizar UPnP para mapear a porta de escuta (predefinição: %u) + Use the test chain + Utilize a cadeia de testes + + User Agent comment (%s) contains unsafe characters. Comentário no User Agent (%s) contém caracteres inseguros. @@ -2411,6 +3203,10 @@ A carteira %s reside fora da pasta de dados %s + Wallet debugging/testing options: + Opções de depuração/testes da carteira: + + Wallet options: Opções da carteira: @@ -2671,6 +3467,14 @@ Suportar filtragem de blocos e transacções com fitros bloom (padrão: %u) + This is the transaction fee you may pay when fee estimates are not available. + Esta é a taxa de transação que poderá pagar quando as estimativas da taxa não estão disponíveis. + + + This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. + Este produto inclui software desenvolvido pelo Projeto de OpenSSL para utilização no OpenSSL Toolkit %s e software criptográfico escrito por Eric Young e software UPnP escrito por Thomas Bernard. + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. Comprimento total da entrada da versão de rede (%i) excede o comprimento máximo (%i). Reduzir o número ou o tamanho de uacomments. @@ -2775,10 +3579,26 @@ Gastar o troco não confirmado quando enviar transações (predefinição: %u) + This is the transaction fee you will pay if you send a transaction. + Esta é a taxa de transação que irá pagar se enviar uma transação. + + Threshold for disconnecting misbehaving peers (default: %u) Tolerância para desligar nós com comportamento indesejável (padrão: %u) + Transaction amounts must not be negative + Os valores da transação não devem ser negativos + + + Transaction has too long of a mempool chain + A transação é muito grande de uma cadeia do banco de memória + + + Transaction must have at least one recipient + A transação dever pelo menos um destinatário + + Unknown network specified in -onlynet: '%s' Rede desconhecida especificada em -onlynet: '%s' diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index b5f40fc0589..7d013416ff7 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -330,6 +330,10 @@ Кликните, чтобы снова разрешить сетевую активность. + Syncing Headers (%1%)... + Синхронизация заголовков (%1%)... + + Reindexing blocks on disk... Идёт переиндексация блоков на диске... @@ -3090,6 +3094,14 @@ Выполнить команду, когда меняется транзакция в бумажнике (%s в команде заменяется на TxID) + Extra transactions to keep in memory for compact block reconstructions (default: %u) + Хранить в памяти дополнительные транзакции для реконструкции компактных блоков (по умолчанию: %u) + + + If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s) + Если этот блок в цепи, считать его и последующие блоки верными и потенциально пропускать проверку их скриптов (0 для проверки всех, по умолчанию: %s, тестовая сеть: %s) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) Максимально допустимое среднее отклонение времени участников. Локальное представление времени может меняться вперед или назад на это количество. (по умолчанию: %u секунд) @@ -3106,6 +3118,14 @@ Пожалуйста, внести свой вклад, если вы найдете %s полезными. Посетите %s для получения дополнительной информации о программном обеспечении. + Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB) + Уменьшить размер хранилища за счёт обрезания (удаления) старых блоков. Будет разрешён вызов RPC метода pruneblockchain для удаления определённых блоков и разрешено автоматическое обрезание старых блоков, если указан целевой размер в Мб. Этот режим несовместим с -txindex и -rescan. Внимание: переключение этой опции обратно потребует полной загрузки цепи блоков. (по умолчанию: 0 = отключить обрезание блоков, 1 = разрешить ручное обрезание через RPC, >%u = автоматически обрезать файлы блоков, чтобы они были меньше указанного размера в Мб) + + + Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s) + Задать минимальный курс комиссии (в %s/Кб) для транзакцийб включаемых в создаваемый блок. (по умолчанию: %s) + + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) Задать число потоков проверки скрипта (от %u до %d, 0=авто, <0 = оставить столько ядер свободными, по умолчанию: %d) diff --git a/src/qt/locale/bitcoin_ru_RU.ts b/src/qt/locale/bitcoin_ru_RU.ts index 60d98c41d95..66ab7c81f49 100644 --- a/src/qt/locale/bitcoin_ru_RU.ts +++ b/src/qt/locale/bitcoin_ru_RU.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Кликните правой кнопкой мыши для редоктирования адреса или ярлыка + Кликните правой кнопкой мыши для редактирования адреса или метки Create a new address @@ -15,7 +15,7 @@ Copy the currently selected address to the system clipboard - Copy the currently selected address to the system clipboardый адрес в буфер + Скопировать текущий выбранный адрес в буфер обмена системы &Copy @@ -41,6 +41,14 @@ &Delete Удалить + + Choose the address to send coins to + Выбрать адрес для отправки монет + + + Choose the address to receive coins with + Выбрать адрес для получения монет + AddressTableModel diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts index 87dc620f0e1..fdf9fc6db6e 100644 --- a/src/qt/locale/bitcoin_sk.ts +++ b/src/qt/locale/bitcoin_sk.ts @@ -41,10 +41,74 @@ &Delete &Zmazať - + + Choose the address to send coins to + Zvoľte adresu kam poslať mince + + + Choose the address to receive coins with + Zvoľte adresu na ktorú chcete prijať mince + + + C&hoose + Vybrať + + + Sending addresses + Odosielajúce adresy + + + Receiving addresses + Prijímajúce adresy + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + Toto sú Vaše Bitcoin adresy pre posielanie platieb. Vždy skontrolujte sumu a prijímaciu adresu pred poslaním mincí. + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + Toto sú vaše Bitcoin adresy pre prijímanie platieb. Odporúča sa použiť vždy novú prijímaciu adresu pre každú transakciu. + + + &Copy Address + &Kopírovať adresu + + + Copy &Label + Kopírovať &popis + + + &Edit + &Upraviť + + + Export Address List + Exportovať zoznam adries + + + Comma separated file (*.csv) + Čiarkou oddelovaný súbor (*.csv) + + + Exporting Failed + Export zlyhal + + + There was an error trying to save the address list to %1. Please try again. + Nastala chyba pri pokuse uložiť zoznam adries do %1. Skúste znovu. + + AddressTableModel + Label + Popis + + + Address + Adresa + + (no label) (bez popisu) @@ -67,7 +131,95 @@ Repeat new passphrase Zopakujte nové heslo - + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. + Zadajte nové heslo k peňaženke.<br/>Prosím použite heslo s dĺžkou <b>desať alebo viac náhodných znakov</b>, prípadne <b>osem alebo viac slov</b>. + + + Encrypt wallet + Zašifrovať peňaženku + + + This operation needs your wallet passphrase to unlock the wallet. + Táto operácia potrebuje heslo k vašej peňaženke aby ju mohla odomknúť. + + + Unlock wallet + Odomknúť peňaženku + + + This operation needs your wallet passphrase to decrypt the wallet. + Táto operácia potrebuje heslo k vašej peňaženke na dešifrovanie peňaženky. + + + Decrypt wallet + Dešifrovať peňaženku + + + Change passphrase + Zmena hesla + + + Enter the old passphrase and new passphrase to the wallet. + Zadajte staré heslo a nové heslo k peňaženke. + + + Confirm wallet encryption + Potvrďte zašifrovanie peňaženky + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + Varovanie: Ak zašifrujete peňaženku a stratíte heslo, <b>STRATÍTE VŠETKY VAŠE BITCOINY</b>! + + + Are you sure you wish to encrypt your wallet? + Ste si istí, že si želáte zašifrovať peňaženku? + + + Wallet encrypted + Peňaženka zašifrovaná + + + %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + %1 sa teraz zavrie, aby sa ukončil proces šifrovania. Zašifrovanie peňaženky neochráni úplne pred krádežou bitcoinov škodlivými programami, ktoré prenikli do vášho počítača. + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + DÔLEŽITÉ: Všetky predchádzajúce zálohy vašej peňaženky, ktoré ste vykonali by mali byť nahradené novo vytvorenou, zašifrovanou peňaženkou. Z bezpečnostných dôvodov bude predchádzajúca záloha nezašifrovanej peňaženky k ničomu, akonáhle začnete používať novú, zašifrovanú peňaženku. + + + Wallet encryption failed + Šifrovanie peňaženky zlyhalo + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Šifrovanie peňaženky zlyhalo kôli internej chybe. Vaša peňaženka nebola zašifrovaná. + + + The supplied passphrases do not match. + Zadané heslá nesúhlasia. + + + Wallet unlock failed + Odomykanie peňaženky zlyhalo + + + The passphrase entered for the wallet decryption was incorrect. + Zadané heslo pre dešifrovanie peňaženky bolo nesprávne. + + + Wallet decryption failed + Zlyhalo šifrovanie peňaženky. + + + Wallet passphrase was successfully changed. + Heslo k peňaženke bolo úspešne zmenené. + + + Warning: The Caps Lock key is on! + Upozornenie: Máte zapnutý Caps Lock! + + BanTableModel @@ -166,6 +318,22 @@ Otvoriť &URI... + Click to disable network activity. + Kliknite pre zakázanie sieťovej aktivity. + + + Network activity disabled. + Sieťová aktivita zakázaná. + + + Click to enable network activity again. + Kliknite pre povolenie sieťovej aktivity. + + + Syncing Headers (%1%)... + Synchronizujú sa hlavičky (%1%)... + + Reindexing blocks on disk... Preindexúvam bloky na disku... @@ -287,7 +455,7 @@ Last received block was generated %1 ago. - Posledný prijatý blok bol vygenerovaný pred %1. + Posledný prijatý blok bol vygenerovaný pred: %1. Transactions after this will not yet be visible. @@ -318,6 +486,10 @@ %1 klient + Connecting to peers... + Pripája sa k partnerom... + + Catching up... Sťahujem... @@ -360,6 +532,14 @@ Prijatá transakcia + HD key generation is <b>enabled</b> + Generovanie HD kľúčov je <b>zapnuté</b> + + + HD key generation is <b>disabled</b> + Generovanie HD kľúčov je <b>vypnuté</b> + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> Peňaženka je <b>zašifrovaná</b> a momentálne <b>odomknutá</b> @@ -367,7 +547,11 @@ Wallet is <b>encrypted</b> and currently <b>locked</b> Peňaženka je <b>zašifrovaná</b> a momentálne <b>zamknutá</b> - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + Vyskytla sa kritická chyba. Bitcoin nemôže ďalej bezpečne pokračovať a ukončí sa. + + CoinControlDialog @@ -439,10 +623,86 @@ Potvrdené + Copy address + Kopírovať adresu + + + Copy label + Kopírovať popis + + + Copy amount + Kopírovať sumu + + + Copy transaction ID + Kopírovať ID transakcie + + + Lock unspent + Uzamknúť neminuté + + + Unlock unspent + Odomknúť neminuté + + + Copy quantity + Kopírovať množstvo + + + Copy fee + Kopírovať poplatok + + + Copy after fee + Kopírovať po poplatkoch + + + Copy bytes + Kopírovať bajty + + + Copy dust + Kopírovať prach + + + Copy change + Kopírovať zmenu + + + (%1 locked) + (%1 zamknutých) + + + yes + áno + + + no + nie + + + This label turns red if any recipient receives an amount smaller than the current dust threshold. + Tento popis sčervenie ak ktorýkoľvek príjemca dostane sumu menšiu ako súčasný limit pre "prach". + + + Can vary +/- %1 satoshi(s) per input. + Môže sa líšiť o +/- %1 satoshi pre každý vstup. + + (no label) (bez popisu) - + + change from %1 (%2) + zmena od %1 (%2) + + + (change) + (zmena) + + EditAddressDialog @@ -465,7 +725,39 @@ &Address &Adresa - + + New receiving address + Nová adresa pre prijímanie + + + New sending address + Nová adresa pre odoslanie + + + Edit receiving address + Upraviť prijímajúcu adresu + + + Edit sending address + Upraviť odosielaciu adresu + + + The entered address "%1" is not a valid Bitcoin address. + Vložená adresa "%1" nieje platnou adresou Bitcoin. + + + The entered address "%1" is already in the address book. + Vložená adresa "%1" sa už nachádza v adresári. + + + Could not unlock wallet. + Nepodarilo sa odomknúť peňaženku. + + + New key generation failed. + Generovanie nového kľúča zlyhalo. + + FreespaceChecker @@ -594,14 +886,50 @@ Forma + Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below. + Nedávne transakcie nemusia byť ešte viditeľné preto môže byť zostatok vo vašej peňaženke nesprávny. Táto informácia bude správna keď sa dokončí synchronizovanie peňaženky so sieťou bitcoin, ako je rozpísané nižšie. + + + Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network. + Pokus o minutie bitcoinov, ktoré sú ovplyvnené ešte nezobrazenými transakciami, nebude sieťou akceptovaný. + + + Number of blocks left + Počet zostávajúcich blokov + + + Unknown... + Neznáme... + + Last block time Čas posledného bloku + Progress + Postup synchronizácie + + + Progress increase per hour + Prírastok postupu za hodinu + + + calculating... + počíta sa... + + + Estimated time left until synced + Odhadovaný čas do ukončenia synchronizácie + + Hide Skryť - + + Unknown. Syncing Headers (%1)... + Neznámy. Synchronizujú sa hlavičky (%1)... + + OpenURIDialog @@ -620,7 +948,11 @@ Select payment request file Vyberte súbor s výzvou k platbe - + + Select payment request file to open + Vyberte ktorý súbor s výzvou na platbu otvoriť + + OptionsDialog @@ -933,7 +1265,91 @@ PaymentServer - + + Payment request error + Chyba pri vyžiadaní platby + + + URI handling + URI manipulácia + + + Payment request fetch URL is invalid: %1 + URL pre stiahnutie výzvy na zaplatenie je neplatné: %1 + + + Invalid payment address %1 + Neplatná adresa platby %1 + + + URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. + URI sa nedá analyzovať! To môže byť spôsobené neplatnou Bitcoin adresou alebo zle nastavenými vlastnosťami URI. + + + Payment request file handling + Obsluha súboru s požiadavkou na platbu + + + Payment request file cannot be read! This can be caused by an invalid payment request file. + Súbor s výzvou na zaplatenie sa nedá čítať! To môže byť spôsobené aj neplatným súborom s výzvou. + + + Payment request rejected + Požiadavka na platbu zamietnutá + + + Payment request network doesn't match client network. + Sieť požiadavky na platbu nie je zhodná so sieťou klienta. + + + Payment request expired. + Vypršala platnosť požiadavky na platbu. + + + Payment request is not initialized. + Požiadavka na platbu nie je inicializovaná + + + Unverified payment requests to custom payment scripts are unsupported. + Program nepodporuje neoverené platobné požiadavky na vlastné skripty. + + + Invalid payment request. + Chybná požiadavka na platbu. + + + Requested payment amount of %1 is too small (considered dust). + Požadovaná suma platby %1 je príliš nízka (považovaná za prach). + + + Refund from %1 + Vrátenie z %1 + + + Payment request %1 is too large (%2 bytes, allowed %3 bytes). + Požiadavka na platbu %1 je príliš veľká (%2 bajtov, povolené je %3 bajtov). + + + Error communicating with %1: %2 + Chyba komunikácie s %1: %2 + + + Payment request cannot be parsed! + Požiadavka na platbu nemôže byť analyzovaná! + + + Bad response from server %1 + Zlá odpoveď zo servera %1 + + + Network request error + Chyba požiadavky siete + + + Payment acknowledged + Platba potvrdená + + PeerTableModel @@ -944,7 +1360,15 @@ Node/Service Uzol/Služba - + + NodeId + ID uzlu + + + Ping + Odozva + + QObject @@ -983,17 +1407,65 @@ %1 ms %1 ms + + %n second(s) + %n sekunda%n sekundy%n sekúnd + + + %n minute(s) + %n minúta%n minúty%n minút + + + %n hour(s) + %n hodina%n hodiny%n hodín + + + %n day(s) + %n deň%n dni%n dní + + + %n week(s) + %n týždeň%n týždne%n týždňov + %1 and %2 %1 a %2 - + + %n year(s) + %n rok%n roky%n rokov + + + %1 didn't yet exit safely... + %1 ešte nebol bezpečne ukončený... + + QObject::QObject - + + Error: %1 + Chyba: %1 + + QRImageWidget - + + &Save Image... + Uložiť obrázok... + + + &Copy Image + Kopírovať obrázok + + + Save QR Code + Uložiť QR Code + + + PNG Image (*.png) + PNG obrázok (*.png) + + RPCConsole @@ -1018,11 +1490,11 @@ Using BerkeleyDB version - Používa BerkeleyDB verziu + Používa verziu BerkeleyDB Datadir - Zložka s dátami + Priečinok s dátami Startup time @@ -1054,7 +1526,7 @@ Current number of transactions - Aktuálny počet tranzakcií + Aktuálny počet transakcií Memory usage @@ -1094,7 +1566,7 @@ Starting Block - Počiatočný Blok + Počiatočný blok Synced Headers @@ -1147,11 +1619,15 @@ The duration of a currently outstanding ping. - Trvanie aktuálneho pingu + Trvanie aktuálnej požiadavky na odozvu. Ping Wait - Čakanie na ping + Čakanie na odozvu + + + Min Ping + Minimálna odozva Time Offset @@ -1214,11 +1690,23 @@ 1 &rok - Welcome to the %1 RPC console. - Vitajte v %1 RPC konzole + &Disconnect + &Odpojiť - Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Ban for + Zakázať na + + + &Unban + &Zrušiť zákaz + + + Welcome to the %1 RPC console. + Vitajte v %1 RPC konzole + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. Použi šípky hore a dolu pre navigáciu históriou a <b>Ctrl-L</b> pre vyčistenie obrazovky. @@ -1226,6 +1714,14 @@ Napíš <b>help</b> pre prehľad dostupných príkazov. + WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramification of a command. + VAROVANIE: Podvodníci sú aktívni a môžu nabádať používateľov napísať sem príkazy, pomocou ktorých ukradnú ich obsah peňaženky. Nepoužívajte túto konzolu ak nerozumiete presne účinkom príkazov. + + + Network activity disabled + Sieťová aktivita zakázaná + + %1 B %1 B @@ -1344,7 +1840,23 @@ Remove Odstrániť - + + Copy URI + Kopírovať URI + + + Copy label + Kopírovať popis + + + Copy message + Kopírovať správu + + + Copy amount + Kopírovať sumu + + ReceiveRequestDialog @@ -1363,14 +1875,74 @@ &Save Image... Uložiť obrázok... - + + Request payment to %1 + Vyžiadať platbu pre %1 + + + Payment information + Informácia o platbe + + + URI + URI + + + Address + Adresa + + + Amount + Suma + + + Label + Popis + + + Message + Správa + + + Resulting URI too long, try to reduce the text for label / message. + Výsledné URI je príliš dlhé, skúste skrátiť text pre popis alebo správu. + + + Error encoding URI into QR Code. + Chyba kódovania URI do QR Code. + + RecentRequestsTableModel + Date + Dátum + + + Label + Popis + + + Message + Správa + + (no label) (bez popisu) - + + (no message) + (žiadna správa) + + + (no amount requested) + (nepožadovaná žiadna suma) + + + Requested + Požadované + + SendCoinsDialog @@ -1471,7 +2043,7 @@ (Smart fee not initialized yet. This usually takes a few blocks...) - (Automatický poplatok ešte nebol aktivovaný. Toto zvyčajne trvá niekoľko blokov...) + (Automatický poplatok ešte nebol vypočítaný. Toto zvyčajne trvá niekoľko blokov...) normal @@ -1498,6 +2070,10 @@ Prach: + Confirmation time target: + Cieľový čas potvrdenia: + + Clear &All &Zmazať všetko @@ -1514,10 +2090,122 @@ &Odoslať + Copy quantity + Kopírovať množstvo + + + Copy amount + Kopírovať sumu + + + Copy fee + Kopírovať poplatok + + + Copy after fee + Kopírovať po poplatkoch + + + Copy bytes + Kopírovať bajty + + + Copy dust + Kopírovať prach + + + Copy change + Kopírovať zmenu + + + %1 to %2 + %1 do %2 + + + Are you sure you want to send? + Určite chcete odoslať transakciu? + + + added as transaction fee + pridané ako poplatok za transakciu + + + Total Amount %1 + Celková suma %1 + + or alebo + Confirm send coins + Potvrďte odoslanie mincí + + + The recipient address is not valid. Please recheck. + Adresa príjemcu je neplatná. Prosím, overte ju. + + + The amount to pay must be larger than 0. + Suma na úhradu musí byť väčšia ako 0. + + + The amount exceeds your balance. + Suma je vyššia ako Váš zostatok. + + + The total exceeds your balance when the %1 transaction fee is included. + Celková suma prevyšuje Váš zostatok ak sú započítané aj transakčné poplatky %1. + + + Duplicate address found: addresses should only be used once each. + Našla sa duplicitná adresa: každá adresa by sa mala použiť len raz. + + + Transaction creation failed! + Vytvorenie transakcie zlyhalo! + + + The transaction was rejected with the following reason: %1 + Transakcia bola odmietnutá z nasledujúceho dôvodu: %1 + + + A fee higher than %1 is considered an absurdly high fee. + Poplatok vyšší ako %1 sa považuje za neprimerane vysoký. + + + Payment request expired. + Vypršala platnosť požiadavky na platbu. + + + %n block(s) + %n blok%n bloky%n blokov + + + Pay only the required fee of %1 + Zaplatiť iba požadovaný poplatok %1 + + + Estimated to begin confirmation within %n block(s). + Odhadovaný začiatok potvrdzovania po %n bloku.Odhadovaný začiatok potvrdzovania po %n blokoch.Odhadovaný začiatok potvrdzovania po %n blokoch. + + + Warning: Invalid Bitcoin address + Varovanie: Neplatná Bitcoin adresa + + + Warning: Unknown change address + UPOZORNENIE: Neznáma zmena adresy + + + Confirm custom change address + Potvrďte zmenu adresy + + + The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure? + Zadaná adresa nie je súčasťou tejto peňaženky. Časť alebo všetky peniaze z peňaženky môžu byť odoslané na túto adresu. Ste si istý? + + (no label) (bez popisu) @@ -1554,7 +2242,7 @@ Paste address from clipboard - Vložte adresu z klipbordu + Vložiť adresu zo schránky Alt+P @@ -1600,10 +2288,18 @@ Memo: Poznámka: - + + Enter a label for this address to add it to your address book + Zadajte popis pre túto adresu pre pridanie do adresára + + SendConfirmationDialog - + + Yes + áno + + ShutdownWindow @@ -1626,6 +2322,10 @@ &Podpísať Správu + You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Môžete podpísať správy svojou adresou a dokázať, že viete prijímať mince zaslané na túto adresu. Buďte však opatrní a podpíšte len podrobné prehlásenia, s ktorými plne súhlasíte, nakoľko útoky typu "phishing" Vás môžu lákať k podpísaniu nejasných alebo príliš všeobecných tvrdení čím prevezmú vašu identitu. + + The Bitcoin address to sign the message with Bitcoin adresa pre podpísanie správy s @@ -1639,7 +2339,7 @@ Paste address from clipboard - Vložte adresu z klipbordu + Vložiť adresu zo schránky Alt+P @@ -1655,7 +2355,7 @@ Copy the current signature to the system clipboard - Kopírovať práve zvolenú adresu do systémového klipbordu + Kopírovať tento podpis do systémovej schránky Sign the message to prove you own this Bitcoin address @@ -1678,6 +2378,10 @@ O&veriť správu... + Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction! + Vložte adresu príjemcu, správu (uistite sa, že presne kopírujete ukončenia riadkov, medzery, odrážky, atď.) a podpis pre potvrdenie správy. Buďte opatrní a nedomýšľajte si viac než je uvedené v samotnej podpísanej správe a môžete sa tak vyhnúť podvodu MITM útokom. Toto len potvrdzuje, že podpisujúca strana môže prijímať na tejto adrese, nepotvrdzuje to vlastníctvo žiadnej transakcie! + + The Bitcoin address the message was signed with Adresa Bitcoin, ktorou bola podpísaná správa @@ -1693,7 +2397,59 @@ Reset all verify message fields Obnoviť všetky polia v overiť správu - + + Click "Sign Message" to generate signature + Kliknite "Podpísať správu" pre vytvorenie podpisu + + + The entered address is invalid. + Zadaná adresa je neplatná. + + + Please check the address and try again. + Prosím skontrolujte adresu a skúste znova. + + + The entered address does not refer to a key. + Vložená adresa nezodpovedá žiadnemu kľúču. + + + Wallet unlock was cancelled. + Odomknutie peňaženky bolo zrušené. + + + Private key for the entered address is not available. + Súkromný kľúč pre zadanú adresu nieje k dispozícii. + + + Message signing failed. + Podpísanie správy zlyhalo. + + + Message signed. + Správa podpísaná. + + + The signature could not be decoded. + Podpis nie je možné dekódovať. + + + Please check the signature and try again. + Prosím skontrolujte podpis a skúste znova. + + + The signature did not match the message digest. + Podpis sa nezhoduje so zhrnutím správy. + + + Message verification failed. + Overenie správy zlyhalo. + + + Message verified. + Správa overená. + + SplashScreen @@ -1710,24 +2466,416 @@ TransactionDesc - + + Open until %1 + Otvorené do %1 + + + conflicted with a transaction with %1 confirmations + koliduje s transakciou s %1 potvrdeniami + + + %1/offline + %1/offline + + + 0/unconfirmed, %1 + 0/nepotvrdené, %1 + + + %1/unconfirmed + %1/nepotvrdené + + + %1 confirmations + %1 potvrdení + + + Status + Stav + + + , has not been successfully broadcast yet + , ešte nebola úspešne odoslaná + + + Date + Dátum + + + Source + Zdroj + + + Generated + Vygenerované + + + From + Od + + + unknown + neznámy + + + To + do + + + own address + vlastná adresa + + + watch-only + Iba sledovanie + + + label + popis + + + Credit + Kredit + + + not accepted + neprijaté + + + Debit + Debet + + + Total debit + Celkový debet + + + Total credit + Celkový kredit + + + Transaction fee + Transakčný poplatok + + + Net amount + Suma netto + + + Message + Správa + + + Comment + Komentár + + + Transaction ID + ID transakcie + + + Transaction total size + Celková veľkosť transakcie + + + Merchant + Kupec + + + Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Vytvorené coins musia dospieť %1 blokov kým môžu byť minuté. Keď vytvoríte tento blok, bude rozoslaný do siete aby bol akceptovaný do reťaze blokov. Ak sa nedostane reťaze, jeho stav sa zmení na "zamietnutý" a nebude sa dať minúť. Toto sa môže občas stať ak iná nóda vytvorí blok približne v tom istom čase. + + + Debug information + Ladiace informácie + + + Transaction + Transakcie + + + Inputs + Vstupy + + + Amount + Suma + + + true + pravda + + + false + nepravda + + TransactionDescDialog This pane shows a detailed description of the transaction Táto časť obrazovky zobrazuje detailný popis transakcie - + + Details for %1 + Podrobnosti pre %1 + + TransactionTableModel + Date + Dátum + + + Type + Typ + + + Label + Popis + + + Open until %1 + Otvorené do %1 + + + Offline + Offline + + + Unconfirmed + Nepotvrdené + + + Confirming (%1 of %2 recommended confirmations) + Potvrdzujem (%1 z %2 odporúčaných potvrdení) + + + Confirmed (%1 confirmations) + Potvrdené (%1 potvrdení) + + + Conflicted + V rozpore + + + Immature (%1 confirmations, will be available after %2) + Nezrelé (%1 potvrdení, bude dostupné po %2) + + + This block was not received by any other nodes and will probably not be accepted! + Ten blok nebol prijatý žiadnym iným uzlom a pravdepodobne nebude akceptovaný! + + + Generated but not accepted + Vypočítané ale neakceptované + + + Received with + Prijaté s + + + Received from + Prijaté od + + + Sent to + Odoslané na + + + Payment to yourself + Platba sebe samému + + + Mined + Vyťažené + + + watch-only + Iba sledovanie + + + (n/a) + (n/a) + + (no label) (bez popisu) - + + Transaction status. Hover over this field to show number of confirmations. + Stav transakcie. Prejdite ponad toto pole pre zobrazenie počtu potvrdení. + + + Date and time that the transaction was received. + Dátum a čas prijatia transakcie. + + + Type of transaction. + Typ transakcie. + + + Whether or not a watch-only address is involved in this transaction. + Či je v tejto transakcii adresy iba na sledovanie. + + + Amount removed from or added to balance. + Suma pridaná alebo odobraná k zostatku. + + TransactionView - + + All + Všetky + + + Today + Dnes + + + This week + Tento týždeň + + + This month + Tento mesiac + + + Last month + Minulý mesiac + + + This year + Tento rok + + + Range... + Rozsah... + + + Received with + Prijaté s + + + Sent to + Odoslané na + + + To yourself + Ku mne + + + Mined + Vyťažené + + + Other + Iné + + + Enter address or label to search + Zadajte adresu alebo popis pre hľadanie + + + Min amount + Minimálna suma + + + Copy address + Kopírovať adresu + + + Copy label + Kopírovať popis + + + Copy amount + Kopírovať sumu + + + Copy transaction ID + Kopírovať ID transakcie + + + Copy raw transaction + Skopírovať neupravenú transakciu + + + Copy full transaction details + Kopírovať všetky podrobnosti o transakcii + + + Edit label + Upraviť popis + + + Show transaction details + Zobraziť podrobnosti transakcie + + + Export Transaction History + Exportovať históriu transakcií + + + Comma separated file (*.csv) + Čiarkou oddelovaný súbor (*.csv) + + + Confirmed + Potvrdené + + + Watch-only + Iba sledovanie + + + Date + Dátum + + + Type + Typ + + + Label + Popis + + + Address + Adresa + + + ID + ID + + + Exporting Failed + Export zlyhal + + + There was an error trying to save the transaction history to %1. + Vyskytla sa chyba pri pokuse o uloženie histórie transakcií do %1. + + + Exporting Successful + Export úspešný + + + The transaction history was successfully saved to %1. + História transakciá bola úspešne uložená do %1. + + + Range: + Rozsah: + + + to + do + + UnitDisplayStatusBarControl @@ -1737,13 +2885,53 @@ WalletFrame - + + No wallet has been loaded. + Nie je načítaná peňaženka. + + WalletModel - + + Send Coins + Poslať mince + + WalletView - + + &Export + &Exportovať... + + + Export the data in the current tab to a file + Exportovať dáta v aktuálnej karte do súboru + + + Backup Wallet + Zálohovanie peňaženky + + + Wallet Data (*.dat) + Dáta peňaženky (*.dat) + + + Backup Failed + Zálohovanie zlyhalo + + + There was an error trying to save the wallet data to %1. + Vyskytla sa chyba pri pokuse o uloženie dát peňaženky do %1. + + + Backup Successful + Záloha úspešná + + + The wallet data was successfully saved to %1. + Dáta peňaženky boli úspešne uložené do %1. + + bitcoin-core @@ -1767,6 +2955,10 @@ Prijímať príkazy z príkazového riadku a JSON-RPC + Distributed under the MIT software license, see the accompanying file %s or %s + Distribuované pod softvérovou licenciou MIT, viď sprievodný súbor %s alebo %s + + If <category> is not supplied or if <category> = 1, output all debugging information. Pokiaľ <category> nie je nastavená, alebo <category> = 1, vypíš všetky informácie pre ladenie. @@ -1780,7 +2972,7 @@ Fee (in %s/kB) to add to transactions you send (default: %s) - Poplatok (za %s/kB) pridaný do tranzakcie, ktorú posielate (predvolené: %s) + Poplatok (za %s/kB) pridaný do transakcie, ktorú posielate (predvolené: %s) Pruning blockstore... @@ -1796,13 +2988,17 @@ Bitcoin Core - Jadro Bitcoin + Bitcoin Core The %s developers Vývojári %s + Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d) + Akceptovať postúpené transakcie od povolených partnerov aj keď normálne nepostupujete transakcie (predvolené: %d) + + Bind to given address and always listen on it. Use [host]:port notation for IPv6 Spojiť s danou adresou a vždy na nej počúvať. Použite zápis [host]:port pre IPv6 @@ -1839,6 +3035,26 @@ Databáza blokov obsahuje blok, ktorý vyzerá byť z budúcnosti. Toto môže byť spôsobené nesprávnym systémovým časom vášho počítača. Obnovujte databázu blokov len keď ste si istý, že systémový čas je nastavený správne. + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications + Toto je predbežná testovacia zostava - používate na vlastné riziko - nepoužívajte na ťaženie alebo obchodné aplikácie + + + Use UPnP to map the listening port (default: 1 when listening and no -proxy) + Skúsiť použiť UPnP pre mapovanie počúvajúceho portu (predvolené: 1 počas počúvania a bez -proxy) + + + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. + Varovanie: Javí sa že sieť sieť úplne nesúhlasí! Niektorí mineri zjavne majú ťažkosti. + + + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. + Varovanie: Zjavne sa úplne nezhodujeme s našimi peer-mi! Možno potrebujete prejsť na novšiu verziu alebo ostatné uzly potrebujú vyššiu verziu. + + + You need to rebuild the database using -reindex-chainstate to change -txindex + Potrebujete prebudovať databázu použitím -reindex-chainstate pre zmenu -txindex + + %s corrupt, salvage failed %s je poškodený, záchrana zlyhala @@ -1851,6 +3067,10 @@ <category> môže byť: + Attempt to recover private keys from a corrupt wallet on startup + Pokúsiť sa o obnovenie privátnych kľúčov z poškodenej peňaženky pri spustení + + Block creation options: Voľby vytvorenia bloku: @@ -1888,7 +3108,7 @@ Enable publish hash transaction in <address> - Povoliť zverejnenie hash tranzakcií pre <address> + Povoliť zverejnenie hash transakcií pre <address> Enable publish raw block in <address> @@ -1964,7 +3184,7 @@ Location of the auth cookie (default: data dir) - Poloha overovacieho cookie súboru (predvolená: zložka s dátami) + Umiestnenie overovacieho cookie súboru (predvolená: Priečinok s dátami) Not enough file descriptors available. @@ -2035,6 +3255,10 @@ Použiť UPnP pre mapovanie počúvajúceho portu (predvolené: %u) + Use the test chain + Použiť testovaciu sieť + + Verifying blocks... Overujem bloky... @@ -2087,6 +3311,10 @@ Vykonať príkaz po prijatí patričného varovania alebo uvidíme veľmi dlhé rozdvojenie siete (%s v cmd je nahradené správou) + Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s) + Poplatky (v %s/kB) menšie ako toto, sú považované za nulový transakčný poplatok (predvolené: %s) + + If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u) Ak nie je nastavené paytxfee, pridať dostatočný poplatok aby sa transakcia začala potvrdzovať priemerne v rámci bloku (predvolené: %u) @@ -2104,7 +3332,7 @@ The transaction amount is too small to send after the fee has been deducted - Suma je príliš malá pre odoslanie tranzakcie + Suma je príliš malá pre odoslanie transakcie Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway @@ -2188,7 +3416,7 @@ The transaction amount is too small to pay the fee - Suma tranzakcie je príliš malá na zaplatenie poplatku + Suma transakcie je príliš malá na zaplatenie poplatku This is experimental software. @@ -2255,6 +3483,10 @@ (1 = zachovať metaúdaje tx napr. vlastníka účtu a informácie o platobných príkazoch, 2 = zahodiť metaúdaje tx) + Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s) + Poplatky (v %s/kB) menšie ako toto, sú považované za nulový transakčný poplatok (predvolené: %s) + + How thorough the block verification of -checkblocks is (0-4, default: %u) Ako dôkladné je -checkblocks overenie blokov (0-4, predvolené: %u) @@ -2271,6 +3503,10 @@ Výstupné ladiace informácie (predvolené: %u, dodanie <category> je voliteľné) + This is the transaction fee you may pay when fee estimates are not available. + Toto je poplatok za transakciu keď odhad poplatkov ešte nie je k dispozícii. + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. Celková dĺžka verzie sieťového reťazca (%i) prekračuje maximálnu dĺžku (%i). Znížte počet a veľkosť komentárov. @@ -2299,6 +3535,14 @@ Varovanie: Peňaženka poškodená, dáta boli zachránené! Originálna %s ako %s v %s; ak váš zostatok alebo transakcie sú nesprávne, mali by ste obnoviť zálohu. + Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times. + Povoliť partnerov pripájajúcich sa z danej IP adresy (napr. 1.2.3.4) alebo zo siete vo formáte CIDR (napr. 1.2.3.0/24). Môže byť zadané viackrát. + + + %s is set very high! + Hodnota %s je nastavená veľmi vysoko! + + (default: %s) (predvolené: %s) @@ -2375,10 +3619,34 @@ Minúť nepotvrdené zmenu pri posielaní transakcií (predvolené: %u) + Starting network threads... + Spúšťajú sa sieťové vlákna... + + + The wallet will avoid paying less than the minimum relay fee. + Peňaženka zabráni zaplateniu menšej sumy ako je minimálny poplatok. + + + This is the minimum transaction fee you pay on every transaction. + Toto je minimálny poplatok za transakciu pri každej transakcii. + + + This is the transaction fee you will pay if you send a transaction. + Toto je poplatok za transakciu pri odoslaní transakcie. + + Threshold for disconnecting misbehaving peers (default: %u) Hranica pre odpájanie zle sa správajúcim partnerským uzlom (predvolené: %u) + Transaction amounts must not be negative + Sumy transakcií nesmú byť záporné + + + Transaction must have at least one recipient + Transakcia musí mať aspoň jedného príjemcu + + Unknown network specified in -onlynet: '%s' Neznáma sieť upresnená v -onlynet: '%s' diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts index 2986115a620..173abbb7d92 100644 --- a/src/qt/locale/bitcoin_sv.ts +++ b/src/qt/locale/bitcoin_sv.ts @@ -3,7 +3,7 @@ AddressBookPage Right-click to edit address or label - Högerklicka för att ändra adressen eller etiketten. + Högerklicka för att ändra adressen eller etiketten Create a new address @@ -533,6 +533,14 @@ Var vänlig och försök igen. Inkommande transaktion + HD key generation is <b>enabled</b> + HD-nyckelgenerering är <b>aktiverad</b> + + + HD key generation is <b>disabled</b> + HD-nyckelgenerering är <b>inaktiverad</b> + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> Denna plånbok är <b>krypterad</b> och för närvarande <b>olåst</b> @@ -540,7 +548,11 @@ Var vänlig och försök igen. Wallet is <b>encrypted</b> and currently <b>locked</b> Denna plånbok är <b>krypterad</b> och för närvarande <b>låst</b> - + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + Ett kritiskt fel uppstod. Bitcoin kan inte fortsätta att köra säkert och kommer att avslutas. + + CoinControlDialog @@ -628,6 +640,42 @@ Var vänlig och försök igen. Kopiera transaktions-ID + Lock unspent + Lås ospenderat + + + Unlock unspent + Lås upp ospenderat + + + Copy quantity + Kopiera kvantitet + + + Copy fee + Kopiera avgift + + + Copy after fee + Kopiera efter avgift + + + Copy bytes + Kopiera byte + + + Copy dust + Kopiera damm + + + Copy change + Kopiera växel + + + (%1 locked) + (%1 låst) + + yes ja @@ -636,10 +684,26 @@ Var vänlig och försök igen. nej + This label turns red if any recipient receives an amount smaller than the current dust threshold. + Denna etikett blir röd om någon mottagare får en betalning som är mindre än aktuella dammtröskeln. + + + Can vary +/- %1 satoshi(s) per input. + Kan variera +/- %1 satoshi per inmatning. + + (no label) (Ingen etikett) - + + change from %1 (%2) + växel från %1 (%2) + + + (change) + (växel) + + EditAddressDialog @@ -663,10 +727,38 @@ Var vänlig och försök igen. &Adress + New receiving address + Ny mottagaradress + + + New sending address + Ny avsändaradress + + + Edit receiving address + Redigera mottagaradress + + + Edit sending address + Redigera avsändaradress + + + The entered address "%1" is not a valid Bitcoin address. + Den angivna adressen "%1" är inte en giltig Bitcoin-adress. + + + The entered address "%1" is already in the address book. + Den angivna adressen "%1" finns redan i adressboken. + + Could not unlock wallet. Kunde inte låsa upp plånboken. - + + New key generation failed. + Misslyckades med generering av ny nyckel. + + FreespaceChecker @@ -679,7 +771,7 @@ Var vänlig och försök igen. Directory already exists. Add %1 if you intend to create a new directory here. - Katalogen finns redan. Läggtill %1 om du vill skapa en ny katalog här. + Katalogen finns redan. Lägg till %1 om du vill skapa en ny katalog här. Path already exists, and is not a directory. @@ -811,10 +903,18 @@ Var vänlig och försök igen. Förlopp + Progress increase per hour + Framstegssökning per timme + + calculating... beräknar... + Estimated time left until synced + Beräknad tid kvar tills synkroniserad + + Hide Göm @@ -841,7 +941,11 @@ Var vänlig och försök igen. Select payment request file Välj betalningsbegäransfil - + + Select payment request file to open + Välj betalningsförfrågningsfil som ska öppnas + + OptionsDialog @@ -1155,18 +1259,94 @@ Var vänlig och försök igen. PaymentServer + Payment request error + Fel vid betalningsbegäran + + + Cannot start bitcoin: click-to-pay handler + Kan inte starta bitcoin: klicka-och-betala handhavare + + URI handling URI-hantering + Payment request fetch URL is invalid: %1 + Hämtningsadressen för betalningsförfrågan är ogiltig: %1 + + + Invalid payment address %1 + Ogiltig betalningsadress %1 + + + URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. + URI kan inte tolkas! Detta kan orsakas av en ogiltig Bitcoin-adress eller felaktiga URI parametrar. + + + Payment request file handling + Hantering av betalningsförfrågningsfil + + + Payment request file cannot be read! This can be caused by an invalid payment request file. + Betalningsförfrågningsfilen kan inte läsas! Detta kan orsakas av en felaktig betalningsförfrågnigsfil. + + + Payment request rejected + Betalningsbegäran avslogs + + + Payment request network doesn't match client network. + Betalningsbegärans nätverk matchar inte klientens nätverk. + + + Payment request expired. + Betalningsbegäran löpte ut. + + + Payment request is not initialized. + Betalningsbegäran är inte initierad. + + + Unverified payment requests to custom payment scripts are unsupported. + Overifierade betalningsförfrågningar till anpassade betalningsskript stöds inte. + + + Invalid payment request. + Ogiltig betalningsbegäran. + + + Requested payment amount of %1 is too small (considered dust). + Begärd betalning av %1 är för liten (betraktas som damm). + + Refund from %1 Återbetalning från %1 + Payment request %1 is too large (%2 bytes, allowed %3 bytes). + Betalningsbegäran %1 är för stor (%2 bytes, tillåten %3 bytes). + + + Error communicating with %1: %2 + Kommunikationsfel med %1: %2 + + + Payment request cannot be parsed! + Betalningsbegäran kan inte behandlas! + + Bad response from server %1 Felaktigt svar från server %1 - + + Network request error + Fel vid närverksbegäran + + + Payment acknowledged + Betalningen bekräftad + + PeerTableModel @@ -1248,17 +1428,45 @@ Var vänlig och försök igen. %n year(s) %n år%n år - + + %1 didn't yet exit safely... + %1 avslutades inte ännu säkert... + + QObject::QObject + Error: Specified data directory "%1" does not exist. + Fel: Den angivna datakatalogen "%1" finns inte. + + + Error: Cannot parse configuration file: %1. Only use key=value syntax. + Fel: Kan inte läsa konfigurationsfilen: %1. Använd bara nyckel=värde formatet. + + Error: %1 Fel: %1 QRImageWidget - + + &Save Image... + &Spara Bild... + + + &Copy Image + &Kopiera Bild + + + Save QR Code + Spara QR-kod + + + PNG Image (*.png) + PNG-bild (*.png) + + RPCConsole @@ -1478,6 +1686,10 @@ Var vänlig och försök igen. 1 &år + &Disconnect + &Koppla ner + + Welcome to the %1 RPC console. Välkommen till %1 RPC-konsolen. @@ -1490,6 +1702,10 @@ Var vänlig och försök igen. Skriv <b>help</b> för en översikt av alla kommandon. + Network activity disabled + Nätverksaktivitet inaktiverad + + %1 B %1 B @@ -1644,6 +1860,10 @@ Var vänlig och försök igen. &Spara Bild... + Request payment to %1 + Begär betalning till %1 + + Payment information Betalinformaton @@ -1656,6 +1876,10 @@ Var vänlig och försök igen. Adress + Amount + Belopp: + + Label Etikett @@ -1663,7 +1887,15 @@ Var vänlig och försök igen. Message Meddelande - + + Resulting URI too long, try to reduce the text for label / message. + URI:n är för lång, försöka minska texten för etikett / meddelande. + + + Error encoding URI into QR Code. + Fel vid skapande av QR-kod från URI. + + RecentRequestsTableModel @@ -1686,7 +1918,15 @@ Var vänlig och försök igen. (no message) (inget meddelande) - + + (no amount requested) + (ingen summa begärd) + + + Requested + Begärd + + SendCoinsDialog @@ -1814,6 +2054,10 @@ Var vänlig och försök igen. Damm: + Confirmation time target: + Bekräftelsestidsmål: + + Clear &All Rensa &alla @@ -1830,22 +2074,118 @@ Var vänlig och försök igen. &Skicka + Copy quantity + Kopiera kvantitet + + Copy amount Kopiera belopp + Copy fee + Kopiera avgift + + + Copy after fee + Kopiera efter avgift + + + Copy bytes + Kopiera byte + + + Copy dust + Kopiera damm + + + Copy change + Kopiera växel + + %1 to %2 %1 till %2 + Are you sure you want to send? + Är du säker på att du vill skicka? + + + added as transaction fee + adderad som transaktionsavgift + + + Total Amount %1 + Totalt belopp %1 + + or eller + + Confirm send coins + Bekräfta skickade mynt + + + The recipient address is not valid. Please recheck. + Mottagarens adress är ogiltig. Kontrollera igen. + + + The amount to pay must be larger than 0. + Det betalade beloppet måste vara större än 0. + + + The amount exceeds your balance. + Värdet överstiger ditt saldo. + + + The total exceeds your balance when the %1 transaction fee is included. + Totalvärdet överstiger ditt saldo när transaktionsavgiften %1 är pålagd. + + + Duplicate address found: addresses should only be used once each. + Duplicerad adress upptäckt: adresser skall endast användas en gång var. + + + Transaction creation failed! + Transaktionen gick inte att skapa! + + + The transaction was rejected with the following reason: %1 + Transaktionen avvisades med följande orsak: %1 + + + A fee higher than %1 is considered an absurdly high fee. + En avgift högre än %1 anses vara en absurd hög avgift. + + + Payment request expired. + Betalningsbegäran löpte ut. + %n block(s) %n block%n block + Pay only the required fee of %1 + Betala endast den nödvändiga avgiften på %1 + + + Warning: Invalid Bitcoin address + Varning: Felaktig Bitcoinadress + + + Warning: Unknown change address + Varning: Okänd växeladress + + + Confirm custom change address + Bekräfta anpassad växlingsadress + + + The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure? + Den adress du valt för växel ingår inte i denna plånbok. Eventuella eller alla pengar i din plånbok kan skickas till den här adressen. Är du säker? + + (no label) (Ingen etikett) @@ -1928,7 +2268,11 @@ Var vänlig och försök igen. Memo: PM: - + + Enter a label for this address to add it to your address book + Ange en etikett för den här adressen och lägg till den i din adressbok + + SendConfirmationDialog @@ -2034,6 +2378,34 @@ Var vänlig och försök igen. Rensa alla fält + Click "Sign Message" to generate signature + Klicka "Signera Meddelande" för att få en signatur + + + The entered address is invalid. + Den angivna adressen är ogiltig. + + + Please check the address and try again. + Vad god kontrollera adressen och försök igen. + + + The entered address does not refer to a key. + Den angivna adressen refererar inte till en nyckel. + + + Wallet unlock was cancelled. + Upplåsningen av plånboken avbröts. + + + Private key for the entered address is not available. + Privata nyckel för den angivna adressen är inte tillgänglig. + + + Message signing failed. + Signeringen av meddelandet misslyckades. + + Message signed. Meddelande signerat. @@ -2042,6 +2414,18 @@ Var vänlig och försök igen. Signaturen kunde inte avkodas. + Please check the signature and try again. + Kontrollera signaturen och försök igen. + + + The signature did not match the message digest. + Signaturen matchade inte meddelandesammanfattningen. + + + Message verification failed. + Meddelandeverifikation misslyckades. + + Message verified. Meddelande verifierat. @@ -2062,6 +2446,46 @@ Var vänlig och försök igen. TransactionDesc + + Open for %n more block(s) + Öppet för %n mer blockÖppet för %n mer block + + + Open until %1 + Öppet till %1 + + + conflicted with a transaction with %1 confirmations + konflikt med en transaktion med %1 konfirmationer + + + %1/offline + %1/nerkopplad + + + 0/unconfirmed, %1 + 0/obekräftade, %1 + + + in memory pool + i minnespoolen + + + not in memory pool + ej i minnespoolen + + + abandoned + övergiven + + + %1/unconfirmed + %1/obekräftade + + + %1 confirmations + %1 bekräftelser + Status Status @@ -2071,17 +2495,113 @@ Var vänlig och försök igen. Datum + Source + Källa + + + Generated + Genererad + + + From + Från + + + unknown + okänd + + + To + Till + + + own address + egen adress + + + watch-only + granska-bara + + + label + etikett + + + matures in %n more block(s) + mognar om %n mer blockmognar om %n fler block + + + not accepted + inte accepterad + + + Debit + Belasta + + + Transaction fee + Transaktionsavgift + + Message Meddelande - + + Comment + Kommentar + + + Transaction ID + Transaktions-ID + + + Transaction total size + Transaktionens totala storlek + + + Merchant + Handlare + + + Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Genererade mynt måste vänta %1 block innan de kan användas. När du skapade detta block sändes det till nätverket för att läggas till i blockkedjan. Om blocket inte kommer in i kedjan kommer dess status att ändras till "accepteras inte" och kommer ej att gå att spendera. Detta kan ibland hända om en annan nod genererar ett block nästan samtidigt som dig. + + + Debug information + Debug information + + + Transaction + Transaktion + + + Inputs + Inmatningar + + + Amount + Belopp: + + + true + sant + + + false + falsk + + TransactionDescDialog This pane shows a detailed description of the transaction Den här panelen visar en detaljerad beskrivning av transaktionen - + + Details for %1 + Detaljer för %1 + + TransactionTableModel @@ -2089,17 +2609,169 @@ Var vänlig och försök igen. Datum + Type + Typ + + Label Etikett + + Open for %n more block(s) + Öppet för %n mer blockÖppet för %n mer block + + + Open until %1 + Öppet till %1 + + + Offline + Nerkopplad + + + Unconfirmed + Obekräftade: + + + Abandoned + Övergiven + + + Confirming (%1 of %2 recommended confirmations) + Bekräftar (%1 av %2 bekräftelser) + + + Confirmed (%1 confirmations) + Bekräftad (%1 bekräftelser) + + + Immature (%1 confirmations, will be available after %2) + Omogen (%1 bekräftelser, blir tillgänglig efter %2) + + + This block was not received by any other nodes and will probably not be accepted! + Det här blocket togs inte emot av några andra noder och kommer antagligen inte att bli accepterad! + + + Generated but not accepted + Genererad men inte accepterad + + + Received with + Mottagen med + + + Received from + Mottaget från + + + Sent to + Skickad till + + + Payment to yourself + Betalning till dig själv + + + Mined + Genererade + + + watch-only + granska-bara + + + (n/a) + (n/a) + (no label) (Ingen etikett) - + + Transaction status. Hover over this field to show number of confirmations. + Transaktionsstatus. Håll muspekaren över för att se antal bekräftelser. + + + Date and time that the transaction was received. + Tidpunkt då transaktionen mottogs. + + + Type of transaction. + Transaktionstyp. + + + Whether or not a watch-only address is involved in this transaction. + Anger om granska-bara--adresser är involverade i denna transaktion. + + + User-defined intent/purpose of the transaction. + Användardefinierat syfte/ändamål för transaktionen. + + + Amount removed from or added to balance. + Belopp draget eller tillagt till balans. + + TransactionView + All + Alla + + + Today + Idag + + + This week + Denna vecka + + + This month + Denna månad + + + Last month + Föregående månad + + + This year + Det här året + + + Received with + Mottagen med + + + Sent to + Skickad till + + + To yourself + Till dig själv + + + Mined + Genererade + + + Other + Övriga + + + Enter address or label to search + Ange en adress eller etikett att söka efter + + + Min amount + Minsta belopp + + + Abandon transaction + Avbryt transaktionen + + Copy address Kopiera adress @@ -2116,14 +2788,42 @@ Var vänlig och försök igen. Kopiera transaktions-ID + Copy raw transaction + Kopiera rå transaktion + + + Copy full transaction details + Kopiera alla transaktionsdetaljerna + + + Edit label + Ändra etikett + + + Show transaction details + Visa transaktionsdetaljer + + + Export Transaction History + Exportera Transaktionshistoriken + + Comma separated file (*.csv) Kommaseparerad fil (*.csv) + Confirmed + Bekräftad + + Date Datum + Type + Typ + + Label Etikett @@ -2132,26 +2832,86 @@ Var vänlig och försök igen. Adress + ID + ID + + Exporting Failed Export misslyckades - + + There was an error trying to save the transaction history to %1. + Det inträffade ett fel när transaktionshistoriken skulle sparas till %1. + + + Exporting Successful + Exporteringen lyckades + + + The transaction history was successfully saved to %1. + Transaktionshistoriken sparades utan problem till %1. + + + to + till + + UnitDisplayStatusBarControl Unit to show amounts in. Click to select another unit. - &Enhet att visa belopp i. Klicka för att välja annan enhet. + Enhet att visa belopp i. Klicka för att välja annan enhet. WalletFrame - + + No wallet has been loaded. + Ingen plånbok har laddats in. + + WalletModel - + + Send Coins + Skicka Bitcoins + + WalletView - + + &Export + &Exportera + + + Export the data in the current tab to a file + Exportera informationen i den nuvarande fliken till en fil + + + Backup Wallet + Säkerhetskopiera Plånbok + + + Wallet Data (*.dat) + Plånboks-data (*.dat) + + + Backup Failed + Säkerhetskopiering misslyckades + + + There was an error trying to save the wallet data to %1. + Det inträffade ett fel när plånbokens data skulle sparas till %1. + + + Backup Successful + Säkerhetskopiering lyckades + + + The wallet data was successfully saved to %1. + Plånbokens data sparades utan problem till %1. + + bitcoin-core @@ -2175,6 +2935,18 @@ Var vänlig och försök igen. Tillåt kommandon från kommandotolken och JSON-RPC-kommandon + Accept connections from outside (default: 1 if no -proxy or -connect/-noconnect) + Acceptera anslutningar utifrån (förvalt: 1 om ingen -proxy eller -connect/-noconnect) + + + Connect only to the specified node(s); -noconnect or -connect=0 alone to disable automatic connections + Anslut endast till angivna nod(er); -noconnect eller -connect=0 ensam för att inaktivera automatiska anslutningar + + + Distributed under the MIT software license, see the accompanying file %s or %s + Distribuerad under MIT mjukvarulicens, se den bifogade filen %s eller %s + + If <category> is not supplied or if <category> = 1, output all debugging information. Om <kategori> inte anges eller om <category> = 1, visa all avlusningsinformation. @@ -2251,6 +3023,10 @@ Var vänlig och försök igen. Exekvera kommando när en plånbokstransaktion ändras (%s i cmd är ersatt av TxID) + Extra transactions to keep in memory for compact block reconstructions (default: %u) + Extra transaktioner att hålla i minnet för kompakta blockrekonstruktioner (standard: %u) + + Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds) Maximalt tillåten median-peer tidsoffset justering. Lokalt perspektiv av tiden kan bli påverkad av partners, framåt eller bakåt denna tidsrymd. (förvalt: %u sekunder) @@ -2275,6 +3051,10 @@ Var vänlig och försök igen. Blockdatabasen innehåller ett block som verkar vara från framtiden. Detta kan vara på grund av att din dators datum och tid är felaktiga. Bygg bara om blockdatabasen om du är säker på att datorns datum och tid är korrekt + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications + Detta är ett förhandstestbygge - använd på egen risk - använd inte för mining eller handels applikationer + + Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain Kan inte spola tillbaka databasen till obeskärt läge. Du måste ladda ner blockkedjan igen @@ -2283,6 +3063,22 @@ Var vänlig och försök igen. Använd UPnP för att mappa den lyssnande porten (förvalt: 1 när lyssning aktiverat och utan -proxy) + Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times + Användarnamn och hashat lösenord för JSON-RPC-anslutningar. Fältet <userpw> kommer i formatet: <USERNAME>:<SALT>$<HASH>. Ett kanoniskt pythonskript finns inkluderat i share/rpcuser. Klienten kopplas sedan normalt med rpcuser=<USERNAME>/rpcpassword=<PASSWORD> par argument. Detta alternativ kan anges flera gånger + + + Wallet will not create transactions that violate mempool chain limits (default: %u) + Plånboken skapar inte transaktioner som bryter mot mempools kedjegränser (förval: %u) + + + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. + Varning: Nätverket verkar inte vara helt överens! Några miners verkar ha problem. + + + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. + Varning: Vi verkar inte helt överens med våra peers! Du kan behöva uppgradera, eller andra noder kan behöva uppgradera. + + You need to rebuild the database using -reindex-chainstate to change -txindex Du måste återskapa databasen med -reindex-chainstate för att ändra -txindex @@ -2511,6 +3307,10 @@ Var vänlig och försök igen. Använd UPnP för att mappa den lyssnande porten (förvalt: %u) + Use the test chain + Använd testkedjan + + User Agent comment (%s) contains unsafe characters. Kommentaren i användaragent (%s) innehåller osäkra tecken. @@ -2783,6 +3583,10 @@ Var vänlig och försök igen. Avgifter (i %s/kB) mindre än detta anses vara nollavgifter vid skapande av transaktion (standard: %s) + Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d) + Vidarebefordra alltid transaktioner från vitlistade noder även om de bryter mot den lokala reläpolicyn (förvalt: %d) + + How thorough the block verification of -checkblocks is (0-4, default: %u) Hur grundlig blockverifikationen vid -checkblocks är (0-4, förvalt: %u) @@ -2799,10 +3603,22 @@ Var vänlig och försök igen. Skriv ut avlusningsinformation (förvalt: %u, att ange <category> är frivilligt) + Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect/-noconnect) + Sök efter klientadresser med DNS sökningen, om det finns otillräckligt med adresser (förvalt: 1 om inte -connect/-noconnect) + + Support filtering of blocks and transaction with bloom filters (default: %u) Stöd filtrering av block och transaktioner med bloomfilter (standard: %u) + This is the transaction fee you may pay when fee estimates are not available. + Detta är transaktionsavgiften du kan komma att betala om uppskattad avgift inte finns tillgänglig. + + + This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard. + Denna produkten innehåller mjukvara utvecklad av OpenSSL Project för användning i OpenSSL Toolkit %s och kryptografisk mjukvara utvecklad av Eric Young samt UPnP-mjukvara skriven av Thomas Bernard. + + Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments. Total längd på strängen för nätverksversion (%i) överskrider maxlängden (%i). Minska numret eller storleken på uacomments. @@ -2831,6 +3647,10 @@ Var vänlig och försök igen. Varning: Plånboksfilen var korrupt, datat har räddats! Den ursprungliga %s har sparas som %s i %s. Om ditt saldo eller transaktioner är felaktiga bör du återställa från en säkerhetskopia. + %s is set very high! + %s är satt väldigt högt! + + (default: %s) (förvalt: %s) @@ -2915,10 +3735,38 @@ Var vänlig och försök igen. Spendera okonfirmerad växel när transaktioner sänds (förvalt: %u) + Starting network threads... + Startar nätverkstrådar... + + + The wallet will avoid paying less than the minimum relay fee. + Plånboken undviker att betala mindre än lägsta reläavgift. + + + This is the minimum transaction fee you pay on every transaction. + Det här är minimum avgiften du kommer betala för varje transaktion. + + + This is the transaction fee you will pay if you send a transaction. + Det här är transaktionsavgiften du kommer betala om du skickar en transaktion. + + Threshold for disconnecting misbehaving peers (default: %u) Tröskelvärde för att koppla ifrån klienter som missköter sig (förvalt: %u) + Transaction amounts must not be negative + Transaktionens belopp får ej vara negativ + + + Transaction has too long of a mempool chain + Transaktionen har för lång mempool-kedja + + + Transaction must have at least one recipient + Transaktionen måste ha minst en mottagare + + Unknown network specified in -onlynet: '%s' Okänt nätverk som anges i -onlynet: '%s' diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts index 2de0d14ddd2..321effc7e13 100644 --- a/src/qt/locale/bitcoin_tr.ts +++ b/src/qt/locale/bitcoin_tr.ts @@ -295,15 +295,15 @@ &Encrypt Wallet... - Cüzdanı &Şifrele... + &Cüzdanı Şifrele... &Backup Wallet... - Cüzdanı &Yedekle... + &Cüzdanı Yedekle... &Change Passphrase... - Parolayı &Değiştir... + &Parolayı Değiştir... &Sending addresses... diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts index 2c017fc52e2..7126b2e5c15 100644 --- a/src/qt/locale/bitcoin_uk.ts +++ b/src/qt/locale/bitcoin_uk.ts @@ -41,10 +41,62 @@ &Delete &Видалити - + + Choose the address to send coins to + Оберіть адресу для відправки монет + + + Choose the address to receive coins with + Оберіть адресу для отримання монет + + + C&hoose + О&брати + + + Sending addresses + Адреса відправлення + + + Receiving addresses + Адреса отримання + + + Copy &Label + Зкопіювати&Створити мітку + + + &Edit + &Редагувати + + + Export Address List + Експотувати список адрес + + + Comma separated file (*.csv) + Файли (*.csv) розділеі комами + + + Exporting Failed + Експортування пройшло не успішно + + + There was an error trying to save the address list to %1. Please try again. + Виникла помилка при спрбі збереження списку адрес %1. Будь-ласка, спробувати пізніше. + + AddressTableModel - + + Label + Мітка + + + (no label) + (немає мітки) + + AskPassphraseDialog @@ -410,6 +462,10 @@ Confirmed Підтверджені + + (no label) + немає мітки + EditAddressDialog @@ -1270,9 +1326,21 @@ &Save Image... &Зберегти зображення... + + Label + Мітка + RecentRequestsTableModel + + Label + Мітка + + + (no label) + немає мітки + SendCoinsDialog @@ -1416,7 +1484,11 @@ S&end &Відправити - + + (no label) + немає мітки + + SendCoinsEntry @@ -1619,9 +1691,29 @@ TransactionTableModel + + Label + Мітка + + + (no label) + немає мітки + TransactionView + + Comma separated file (*.csv) + Файли (*.csv) розділеі комами + + + Label + Мітка + + + Exporting Failed + Експортування пройшло не успішно + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_ur_PK.ts b/src/qt/locale/bitcoin_ur_PK.ts index 923198c91a3..bd0ef617ae7 100644 --- a/src/qt/locale/bitcoin_ur_PK.ts +++ b/src/qt/locale/bitcoin_ur_PK.ts @@ -41,9 +41,25 @@ &Delete مٹا + + Choose the address to send coins to + کوئین وصول کرنے والے کا پتہ + + + Choose the address to receive coins with + کوئین وصول کرنے والے کا پتہ + + + C&hoose + چننا + AddressTableModel + + Address + پتہ + AskPassphraseDialog @@ -152,6 +168,10 @@ Copy &Address کاپی پتہ + + Address + پتہ + RecentRequestsTableModel @@ -200,6 +220,10 @@ TransactionView + + Address + پتہ + UnitDisplayStatusBarControl diff --git a/src/qt/locale/bitcoin_vi_VN.ts b/src/qt/locale/bitcoin_vi_VN.ts index c27111a52a2..8c4bececa14 100644 --- a/src/qt/locale/bitcoin_vi_VN.ts +++ b/src/qt/locale/bitcoin_vi_VN.ts @@ -41,6 +41,26 @@ &Delete &Xó&a + + Choose the address to send coins to + Chọn địa chỉ để gửi coin đến + + + Choose the address to receive coins with + Chọn địa chỉ để nhận coin + + + C&hoose + Chọn + + + Sending addresses + Địa chỉ gửi đến + + + Receiving addresses + Địa chỉ nhận + AddressTableModel diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts index 20875c23272..77d32402d3c 100644 --- a/src/qt/locale/bitcoin_zh_CN.ts +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -330,6 +330,10 @@ 点击重新开启网络活动。 + Syncing Headers (%1%)... + 同步区块头 (%1%)... + + Reindexing blocks on disk... 正在为数据块重建索引... @@ -3241,6 +3245,10 @@ 钱包 %s 在外部的数据目录 %s + Wallet debugging/testing options: + 钱包调试/测试选项: + + Wallet options: 钱包选项: diff --git a/src/qt/locale/bitcoin_zh_HK.ts b/src/qt/locale/bitcoin_zh_HK.ts index 2f3a8d1f161..44d4ac1e762 100644 --- a/src/qt/locale/bitcoin_zh_HK.ts +++ b/src/qt/locale/bitcoin_zh_HK.ts @@ -41,10 +41,70 @@ &Delete 刪除 &D - + + Choose the address to send coins to + 選擇要付錢過去的地址 + + + Choose the address to receive coins with + 選擇要收錢的地址 + + + C&hoose + 選擇 &h + + + Sending addresses + 付款地址 + + + Receiving addresses + 收款地址 + + + &Copy Address + 複製地址 &C + + + Copy &Label + 複製標記 &L + + + &Edit + 編輯 &E + + + Export Address List + 匯出地址清單 + + + Comma separated file (*.csv) + 逗號分隔檔 (*.csv) + + + Exporting Failed + 匯出失敗 + + + There was an error trying to save the address list to %1. Please try again. + 儲存地址列表到 %1 時發生錯誤。請再試一次。 + + AddressTableModel - + + Label + 標記 + + + Address + 地址 + + + (no label) + (無標記) + + AskPassphraseDialog @@ -63,7 +123,91 @@ Repeat new passphrase 重複新密碼 - + + Encrypt wallet + 加密錢包 + + + This operation needs your wallet passphrase to unlock the wallet. + 這個動作需要你的錢包密碼來將錢包解鎖。 + + + Unlock wallet + 解鎖錢包 + + + This operation needs your wallet passphrase to decrypt the wallet. + 這個動作需要你的錢包密碼來將錢包解密。 + + + Decrypt wallet + 解密錢包 + + + Change passphrase + 更改密碼 + + + Enter the old passphrase and new passphrase to the wallet. + 輸入舊密碼和新密碼至錢包。 + + + Confirm wallet encryption + 確認錢包加密 + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + 警告: 如果你將錢包加密後又忘記密碼,你就會<b>失去所有 Bitcoin 了</b>! + + + Are you sure you wish to encrypt your wallet? + 你確定要把錢包加密嗎? + + + Wallet encrypted + 錢包已加密 + + + %1 will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer. + %1 現在要關閉來完成加密程序。請記得將錢包加密不能完全防止你的 Bitcoins 經被入侵電腦的惡意程式偷取。 + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + 重要: 請改用新產生的加密錢包檔,來取代所以舊錢包檔的備份。為安全計,當你開始使用新的加密錢包檔後,舊錢包檔的備份就不能再使用了。 + + + Wallet encryption failed + 錢包加密失敗 + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + 因內部錯誤導致錢包加密失敗,你的錢包尚未加密。 + + + The supplied passphrases do not match. + 提供的密碼不一致。 + + + Wallet unlock failed + 錢包解鎖失敗 + + + The passphrase entered for the wallet decryption was incorrect. + 用來解密錢包的密碼不對。 + + + Wallet decryption failed + 錢包解密失敗 + + + Wallet passphrase was successfully changed. + 錢包密碼已成功更改。 + + + Warning: The Caps Lock key is on! + 警告: Caps Lock 已啟用! + + BanTableModel @@ -114,6 +258,14 @@ 結束應用程式 + &About %1 + 關於 %1 &A + + + Show information about %1 + 顯示 %1 的相關資訊 + + About &Qt 關於 Qt &Q @@ -126,6 +278,10 @@ 選項... &O + Modify configuration options for %1 + 修正 %1 的設定選項 + + &Encrypt Wallet... 加密錢包... &E @@ -201,9 +357,51 @@ Show or hide the main Window 顯示或隱藏主視窗 + + &File + 檔案 &F + + + &Settings + 設定 &S + + + &Help + 說明 &H + + + Request payments (generates QR codes and bitcoin: URIs) + 要求付款 (產生QR碼 bitcoin: URIs) + + + Indexing blocks on disk... + 正在為磁碟區塊建立索引... + + + Error + 錯誤 + + + Warning + 警告 + + + Information + 資訊 + + + Date: %1 + + 日期: %1 + + CoinControlDialog + + (no label) + (無標記) + EditAddressDialog @@ -216,6 +414,10 @@ Intro + + Error + 錯誤 + ModalOverlay @@ -237,28 +439,144 @@ QObject + + Enter a Bitcoin address (e.g. %1) + 輸入一個 Bitcoin 位址 (例如 %1) + + + %1 d + %1 日 + + + %1 h + %1 小時 + + + %1 m + %1 分 + + + %1 s + %1 秒 + + + None + 沒有 + + + N/A + N/A + + + %1 ms + %1 亳秒 + + + %n second(s) + %n 秒 + + + %n minute(s) + %n 分鐘 + + + %n hour(s) + %n 小時 + + + %n day(s) + %n 日 + + + %n week(s) + %n 星期 + + + %1 and %2 + %1 和 %2 + + + %n year(s) + %n 年 + QObject::QObject QRImageWidget - + + Save QR Code + 儲存 QR 碼 + + + PNG Image (*.png) + PNG 影像(*.png) + + RPCConsole + + N/A + N/A + + + &Information + 資訊 &I + + + Debug window + 除錯視窗 + + + General + 一般 + + + Received + 已接收 + + + Sent + 已送出 + + + Version + 版本 + ReceiveCoinsDialog ReceiveRequestDialog + + Address + 地址 + + + Label + 標記 + RecentRequestsTableModel + + Label + 標記 + + + (no label) + (無標記) + SendCoinsDialog - + + (no label) + (無標記) + + SendCoinsEntry @@ -279,15 +597,47 @@ TransactionDesc + + Open until %1 + 開放至 %1 + TransactionDescDialog TransactionTableModel + + Label + 標記 + + + Open until %1 + 開放至 %1 + + + (no label) + (無標記) + TransactionView + + Comma separated file (*.csv) + 逗號分隔檔 (*.csv) + + + Label + 標記 + + + Address + 地址 + + + Exporting Failed + 匯出失敗 + UnitDisplayStatusBarControl @@ -300,8 +650,28 @@ WalletView + + &Export + 匯出 &E + + + Export the data in the current tab to a file + 把目前分頁的資料匯出至檔案 + bitcoin-core - + + Information + 資訊 + + + Warning + 警告 + + + Error + 錯誤 + + \ No newline at end of file From f999c46caebca32fea16362f6d070b9466f3da83 Mon Sep 17 00:00:00 2001 From: Karl-Johan Alm Date: Tue, 24 Jan 2017 14:27:22 +0900 Subject: [PATCH 131/148] listsinceblock: optionally find and list any transactions that were undone due to reorg when requesting a non-main chain block in a new 'removed' array. --- src/rpc/client.cpp | 1 + src/wallet/rpcwallet.cpp | 80 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 7c75586d033..41794537824 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -68,6 +68,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getblocktemplate", 0, "template_request" }, { "listsinceblock", 1, "target_confirmations" }, { "listsinceblock", 2, "include_watchonly" }, + { "listsinceblock", 3, "include_removed" }, { "sendmany", 1, "amounts" }, { "sendmany", 2, "minconf" }, { "sendmany", 4, "subtractfeefrom" }, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4275a9181d6..e0d32f9bcb5 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1426,6 +1426,17 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest) entry.push_back(Pair("address", addr.ToString())); } +/** + * List transactions based on the given criteria. + * + * @param pwallet The wallet. + * @param wtx The wallet transaction. + * @param strAccount The account, if any, or "*" for all. + * @param nMinDepth The minimum confirmation depth. + * @param fLong Whether to include the JSON version of the transaction. + * @param ret The UniValue into which the result is stored. + * @param filter The "is mine" filter bool. + */ void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter) { CAmount nFee; @@ -1742,14 +1753,18 @@ UniValue listsinceblock(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 3) + if (request.fHelp || request.params.size() > 4) throw std::runtime_error( - "listsinceblock ( \"blockhash\" target_confirmations include_watchonly)\n" - "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n" + "listsinceblock ( \"blockhash\" target_confirmations include_watchonly include_removed )\n" + "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted.\n" + "If \"blockhash\" is no longer a part of the main chain, transactions from the fork point onward are included.\n" + "Additionally, if include_removed is set, transactions affecting the wallet which were removed are returned in the \"removed\" array.\n" "\nArguments:\n" "1. \"blockhash\" (string, optional) The block hash to list transactions since\n" - "2. target_confirmations: (numeric, optional) The confirmations required, must be 1 or more\n" - "3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')" + "2. target_confirmations: (numeric, optional, default=1) The confirmations required, must be 1 or more\n" + "3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n" + "4. include_removed: (bool, optional, default=true) Show transactions that were removed due to a reorg in the \"removed\" array\n" + " (not guaranteed to work on pruned nodes)\n" "\nResult:\n" "{\n" " \"transactions\": [\n" @@ -1774,7 +1789,11 @@ UniValue listsinceblock(const JSONRPCRequest& request) " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n" " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n" " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n" - " ],\n" + " ],\n" + " \"removed\": [\n" + " \n" + " Note: transactions that were readded in the active chain will appear as-is in this array, and may thus have a positive confirmation count.\n" + " ],\n" " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n" "}\n" "\nExamples:\n" @@ -1785,21 +1804,19 @@ UniValue listsinceblock(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); - const CBlockIndex *pindex = NULL; + const CBlockIndex* pindex = NULL; // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain. + const CBlockIndex* paltindex = NULL; // Block index of the specified block, even if it's in a deactivated chain. int target_confirms = 1; isminefilter filter = ISMINE_SPENDABLE; - if (!request.params[0].isNull()) - { + if (!request.params[0].isNull()) { uint256 blockId; blockId.SetHex(request.params[0].get_str()); BlockMap::iterator it = mapBlockIndex.find(blockId); - if (it != mapBlockIndex.end()) - { - pindex = it->second; - if (chainActive[pindex->nHeight] != pindex) - { + if (it != mapBlockIndex.end()) { + paltindex = pindex = it->second; + if (chainActive[pindex->nHeight] != pindex) { // the block being asked for is a part of a deactivated chain; // we don't want to depend on its perceived height in the block // chain, we want to instead use the last common ancestor @@ -1808,19 +1825,20 @@ UniValue listsinceblock(const JSONRPCRequest& request) } } - if (!request.params[1].isNull()) - { + if (!request.params[1].isNull()) { target_confirms = request.params[1].get_int(); - if (target_confirms < 1) + if (target_confirms < 1) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); + } } - if (request.params.size() > 2 && request.params[2].get_bool()) - { + if (!request.params[2].isNull() && request.params[2].get_bool()) { filter = filter | ISMINE_WATCH_ONLY; } + bool include_removed = (request.params[3].isNull() || request.params[3].get_bool()); + int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1; UniValue transactions(UniValue::VARR); @@ -1828,8 +1846,27 @@ UniValue listsinceblock(const JSONRPCRequest& request) for (const std::pair& pairWtx : pwallet->mapWallet) { CWalletTx tx = pairWtx.second; - if (depth == -1 || tx.GetDepthInMainChain() < depth) + if (depth == -1 || tx.GetDepthInMainChain() < depth) { ListTransactions(pwallet, tx, "*", 0, true, transactions, filter); + } + } + + // when a reorg'd block is requested, we also list any relevant transactions + // in the blocks of the chain that was detached + UniValue removed(UniValue::VARR); + while (include_removed && paltindex && paltindex != pindex) { + CBlock block; + if (!ReadBlockFromDisk(block, paltindex, Params().GetConsensus())) { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + } + for (const CTransactionRef& tx : block.vtx) { + if (pwallet->mapWallet.count(tx->GetHash()) > 0) { + // We want all transactions regardless of confirmation count to appear here, + // even negative confirmation ones, hence the big negative. + ListTransactions(pwallet, pwallet->mapWallet[tx->GetHash()], "*", -100000000, true, removed, filter); + } + } + paltindex = paltindex->pprev; } CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms]; @@ -1837,6 +1874,7 @@ UniValue listsinceblock(const JSONRPCRequest& request) UniValue ret(UniValue::VOBJ); ret.push_back(Pair("transactions", transactions)); + if (include_removed) ret.push_back(Pair("removed", removed)); ret.push_back(Pair("lastblock", lastblock.GetHex())); return ret; @@ -3082,7 +3120,7 @@ static const CRPCCommand commands[] = { "wallet", "listlockunspent", &listlockunspent, false, {} }, { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, {"minconf","include_empty","include_watchonly"} }, { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","include_empty","include_watchonly"} }, - { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} }, + { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly","include_removed"} }, { "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} }, { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe","query_options"} }, { "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} }, From 876e92bf54f7c416c1f4f38932b95301dfb4e3bf Mon Sep 17 00:00:00 2001 From: Karl-Johan Alm Date: Tue, 24 Jan 2017 14:28:34 +0900 Subject: [PATCH 132/148] Testing: listsinceblock should display all transactions that were affected since the given block, including transactions that were removed due to a reorg. --- test/functional/listsinceblock.py | 190 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 180 insertions(+), 10 deletions(-) diff --git a/test/functional/listsinceblock.py b/test/functional/listsinceblock.py index f3d41e573ed..ce2d556ef02 100755 --- a/test/functional/listsinceblock.py +++ b/test/functional/listsinceblock.py @@ -14,7 +14,15 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 4 - def run_test (self): + def run_test(self): + self.nodes[2].generate(101) + self.sync_all() + + self.test_reorg() + self.test_double_spend() + self.test_double_send() + + def test_reorg(self): ''' `listsinceblock` did not behave correctly when handed a block that was no longer in the main chain: @@ -43,14 +51,6 @@ def run_test (self): This test only checks that [tx0] is present. ''' - self.nodes[2].generate(101) - self.sync_all() - - assert_equal(self.nodes[0].getbalance(), 0) - assert_equal(self.nodes[1].getbalance(), 0) - assert_equal(self.nodes[2].getbalance(), 50) - assert_equal(self.nodes[3].getbalance(), 0) - # Split network into two self.split_network() @@ -73,7 +73,177 @@ def run_test (self): if tx['txid'] == senttx: found = True break - assert_equal(found, True) + assert found + + def test_double_spend(self): + ''' + This tests the case where the same UTXO is spent twice on two separate + blocks as part of a reorg. + + ab0 + / \ + aa1 [tx1] bb1 [tx2] + | | + aa2 bb2 + | | + aa3 bb3 + | + bb4 + + Problematic case: + + 1. User 1 receives BTC in tx1 from utxo1 in block aa1. + 2. User 2 receives BTC in tx2 from utxo1 (same) in block bb1 + 3. User 1 sees 2 confirmations at block aa3. + 4. Reorg into bb chain. + 5. User 1 asks `listsinceblock aa3` and does not see that tx1 is now + invalidated. + + Currently the solution to this is to detect that a reorg'd block is + asked for in listsinceblock, and to iterate back over existing blocks up + until the fork point, and to include all transactions that relate to the + node wallet. + ''' + + self.sync_all() + + # Split network into two + self.split_network() + + # share utxo between nodes[1] and nodes[2] + utxos = self.nodes[2].listunspent() + utxo = utxos[0] + privkey = self.nodes[2].dumpprivkey(utxo['address']) + self.nodes[1].importprivkey(privkey) + + # send from nodes[1] using utxo to nodes[0] + change = '%.8f' % (float(utxo['amount']) - 1.0003) + recipientDict = { + self.nodes[0].getnewaddress(): 1, + self.nodes[1].getnewaddress(): change, + } + utxoDicts = [{ + 'txid': utxo['txid'], + 'vout': utxo['vout'], + }] + txid1 = self.nodes[1].sendrawtransaction( + self.nodes[1].signrawtransaction( + self.nodes[1].createrawtransaction(utxoDicts, recipientDict))['hex']) + + # send from nodes[2] using utxo to nodes[3] + recipientDict2 = { + self.nodes[3].getnewaddress(): 1, + self.nodes[2].getnewaddress(): change, + } + self.nodes[2].sendrawtransaction( + self.nodes[2].signrawtransaction( + self.nodes[2].createrawtransaction(utxoDicts, recipientDict2))['hex']) + + # generate on both sides + lastblockhash = self.nodes[1].generate(3)[2] + self.nodes[2].generate(4) + + self.join_network() + + self.sync_all() + + # gettransaction should work for txid1 + assert self.nodes[0].gettransaction(txid1)['txid'] == txid1, "gettransaction failed to find txid1" + + # listsinceblock(lastblockhash) should now include txid1, as seen from nodes[0] + lsbres = self.nodes[0].listsinceblock(lastblockhash) + assert any(tx['txid'] == txid1 for tx in lsbres['removed']) + + # but it should not include 'removed' if include_removed=false + lsbres2 = self.nodes[0].listsinceblock(blockhash=lastblockhash, include_removed=False) + assert 'removed' not in lsbres2 + + def test_double_send(self): + ''' + This tests the case where the same transaction is submitted twice on two + separate blocks as part of a reorg. The former will vanish and the + latter will appear as the true transaction (with confirmations dropping + as a result). + + ab0 + / \ + aa1 [tx1] bb1 + | | + aa2 bb2 + | | + aa3 bb3 [tx1] + | + bb4 + + Asserted: + + 1. tx1 is listed in listsinceblock. + 2. It is included in 'removed' as it was removed, even though it is now + present in a different block. + 3. It is listed with a confirmations count of 2 (bb3, bb4), not + 3 (aa1, aa2, aa3). + ''' + + self.sync_all() + + # Split network into two + self.split_network() + + # create and sign a transaction + utxos = self.nodes[2].listunspent() + utxo = utxos[0] + change = '%.8f' % (float(utxo['amount']) - 1.0003) + recipientDict = { + self.nodes[0].getnewaddress(): 1, + self.nodes[2].getnewaddress(): change, + } + utxoDicts = [{ + 'txid': utxo['txid'], + 'vout': utxo['vout'], + }] + signedtxres = self.nodes[2].signrawtransaction( + self.nodes[2].createrawtransaction(utxoDicts, recipientDict)) + assert signedtxres['complete'] + + signedtx = signedtxres['hex'] + + # send from nodes[1]; this will end up in aa1 + txid1 = self.nodes[1].sendrawtransaction(signedtx) + + # generate bb1-bb2 on right side + self.nodes[2].generate(2) + + # send from nodes[2]; this will end up in bb3 + txid2 = self.nodes[2].sendrawtransaction(signedtx) + + assert_equal(txid1, txid2) + + # generate on both sides + lastblockhash = self.nodes[1].generate(3)[2] + self.nodes[2].generate(2) + + self.join_network() + + self.sync_all() + + # gettransaction should work for txid1 + self.nodes[0].gettransaction(txid1) + + # listsinceblock(lastblockhash) should now include txid1 in transactions + # as well as in removed + lsbres = self.nodes[0].listsinceblock(lastblockhash) + assert any(tx['txid'] == txid1 for tx in lsbres['transactions']) + assert any(tx['txid'] == txid1 for tx in lsbres['removed']) + + # find transaction and ensure confirmations is valid + for tx in lsbres['transactions']: + if tx['txid'] == txid1: + assert_equal(tx['confirmations'], 2) + + # the same check for the removed array; confirmations should STILL be 2 + for tx in lsbres['removed']: + if tx['txid'] == txid1: + assert_equal(tx['confirmations'], 2) if __name__ == '__main__': ListSinceBlockTest().main() From 44eb9d406ab131b628a3113181d6198b205d83ac Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 21 Jul 2017 15:48:30 +0200 Subject: [PATCH 133/148] [QA] Avoid running multiwallet.py twice --- test/functional/test_runner.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index c158eaa34e0..a043560ea81 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -63,7 +63,6 @@ 'segwit.py', # vv Tests less than 2m vv 'wallet.py', - 'multiwallet.py', 'wallet-accounts.py', 'p2p-segwit.py', 'wallet-dump.py', From 0be03c71bd91db25f30bcf4d45facf1e26dcfd30 Mon Sep 17 00:00:00 2001 From: Brian McMichael Date: Fri, 21 Jul 2017 17:20:14 -0400 Subject: [PATCH 134/148] Qt: Use _putenv_s instead of setenv on Windows builds --- src/qt/test/test_main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index cae18f41a5c..1b28a285f1e 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -59,7 +59,11 @@ int main(int argc, char *argv[]) // Prefer the "minimal" platform for the test instead of the normal default // platform ("xcb", "windows", or "cocoa") so tests can't unintentially // interfere with any background GUIs and don't require extra resources. - setenv("QT_QPA_PLATFORM", "minimal", 0); + #if defined(WIN32) + _putenv_s("QT_QPA_PLATFORM", "minimal"); + #else + setenv("QT_QPA_PLATFORM", "minimal", 0); + #endif // Don't remove this, it's needed to access // QApplication:: and QCoreApplication:: in the tests From 05e023f2ec8d8dc37bb0f20db1c606f06aea69f5 Mon Sep 17 00:00:00 2001 From: Dag Robole Date: Tue, 18 Jul 2017 16:24:46 +0200 Subject: [PATCH 135/148] Move CloseSocket out of SetSocketNonBlocking and pass SOCKET by const reference in SetSocket* functions --- src/compat.h | 2 +- src/net.cpp | 1 + src/netbase.cpp | 12 ++++++------ src/netbase.h | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/compat.h b/src/compat.h index e76ab94c82b..e022659c018 100644 --- a/src/compat.h +++ b/src/compat.h @@ -76,7 +76,7 @@ typedef unsigned int SOCKET; size_t strnlen( const char *start, size_t max_len); #endif // HAVE_DECL_STRNLEN -bool static inline IsSelectableSocket(SOCKET s) { +bool static inline IsSelectableSocket(const SOCKET& s) { #ifdef WIN32 return true; #else diff --git a/src/net.cpp b/src/net.cpp index 5bf3af7ea37..0994af30219 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2076,6 +2076,7 @@ bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, b // Set to non-blocking, incoming connections will also inherit this if (!SetSocketNonBlocking(hListenSocket, true)) { + CloseSocket(hListenSocket); strError = strprintf("BindListenPort: Setting listening socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); LogPrintf("%s\n", strError); return false; diff --git a/src/netbase.cpp b/src/netbase.cpp index 1f668a5d4c9..8952468ecd3 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -203,7 +203,7 @@ enum class IntrRecvError { * * @note This function requires that hSocket is in non-blocking mode. */ -static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket) +static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, const SOCKET& hSocket) { int64_t curTime = GetTimeMillis(); int64_t endTime = curTime + timeout; @@ -424,8 +424,10 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe SetSocketNoDelay(hSocket); // Set to non-blocking - if (!SetSocketNonBlocking(hSocket, true)) + if (!SetSocketNonBlocking(hSocket, true)) { + CloseSocket(hSocket); return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); + } if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { @@ -682,7 +684,7 @@ bool CloseSocket(SOCKET& hSocket) return ret != SOCKET_ERROR; } -bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking) +bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking) { if (fNonBlocking) { #ifdef WIN32 @@ -692,7 +694,6 @@ bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking) int fFlags = fcntl(hSocket, F_GETFL, 0); if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) { #endif - CloseSocket(hSocket); return false; } } else { @@ -703,7 +704,6 @@ bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking) int fFlags = fcntl(hSocket, F_GETFL, 0); if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) { #endif - CloseSocket(hSocket); return false; } } @@ -711,7 +711,7 @@ bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking) return true; } -bool SetSocketNoDelay(SOCKET& hSocket) +bool SetSocketNoDelay(const SOCKET& hSocket) { int set = 1; int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int)); diff --git a/src/netbase.h b/src/netbase.h index fd4b34c8f1e..941da31f9ce 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -57,9 +57,9 @@ std::string NetworkErrorString(int err); /** Close socket and set hSocket to INVALID_SOCKET */ bool CloseSocket(SOCKET& hSocket); /** Disable or enable blocking-mode for a socket */ -bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking); +bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking); /** Set the TCP_NODELAY flag on a socket */ -bool SetSocketNoDelay(SOCKET& hSocket); +bool SetSocketNoDelay(const SOCKET& hSocket); /** * Convert milliseconds to a struct timeval for e.g. select. */ From f228b8e16308ef33792f54360f0f2c2f8310b158 Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Thu, 1 Jun 2017 19:13:51 +0200 Subject: [PATCH 136/148] remove some unused functions Identified with `cppcheck --enable=unusedFunction .`. - GetSendBufferSize()'s last use removed in 991955ee81034dc3fbc1c2a8e60c04fc9e0b538c - SetPort()'s last use removed in 7e195e8459ad741368db6bb574981fccb1707268 - GetfLargeWorkInvalidChainFound() was introduced in e3ba0ef95636290a3bb597ddd25d13ea13b034aa and never used --- src/net.cpp | 1 - src/net.h | 2 -- src/netaddress.cpp | 5 ----- src/netaddress.h | 1 - src/warnings.cpp | 6 ------ src/warnings.h | 1 - 6 files changed, 16 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 5bf3af7ea37..b4b2de09f60 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2691,7 +2691,6 @@ 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, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string& addrNameIn, bool fInboundIn) : nTimeConnected(GetSystemTimeInSeconds()), diff --git a/src/net.h b/src/net.h index b9a11c62f21..1c9413c1dd5 100644 --- a/src/net.h +++ b/src/net.h @@ -242,8 +242,6 @@ class CConnman bool DisconnectNode(const std::string& node); bool DisconnectNode(NodeId id); - unsigned int GetSendBufferSize() const; - ServiceFlags GetLocalServices() const; //!set the max outbound target in bytes diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 110e778fbd8..f31b2fc49b6 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -598,11 +598,6 @@ std::string CService::ToString() const return ToStringIPPort(); } -void CService::SetPort(unsigned short portIn) -{ - port = portIn; -} - CSubNet::CSubNet(): valid(false) { diff --git a/src/netaddress.h b/src/netaddress.h index 80716600d17..61afe0f1fe6 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -148,7 +148,6 @@ class CService : public CNetAddr CService(const struct in_addr& ipv4Addr, unsigned short port); CService(const struct sockaddr_in& addr); void Init(); - void SetPort(unsigned short portIn); unsigned short GetPort() const; bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const; bool SetSockAddr(const struct sockaddr* paddr); diff --git a/src/warnings.cpp b/src/warnings.cpp index 2c1b1b0e12d..75ccfeb116e 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -37,12 +37,6 @@ void SetfLargeWorkInvalidChainFound(bool flag) fLargeWorkInvalidChainFound = flag; } -bool GetfLargeWorkInvalidChainFound() -{ - LOCK(cs_warnings); - return fLargeWorkInvalidChainFound; -} - std::string GetWarnings(const std::string& strFor) { std::string strStatusBar; diff --git a/src/warnings.h b/src/warnings.h index fd0ca539423..e8e982c0e30 100644 --- a/src/warnings.h +++ b/src/warnings.h @@ -13,7 +13,6 @@ void SetMiscWarning(const std::string& strWarning); void SetfLargeWorkForkFound(bool flag); bool GetfLargeWorkForkFound(); void SetfLargeWorkInvalidChainFound(bool flag); -bool GetfLargeWorkInvalidChainFound(); /** Format a string that describes several potential problems detected by the core. * strFor can have three values: * - "rpc": get critical warnings, which should put the client in safe mode if non-empty From a56f8b0be3700d608a5634af8c862910f4be2191 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Sun, 23 Jul 2017 14:51:22 -0400 Subject: [PATCH 137/148] Add missing lock in CScheduler::AreThreadsServicingQueue() Not an actual bug as this is only used in asserts right now, but nice to not have a missing lock. --- src/scheduler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 36a6d5110d9..1d3fb1f6ea8 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -141,6 +141,7 @@ size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first, } bool CScheduler::AreThreadsServicingQueue() const { + boost::unique_lock lock(newTaskMutex); return nThreadsServicingQueue; } From 72f00608d0a130a1488dc49df1073abe01d49519 Mon Sep 17 00:00:00 2001 From: Dag Robole Date: Fri, 21 Jul 2017 12:27:23 +0200 Subject: [PATCH 138/148] Replace traditional for with ranged for in primitives --- src/primitives/block.cpp | 5 ++--- src/primitives/transaction.cpp | 19 +++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 24be67c84fb..3774ac3e4b5 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -25,9 +25,8 @@ std::string CBlock::ToString() const hashMerkleRoot.ToString(), nTime, nBits, nNonce, vtx.size()); - for (unsigned int i = 0; i < vtx.size(); i++) - { - s << " " << vtx[i]->ToString() << "\n"; + for (const auto& tx : vtx) { + s << " " << tx->ToString() << "\n"; } return s.str(); } diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index f87934d5868..9b6a814e1f3 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -83,10 +83,9 @@ CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), vi CAmount CTransaction::GetValueOut() const { CAmount nValueOut = 0; - for (std::vector::const_iterator it(vout.begin()); it != vout.end(); ++it) - { - nValueOut += it->nValue; - if (!MoneyRange(it->nValue) || !MoneyRange(nValueOut)) + for (const auto& tx_out : vout) { + nValueOut += tx_out.nValue; + if (!MoneyRange(tx_out.nValue) || !MoneyRange(nValueOut)) throw std::runtime_error(std::string(__func__) + ": value out of range"); } return nValueOut; @@ -106,11 +105,11 @@ std::string CTransaction::ToString() const vin.size(), vout.size(), nLockTime); - for (unsigned int i = 0; i < vin.size(); i++) - str += " " + vin[i].ToString() + "\n"; - for (unsigned int i = 0; i < vin.size(); i++) - str += " " + vin[i].scriptWitness.ToString() + "\n"; - for (unsigned int i = 0; i < vout.size(); i++) - str += " " + vout[i].ToString() + "\n"; + for (const auto& tx_in : vin) + str += " " + tx_in.ToString() + "\n"; + for (const auto& tx_in : vin) + str += " " + tx_in.scriptWitness.ToString() + "\n"; + for (const auto& tx_out : vout) + str += " " + tx_out.ToString() + "\n"; return str; } From 4a7a4ff1f1f327d68fafc0d413f16ad0fdf656af Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Mon, 24 Jul 2017 08:45:58 +0200 Subject: [PATCH 139/148] developer-notes: add reference to snake_case and PascalCase CamelCase is ambiguous as it refers to both lowerCamelCase and UpperCamelCase, whereas PascalCase is only UpperCamelCase. --- doc/developer-notes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 81bdcc9fdb9..458e7bcbff8 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -28,12 +28,12 @@ tool to clean up patches automatically before submission. required when doing so would need changes to significant pieces of existing code. - Variable and namespace names are all lowercase, and may use `_` to - separate words. + separate words (snake_case). - Class member variables have a `m_` prefix. - Global variables have a `g_` prefix. - Constant names are all uppercase, and use `_` to separate words. - - Class names, function names and method names are CamelCase. Do not prefix - class names with `C`. + - Class names, function names and method names are UpperCamelCase + (PascalCase). Do not prefix class names with `C`. - **Miscellaneous** - `++i` is preferred over `i++`. From 88af2276876868fc5b17a67ecaa86b219969d4c6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 25 Jul 2017 14:43:26 +0200 Subject: [PATCH 140/148] test: Make sure wallet.backup is created in temp path This assures that we don't overwrite a random file called `wallet.backup` that happens to be in the current directory. It also assures that the temporary file will be cleaned up. Noticed by Evan Klitzke, came up in discussion here: https://github.com/bitcoin/bitcoin/pull/10880#discussion_r128460722 --- src/wallet/test/wallet_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 8176a0017c9..4a2cc9a1399 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -469,7 +469,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); - request.params.push_back("wallet.backup"); + request.params.push_back((pathTemp / "wallet.backup").string()); vpwallets.insert(vpwallets.begin(), &wallet); ::dumpwallet(request); } @@ -481,7 +481,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); - request.params.push_back("wallet.backup"); + request.params.push_back((pathTemp / "wallet.backup").string()); vpwallets[0] = &wallet; ::importwallet(request); From 9f8a46f077e2f8b6829faa10212c6707e2402f40 Mon Sep 17 00:00:00 2001 From: Ryan Havar Date: Tue, 25 Jul 2017 19:25:07 +0000 Subject: [PATCH 141/148] Properly document target_confirmations in listsinceblock --- src/wallet/rpcwallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index fb4d30d4934..9371f734742 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1761,7 +1761,7 @@ UniValue listsinceblock(const JSONRPCRequest& request) "Additionally, if include_removed is set, transactions affecting the wallet which were removed are returned in the \"removed\" array.\n" "\nArguments:\n" "1. \"blockhash\" (string, optional) The block hash to list transactions since\n" - "2. target_confirmations: (numeric, optional, default=1) The confirmations required, must be 1 or more\n" + "2. target_confirmations: (numeric, optional, default=1) Return the nth block hash from the main chain. e.g. 1 would mean the best block hash. Note: this is not used as a filter, but only affects [lastblock] in the return value\n" "3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n" "4. include_removed: (bool, optional, default=true) Show transactions that were removed due to a reorg in the \"removed\" array\n" " (not guaranteed to work on pruned nodes)\n" @@ -1794,7 +1794,7 @@ UniValue listsinceblock(const JSONRPCRequest& request) " \n" " Note: transactions that were readded in the active chain will appear as-is in this array, and may thus have a positive confirmation count.\n" " ],\n" - " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n" + " \"lastblock\": \"lastblockhash\" (string) The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones\n" "}\n" "\nExamples:\n" + HelpExampleCli("listsinceblock", "") From 60f9778abfea615beac384a08e6a13ebec65275b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 25 Jul 2017 21:39:39 +0200 Subject: [PATCH 142/148] Revert "[tests] Allow tests to pass when stderr is non-empty" This reverts commit d64ac3f4aab13a1a4e8d320b52e7a2b934e011b2 after further discussion. Tree-SHA512: db1e4ff5b17bcd6fd000a3d21aa74f6b7e4c194e0663c1896a100612671910a7cdadd896b59642420ea016598895b54a8468914847ebefef105a3c47c311d4b2 --- test/functional/test_runner.py | 51 ++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 92c95b1b8f2..a043560ea81 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -27,7 +27,8 @@ import re import logging -# Formatting. +# Formatting. Default colors to empty strings. +BOLD, BLUE, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "") try: # Make sure python thinks it can write unicode to its stdout "\u2713".encode("utf_8").decode(sys.stdout.encoding) @@ -39,28 +40,17 @@ CROSS = "x " CIRCLE = "o " -# Default colors to empty strings. -BOLD, BLUE, RED, GREY, MAGENTA = [("", "")] * 5 if os.name == 'posix': # primitive formatting on supported # terminal via ANSI escape sequences: BOLD = ('\033[0m', '\033[1m') - GREY = ('\033[0m', '\033[1;30m') - RED = ('\033[0m', '\033[0;31m') BLUE = ('\033[0m', '\033[0;34m') - MAGENTA = ('\033[0m', '\033[0;35m') + RED = ('\033[0m', '\033[0;31m') + GREY = ('\033[0m', '\033[1;30m') TEST_EXIT_PASSED = 0 TEST_EXIT_SKIPPED = 77 -STATUS_PASSED = "Passed" -STATUS_PASSED_WITH_WARNINGS = "Passed with warnings" -STATUS_SKIPPED = "Skipped" -STATUS_FAILED = "Failed" -STATUSES = [STATUS_PASSED, STATUS_PASSED_WITH_WARNINGS, STATUS_SKIPPED, STATUS_FAILED] - -STATUS_MAX_LEN = max([len(st) for st in STATUSES]) - BASE_SCRIPTS= [ # Scripts that are run by the travis build process. # Longest test should go first, to favor running tests in parallel @@ -317,11 +307,9 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove test_result, stdout, stderr = job_queue.get_next() test_results.append(test_result) - if test_result.status == STATUS_PASSED: + if test_result.status == "Passed": logging.debug("\n%s%s%s passed, Duration: %s s" % (BOLD[1], test_result.name, BOLD[0], test_result.time)) - elif test_result.status == STATUS_PASSED_WITH_WARNINGS: - logging.debug("\n%s%s%s passed with warnings, Duration: %s s" % (BOLD[1], test_result.name, BOLD[0], test_result.time)) - elif test_result.status == STATUS_SKIPPED: + elif test_result.status == "Skipped": logging.debug("\n%s%s%s skipped" % (BOLD[1], test_result.name, BOLD[0])) else: print("\n%s%s%s failed, Duration: %s s\n" % (BOLD[1], test_result.name, BOLD[0], test_result.time)) @@ -345,7 +333,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove sys.exit(not all_passed) def print_results(test_results, max_len_name, runtime): - results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), " STATUS".ljust(STATUS_MAX_LEN + 2), "DURATION") + BOLD[0] + results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] test_results.sort(key=lambda result: result.name.lower()) all_passed = True @@ -358,7 +346,7 @@ def print_results(test_results, max_len_name, runtime): results += str(test_result) status = TICK + "Passed" if all_passed else CROSS + "Failed" - results += BOLD[1] + "\n%s | %s | %s s (accumulated) \n" % ("ALL".ljust(max_len_name), status.ljust(STATUS_MAX_LEN + 2), time_sum) + BOLD[0] + results += BOLD[1] + "\n%s | %s | %s s (accumulated) \n" % ("ALL".ljust(max_len_name), status.ljust(9), time_sum) + BOLD[0] results += "Runtime: %s s\n" % (runtime) print(results) @@ -416,13 +404,11 @@ def get_next(self): [stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)] log_out.close(), log_err.close() if proc.returncode == TEST_EXIT_PASSED and stderr == "": - status = STATUS_PASSED - elif proc.returncode == TEST_EXIT_PASSED: - status = STATUS_PASSED_WITH_WARNINGS + status = "Passed" elif proc.returncode == TEST_EXIT_SKIPPED: - status = STATUS_SKIPPED + status = "Skipped" else: - status = STATUS_FAILED + status = "Failed" self.num_running -= 1 self.jobs.remove(j) @@ -437,20 +423,17 @@ def __init__(self, name, status, time): self.padding = 0 def __repr__(self): - if self.status == STATUS_PASSED: + if self.status == "Passed": color = BLUE glyph = TICK - if self.status == STATUS_PASSED_WITH_WARNINGS: - color = MAGENTA - glyph = TICK - elif self.status == STATUS_SKIPPED: - color = GREY - glyph = CIRCLE - elif self.status == STATUS_FAILED: + elif self.status == "Failed": color = RED glyph = CROSS + elif self.status == "Skipped": + color = GREY + glyph = CIRCLE - return color[1] + "%s | %s%s | %s s\n" % (self.name.ljust(self.padding), glyph, self.status.ljust(STATUS_MAX_LEN), self.time) + color[0] + return color[1] + "%s | %s%s | %s s\n" % (self.name.ljust(self.padding), glyph, self.status.ljust(7), self.time) + color[0] @property def was_successful(self): From 065039da1f83d0fe5b74d3b33be6d48e19d78d7f Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sat, 22 Jul 2017 23:52:57 +0200 Subject: [PATCH 143/148] =?UTF-8?q?[tests]=20Fix=20incorrect=20memory=5Fcl?= =?UTF-8?q?eanse(=E2=80=A6)=20call=20in=20crypto=5Ftests.cpp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chKey and chIV are pointers, not arrays :-) Probably the result of copy-pasting of old code which was operating on arrays instead of pointers. --- src/wallet/test/crypto_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp index 524a72c303f..744063624c1 100644 --- a/src/wallet/test/crypto_tests.cpp +++ b/src/wallet/test/crypto_tests.cpp @@ -26,8 +26,8 @@ bool OldSetKeyFromPassphrase(const SecureString& strKeyData, const std::vector Date: Mon, 17 Jul 2017 05:42:30 -0400 Subject: [PATCH 144/148] Fix misleading "Method not found" multiwallet errors Raise RPC_WALLET_NOT_SPECIFIED instead of RPC_METHOD_NOT_FOUND when a required wallet filename was not specified in an RPC call. Also raise more specific RPC_WALLET_NOT_FOUND error instead of RPC_INVALID_PARAMETER in case an invalid wallet was specified, for consistency. --- src/bitcoin-cli.cpp | 4 ++++ src/rpc/protocol.h | 2 ++ src/wallet/rpcwallet.cpp | 17 +++++++++-------- test/functional/multiwallet.py | 5 ++++- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 445b9d8e89a..c1a7c927e30 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -337,6 +337,10 @@ int CommandLineRPC(int argc, char *argv[]) if (errMsg.isStr()) strPrint += "error message:\n"+errMsg.get_str(); + + if (errCode.isNum() && errCode.get_int() == RPC_WALLET_NOT_SPECIFIED) { + strPrint += "\nTry adding \"-rpcwallet=\" option to bitcoin-cli command line."; + } } } else { // Result diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 70f7092cfeb..4bd4702d624 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -82,6 +82,8 @@ enum RPCErrorCode RPC_WALLET_WRONG_ENC_STATE = -15, //!< Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) RPC_WALLET_ENCRYPTION_FAILED = -16, //!< Failed to encrypt the wallet RPC_WALLET_ALREADY_UNLOCKED = -17, //!< Wallet is already unlocked + RPC_WALLET_NOT_FOUND = -18, //!< Invalid wallet specified + RPC_WALLET_NOT_SPECIFIED = -19, //!< No wallet specified (error when there are multiple wallets loaded) }; UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e956adaf894..64dc70f2a46 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -43,7 +43,7 @@ CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request) return pwallet; } } - throw JSONRPCError(RPC_INVALID_PARAMETER, "Requested wallet does not exist or is not loaded"); + throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded"); } return ::vpwallets.size() == 1 || (request.fHelp && ::vpwallets.size() > 0) ? ::vpwallets[0] : nullptr; } @@ -57,13 +57,14 @@ std::string HelpRequiringPassphrase(CWallet * const pwallet) bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException) { - if (!pwallet) { - if (!avoidException) - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); - else - return false; - } - return true; + if (pwallet) return true; + if (avoidException) return false; + if (::vpwallets.empty()) { + // Wallet RPC methods are disabled if no wallets are loaded. + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); + } + throw JSONRPCError(RPC_WALLET_NOT_SPECIFIED, + "Wallet file not specified (must request wallet RPC through /wallet/ uri-path)."); } void EnsureWalletIsUnlocked(CWallet * const pwallet) diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py index f0929a8e28f..173f06cf5dc 100755 --- a/test/functional/multiwallet.py +++ b/test/functional/multiwallet.py @@ -21,8 +21,11 @@ def run_test(self): w1 = self.nodes[0] / "wallet/w1" w1.generate(1) + # accessing invalid wallet fails + assert_raises_jsonrpc(-18, "Requested wallet does not exist or is not loaded", (self.nodes[0] / "wallet/bad").getwalletinfo) + # accessing wallet RPC without using wallet endpoint fails - assert_raises_jsonrpc(-32601, "Method not found", self.nodes[0].getwalletinfo) + assert_raises_jsonrpc(-19, "Wallet file not specified", self.nodes[0].getwalletinfo) # check w1 wallet balance w1_info = w1.getwalletinfo() From df389bca2048f5814387987463fe3298766bc6b6 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Wed, 26 Jul 2017 09:35:17 -0400 Subject: [PATCH 145/148] Change wallet method disabled error text Not strictly backwards compatible because the error is not new in this release. --- src/wallet/rpcwallet.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 64dc70f2a46..14560860cb4 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -60,8 +60,13 @@ bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException) if (pwallet) return true; if (avoidException) return false; if (::vpwallets.empty()) { - // Wallet RPC methods are disabled if no wallets are loaded. - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); + // Note: It isn't currently possible to trigger this error because + // wallet RPC methods aren't registered unless a wallet is loaded. But + // this error is being kept as a precaution, because it's possible in + // the future that wallet RPC methods might get or remain registered + // when no wallets are loaded. + throw JSONRPCError( + RPC_METHOD_NOT_FOUND, "Method not found (wallet method is disabled because no wallet is loaded)"); } throw JSONRPCError(RPC_WALLET_NOT_SPECIFIED, "Wallet file not specified (must request wallet RPC through /wallet/ uri-path)."); From 3ef77a0c1288df524fdf0c90ca70c986f473b787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 27 Jul 2017 00:56:30 +0100 Subject: [PATCH 146/148] Reject duplicate wallet filenames --- src/wallet/wallet.cpp | 13 ++++++++++++- test/functional/multiwallet.py | 7 +++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3e9c531f007..ccf5353eb7a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -468,13 +468,24 @@ bool CWallet::Verify() uiInterface.InitMessage(_("Verifying wallet(s)...")); + // Keep track of each wallet absolute path to detect duplicates. + std::set wallet_paths; + for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { if (boost::filesystem::path(walletFile).filename() != walletFile) { return InitError(_("-wallet parameter must only specify a filename (not a path)")); - } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { + } + + if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { return InitError(_("Invalid characters in -wallet filename")); } + fs::path wallet_path = fs::absolute(walletFile, GetDataDir()); + + if (!wallet_paths.insert(wallet_path).second) { + return InitError(_("Duplicate -wallet filename")); + } + std::string strError; if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) { return InitError(strError); diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py index 173f06cf5dc..5844d991397 100755 --- a/test/functional/multiwallet.py +++ b/test/functional/multiwallet.py @@ -18,6 +18,13 @@ def __init__(self): self.extra_args = [['-wallet=w1', '-wallet=w2', '-wallet=w3']] def run_test(self): + self.stop_node(0) + + # should not initialize if there are duplicate wallets + self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w1', '-wallet=w1'], 'Duplicate -wallet filename') + + self.nodes[0] = self.start_node(0, self.options.tmpdir, self.extra_args[0]) + w1 = self.nodes[0] / "wallet/w1" w1.generate(1) From a6da027d83e48f05c933149ff89c9b9ad5ced915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 27 Jul 2017 00:57:02 +0100 Subject: [PATCH 147/148] Reject invalid wallet files --- src/wallet/wallet.cpp | 4 ++++ test/functional/multiwallet.py | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ccf5353eb7a..ef1d764146c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -482,6 +482,10 @@ bool CWallet::Verify() fs::path wallet_path = fs::absolute(walletFile, GetDataDir()); + if (fs::exists(wallet_path) && (!fs::is_regular_file(wallet_path) || fs::is_symlink(wallet_path))) { + return InitError(_("Invalid -wallet file")); + } + if (!wallet_paths.insert(wallet_path).second) { return InitError(_("Duplicate -wallet filename")); } diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py index 5844d991397..c60d345acb5 100755 --- a/test/functional/multiwallet.py +++ b/test/functional/multiwallet.py @@ -6,6 +6,8 @@ Verify that a bitcoind node can load multiple wallet files """ +import os + from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_raises_jsonrpc @@ -23,6 +25,14 @@ def run_test(self): # should not initialize if there are duplicate wallets self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w1', '-wallet=w1'], 'Duplicate -wallet filename') + # should not initialize if wallet file is a directory + os.mkdir(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w11')) + self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w11'], 'Invalid -wallet file') + + # should not initialize if wallet file is a symlink + os.symlink(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w1'), os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w12')) + self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w12'], 'Invalid -wallet file') + self.nodes[0] = self.start_node(0, self.options.tmpdir, self.extra_args[0]) w1 = self.nodes[0] / "wallet/w1" From d84e78ec393049cb067170a4905a1679ff794368 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Fri, 28 Jul 2017 06:03:03 -0400 Subject: [PATCH 148/148] [wallet] Specify wallet name in wallet loading errors --- src/wallet/wallet.cpp | 8 ++++---- test/functional/multiwallet.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ef1d764146c..36c295e5d85 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -473,21 +473,21 @@ bool CWallet::Verify() for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { if (boost::filesystem::path(walletFile).filename() != walletFile) { - return InitError(_("-wallet parameter must only specify a filename (not a path)")); + return InitError(strprintf(_("Error loading wallet %s. -wallet parameter must only specify a filename (not a path)."), walletFile)); } if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { - return InitError(_("Invalid characters in -wallet filename")); + return InitError(strprintf(_("Error loading wallet %s. Invalid characters in -wallet filename."), walletFile)); } fs::path wallet_path = fs::absolute(walletFile, GetDataDir()); if (fs::exists(wallet_path) && (!fs::is_regular_file(wallet_path) || fs::is_symlink(wallet_path))) { - return InitError(_("Invalid -wallet file")); + return InitError(strprintf(_("Error loading wallet %s. -wallet filename must be a regular file."), walletFile)); } if (!wallet_paths.insert(wallet_path).second) { - return InitError(_("Duplicate -wallet filename")); + return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), walletFile)); } std::string strError; diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py index c60d345acb5..5679f405037 100755 --- a/test/functional/multiwallet.py +++ b/test/functional/multiwallet.py @@ -23,15 +23,15 @@ def run_test(self): self.stop_node(0) # should not initialize if there are duplicate wallets - self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w1', '-wallet=w1'], 'Duplicate -wallet filename') + self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w1', '-wallet=w1'], 'Error loading wallet w1. Duplicate -wallet filename specified.') # should not initialize if wallet file is a directory os.mkdir(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w11')) - self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w11'], 'Invalid -wallet file') + self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w11'], 'Error loading wallet w11. -wallet filename must be a regular file.') # should not initialize if wallet file is a symlink os.symlink(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w1'), os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w12')) - self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w12'], 'Invalid -wallet file') + self.assert_start_raises_init_error(0, self.options.tmpdir, ['-wallet=w12'], 'Error loading wallet w12. -wallet filename must be a regular file.') self.nodes[0] = self.start_node(0, self.options.tmpdir, self.extra_args[0])