aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac9
-rw-r--r--contrib/bitrpc/bitrpc.py12
-rw-r--r--doc/release-process.md37
-rwxr-xr-xqa/rpc-tests/receivedby.py225
-rw-r--r--qa/rpc-tests/util.py4
-rw-r--r--src/Makefile.am23
-rw-r--r--src/Makefile.qt.include2
-rw-r--r--src/Makefile.qttest.include2
-rw-r--r--src/Makefile.test.include4
-rw-r--r--src/bloom.cpp3
-rw-r--r--src/bloom.h2
-rw-r--r--src/chainparams.cpp5
-rw-r--r--src/chainparams.h3
-rw-r--r--src/clientversion.h2
-rw-r--r--src/compat/glibc_compat.cpp19
-rw-r--r--src/compat/glibc_sanity.cpp67
-rw-r--r--src/compat/glibcxx_compat.cpp50
-rw-r--r--src/compat/glibcxx_sanity.cpp65
-rw-r--r--src/compat/sanity.h11
-rw-r--r--src/config/.empty0
-rw-r--r--src/core.cpp25
-rw-r--r--src/core.h99
-rw-r--r--src/crypto/common.h93
-rw-r--r--src/crypto/ripemd160.cpp204
-rw-r--r--src/crypto/ripemd160.h27
-rw-r--r--src/crypto/sha1.cpp192
-rw-r--r--src/crypto/sha1.h27
-rw-r--r--src/crypto/sha2.cpp398
-rw-r--r--src/crypto/sha2.h60
-rw-r--r--src/hash.cpp41
-rw-r--r--src/hash.h189
-rw-r--r--src/init.cpp23
-rw-r--r--src/key.cpp19
-rw-r--r--src/main.cpp103
-rw-r--r--src/main.h8
-rw-r--r--src/miner.cpp183
-rw-r--r--src/miner.h4
-rw-r--r--src/net.cpp24
-rw-r--r--src/net.h6
-rw-r--r--src/netbase.h2
-rw-r--r--src/protocol.h8
-rw-r--r--src/qt/addressbookpage.cpp2
-rw-r--r--src/qt/bitcoin.cpp2
-rw-r--r--src/qt/bitcoingui.h2
-rw-r--r--src/qt/coincontroldialog.cpp21
-rw-r--r--src/qt/forms/rpcconsole.ui4
-rw-r--r--src/qt/notificator.h2
-rw-r--r--src/qt/optionsdialog.cpp2
-rw-r--r--src/qt/optionsmodel.cpp2
-rw-r--r--src/qt/receiverequestdialog.cpp2
-rw-r--r--src/qt/rpcconsole.cpp3
-rw-r--r--src/qt/rpcconsole.h1
-rw-r--r--src/qt/test/test_main.cpp2
-rw-r--r--src/rpcblockchain.cpp2
-rw-r--r--src/rpcmining.cpp163
-rw-r--r--src/rpcmisc.cpp2
-rw-r--r--src/rpcnet.cpp6
-rw-r--r--src/rpcrawtransaction.cpp16
-rw-r--r--src/rpcserver.cpp18
-rw-r--r--src/rpcserver.h1
-rw-r--r--src/script.cpp25
-rw-r--r--src/script.h13
-rw-r--r--src/serialize.h34
-rw-r--r--src/test/DoS_tests.cpp12
-rw-r--r--src/test/accounting_tests.cpp12
-rw-r--r--src/test/bloom_tests.cpp26
-rw-r--r--src/test/crypto_tests.cpp203
-rw-r--r--src/test/hmac_tests.cpp129
-rw-r--r--src/test/miner_tests.cpp40
-rw-r--r--src/test/multisig_tests.cpp8
-rw-r--r--src/test/pmt_tests.cpp4
-rw-r--r--src/test/script_P2SH_tests.cpp18
-rw-r--r--src/test/script_tests.cpp12
-rw-r--r--src/test/sighash_tests.cpp6
-rw-r--r--src/test/transaction_tests.cpp14
-rw-r--r--src/test/wallet_tests.cpp10
-rw-r--r--src/util.h2
-rw-r--r--src/wallet.cpp35
-rw-r--r--src/wallet.h4
79 files changed, 2212 insertions, 928 deletions
diff --git a/configure.ac b/configure.ac
index d8521ad3ad..811ef1dd80 100644
--- a/configure.ac
+++ b/configure.ac
@@ -111,7 +111,7 @@ AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[spec
AC_CONFIG_SRCDIR([src])
-AC_CONFIG_HEADERS([src/bitcoin-config.h])
+AC_CONFIG_HEADERS([src/config/bitcoin-config.h])
dnl Checks for programs.
AC_PROG_CXX
@@ -368,7 +368,12 @@ if test x$TARGET_OS = xdarwin; then
AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"])
fi
-AC_CHECK_HEADERS([stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h])
+AC_CHECK_HEADERS([endian.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h])
+
+AC_CHECK_DECLS([le32toh, le64toh, htole32, htole64, be32toh, be64toh, htobe32, htobe64],,,
+ [#if HAVE_ENDIAN_H
+ #include <endian.h>
+ #endif])
dnl Check for MSG_NOSIGNAL
AC_MSG_CHECKING(for MSG_NOSIGNAL)
diff --git a/contrib/bitrpc/bitrpc.py b/contrib/bitrpc/bitrpc.py
index a84d7e34dd..02577b1b6a 100644
--- a/contrib/bitrpc/bitrpc.py
+++ b/contrib/bitrpc/bitrpc.py
@@ -22,6 +22,18 @@ if cmd == "backupwallet":
print access.backupwallet(path)
except:
print "\n---An error occurred---\n"
+
+elif cmd == "encryptwallet":
+ try:
+ pwd = getpass.getpass(prompt="Enter passphrase: ")
+ pwd2 = getpass.getpass(prompt="Repeat passphrase: ")
+ if pwd == pwd2:
+ access.encryptwallet(pwd)
+ print "\n---Wallet encrypted. Server stopping, restart to run with encrypted wallet---\n"
+ else:
+ print "\n---Passphrases do not match---\n"
+ except:
+ print "\n---An error occurred---\n"
elif cmd == "getaccount":
try:
diff --git a/doc/release-process.md b/doc/release-process.md
index 5b96e53753..affe6ed13a 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -50,8 +50,7 @@ Release Process
wget 'ftp://ftp.simplesystems.org/pub/png/src/history/libpng16/libpng-1.6.8.tar.gz'
wget 'https://fukuchi.org/works/qrencode/qrencode-3.4.3.tar.bz2'
wget 'https://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2'
- wget 'https://svn.boost.org/trac/boost/raw-attachment/ticket/7262/boost-mingw.patch' -O \
- boost-mingw-gas-cross-compile-2013-03-03.patch
+ wget 'https://svn.boost.org/trac/boost/raw-attachment/ticket/7262/boost-mingw.patch' -O boost-mingw-gas-cross-compile-2013-03-03.patch
wget 'https://download.qt-project.org/official_releases/qt/5.2/5.2.0/single/qt-everywhere-opensource-src-5.2.0.tar.gz'
wget 'https://download.qt-project.org/archive/qt/4.6/qt-everywhere-opensource-src-4.6.4.tar.gz'
wget 'https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.bz2'
@@ -61,10 +60,8 @@ Release Process
wget 'http://www.opensource.apple.com/tarballs/ld64/ld64-127.2.tar.gz'
wget 'http://cdrkit.org/releases/cdrkit-1.1.11.tar.gz'
wget 'https://github.com/theuni/libdmg-hfsplus/archive/libdmg-hfsplus-v0.1.tar.gz'
- wget 'http://llvm.org/releases/3.2/clang+llvm-3.2-x86-linux-ubuntu-12.04.tar.gz' -O \
- clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz
- wget 'https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff' -O \
- cdrkit-deterministic.patch
+ wget 'http://llvm.org/releases/3.2/clang+llvm-3.2-x86-linux-ubuntu-12.04.tar.gz' -O clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz
+ wget 'https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff' -O cdrkit-deterministic.patch
cd ..
./bin/gbuild ../bitcoin/contrib/gitian-descriptors/boost-linux.yml
mv build/out/boost-*.zip inputs/
@@ -180,34 +177,6 @@ Commit your signature to gitian.sigs:
### After 3 or more people have gitian-built, repackage gitian-signed zips:
-From a directory containing bitcoin source, gitian.sigs and gitian zips
-
- export VERSION=(new version, e.g. 0.8.0)
- mkdir bitcoin-${VERSION}-linux-gitian
- pushd bitcoin-${VERSION}-linux-gitian
- unzip ../bitcoin-${VERSION}-linux-gitian.zip
- mkdir gitian
- cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/
- for signer in $(ls ../gitian.sigs/${VERSION}/); do
- cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert
- cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig
- done
- zip -r bitcoin-${VERSION}-linux-gitian.zip *
- cp bitcoin-${VERSION}-linux-gitian.zip ../
- popd
- mkdir bitcoin-${VERSION}-win-gitian
- pushd bitcoin-${VERSION}-win-gitian
- unzip ../bitcoin-${VERSION}-win-gitian.zip
- mkdir gitian
- cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/
- for signer in $(ls ../gitian.sigs/${VERSION}-win/); do
- cp ../gitian.sigs/${VERSION}-win/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert
- cp ../gitian.sigs/${VERSION}-win/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig
- done
- zip -r bitcoin-${VERSION}-win-gitian.zip *
- cp bitcoin-${VERSION}-win-gitian.zip ../
- popd
-
- Upload gitian zips to SourceForge
- Announce the release:
diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py
new file mode 100755
index 0000000000..7f2d79b3c1
--- /dev/null
+++ b/qa/rpc-tests/receivedby.py
@@ -0,0 +1,225 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT/X11 software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+# Exercise the listtransactions API
+
+# Add python-bitcoinrpc to module search path:
+
+import os
+import sys
+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc"))
+
+import json
+import shutil
+import subprocess
+import tempfile
+import traceback
+
+from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
+from util import *
+
+def get_sub_array_from_array(object_array, to_match):
+ '''
+ Finds and returns a sub array from an array of arrays.
+ to_match should be a unique idetifier of a sub array
+ '''
+ num_matched = 0
+ for item in object_array:
+ all_match = True
+ for key,value in to_match.items():
+ if item[key] != value:
+ all_match = False
+ if not all_match:
+ continue
+ return item
+ return []
+
+def check_array_result(object_array, to_match, expected, should_not_find = False):
+ """
+ Pass in array of JSON objects, a dictionary with key/value pairs
+ to match against, and another dictionary with expected key/value
+ pairs.
+ If the should_not_find flag is true, to_match should not be found in object_array
+ """
+ if should_not_find == True:
+ expected = { }
+ num_matched = 0
+ for item in object_array:
+ all_match = True
+ for key,value in to_match.items():
+ if item[key] != value:
+ all_match = False
+ if not all_match:
+ continue
+ for key,value in expected.items():
+ if item[key] != value:
+ raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
+ num_matched = num_matched+1
+ if num_matched == 0 and should_not_find != True:
+ raise AssertionError("No objects matched %s"%(str(to_match)))
+ if num_matched > 0 and should_not_find == True:
+ raise AssertionError("Objects was matched %s"%(str(to_match)))
+
+def run_test(nodes):
+ '''
+ listreceivedbyaddress Test
+ '''
+ # Send from node 0 to 1
+ addr = nodes[1].getnewaddress()
+ txid = nodes[0].sendtoaddress(addr, 0.1)
+ sync_mempools(nodes)
+
+ #Check not listed in listreceivedbyaddress because has 0 confirmations
+ check_array_result(nodes[1].listreceivedbyaddress(),
+ {"address":addr},
+ { },
+ True)
+ #Bury Tx under 10 block so it will be returned by listreceivedbyaddress
+ nodes[1].setgenerate(True, 10)
+ sync_blocks(nodes)
+ check_array_result(nodes[1].listreceivedbyaddress(),
+ {"address":addr},
+ {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
+ #With min confidence < 10
+ check_array_result(nodes[1].listreceivedbyaddress(5),
+ {"address":addr},
+ {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
+ #With min confidence > 10, should not find Tx
+ check_array_result(nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
+
+ #Empty Tx
+ addr = nodes[1].getnewaddress()
+ check_array_result(nodes[1].listreceivedbyaddress(0,True),
+ {"address":addr},
+ {"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]})
+
+ '''
+ getreceivedbyaddress Test
+ '''
+ # Send from node 0 to 1
+ addr = nodes[1].getnewaddress()
+ txid = nodes[0].sendtoaddress(addr, 0.1)
+ sync_mempools(nodes)
+
+ #Check balance is 0 because of 0 confirmations
+ balance = nodes[1].getreceivedbyaddress(addr)
+ if balance != Decimal("0.0"):
+ raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
+
+ #Check balance is 0.1
+ balance = nodes[1].getreceivedbyaddress(addr,0)
+ if balance != Decimal("0.1"):
+ raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
+
+ #Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress
+ nodes[1].setgenerate(True, 10)
+ sync_blocks(nodes)
+ balance = nodes[1].getreceivedbyaddress(addr)
+ if balance != Decimal("0.1"):
+ raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
+
+ '''
+ listreceivedbyaccount + getreceivedbyaccount Test
+ '''
+ #set pre-state
+ addrArr = nodes[1].getnewaddress()
+ account = nodes[1].getaccount(addrArr)
+ received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(),{"account":account})
+ if len(received_by_account_json) == 0:
+ raise AssertionError("No accounts found in node")
+ balance_by_account = rec_by_accountArr = nodes[1].getreceivedbyaccount(account)
+
+ txid = nodes[0].sendtoaddress(addr, 0.1)
+
+ # listreceivedbyaccount should return received_by_account_json because of 0 confirmations
+ check_array_result(nodes[1].listreceivedbyaccount(),
+ {"account":account},
+ received_by_account_json)
+
+ # getreceivedbyaddress should return same balance because of 0 confirmations
+ balance = nodes[1].getreceivedbyaccount(account)
+ if balance != balance_by_account:
+ raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
+
+ nodes[1].setgenerate(True, 10)
+ sync_blocks(nodes)
+ # listreceivedbyaccount should return updated account balance
+ check_array_result(nodes[1].listreceivedbyaccount(),
+ {"account":account},
+ {"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))})
+
+ # getreceivedbyaddress should return updates balance
+ balance = nodes[1].getreceivedbyaccount(account)
+ if balance != balance_by_account + Decimal("0.1"):
+ raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
+
+ #Create a new account named "mynewaccount" that has a 0 balance
+ nodes[1].getaccountaddress("mynewaccount")
+ received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(0,True),{"account":"mynewaccount"})
+ if len(received_by_account_json) == 0:
+ raise AssertionError("No accounts found in node")
+
+ # Test includeempty of listreceivedbyaccount
+ if received_by_account_json["amount"] != Decimal("0.0"):
+ raise AssertionError("Wrong balance returned by listreceivedbyaccount, %0.2f"%(received_by_account_json["amount"]))
+
+ # Test getreceivedbyaccount for 0 amount accounts
+ balance = nodes[1].getreceivedbyaccount("mynewaccount")
+ if balance != Decimal("0.0"):
+ raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
+
+def main():
+ import optparse
+
+ parser = optparse.OptionParser(usage="%prog [options]")
+ parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true",
+ help="Leave bitcoinds and test.* datadir on exit or error")
+ parser.add_option("--srcdir", dest="srcdir", default="../../src",
+ help="Source directory containing bitcoind/bitcoin-cli (default: %default%)")
+ parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"),
+ help="Root directory for datadirs")
+ (options, args) = parser.parse_args()
+
+ os.environ['PATH'] = options.srcdir+":"+os.environ['PATH']
+
+ check_json_precision()
+
+ success = False
+ nodes = []
+ try:
+ print("Initializing test directory "+options.tmpdir)
+ if not os.path.isdir(options.tmpdir):
+ os.makedirs(options.tmpdir)
+ initialize_chain(options.tmpdir)
+
+ nodes = start_nodes(2, options.tmpdir)
+ connect_nodes(nodes[1], 0)
+ sync_blocks(nodes)
+
+ run_test(nodes)
+
+ success = True
+
+ except AssertionError as e:
+ print("Assertion failed: "+e.message)
+ except Exception as e:
+ print("Unexpected exception caught during testing: "+str(e))
+ traceback.print_tb(sys.exc_info()[2])
+
+ if not options.nocleanup:
+ print("Cleaning up")
+ stop_nodes(nodes)
+ wait_bitcoinds()
+ shutil.rmtree(options.tmpdir)
+
+ if success:
+ print("Tests successful")
+ sys.exit(0)
+ else:
+ print("Failed")
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()
diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py
index eded098c7c..27c9f778f6 100644
--- a/qa/rpc-tests/util.py
+++ b/qa/rpc-tests/util.py
@@ -182,6 +182,10 @@ def wait_bitcoinds():
def connect_nodes(from_connection, node_num):
ip_port = "127.0.0.1:"+str(p2p_port(node_num))
from_connection.addnode(ip_port, "onetry")
+ # poll until version handshake complete to avoid race conditions
+ # with transaction relaying
+ while any(peer['version'] == 0 for peer in from_connection.getpeerinfo()):
+ time.sleep(0.1)
def find_output(node, txid, amount):
"""
diff --git a/src/Makefile.am b/src/Makefile.am
index 0a76829197..5ecded442c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,12 +17,14 @@ $(LIBLEVELDB) $(LIBMEMENV):
OPT="$(CXXFLAGS) $(CPPFLAGS)"
endif
+BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS)
noinst_LIBRARIES = \
libbitcoin_server.a \
libbitcoin_common.a \
- libbitcoin_cli.a
+ libbitcoin_cli.a \
+ crypto/libbitcoin_crypto.a
if ENABLE_WALLET
BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
noinst_LIBRARIES += libbitcoin_wallet.a
@@ -85,7 +87,8 @@ BITCOIN_CORE_H = \
util.h \
version.h \
walletdb.h \
- wallet.h
+ wallet.h \
+ compat/sanity.h
JSON_H = \
json/json_spirit.h \
@@ -139,6 +142,16 @@ libbitcoin_wallet_a_SOURCES = \
walletdb.cpp \
$(BITCOIN_CORE_H)
+crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES)
+crypto_libbitcoin_crypto_a_SOURCES = \
+ crypto/sha1.cpp \
+ crypto/sha2.cpp \
+ crypto/ripemd160.cpp \
+ crypto/common.h \
+ crypto/sha2.h \
+ crypto/sha1.h \
+ crypto/ripemd160.h
+
libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_common_a_SOURCES = \
base58.cpp \
@@ -154,6 +167,8 @@ libbitcoin_common_a_SOURCES = \
sync.cpp \
util.cpp \
version.cpp \
+ compat/glibc_sanity.cpp \
+ compat/glibcxx_sanity.cpp \
$(BITCOIN_CORE_H)
if GLIBC_BACK_COMPAT
@@ -172,6 +187,7 @@ nodist_libbitcoin_common_a_SOURCES = $(srcdir)/obj/build.h
bitcoind_LDADD = \
libbitcoin_server.a \
libbitcoin_common.a \
+ crypto/libbitcoin_crypto.a \
$(LIBLEVELDB) \
$(LIBMEMENV)
if ENABLE_WALLET
@@ -191,6 +207,7 @@ bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES)
bitcoin_cli_LDADD = \
libbitcoin_cli.a \
libbitcoin_common.a \
+ crypto/libbitcoin_crypto.a \
$(BOOST_LIBS)
bitcoin_cli_SOURCES = bitcoin-cli.cpp
bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
@@ -209,6 +226,7 @@ EXTRA_DIST = leveldb
clean-local:
-$(MAKE) -C leveldb clean
rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
+ -rm -f config.h
.rc.o:
@test -f $(WINDRES)
@@ -226,6 +244,7 @@ LIBBITCOIN_SERVER=libbitcoin_server.a
LIBBITCOIN_WALLET=libbitcoin_wallet.a
LIBBITCOIN_COMMON=libbitcoin_common.a
LIBBITCOIN_CLI=libbitcoin_cli.a
+LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
LIBBITCOINQT=qt/libbitcoinqt.a
if ENABLE_TESTS
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 647434e1ef..091138dc38 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -355,7 +355,7 @@ qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER)
if ENABLE_WALLET
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
endif
-qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
+qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
qt_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS)
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index e0b49d0240..0aa31a406d 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -30,7 +30,7 @@ qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER)
if ENABLE_WALLET
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
endif
-qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \
+qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) \
$(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
qt_test_test_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 988830260c..64f997f4b5 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -31,8 +31,10 @@ BITCOIN_TESTS =\
test/checkblock_tests.cpp \
test/Checkpoints_tests.cpp \
test/compress_tests.cpp \
+ test/crypto_tests.cpp \
test/DoS_tests.cpp \
test/getarg_tests.cpp \
+ test/hash_tests.cpp \
test/key_tests.cpp \
test/main_tests.cpp \
test/miner_tests.cpp \
@@ -61,7 +63,7 @@ endif
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS)
-test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
+test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB)
if ENABLE_WALLET
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
diff --git a/src/bloom.cpp b/src/bloom.cpp
index 1bfcbd406f..26e366179c 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -99,7 +99,7 @@ bool CBloomFilter::IsWithinSizeConstraints() const
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
}
-bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& hash)
+bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
{
bool fFound = false;
// Match if the filter contains the hash of tx
@@ -108,6 +108,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& ha
return true;
if (isEmpty)
return false;
+ const uint256& hash = tx.GetHash();
if (contains(hash))
fFound = true;
diff --git a/src/bloom.h b/src/bloom.h
index 75e3f38c55..956bead87f 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -83,7 +83,7 @@ public:
bool IsWithinSizeConstraints() const;
// Also adds any outputs which match the filter to the filter (to match their spending txes)
- bool IsRelevantAndUpdate(const CTransaction& tx, const uint256& hash);
+ bool IsRelevantAndUpdate(const CTransaction& tx);
// Checks for empty and full filters to avoid wasting cpu
void UpdateEmptyFull();
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 6b2cfa1d1f..afbae6fc57 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -127,7 +127,7 @@ public:
// CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
// vMerkleTree: 4a5e1e
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
- CTransaction txNew;
+ CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
@@ -178,7 +178,6 @@ public:
fDefaultCheckMemPool = false;
fAllowMinDifficultyBlocks = false;
fRequireStandard = true;
- fRPCisTestNet = false;
fMineBlocksOnDemand = false;
}
};
@@ -230,7 +229,6 @@ public:
fDefaultCheckMemPool = false;
fAllowMinDifficultyBlocks = true;
fRequireStandard = false;
- fRPCisTestNet = true;
fMineBlocksOnDemand = false;
}
};
@@ -269,7 +267,6 @@ public:
fDefaultCheckMemPool = true;
fAllowMinDifficultyBlocks = true;
fRequireStandard = false;
- fRPCisTestNet = true;
fMineBlocksOnDemand = true;
}
};
diff --git a/src/chainparams.h b/src/chainparams.h
index 28a51cbb0c..c0a6ebda6b 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -70,8 +70,6 @@ public:
bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; }
/* Make standard checks */
bool RequireStandard() const { return fRequireStandard; }
- /* Make standard checks */
- bool RPCisTestNet() const { return fRPCisTestNet; }
const std::string& DataDir() const { return strDataDir; }
/* Make miner stop after a block is found. In RPC, don't return
* until nGenProcLimit blocks are generated */
@@ -110,7 +108,6 @@ protected:
bool fDefaultCheckMemPool;
bool fAllowMinDifficultyBlocks;
bool fRequireStandard;
- bool fRPCisTestNet;
bool fMineBlocksOnDemand;
};
diff --git a/src/clientversion.h b/src/clientversion.h
index 29b4aa3764..a30bbff06b 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -2,7 +2,7 @@
#define CLIENTVERSION_H
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#else
//
// client versioning and copyright year
diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp
index 5b73e6051a..22f82e4259 100644
--- a/src/compat/glibc_compat.cpp
+++ b/src/compat/glibc_compat.cpp
@@ -1,19 +1,28 @@
-#include "bitcoin-config.h"
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#if defined(HAVE_CONFIG_H)
+#include "config/bitcoin-config.h"
+#endif
+
#include <cstddef>
+#if defined(HAVE_SYS_SELECT_H)
#include <sys/select.h>
+#endif
// Prior to GLIBC_2.14, memcpy was aliased to memmove.
extern "C" void* memmove(void* a, const void* b, size_t c);
extern "C" void* memcpy(void* a, const void* b, size_t c)
{
- return memmove(a, b, c);
+ return memmove(a, b, c);
}
extern "C" void __chk_fail (void) __attribute__((__noreturn__));
extern "C" FDELT_TYPE __fdelt_warn(FDELT_TYPE a)
{
- if (a >= FD_SETSIZE)
- __chk_fail ();
- return a / __NFDBITS;
+ if (a >= FD_SETSIZE)
+ __chk_fail ();
+ return a / __NFDBITS;
}
extern "C" FDELT_TYPE __fdelt_chk(FDELT_TYPE) __attribute__((weak, alias("__fdelt_warn")));
diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp
new file mode 100644
index 0000000000..d93602e0fe
--- /dev/null
+++ b/src/compat/glibc_sanity.cpp
@@ -0,0 +1,67 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#if defined(HAVE_CONFIG_H)
+#include "config/bitcoin-config.h"
+#endif
+
+#include <cstddef>
+#if defined(HAVE_SYS_SELECT_H)
+#include <sys/select.h>
+#endif
+
+extern "C" void* memcpy(void* a, const void* b, size_t c);
+void* memcpy_int(void* a, const void* b, size_t c)
+{
+ return memcpy(a,b,c);
+}
+
+namespace {
+// trigger: Use the memcpy_int wrapper which calls our internal memcpy.
+// A direct call to memcpy may be optimized away by the compiler.
+// test: Fill an array with a sequence of integers. memcpy to a new empty array.
+// Verify that the arrays are equal. Use an odd size to decrease the odds of
+// the call being optimized away.
+template <unsigned int T>
+bool sanity_test_memcpy()
+{
+ unsigned int memcpy_test[T];
+ unsigned int memcpy_verify[T] = {};
+ for (unsigned int i = 0; i != T; ++i)
+ memcpy_test[i] = i;
+
+ memcpy_int(memcpy_verify,memcpy_test,sizeof(memcpy_test));
+
+ for (unsigned int i = 0; i != T; ++i)
+ {
+ if(memcpy_verify[i] != i)
+ return false;
+ }
+ return true;
+}
+
+#if defined(HAVE_SYS_SELECT_H)
+// trigger: Call FD_SET to trigger __fdelt_chk. FORTIFY_SOURCE must be defined
+// as >0 and optimizations must be set to at least -O2.
+// test: Add a file descriptor to an empty fd_set. Verify that it has been
+// correctly added.
+bool sanity_test_fdelt()
+{
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ return FD_ISSET(0,&fds);
+}
+#endif
+
+} // anon namespace
+
+bool glibc_sanity_test()
+{
+#if defined(HAVE_SYS_SELECT_H)
+ if (!sanity_test_fdelt())
+ return false;
+#endif
+ return sanity_test_memcpy<1025>();
+}
diff --git a/src/compat/glibcxx_compat.cpp b/src/compat/glibcxx_compat.cpp
index e91376f818..417166aeda 100644
--- a/src/compat/glibcxx_compat.cpp
+++ b/src/compat/glibcxx_compat.cpp
@@ -1,49 +1,55 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#include <cstddef>
#include <istream>
#include <stdexcept>
#include <typeinfo>
#ifndef _GLIBCXX_USE_NOEXCEPT
- #define _GLIBCXX_USE_NOEXCEPT throw()
+#define _GLIBCXX_USE_NOEXCEPT throw()
#endif
namespace std {
const char* bad_exception::what() const throw()
{
- return "std::bad_exception";
+ return "std::bad_exception";
}
const char* bad_cast::what() const throw()
{
- return "std::bad_cast";
+ return "std::bad_cast";
}
const char* bad_alloc::what() const throw()
{
- return "std::bad_alloc";
+ return "std::bad_alloc";
}
namespace __detail
{
struct _List_node_base
{
- void _M_hook(std::__detail::_List_node_base* const __position) throw () __attribute__((used))
- {
- _M_next = __position;
- _M_prev = __position->_M_prev;
- __position->_M_prev->_M_next = this;
- __position->_M_prev = this;
- }
- void _M_unhook() __attribute__((used))
- {
- _List_node_base* const __next_node = _M_next;
- _List_node_base* const __prev_node = _M_prev;
- __prev_node->_M_next = __next_node;
- __next_node->_M_prev = __prev_node;
- }
- _List_node_base* _M_next;
- _List_node_base* _M_prev;
+ void _M_hook(std::__detail::_List_node_base* const __position) throw () __attribute__((used))
+ {
+ _M_next = __position;
+ _M_prev = __position->_M_prev;
+ __position->_M_prev->_M_next = this;
+ __position->_M_prev = this;
+ }
+
+ void _M_unhook() __attribute__((used))
+ {
+ _List_node_base* const __next_node = _M_next;
+ _List_node_base* const __prev_node = _M_prev;
+ __prev_node->_M_next = __next_node;
+ __next_node->_M_prev = __prev_node;
+ }
+
+ _List_node_base* _M_next;
+ _List_node_base* _M_prev;
};
} // namespace detail
@@ -61,8 +67,8 @@ out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT { }
// Used with permission.
// See: https://github.com/madlib/madlib/commit/c3db418c0d34d6813608f2137fef1012ce03043d
-void
-ctype<char>::_M_widen_init() const {
+void ctype<char>::_M_widen_init() const
+{
char __tmp[sizeof(_M_widen)];
for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
__tmp[__i] = __i;
diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp
new file mode 100644
index 0000000000..cd8da4fd67
--- /dev/null
+++ b/src/compat/glibcxx_sanity.cpp
@@ -0,0 +1,65 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <list>
+#include <locale>
+#include <stdexcept>
+
+namespace{
+
+// trigger: use ctype<char>::widen to trigger ctype<char>::_M_widen_init().
+// test: convert a char from narrow to wide and back. Verify that the result
+// matches the original.
+bool sanity_test_widen(char testchar)
+{
+ const std::ctype<char>& test(std::use_facet< std::ctype<char> >(std::locale()));
+ return test.narrow(test.widen(testchar),'b') == testchar;
+}
+
+// trigger: use list::push_back and list::pop_back to trigger _M_hook and
+// _M_unhook.
+// test: Push a sequence of integers into a list. Pop them off and verify that
+// they match the original sequence.
+bool sanity_test_list(unsigned int size)
+{
+ std::list<unsigned int> test;
+ for (unsigned int i = 0; i != size; ++i)
+ test.push_back(i+1);
+
+ if (test.size() != size)
+ return false;
+
+ while (!test.empty())
+ {
+ if(test.back() != test.size())
+ return false;
+ test.pop_back();
+ }
+ return true;
+}
+
+} // anon namespace
+
+// trigger: string::at(x) on an empty string to trigger __throw_out_of_range_fmt.
+// test: force std::string to throw an out_of_range exception. Verify that
+// it's caught correctly.
+bool sanity_test_range_fmt()
+{
+ std::string test;
+ try
+ {
+ test.at(1);
+ }
+ catch (const std::out_of_range&)
+ {
+ return true;
+ }
+ catch (...){}
+ return false;
+}
+
+bool glibcxx_sanity_test()
+{
+ return sanity_test_widen('a') && sanity_test_list(100) && sanity_test_range_fmt();
+}
diff --git a/src/compat/sanity.h b/src/compat/sanity.h
new file mode 100644
index 0000000000..e7df44307a
--- /dev/null
+++ b/src/compat/sanity.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCON_COMPAT_SANITY_H
+#define BITCON_COMPAT_SANITY_H
+
+bool glibc_sanity_test();
+bool glibcxx_sanity_test();
+
+#endif // BITCON_COMPAT_SANITY_H
diff --git a/src/config/.empty b/src/config/.empty
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/config/.empty
diff --git a/src/core.cpp b/src/core.cpp
index 6039986e6c..6c5ee1c0f8 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -91,11 +91,34 @@ std::string CFeeRate::ToString() const
return result;
}
-uint256 CTransaction::GetHash() const
+CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
+CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
+
+uint256 CMutableTransaction::GetHash() const
{
return SerializeHash(*this);
}
+void CTransaction::UpdateHash() const
+{
+ *const_cast<uint256*>(&hash) = SerializeHash(*this);
+}
+
+CTransaction::CTransaction() : hash(0), nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
+
+CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
+ UpdateHash();
+}
+
+CTransaction& CTransaction::operator=(const CTransaction &tx) {
+ *const_cast<int*>(&nVersion) = tx.nVersion;
+ *const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
+ *const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
+ *const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
+ *const_cast<uint256*>(&hash) = tx.hash;
+ return *this;
+}
+
int64_t CTransaction::GetValueOut() const
{
int64_t nValueOut = 0;
diff --git a/src/core.h b/src/core.h
index 0e59129349..27fda95552 100644
--- a/src/core.h
+++ b/src/core.h
@@ -203,49 +203,59 @@ public:
};
+struct CMutableTransaction;
+
/** The basic transaction that is broadcasted on the network and contained in
* blocks. A transaction can contain multiple inputs and outputs.
*/
class CTransaction
{
+private:
+ /** Memory only. */
+ const uint256 hash;
+ void UpdateHash() const;
+
public:
static CFeeRate minTxFee;
static CFeeRate minRelayTxFee;
static const int CURRENT_VERSION=1;
- int nVersion;
- std::vector<CTxIn> vin;
- std::vector<CTxOut> vout;
- unsigned int nLockTime;
- CTransaction()
- {
- SetNull();
- }
+ // The local variables are made const to prevent unintended modification
+ // without updating the cached hash value. However, CTransaction is not
+ // actually immutable; deserialization and assignment are implemented,
+ // and bypass the constness. This is safe, as they update the entire
+ // structure, including the hash.
+ const int nVersion;
+ const std::vector<CTxIn> vin;
+ const std::vector<CTxOut> vout;
+ const unsigned int nLockTime;
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
+ /** Construct a CTransaction that qualifies as IsNull() */
+ CTransaction();
+
+ /** Convert a CMutableTransaction into a CTransaction. */
+ CTransaction(const CMutableTransaction &tx);
+
+ CTransaction& operator=(const CTransaction& tx);
+
+ IMPLEMENT_SERIALIZE(
+ READWRITE(*const_cast<int*>(&this->nVersion));
nVersion = this->nVersion;
- READWRITE(vin);
- READWRITE(vout);
- READWRITE(nLockTime);
+ READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
+ READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
+ READWRITE(*const_cast<unsigned int*>(&nLockTime));
+ if (fRead)
+ UpdateHash();
)
- void SetNull()
- {
- nVersion = CTransaction::CURRENT_VERSION;
- vin.clear();
- vout.clear();
- nLockTime = 0;
+ bool IsNull() const {
+ return vin.empty() && vout.empty();
}
- bool IsNull() const
- {
- return (vin.empty() && vout.empty());
+ const uint256& GetHash() const {
+ return hash;
}
- uint256 GetHash() const;
-
// Return sum of txouts.
int64_t GetValueOut() const;
// GetValueIn() is a method on CCoinsViewCache, because
@@ -261,22 +271,43 @@ public:
friend bool operator==(const CTransaction& a, const CTransaction& b)
{
- return (a.nVersion == b.nVersion &&
- a.vin == b.vin &&
- a.vout == b.vout &&
- a.nLockTime == b.nLockTime);
+ return a.hash == b.hash;
}
friend bool operator!=(const CTransaction& a, const CTransaction& b)
{
- return !(a == b);
+ return a.hash != b.hash;
}
-
std::string ToString() const;
void print() const;
};
+/** A mutable version of CTransaction. */
+struct CMutableTransaction
+{
+ int nVersion;
+ std::vector<CTxIn> vin;
+ std::vector<CTxOut> vout;
+ unsigned int nLockTime;
+
+ CMutableTransaction();
+ CMutableTransaction(const CTransaction& tx);
+
+ IMPLEMENT_SERIALIZE(
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
+ READWRITE(vin);
+ READWRITE(vout);
+ READWRITE(nLockTime);
+ )
+
+ /** Compute the hash of this CMutableTransaction. This is computed on the
+ * fly, as opposed to GetHash() in CTransaction, which uses a cached result.
+ */
+ uint256 GetHash() const;
+};
+
/** wrapper for CTxOut that provides a more compact serialization */
class CTxOutCompressor
{
@@ -465,12 +496,6 @@ public:
uint256 BuildMerkleTree() const;
- const uint256 &GetTxHash(unsigned int nIndex) const {
- assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
- assert(nIndex < vtx.size());
- return vMerkleTree[nIndex];
- }
-
std::vector<uint256> GetMerkleBranch(int nIndex) const;
static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex);
void print() const;
diff --git a/src/crypto/common.h b/src/crypto/common.h
new file mode 100644
index 0000000000..8f675a16c5
--- /dev/null
+++ b/src/crypto/common.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CRYPTO_COMMON_H
+#define BITCOIN_CRYPTO_COMMON_H
+
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+#include <stdint.h>
+#if defined(HAVE_ENDIAN_H)
+#include <endian.h>
+#endif
+
+uint32_t static inline ReadLE32(const unsigned char *ptr) {
+#if HAVE_DECL_LE32TOH == 1
+ return le32toh(*((uint32_t*)ptr));
+#elif !defined(WORDS_BIGENDIAN)
+ return *((uint32_t*)ptr);
+#else
+ return ((uint32_t)ptr[3] << 24 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[0]);
+#endif
+}
+
+uint64_t static inline ReadLE64(const unsigned char *ptr) {
+
+#if HAVE_DECL_LE64TOH == 1
+ return le64toh(*((uint64_t*)ptr));
+#elif !defined(WORDS_BIGENDIAN)
+ return *((uint64_t*)ptr);
+#else
+ return ((uint64_t)ptr[7] << 56 | (uint64_t)ptr[6] << 48 | (uint64_t)ptr[5] << 40 | (uint64_t)ptr[4] << 32 |
+ (uint64_t)ptr[3] << 24 | (uint64_t)ptr[2] << 16 | (uint64_t)ptr[1] << 8 | (uint64_t)ptr[0]);
+#endif
+}
+
+void static inline WriteLE32(unsigned char *ptr, uint32_t x) {
+#if HAVE_DECL_HTOLE32 == 1
+ *((uint32_t*)ptr) = htole32(x);
+#elif !defined(WORDS_BIGENDIAN)
+ *((uint32_t*)ptr) = x;
+#else
+ ptr[3] = x >> 24; ptr[2] = x >> 16; ptr[1] = x >> 8; ptr[0] = x;
+#endif
+}
+
+void static inline WriteLE64(unsigned char *ptr, uint64_t x) {
+#if HAVE_DECL_HTOLE64 == 1
+ *((uint64_t*)ptr) = htole64(x);
+#elif !defined(WORDS_BIGENDIAN)
+ *((uint64_t*)ptr) = x;
+#else
+ ptr[7] = x >> 56; ptr[6] = x >> 48; ptr[5] = x >> 40; ptr[4] = x >> 32;
+ ptr[3] = x >> 24; ptr[2] = x >> 16; ptr[1] = x >> 8; ptr[0] = x;
+#endif
+}
+
+uint32_t static inline ReadBE32(const unsigned char *ptr) {
+#if HAVE_DECL_BE32TOH == 1
+ return be32toh(*((uint32_t*)ptr));
+#else
+ return ((uint32_t)ptr[0] << 24 | (uint32_t)ptr[1] << 16 | (uint32_t)ptr[2] << 8 | (uint32_t)ptr[3]);
+#endif
+}
+
+uint64_t static inline ReadBE64(const unsigned char *ptr) {
+#if HAVE_DECL_BE64TOH == 1
+ return be64toh(*((uint64_t*)ptr));
+#else
+ return ((uint64_t)ptr[0] << 56 | (uint64_t)ptr[1] << 48 | (uint64_t)ptr[2] << 40 | (uint64_t)ptr[3] << 32 |
+ (uint64_t)ptr[4] << 24 | (uint64_t)ptr[5] << 16 | (uint64_t)ptr[6] << 8 | (uint64_t)ptr[7]);
+#endif
+}
+
+void static inline WriteBE32(unsigned char *ptr, uint32_t x) {
+#if HAVE_DECL_HTOBE32 == 1
+ *((uint32_t*)ptr) = htobe32(x);
+#else
+ ptr[0] = x >> 24; ptr[1] = x >> 16; ptr[2] = x >> 8; ptr[3] = x;
+#endif
+}
+
+void static inline WriteBE64(unsigned char *ptr, uint64_t x) {
+#if HAVE_DECL_HTOBE64 == 1
+ *((uint64_t*)ptr) = htobe64(x);
+#else
+ ptr[0] = x >> 56; ptr[1] = x >> 48; ptr[2] = x >> 40; ptr[3] = x >> 32;
+ ptr[4] = x >> 24; ptr[5] = x >> 16; ptr[6] = x >> 8; ptr[7] = x;
+#endif
+}
+
+#endif
diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp
new file mode 100644
index 0000000000..24bd318d43
--- /dev/null
+++ b/src/crypto/ripemd160.cpp
@@ -0,0 +1,204 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "crypto/ripemd160.h"
+
+#include "crypto/common.h"
+#include <string.h>
+
+// Internal implementation code.
+namespace {
+
+/// Internal RIPEMD-160 implementation.
+namespace ripemd160 {
+
+uint32_t inline f1(uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; }
+uint32_t inline f2(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); }
+uint32_t inline f3(uint32_t x, uint32_t y, uint32_t z) { return (x | ~y) ^ z; }
+uint32_t inline f4(uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~z); }
+uint32_t inline f5(uint32_t x, uint32_t y, uint32_t z) { return x ^ (y | ~z); }
+
+/** Initialize RIPEMD-160 state. */
+void inline Initialize(uint32_t *s) {
+ s[0] = 0x67452301ul;
+ s[1] = 0xEFCDAB89ul;
+ s[2] = 0x98BADCFEul;
+ s[3] = 0x10325476ul;
+ s[4] = 0xC3D2E1F0ul;
+}
+
+uint32_t inline rol(uint32_t x, int i) { return (x << i) | (x >> (32-i)); }
+
+void inline Round(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t f, uint32_t x, uint32_t k, int r) {
+ a = rol(a + f + x + k, r) + e;
+ c = rol(c, 10);
+}
+
+void inline R11(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); }
+void inline R21(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x5A827999ul, r); }
+void inline R31(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6ED9EBA1ul, r); }
+void inline R41(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x8F1BBCDCul, r); }
+void inline R51(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0xA953FD4Eul, r); }
+
+void inline R12(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0x50A28BE6ul, r); }
+void inline R22(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x5C4DD124ul, r); }
+void inline R32(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6D703EF3ul, r); }
+void inline R42(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x7A6D76E9ul, r); }
+void inline R52(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); }
+
+/** Perform a RIPEMD-160 transformation, processing a 64-byte chunk. */
+void Transform(uint32_t *s, const unsigned char *chunk) {
+ uint32_t a1 = s[0], b1 = s[1], c1 = s[2], d1 = s[3], e1 = s[4];
+ uint32_t a2 = a1 , b2 = b1 , c2 = c1 , d2 = d1 , e2 = e1 ;
+ uint32_t w0 = ReadLE32(chunk + 0), w1 = ReadLE32(chunk + 4), w2 = ReadLE32(chunk + 8), w3 = ReadLE32(chunk + 12);
+ uint32_t w4 = ReadLE32(chunk + 16), w5 = ReadLE32(chunk + 20), w6 = ReadLE32(chunk + 24), w7 = ReadLE32(chunk + 28);
+ uint32_t w8 = ReadLE32(chunk + 32), w9 = ReadLE32(chunk + 36), w10 = ReadLE32(chunk + 40), w11 = ReadLE32(chunk + 44);
+ uint32_t w12 = ReadLE32(chunk + 48), w13 = ReadLE32(chunk + 52), w14 = ReadLE32(chunk + 56), w15 = ReadLE32(chunk + 60);
+
+ R11(a1, b1, c1, d1, e1, w0 , 11); R12(a2, b2, c2, d2, e2, w5 , 8);
+ R11(e1, a1, b1, c1, d1, w1 , 14); R12(e2, a2, b2, c2, d2, w14, 9);
+ R11(d1, e1, a1, b1, c1, w2 , 15); R12(d2, e2, a2, b2, c2, w7 , 9);
+ R11(c1, d1, e1, a1, b1, w3 , 12); R12(c2, d2, e2, a2, b2, w0 , 11);
+ R11(b1, c1, d1, e1, a1, w4 , 5); R12(b2, c2, d2, e2, a2, w9 , 13);
+ R11(a1, b1, c1, d1, e1, w5 , 8); R12(a2, b2, c2, d2, e2, w2 , 15);
+ R11(e1, a1, b1, c1, d1, w6 , 7); R12(e2, a2, b2, c2, d2, w11, 15);
+ R11(d1, e1, a1, b1, c1, w7 , 9); R12(d2, e2, a2, b2, c2, w4 , 5);
+ R11(c1, d1, e1, a1, b1, w8 , 11); R12(c2, d2, e2, a2, b2, w13, 7);
+ R11(b1, c1, d1, e1, a1, w9 , 13); R12(b2, c2, d2, e2, a2, w6 , 7);
+ R11(a1, b1, c1, d1, e1, w10, 14); R12(a2, b2, c2, d2, e2, w15, 8);
+ R11(e1, a1, b1, c1, d1, w11, 15); R12(e2, a2, b2, c2, d2, w8 , 11);
+ R11(d1, e1, a1, b1, c1, w12, 6); R12(d2, e2, a2, b2, c2, w1 , 14);
+ R11(c1, d1, e1, a1, b1, w13, 7); R12(c2, d2, e2, a2, b2, w10, 14);
+ R11(b1, c1, d1, e1, a1, w14, 9); R12(b2, c2, d2, e2, a2, w3 , 12);
+ R11(a1, b1, c1, d1, e1, w15, 8); R12(a2, b2, c2, d2, e2, w12, 6);
+
+ R21(e1, a1, b1, c1, d1, w7 , 7); R22(e2, a2, b2, c2, d2, w6 , 9);
+ R21(d1, e1, a1, b1, c1, w4 , 6); R22(d2, e2, a2, b2, c2, w11, 13);
+ R21(c1, d1, e1, a1, b1, w13, 8); R22(c2, d2, e2, a2, b2, w3 , 15);
+ R21(b1, c1, d1, e1, a1, w1 , 13); R22(b2, c2, d2, e2, a2, w7 , 7);
+ R21(a1, b1, c1, d1, e1, w10, 11); R22(a2, b2, c2, d2, e2, w0 , 12);
+ R21(e1, a1, b1, c1, d1, w6 , 9); R22(e2, a2, b2, c2, d2, w13, 8);
+ R21(d1, e1, a1, b1, c1, w15, 7); R22(d2, e2, a2, b2, c2, w5 , 9);
+ R21(c1, d1, e1, a1, b1, w3 , 15); R22(c2, d2, e2, a2, b2, w10, 11);
+ R21(b1, c1, d1, e1, a1, w12, 7); R22(b2, c2, d2, e2, a2, w14, 7);
+ R21(a1, b1, c1, d1, e1, w0 , 12); R22(a2, b2, c2, d2, e2, w15, 7);
+ R21(e1, a1, b1, c1, d1, w9 , 15); R22(e2, a2, b2, c2, d2, w8 , 12);
+ R21(d1, e1, a1, b1, c1, w5 , 9); R22(d2, e2, a2, b2, c2, w12, 7);
+ R21(c1, d1, e1, a1, b1, w2 , 11); R22(c2, d2, e2, a2, b2, w4 , 6);
+ R21(b1, c1, d1, e1, a1, w14, 7); R22(b2, c2, d2, e2, a2, w9 , 15);
+ R21(a1, b1, c1, d1, e1, w11, 13); R22(a2, b2, c2, d2, e2, w1 , 13);
+ R21(e1, a1, b1, c1, d1, w8 , 12); R22(e2, a2, b2, c2, d2, w2 , 11);
+
+ R31(d1, e1, a1, b1, c1, w3 , 11); R32(d2, e2, a2, b2, c2, w15, 9);
+ R31(c1, d1, e1, a1, b1, w10, 13); R32(c2, d2, e2, a2, b2, w5 , 7);
+ R31(b1, c1, d1, e1, a1, w14, 6); R32(b2, c2, d2, e2, a2, w1 , 15);
+ R31(a1, b1, c1, d1, e1, w4 , 7); R32(a2, b2, c2, d2, e2, w3 , 11);
+ R31(e1, a1, b1, c1, d1, w9 , 14); R32(e2, a2, b2, c2, d2, w7 , 8);
+ R31(d1, e1, a1, b1, c1, w15, 9); R32(d2, e2, a2, b2, c2, w14, 6);
+ R31(c1, d1, e1, a1, b1, w8 , 13); R32(c2, d2, e2, a2, b2, w6 , 6);
+ R31(b1, c1, d1, e1, a1, w1 , 15); R32(b2, c2, d2, e2, a2, w9 , 14);
+ R31(a1, b1, c1, d1, e1, w2 , 14); R32(a2, b2, c2, d2, e2, w11, 12);
+ R31(e1, a1, b1, c1, d1, w7 , 8); R32(e2, a2, b2, c2, d2, w8 , 13);
+ R31(d1, e1, a1, b1, c1, w0 , 13); R32(d2, e2, a2, b2, c2, w12, 5);
+ R31(c1, d1, e1, a1, b1, w6 , 6); R32(c2, d2, e2, a2, b2, w2 , 14);
+ R31(b1, c1, d1, e1, a1, w13, 5); R32(b2, c2, d2, e2, a2, w10, 13);
+ R31(a1, b1, c1, d1, e1, w11, 12); R32(a2, b2, c2, d2, e2, w0 , 13);
+ R31(e1, a1, b1, c1, d1, w5 , 7); R32(e2, a2, b2, c2, d2, w4 , 7);
+ R31(d1, e1, a1, b1, c1, w12, 5); R32(d2, e2, a2, b2, c2, w13, 5);
+
+ R41(c1, d1, e1, a1, b1, w1 , 11); R42(c2, d2, e2, a2, b2, w8 , 15);
+ R41(b1, c1, d1, e1, a1, w9 , 12); R42(b2, c2, d2, e2, a2, w6 , 5);
+ R41(a1, b1, c1, d1, e1, w11, 14); R42(a2, b2, c2, d2, e2, w4 , 8);
+ R41(e1, a1, b1, c1, d1, w10, 15); R42(e2, a2, b2, c2, d2, w1 , 11);
+ R41(d1, e1, a1, b1, c1, w0 , 14); R42(d2, e2, a2, b2, c2, w3 , 14);
+ R41(c1, d1, e1, a1, b1, w8 , 15); R42(c2, d2, e2, a2, b2, w11, 14);
+ R41(b1, c1, d1, e1, a1, w12, 9); R42(b2, c2, d2, e2, a2, w15, 6);
+ R41(a1, b1, c1, d1, e1, w4 , 8); R42(a2, b2, c2, d2, e2, w0 , 14);
+ R41(e1, a1, b1, c1, d1, w13, 9); R42(e2, a2, b2, c2, d2, w5 , 6);
+ R41(d1, e1, a1, b1, c1, w3 , 14); R42(d2, e2, a2, b2, c2, w12, 9);
+ R41(c1, d1, e1, a1, b1, w7 , 5); R42(c2, d2, e2, a2, b2, w2 , 12);
+ R41(b1, c1, d1, e1, a1, w15, 6); R42(b2, c2, d2, e2, a2, w13, 9);
+ R41(a1, b1, c1, d1, e1, w14, 8); R42(a2, b2, c2, d2, e2, w9 , 12);
+ R41(e1, a1, b1, c1, d1, w5 , 6); R42(e2, a2, b2, c2, d2, w7 , 5);
+ R41(d1, e1, a1, b1, c1, w6 , 5); R42(d2, e2, a2, b2, c2, w10, 15);
+ R41(c1, d1, e1, a1, b1, w2 , 12); R42(c2, d2, e2, a2, b2, w14, 8);
+
+ R51(b1, c1, d1, e1, a1, w4 , 9); R52(b2, c2, d2, e2, a2, w12, 8);
+ R51(a1, b1, c1, d1, e1, w0 , 15); R52(a2, b2, c2, d2, e2, w15, 5);
+ R51(e1, a1, b1, c1, d1, w5 , 5); R52(e2, a2, b2, c2, d2, w10, 12);
+ R51(d1, e1, a1, b1, c1, w9 , 11); R52(d2, e2, a2, b2, c2, w4 , 9);
+ R51(c1, d1, e1, a1, b1, w7 , 6); R52(c2, d2, e2, a2, b2, w1 , 12);
+ R51(b1, c1, d1, e1, a1, w12, 8); R52(b2, c2, d2, e2, a2, w5 , 5);
+ R51(a1, b1, c1, d1, e1, w2 , 13); R52(a2, b2, c2, d2, e2, w8 , 14);
+ R51(e1, a1, b1, c1, d1, w10, 12); R52(e2, a2, b2, c2, d2, w7 , 6);
+ R51(d1, e1, a1, b1, c1, w14, 5); R52(d2, e2, a2, b2, c2, w6 , 8);
+ R51(c1, d1, e1, a1, b1, w1 , 12); R52(c2, d2, e2, a2, b2, w2 , 13);
+ R51(b1, c1, d1, e1, a1, w3 , 13); R52(b2, c2, d2, e2, a2, w13, 6);
+ R51(a1, b1, c1, d1, e1, w8 , 14); R52(a2, b2, c2, d2, e2, w14, 5);
+ R51(e1, a1, b1, c1, d1, w11, 11); R52(e2, a2, b2, c2, d2, w0 , 15);
+ R51(d1, e1, a1, b1, c1, w6 , 8); R52(d2, e2, a2, b2, c2, w3 , 13);
+ R51(c1, d1, e1, a1, b1, w15, 5); R52(c2, d2, e2, a2, b2, w9 , 11);
+ R51(b1, c1, d1, e1, a1, w13, 6); R52(b2, c2, d2, e2, a2, w11, 11);
+
+ uint32_t t = s[0];
+ s[0] = s[1] + c1 + d2;
+ s[1] = s[2] + d1 + e2;
+ s[2] = s[3] + e1 + a2;
+ s[3] = s[4] + a1 + b2;
+ s[4] = t + b1 + c2;
+}
+
+} // namespace ripemd160
+
+} // namespace
+
+////// RIPEMD160
+
+CRIPEMD160::CRIPEMD160() : bytes(0) {
+ ripemd160::Initialize(s);
+}
+
+CRIPEMD160& CRIPEMD160::Write(const unsigned char *data, size_t len) {
+ const unsigned char *end = data + len;
+ size_t bufsize = bytes % 64;
+ if (bufsize && bufsize + len >= 64) {
+ // Fill the buffer, and process it.
+ memcpy(buf + bufsize, data, 64 - bufsize);
+ bytes += 64 - bufsize;
+ data += 64 - bufsize;
+ ripemd160::Transform(s, buf);
+ bufsize = 0;
+ }
+ while (end >= data + 64) {
+ // Process full chunks directly from the source.
+ ripemd160::Transform(s, data);
+ bytes += 64;
+ data += 64;
+ }
+ if (end > data) {
+ // Fill the buffer with what remains.
+ memcpy(buf + bufsize, data, end - data);
+ bytes += end - data;
+ }
+ return *this;
+}
+
+void CRIPEMD160::Finalize(unsigned char hash[OUTPUT_SIZE]) {
+ static const unsigned char pad[64] = {0x80};
+ unsigned char sizedesc[8];
+ WriteLE64(sizedesc, bytes << 3);
+ Write(pad, 1 + ((119 - (bytes % 64)) % 64));
+ Write(sizedesc, 8);
+ WriteLE32(hash, s[0]);
+ WriteLE32(hash+4, s[1]);
+ WriteLE32(hash+8, s[2]);
+ WriteLE32(hash+12, s[3]);
+ WriteLE32(hash+16, s[4]);
+}
+
+CRIPEMD160& CRIPEMD160::Reset() {
+ bytes = 0;
+ ripemd160::Initialize(s);
+ return *this;
+}
diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h
new file mode 100644
index 0000000000..44bd4879a5
--- /dev/null
+++ b/src/crypto/ripemd160.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_RIPEMD160_H
+#define BITCOIN_RIPEMD160_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** A hasher class for RIPEMD-160. */
+class CRIPEMD160 {
+private:
+ uint32_t s[5];
+ unsigned char buf[64];
+ size_t bytes;
+
+public:
+ static const size_t OUTPUT_SIZE = 20;
+
+ CRIPEMD160();
+ CRIPEMD160& Write(const unsigned char *data, size_t len);
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+ CRIPEMD160& Reset();
+};
+
+#endif
diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp
new file mode 100644
index 0000000000..304401a50f
--- /dev/null
+++ b/src/crypto/sha1.cpp
@@ -0,0 +1,192 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "crypto/sha1.h"
+
+#include "crypto/common.h"
+#include <string.h>
+
+// Internal implementation code.
+namespace {
+
+/// Internal SHA-1 implementation.
+namespace sha1 {
+
+/** One round of SHA-1. */
+void inline Round(uint32_t a, uint32_t &b, uint32_t c, uint32_t d, uint32_t &e,
+ uint32_t f, uint32_t k, uint32_t w) {
+ e += ((a << 5) | (a >> 27)) + f + k + w;
+ b = (b << 30) | (b >> 2);
+}
+
+uint32_t inline f1(uint32_t b, uint32_t c, uint32_t d) { return d ^ (b & (c ^ d)); }
+uint32_t inline f2(uint32_t b, uint32_t c, uint32_t d) { return b ^ c ^ d; }
+uint32_t inline f3(uint32_t b, uint32_t c, uint32_t d) { return (b & c) | (d & (b | c)); }
+
+uint32_t inline left(uint32_t x) { return (x << 1) | (x >> 31); }
+
+/** Initialize SHA-1 state. */
+void inline Initialize(uint32_t *s) {
+ s[0] = 0x67452301ul;
+ s[1] = 0xEFCDAB89ul;
+ s[2] = 0x98BADCFEul;
+ s[3] = 0x10325476ul;
+ s[4] = 0xC3D2E1F0ul;
+}
+
+const uint32_t k1 = 0x5A827999ul;
+const uint32_t k2 = 0x6ED9EBA1ul;
+const uint32_t k3 = 0x8F1BBCDCul;
+const uint32_t k4 = 0xCA62C1D6ul;
+
+/** Perform a SHA-1 transformation, processing a 64-byte chunk. */
+void Transform(uint32_t *s, const unsigned char *chunk) {
+ uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4];
+ uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
+
+ Round(a, b, c, d, e, f1(b, c, d), k1, w0 = ReadBE32(chunk + 0));
+ Round(e, a, b, c, d, f1(a, b, c), k1, w1 = ReadBE32(chunk + 4));
+ Round(d, e, a, b, c, f1(e, a, b), k1, w2 = ReadBE32(chunk + 8));
+ Round(c, d, e, a, b, f1(d, e, a), k1, w3 = ReadBE32(chunk + 12));
+ Round(b, c, d, e, a, f1(c, d, e), k1, w4 = ReadBE32(chunk + 16));
+ Round(a, b, c, d, e, f1(b, c, d), k1, w5 = ReadBE32(chunk + 20));
+ Round(e, a, b, c, d, f1(a, b, c), k1, w6 = ReadBE32(chunk + 24));
+ Round(d, e, a, b, c, f1(e, a, b), k1, w7 = ReadBE32(chunk + 28));
+ Round(c, d, e, a, b, f1(d, e, a), k1, w8 = ReadBE32(chunk + 32));
+ Round(b, c, d, e, a, f1(c, d, e), k1, w9 = ReadBE32(chunk + 36));
+ Round(a, b, c, d, e, f1(b, c, d), k1, w10 = ReadBE32(chunk + 40));
+ Round(e, a, b, c, d, f1(a, b, c), k1, w11 = ReadBE32(chunk + 44));
+ Round(d, e, a, b, c, f1(e, a, b), k1, w12 = ReadBE32(chunk + 48));
+ Round(c, d, e, a, b, f1(d, e, a), k1, w13 = ReadBE32(chunk + 52));
+ Round(b, c, d, e, a, f1(c, d, e), k1, w14 = ReadBE32(chunk + 56));
+ Round(a, b, c, d, e, f1(b, c, d), k1, w15 = ReadBE32(chunk + 60));
+
+ Round(e, a, b, c, d, f1(a, b, c), k1, w0 = left(w0 ^ w13 ^ w8 ^ w2 ));
+ Round(d, e, a, b, c, f1(e, a, b), k1, w1 = left(w1 ^ w14 ^ w9 ^ w3 ));
+ Round(c, d, e, a, b, f1(d, e, a), k1, w2 = left(w2 ^ w15 ^ w10 ^ w4 ));
+ Round(b, c, d, e, a, f1(c, d, e), k1, w3 = left(w3 ^ w0 ^ w11 ^ w5 ));
+ Round(a, b, c, d, e, f2(b, c, d), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6 ));
+ Round(e, a, b, c, d, f2(a, b, c), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7 ));
+ Round(d, e, a, b, c, f2(e, a, b), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8 ));
+ Round(c, d, e, a, b, f2(d, e, a), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9 ));
+ Round(b, c, d, e, a, f2(c, d, e), k2, w8 = left(w8 ^ w5 ^ w0 ^ w10));
+ Round(a, b, c, d, e, f2(b, c, d), k2, w9 = left(w9 ^ w6 ^ w1 ^ w11));
+ Round(e, a, b, c, d, f2(a, b, c), k2, w10 = left(w10 ^ w7 ^ w2 ^ w12));
+ Round(d, e, a, b, c, f2(e, a, b), k2, w11 = left(w11 ^ w8 ^ w3 ^ w13));
+ Round(c, d, e, a, b, f2(d, e, a), k2, w12 = left(w12 ^ w9 ^ w4 ^ w14));
+ Round(b, c, d, e, a, f2(c, d, e), k2, w13 = left(w13 ^ w10 ^ w5 ^ w15));
+ Round(a, b, c, d, e, f2(b, c, d), k2, w14 = left(w14 ^ w11 ^ w6 ^ w0 ));
+ Round(e, a, b, c, d, f2(a, b, c), k2, w15 = left(w15 ^ w12 ^ w7 ^ w1 ));
+
+ Round(d, e, a, b, c, f2(e, a, b), k2, w0 = left(w0 ^ w13 ^ w8 ^ w2 ));
+ Round(c, d, e, a, b, f2(d, e, a), k2, w1 = left(w1 ^ w14 ^ w9 ^ w3 ));
+ Round(b, c, d, e, a, f2(c, d, e), k2, w2 = left(w2 ^ w15 ^ w10 ^ w4 ));
+ Round(a, b, c, d, e, f2(b, c, d), k2, w3 = left(w3 ^ w0 ^ w11 ^ w5 ));
+ Round(e, a, b, c, d, f2(a, b, c), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6 ));
+ Round(d, e, a, b, c, f2(e, a, b), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7 ));
+ Round(c, d, e, a, b, f2(d, e, a), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8 ));
+ Round(b, c, d, e, a, f2(c, d, e), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9 ));
+ Round(a, b, c, d, e, f3(b, c, d), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10));
+ Round(e, a, b, c, d, f3(a, b, c), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11));
+ Round(d, e, a, b, c, f3(e, a, b), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12));
+ Round(c, d, e, a, b, f3(d, e, a), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13));
+ Round(b, c, d, e, a, f3(c, d, e), k3, w12 = left(w12 ^ w9 ^ w4 ^ w14));
+ Round(a, b, c, d, e, f3(b, c, d), k3, w13 = left(w13 ^ w10 ^ w5 ^ w15));
+ Round(e, a, b, c, d, f3(a, b, c), k3, w14 = left(w14 ^ w11 ^ w6 ^ w0 ));
+ Round(d, e, a, b, c, f3(e, a, b), k3, w15 = left(w15 ^ w12 ^ w7 ^ w1 ));
+
+ Round(c, d, e, a, b, f3(d, e, a), k3, w0 = left(w0 ^ w13 ^ w8 ^ w2 ));
+ Round(b, c, d, e, a, f3(c, d, e), k3, w1 = left(w1 ^ w14 ^ w9 ^ w3 ));
+ Round(a, b, c, d, e, f3(b, c, d), k3, w2 = left(w2 ^ w15 ^ w10 ^ w4 ));
+ Round(e, a, b, c, d, f3(a, b, c), k3, w3 = left(w3 ^ w0 ^ w11 ^ w5 ));
+ Round(d, e, a, b, c, f3(e, a, b), k3, w4 = left(w4 ^ w1 ^ w12 ^ w6 ));
+ Round(c, d, e, a, b, f3(d, e, a), k3, w5 = left(w5 ^ w2 ^ w13 ^ w7 ));
+ Round(b, c, d, e, a, f3(c, d, e), k3, w6 = left(w6 ^ w3 ^ w14 ^ w8 ));
+ Round(a, b, c, d, e, f3(b, c, d), k3, w7 = left(w7 ^ w4 ^ w15 ^ w9 ));
+ Round(e, a, b, c, d, f3(a, b, c), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10));
+ Round(d, e, a, b, c, f3(e, a, b), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11));
+ Round(c, d, e, a, b, f3(d, e, a), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12));
+ Round(b, c, d, e, a, f3(c, d, e), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13));
+ Round(a, b, c, d, e, f2(b, c, d), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14));
+ Round(e, a, b, c, d, f2(a, b, c), k4, w13 = left(w13 ^ w10 ^ w5 ^ w15));
+ Round(d, e, a, b, c, f2(e, a, b), k4, w14 = left(w14 ^ w11 ^ w6 ^ w0 ));
+ Round(c, d, e, a, b, f2(d, e, a), k4, w15 = left(w15 ^ w12 ^ w7 ^ w1 ));
+
+ Round(b, c, d, e, a, f2(c, d, e), k4, w0 = left(w0 ^ w13 ^ w8 ^ w2 ));
+ Round(a, b, c, d, e, f2(b, c, d), k4, w1 = left(w1 ^ w14 ^ w9 ^ w3 ));
+ Round(e, a, b, c, d, f2(a, b, c), k4, w2 = left(w2 ^ w15 ^ w10 ^ w4 ));
+ Round(d, e, a, b, c, f2(e, a, b), k4, w3 = left(w3 ^ w0 ^ w11 ^ w5 ));
+ Round(c, d, e, a, b, f2(d, e, a), k4, w4 = left(w4 ^ w1 ^ w12 ^ w6 ));
+ Round(b, c, d, e, a, f2(c, d, e), k4, w5 = left(w5 ^ w2 ^ w13 ^ w7 ));
+ Round(a, b, c, d, e, f2(b, c, d), k4, w6 = left(w6 ^ w3 ^ w14 ^ w8 ));
+ Round(e, a, b, c, d, f2(a, b, c), k4, w7 = left(w7 ^ w4 ^ w15 ^ w9 ));
+ Round(d, e, a, b, c, f2(e, a, b), k4, w8 = left(w8 ^ w5 ^ w0 ^ w10));
+ Round(c, d, e, a, b, f2(d, e, a), k4, w9 = left(w9 ^ w6 ^ w1 ^ w11));
+ Round(b, c, d, e, a, f2(c, d, e), k4, w10 = left(w10 ^ w7 ^ w2 ^ w12));
+ Round(a, b, c, d, e, f2(b, c, d), k4, w11 = left(w11 ^ w8 ^ w3 ^ w13));
+ Round(e, a, b, c, d, f2(a, b, c), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14));
+ Round(d, e, a, b, c, f2(e, a, b), k4, left(w13 ^ w10 ^ w5 ^ w15));
+ Round(c, d, e, a, b, f2(d, e, a), k4, left(w14 ^ w11 ^ w6 ^ w0 ));
+ Round(b, c, d, e, a, f2(c, d, e), k4, left(w15 ^ w12 ^ w7 ^ w1 ));
+
+ s[0] += a;
+ s[1] += b;
+ s[2] += c;
+ s[3] += d;
+ s[4] += e;
+}
+
+} // namespace sha1
+
+} // namespace
+
+////// SHA1
+
+CSHA1::CSHA1() : bytes(0) {
+ sha1::Initialize(s);
+}
+
+CSHA1& CSHA1::Write(const unsigned char *data, size_t len) {
+ const unsigned char *end = data + len;
+ size_t bufsize = bytes % 64;
+ if (bufsize && bufsize + len >= 64) {
+ // Fill the buffer, and process it.
+ memcpy(buf + bufsize, data, 64 - bufsize);
+ bytes += 64 - bufsize;
+ data += 64 - bufsize;
+ sha1::Transform(s, buf);
+ bufsize = 0;
+ }
+ while (end >= data + 64) {
+ // Process full chunks directly from the source.
+ sha1::Transform(s, data);
+ bytes += 64;
+ data += 64;
+ }
+ if (end > data) {
+ // Fill the buffer with what remains.
+ memcpy(buf + bufsize, data, end - data);
+ bytes += end - data;
+ }
+ return *this;
+}
+
+void CSHA1::Finalize(unsigned char hash[OUTPUT_SIZE]) {
+ static const unsigned char pad[64] = {0x80};
+ unsigned char sizedesc[8];
+ WriteBE64(sizedesc, bytes << 3);
+ Write(pad, 1 + ((119 - (bytes % 64)) % 64));
+ Write(sizedesc, 8);
+ WriteBE32(hash, s[0]);
+ WriteBE32(hash+4, s[1]);
+ WriteBE32(hash+8, s[2]);
+ WriteBE32(hash+12, s[3]);
+ WriteBE32(hash+16, s[4]);
+}
+
+CSHA1& CSHA1::Reset() {
+ bytes = 0;
+ sha1::Initialize(s);
+ return *this;
+}
diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h
new file mode 100644
index 0000000000..b16f2c88ce
--- /dev/null
+++ b/src/crypto/sha1.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_SHA1_H
+#define BITCOIN_SHA1_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** A hasher class for SHA1. */
+class CSHA1 {
+private:
+ uint32_t s[5];
+ unsigned char buf[64];
+ size_t bytes;
+
+public:
+ static const size_t OUTPUT_SIZE = 20;
+
+ CSHA1();
+ CSHA1& Write(const unsigned char *data, size_t len);
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+ CSHA1& Reset();
+};
+
+#endif
diff --git a/src/crypto/sha2.cpp b/src/crypto/sha2.cpp
new file mode 100644
index 0000000000..99a251cb12
--- /dev/null
+++ b/src/crypto/sha2.cpp
@@ -0,0 +1,398 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "crypto/sha2.h"
+
+#include "crypto/common.h"
+#include <string.h>
+
+// Internal implementation code.
+namespace {
+
+/// Internal SHA-256 implementation.
+namespace sha256 {
+
+uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); }
+uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); }
+uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); }
+uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); }
+uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); }
+uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); }
+
+/** One round of SHA-256. */
+void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t &d,
+ uint32_t e, uint32_t f, uint32_t g, uint32_t &h,
+ uint32_t k, uint32_t w) {
+ uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
+ uint32_t t2 = Sigma0(a) + Maj(a, b, c);
+ d += t1;
+ h = t1 + t2;
+}
+
+/** Initialize SHA-256 state. */
+void inline Initialize(uint32_t *s) {
+ s[0] = 0x6a09e667ul;
+ s[1] = 0xbb67ae85ul;
+ s[2] = 0x3c6ef372ul;
+ s[3] = 0xa54ff53aul;
+ s[4] = 0x510e527ful;
+ s[5] = 0x9b05688cul;
+ s[6] = 0x1f83d9abul;
+ s[7] = 0x5be0cd19ul;
+}
+
+/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
+void Transform(uint32_t *s, const unsigned char *chunk) {
+ 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;
+}
+
+} // namespace sha256
+
+/// Internal SHA-512 implementation.
+namespace sha512 {
+
+uint64_t inline Ch(uint64_t x, uint64_t y, uint64_t z) { return z ^ (x & (y ^ z)); }
+uint64_t inline Maj(uint64_t x, uint64_t y, uint64_t z) { return (x & y) | (z & (x | y)); }
+uint64_t inline Sigma0(uint64_t x) { return (x >> 28 | x << 36) ^ (x >> 34 | x << 30) ^ (x >> 39 | x << 25); }
+uint64_t inline Sigma1(uint64_t x) { return (x >> 14 | x << 50) ^ (x >> 18 | x << 46) ^ (x >> 41 | x << 23); }
+uint64_t inline sigma0(uint64_t x) { return (x >> 1 | x << 63) ^ (x >> 8 | x << 56) ^ (x >> 7); }
+uint64_t inline sigma1(uint64_t x) { return (x >> 19 | x << 45) ^ (x >> 61 | x << 3) ^ (x >> 6); }
+
+/** One round of SHA-512. */
+void inline Round(uint64_t a, uint64_t b, uint64_t c, uint64_t &d,
+ uint64_t e, uint64_t f, uint64_t g, uint64_t &h,
+ uint64_t k, uint64_t w) {
+ uint64_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
+ uint64_t t2 = Sigma0(a) + Maj(a, b, c);
+ d += t1;
+ h = t1 + t2;
+}
+
+/** Initialize SHA-256 state. */
+void inline Initialize(uint64_t *s) {
+ s[0] = 0x6a09e667f3bcc908ull;
+ s[1] = 0xbb67ae8584caa73bull;
+ s[2] = 0x3c6ef372fe94f82bull;
+ s[3] = 0xa54ff53a5f1d36f1ull;
+ s[4] = 0x510e527fade682d1ull;
+ s[5] = 0x9b05688c2b3e6c1full;
+ s[6] = 0x1f83d9abfb41bd6bull;
+ s[7] = 0x5be0cd19137e2179ull;
+}
+
+/** Perform one SHA-512 transformation, processing a 128-byte chunk. */
+void Transform(uint64_t *s, const unsigned char *chunk) {
+ uint64_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];
+ uint64_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, 0x428a2f98d728ae22ull, w0 = ReadBE64(chunk + 0));
+ Round(h, a, b, c, d, e, f, g, 0x7137449123ef65cdull, w1 = ReadBE64(chunk + 8));
+ Round(g, h, a, b, c, d, e, f, 0xb5c0fbcfec4d3b2full, w2 = ReadBE64(chunk + 16));
+ Round(f, g, h, a, b, c, d, e, 0xe9b5dba58189dbbcull, w3 = ReadBE64(chunk + 24));
+ Round(e, f, g, h, a, b, c, d, 0x3956c25bf348b538ull, w4 = ReadBE64(chunk + 32));
+ Round(d, e, f, g, h, a, b, c, 0x59f111f1b605d019ull, w5 = ReadBE64(chunk + 40));
+ Round(c, d, e, f, g, h, a, b, 0x923f82a4af194f9bull, w6 = ReadBE64(chunk + 48));
+ Round(b, c, d, e, f, g, h, a, 0xab1c5ed5da6d8118ull, w7 = ReadBE64(chunk + 56));
+ Round(a, b, c, d, e, f, g, h, 0xd807aa98a3030242ull, w8 = ReadBE64(chunk + 64));
+ Round(h, a, b, c, d, e, f, g, 0x12835b0145706fbeull, w9 = ReadBE64(chunk + 72));
+ Round(g, h, a, b, c, d, e, f, 0x243185be4ee4b28cull, w10 = ReadBE64(chunk + 80));
+ Round(f, g, h, a, b, c, d, e, 0x550c7dc3d5ffb4e2ull, w11 = ReadBE64(chunk + 88));
+ Round(e, f, g, h, a, b, c, d, 0x72be5d74f27b896full, w12 = ReadBE64(chunk + 96));
+ Round(d, e, f, g, h, a, b, c, 0x80deb1fe3b1696b1ull, w13 = ReadBE64(chunk + 104));
+ Round(c, d, e, f, g, h, a, b, 0x9bdc06a725c71235ull, w14 = ReadBE64(chunk + 112));
+ Round(b, c, d, e, f, g, h, a, 0xc19bf174cf692694ull, w15 = ReadBE64(chunk + 120));
+
+ Round(a, b, c, d, e, f, g, h, 0xe49b69c19ef14ad2ull, w0 += sigma1(w14) + w9 + sigma0( w1));
+ Round(h, a, b, c, d, e, f, g, 0xefbe4786384f25e3ull, w1 += sigma1(w15) + w10 + sigma0( w2));
+ Round(g, h, a, b, c, d, e, f, 0x0fc19dc68b8cd5b5ull, w2 += sigma1( w0) + w11 + sigma0( w3));
+ Round(f, g, h, a, b, c, d, e, 0x240ca1cc77ac9c65ull, w3 += sigma1( w1) + w12 + sigma0( w4));
+ Round(e, f, g, h, a, b, c, d, 0x2de92c6f592b0275ull, w4 += sigma1( w2) + w13 + sigma0( w5));
+ Round(d, e, f, g, h, a, b, c, 0x4a7484aa6ea6e483ull, w5 += sigma1( w3) + w14 + sigma0( w6));
+ Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcbd41fbd4ull, w6 += sigma1( w4) + w15 + sigma0( w7));
+ Round(b, c, d, e, f, g, h, a, 0x76f988da831153b5ull, w7 += sigma1( w5) + w0 + sigma0( w8));
+ Round(a, b, c, d, e, f, g, h, 0x983e5152ee66dfabull, w8 += sigma1( w6) + w1 + sigma0( w9));
+ Round(h, a, b, c, d, e, f, g, 0xa831c66d2db43210ull, w9 += sigma1( w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0xb00327c898fb213full, w10 += sigma1( w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0xbf597fc7beef0ee4ull, w11 += sigma1( w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0xc6e00bf33da88fc2ull, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0xd5a79147930aa725ull, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0x06ca6351e003826full, w14 += sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0x142929670a0e6e70ull, w15 += sigma1(w13) + w8 + sigma0( w0));
+
+ Round(a, b, c, d, e, f, g, h, 0x27b70a8546d22ffcull, w0 += sigma1(w14) + w9 + sigma0( w1));
+ Round(h, a, b, c, d, e, f, g, 0x2e1b21385c26c926ull, w1 += sigma1(w15) + w10 + sigma0( w2));
+ Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc5ac42aedull, w2 += sigma1( w0) + w11 + sigma0( w3));
+ Round(f, g, h, a, b, c, d, e, 0x53380d139d95b3dfull, w3 += sigma1( w1) + w12 + sigma0( w4));
+ Round(e, f, g, h, a, b, c, d, 0x650a73548baf63deull, w4 += sigma1( w2) + w13 + sigma0( w5));
+ Round(d, e, f, g, h, a, b, c, 0x766a0abb3c77b2a8ull, w5 += sigma1( w3) + w14 + sigma0( w6));
+ Round(c, d, e, f, g, h, a, b, 0x81c2c92e47edaee6ull, w6 += sigma1( w4) + w15 + sigma0( w7));
+ Round(b, c, d, e, f, g, h, a, 0x92722c851482353bull, w7 += sigma1( w5) + w0 + sigma0( w8));
+ Round(a, b, c, d, e, f, g, h, 0xa2bfe8a14cf10364ull, w8 += sigma1( w6) + w1 + sigma0( w9));
+ Round(h, a, b, c, d, e, f, g, 0xa81a664bbc423001ull, w9 += sigma1( w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0xc24b8b70d0f89791ull, w10 += sigma1( w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0xc76c51a30654be30ull, w11 += sigma1( w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0xd192e819d6ef5218ull, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0xd69906245565a910ull, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0xf40e35855771202aull, w14 += sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0x106aa07032bbd1b8ull, w15 += sigma1(w13) + w8 + sigma0( w0));
+
+ Round(a, b, c, d, e, f, g, h, 0x19a4c116b8d2d0c8ull, w0 += sigma1(w14) + w9 + sigma0( w1));
+ Round(h, a, b, c, d, e, f, g, 0x1e376c085141ab53ull, w1 += sigma1(w15) + w10 + sigma0( w2));
+ Round(g, h, a, b, c, d, e, f, 0x2748774cdf8eeb99ull, w2 += sigma1( w0) + w11 + sigma0( w3));
+ Round(f, g, h, a, b, c, d, e, 0x34b0bcb5e19b48a8ull, w3 += sigma1( w1) + w12 + sigma0( w4));
+ Round(e, f, g, h, a, b, c, d, 0x391c0cb3c5c95a63ull, w4 += sigma1( w2) + w13 + sigma0( w5));
+ Round(d, e, f, g, h, a, b, c, 0x4ed8aa4ae3418acbull, w5 += sigma1( w3) + w14 + sigma0( w6));
+ Round(c, d, e, f, g, h, a, b, 0x5b9cca4f7763e373ull, w6 += sigma1( w4) + w15 + sigma0( w7));
+ Round(b, c, d, e, f, g, h, a, 0x682e6ff3d6b2b8a3ull, w7 += sigma1( w5) + w0 + sigma0( w8));
+ Round(a, b, c, d, e, f, g, h, 0x748f82ee5defb2fcull, w8 += sigma1( w6) + w1 + sigma0( w9));
+ Round(h, a, b, c, d, e, f, g, 0x78a5636f43172f60ull, w9 += sigma1( w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0x84c87814a1f0ab72ull, w10 += sigma1( w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0x8cc702081a6439ecull, w11 += sigma1( w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0x90befffa23631e28ull, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0xa4506cebde82bde9ull, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0xbef9a3f7b2c67915ull, w14 += sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0xc67178f2e372532bull, w15 += sigma1(w13) + w8 + sigma0( w0));
+
+ Round(a, b, c, d, e, f, g, h, 0xca273eceea26619cull, w0 += sigma1(w14) + w9 + sigma0( w1));
+ Round(h, a, b, c, d, e, f, g, 0xd186b8c721c0c207ull, w1 += sigma1(w15) + w10 + sigma0( w2));
+ Round(g, h, a, b, c, d, e, f, 0xeada7dd6cde0eb1eull, w2 += sigma1( w0) + w11 + sigma0( w3));
+ Round(f, g, h, a, b, c, d, e, 0xf57d4f7fee6ed178ull, w3 += sigma1( w1) + w12 + sigma0( w4));
+ Round(e, f, g, h, a, b, c, d, 0x06f067aa72176fbaull, w4 += sigma1( w2) + w13 + sigma0( w5));
+ Round(d, e, f, g, h, a, b, c, 0x0a637dc5a2c898a6ull, w5 += sigma1( w3) + w14 + sigma0( w6));
+ Round(c, d, e, f, g, h, a, b, 0x113f9804bef90daeull, w6 += sigma1( w4) + w15 + sigma0( w7));
+ Round(b, c, d, e, f, g, h, a, 0x1b710b35131c471bull, w7 += sigma1( w5) + w0 + sigma0( w8));
+ Round(a, b, c, d, e, f, g, h, 0x28db77f523047d84ull, w8 += sigma1( w6) + w1 + sigma0( w9));
+ Round(h, a, b, c, d, e, f, g, 0x32caab7b40c72493ull, w9 += sigma1( w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0x3c9ebe0a15c9bebcull, w10 += sigma1( w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1( w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 += sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, 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;
+}
+
+} // namespace sha512
+
+} // namespace
+
+
+////// SHA-256
+
+CSHA256::CSHA256() : bytes(0) {
+ sha256::Initialize(s);
+}
+
+CSHA256& CSHA256::Write(const unsigned char *data, size_t len) {
+ const unsigned char *end = data + len;
+ size_t bufsize = bytes % 64;
+ if (bufsize && bufsize + len >= 64) {
+ // Fill the buffer, and process it.
+ memcpy(buf + bufsize, data, 64 - bufsize);
+ bytes += 64 - bufsize;
+ data += 64 - bufsize;
+ sha256::Transform(s, buf);
+ bufsize = 0;
+ }
+ while (end >= data + 64) {
+ // Process full chunks directly from the source.
+ sha256::Transform(s, data);
+ bytes += 64;
+ data += 64;
+ }
+ if (end > data) {
+ // Fill the buffer with what remains.
+ memcpy(buf + bufsize, data, end - data);
+ bytes += end - data;
+ }
+ return *this;
+}
+
+void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) {
+ static const unsigned char pad[64] = {0x80};
+ unsigned char sizedesc[8];
+ WriteBE64(sizedesc, bytes << 3);
+ Write(pad, 1 + ((119 - (bytes % 64)) % 64));
+ Write(sizedesc, 8);
+ WriteBE32(hash, s[0]);
+ WriteBE32(hash+4, s[1]);
+ WriteBE32(hash+8, s[2]);
+ WriteBE32(hash+12, s[3]);
+ WriteBE32(hash+16, s[4]);
+ WriteBE32(hash+20, s[5]);
+ WriteBE32(hash+24, s[6]);
+ WriteBE32(hash+28, s[7]);
+}
+
+CSHA256& CSHA256::Reset() {
+ bytes = 0;
+ sha256::Initialize(s);
+ return *this;
+}
+
+////// SHA-512
+
+CSHA512::CSHA512() : bytes(0) {
+ sha512::Initialize(s);
+}
+
+CSHA512& CSHA512::Write(const unsigned char *data, size_t len) {
+ const unsigned char *end = data + len;
+ size_t bufsize = bytes % 128;
+ if (bufsize && bufsize + len >= 128) {
+ // Fill the buffer, and process it.
+ memcpy(buf + bufsize, data, 128 - bufsize);
+ bytes += 128 - bufsize;
+ data += 128 - bufsize;
+ sha512::Transform(s, buf);
+ bufsize = 0;
+ }
+ while (end >= data + 128) {
+ // Process full chunks directly from the source.
+ sha512::Transform(s, data);
+ data += 128;
+ bytes += 128;
+ }
+ if (end > data) {
+ // Fill the buffer with what remains.
+ memcpy(buf + bufsize, data, end - data);
+ bytes += end - data;
+ }
+ return *this;
+}
+
+void CSHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) {
+ static const unsigned char pad[128] = {0x80};
+ unsigned char sizedesc[16] = {0x00};
+ WriteBE64(sizedesc+8, bytes << 3);
+ Write(pad, 1 + ((239 - (bytes % 128)) % 128));
+ Write(sizedesc, 16);
+ WriteBE64(hash, s[0]);
+ WriteBE64(hash+8, s[1]);
+ WriteBE64(hash+16, s[2]);
+ WriteBE64(hash+24, s[3]);
+ WriteBE64(hash+32, s[4]);
+ WriteBE64(hash+40, s[5]);
+ WriteBE64(hash+48, s[6]);
+ WriteBE64(hash+56, s[7]);
+}
+
+CSHA512& CSHA512::Reset() {
+ bytes = 0;
+ sha512::Initialize(s);
+ return *this;
+}
+
+////// HMAC-SHA-512
+
+CHMAC_SHA512::CHMAC_SHA512(const unsigned char *key, size_t keylen) {
+ unsigned char rkey[128];
+ if (keylen <= 128) {
+ memcpy(rkey, key, keylen);
+ memset(rkey + keylen, 0, 128 - keylen);
+ } else {
+ CSHA512().Write(key, keylen).Finalize(rkey);
+ memset(rkey + 64, 0, 64);
+ }
+
+ for (int n=0; n<128; n++)
+ rkey[n] ^= 0x5c;
+ outer.Write(rkey, 128);
+
+ for (int n=0; n<128; n++)
+ rkey[n] ^= 0x5c ^ 0x36;
+ inner.Write(rkey, 128);
+}
+
+void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) {
+ unsigned char temp[64];
+ inner.Finalize(temp);
+ outer.Write(temp, 64).Finalize(hash);
+}
diff --git a/src/crypto/sha2.h b/src/crypto/sha2.h
new file mode 100644
index 0000000000..088d5e194c
--- /dev/null
+++ b/src/crypto/sha2.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_SHA2_H
+#define BITCOIN_SHA2_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** A hasher class for SHA-256. */
+class CSHA256 {
+private:
+ uint32_t s[8];
+ unsigned char buf[64];
+ size_t bytes;
+
+public:
+ static const size_t OUTPUT_SIZE = 32;
+
+ CSHA256();
+ CSHA256& Write(const unsigned char *data, size_t len);
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+ CSHA256& Reset();
+};
+
+/** A hasher class for SHA-512. */
+class CSHA512 {
+private:
+ uint64_t s[8];
+ unsigned char buf[128];
+ size_t bytes;
+
+public:
+ static const size_t OUTPUT_SIZE = 64;
+
+ CSHA512();
+ CSHA512& Write(const unsigned char *data, size_t len);
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+ CSHA512& Reset();
+};
+
+/** A hasher class for HMAC-SHA-512. */
+class CHMAC_SHA512 {
+private:
+ CSHA512 outer;
+ CSHA512 inner;
+
+public:
+ static const size_t OUTPUT_SIZE = 64;
+
+ CHMAC_SHA512(const unsigned char *key, size_t keylen);
+ CHMAC_SHA512& Write(const unsigned char *data, size_t len) {
+ inner.Write(data, len);
+ return *this;
+ }
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+};
+
+#endif
diff --git a/src/hash.cpp b/src/hash.cpp
index 7b054bd154..bddd8abf38 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -56,44 +56,3 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
return h1;
}
-
-int HMAC_SHA512_Init(HMAC_SHA512_CTX *pctx, const void *pkey, size_t len)
-{
- unsigned char key[128];
- if (len <= 128)
- {
- memcpy(key, pkey, len);
- memset(key + len, 0, 128-len);
- }
- else
- {
- SHA512_CTX ctxKey;
- SHA512_Init(&ctxKey);
- SHA512_Update(&ctxKey, pkey, len);
- SHA512_Final(key, &ctxKey);
- memset(key + 64, 0, 64);
- }
-
- for (int n=0; n<128; n++)
- key[n] ^= 0x5c;
- SHA512_Init(&pctx->ctxOuter);
- SHA512_Update(&pctx->ctxOuter, key, 128);
-
- for (int n=0; n<128; n++)
- key[n] ^= 0x5c ^ 0x36;
- SHA512_Init(&pctx->ctxInner);
- return SHA512_Update(&pctx->ctxInner, key, 128);
-}
-
-int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len)
-{
- return SHA512_Update(&pctx->ctxInner, pdata, len);
-}
-
-int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx)
-{
- unsigned char buf[64];
- SHA512_Final(buf, &pctx->ctxInner);
- SHA512_Update(&pctx->ctxOuter, buf, 64);
- return SHA512_Final(pmd, &pctx->ctxOuter);
-}
diff --git a/src/hash.h b/src/hash.h
index 7dbf1b6448..f2a0ebfe1f 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -6,55 +6,138 @@
#ifndef BITCOIN_HASH_H
#define BITCOIN_HASH_H
+#include "crypto/sha2.h"
+#include "crypto/ripemd160.h"
#include "serialize.h"
#include "uint256.h"
#include "version.h"
#include <vector>
-#include <openssl/ripemd.h>
-#include <openssl/sha.h>
+/** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */
+class CHash256 {
+private:
+ CSHA256 sha;
+public:
+ static const size_t OUTPUT_SIZE = CSHA256::OUTPUT_SIZE;
+
+ void Finalize(unsigned char hash[OUTPUT_SIZE]) {
+ unsigned char buf[sha.OUTPUT_SIZE];
+ sha.Finalize(buf);
+ sha.Reset().Write(buf, sha.OUTPUT_SIZE).Finalize(hash);
+ }
+
+ CHash256& Write(const unsigned char *data, size_t len) {
+ sha.Write(data, len);
+ return *this;
+ }
+
+ CHash256& Reset() {
+ sha.Reset();
+ return *this;
+ }
+};
+/** A hasher class for Bitcoin's 160-bit hash (SHA-256 + RIPEMD-160). */
+class CHash160 {
+private:
+ CSHA256 sha;
+public:
+ static const size_t OUTPUT_SIZE = CRIPEMD160::OUTPUT_SIZE;
+
+ void Finalize(unsigned char hash[OUTPUT_SIZE]) {
+ unsigned char buf[sha.OUTPUT_SIZE];
+ sha.Finalize(buf);
+ CRIPEMD160().Write(buf, sha.OUTPUT_SIZE).Finalize(hash);
+ }
+
+ CHash160& Write(const unsigned char *data, size_t len) {
+ sha.Write(data, len);
+ return *this;
+ }
+
+ CHash160& Reset() {
+ sha.Reset();
+ return *this;
+ }
+};
+
+/** Compute the 256-bit hash of an object. */
template<typename T1>
inline uint256 Hash(const T1 pbegin, const T1 pend)
{
- static unsigned char pblank[1];
- uint256 hash1;
- SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);
- uint256 hash2;
- SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
- return hash2;
+ static const unsigned char pblank[1] = {};
+ uint256 result;
+ CHash256().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0]))
+ .Finalize((unsigned char*)&result);
+ return result;
+}
+
+/** Compute the 256-bit hash of the concatenation of two objects. */
+template<typename T1, typename T2>
+inline uint256 Hash(const T1 p1begin, const T1 p1end,
+ const T2 p2begin, const T2 p2end) {
+ static const unsigned char pblank[1] = {};
+ uint256 result;
+ CHash256().Write(p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]))
+ .Write(p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]))
+ .Finalize((unsigned char*)&result);
+ return result;
+}
+
+/** Compute the 256-bit hash of the concatenation of three objects. */
+template<typename T1, typename T2, typename T3>
+inline uint256 Hash(const T1 p1begin, const T1 p1end,
+ const T2 p2begin, const T2 p2end,
+ const T3 p3begin, const T3 p3end) {
+ static const unsigned char pblank[1] = {};
+ uint256 result;
+ CHash256().Write(p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]))
+ .Write(p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]))
+ .Write(p3begin == p3end ? pblank : (const unsigned char*)&p3begin[0], (p3end - p3begin) * sizeof(p3begin[0]))
+ .Finalize((unsigned char*)&result);
+ return result;
+}
+
+/** Compute the 160-bit hash an object. */
+template<typename T1>
+inline uint160 Hash160(const T1 pbegin, const T1 pend)
+{
+ static unsigned char pblank[1] = {};
+ uint160 result;
+ CHash160().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0]))
+ .Finalize((unsigned char*)&result);
+ return result;
}
+/** Compute the 160-bit hash of a vector. */
+inline uint160 Hash160(const std::vector<unsigned char>& vch)
+{
+ return Hash160(vch.begin(), vch.end());
+}
+
+/** A writer stream (for serialization) that computes a 256-bit hash. */
class CHashWriter
{
private:
- SHA256_CTX ctx;
+ CHash256 ctx;
public:
int nType;
int nVersion;
- void Init() {
- SHA256_Init(&ctx);
- }
-
- CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {
- Init();
- }
+ CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {}
CHashWriter& write(const char *pch, size_t size) {
- SHA256_Update(&ctx, pch, size);
+ ctx.Write((const unsigned char*)pch, size);
return (*this);
}
// invalidates the object
uint256 GetHash() {
- uint256 hash1;
- SHA256_Final((unsigned char*)&hash1, &ctx);
- uint256 hash2;
- SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
- return hash2;
+ uint256 result;
+ ctx.Finalize((unsigned char*)&result);
+ return result;
}
template<typename T>
@@ -65,41 +148,7 @@ public:
}
};
-
-template<typename T1, typename T2>
-inline uint256 Hash(const T1 p1begin, const T1 p1end,
- const T2 p2begin, const T2 p2end)
-{
- static unsigned char pblank[1];
- uint256 hash1;
- SHA256_CTX ctx;
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0]));
- SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0]));
- SHA256_Final((unsigned char*)&hash1, &ctx);
- uint256 hash2;
- SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
- return hash2;
-}
-
-template<typename T1, typename T2, typename T3>
-inline uint256 Hash(const T1 p1begin, const T1 p1end,
- const T2 p2begin, const T2 p2end,
- const T3 p3begin, const T3 p3end)
-{
- static unsigned char pblank[1];
- uint256 hash1;
- SHA256_CTX ctx;
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0]));
- SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0]));
- SHA256_Update(&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof(p3begin[0]));
- SHA256_Final((unsigned char*)&hash1, &ctx);
- uint256 hash2;
- SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
- return hash2;
-}
-
+/** Compute the 256-bit hash of an object's serialization. */
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
{
@@ -108,32 +157,6 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
return ss.GetHash();
}
-template<typename T1>
-inline uint160 Hash160(const T1 pbegin, const T1 pend)
-{
- static unsigned char pblank[1];
- uint256 hash1;
- SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);
- uint160 hash2;
- RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
- return hash2;
-}
-
-inline uint160 Hash160(const std::vector<unsigned char>& vch)
-{
- return Hash160(vch.begin(), vch.end());
-}
-
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
-typedef struct
-{
- SHA512_CTX ctxInner;
- SHA512_CTX ctxOuter;
-} HMAC_SHA512_CTX;
-
-int HMAC_SHA512_Init(HMAC_SHA512_CTX *pctx, const void *pkey, size_t len);
-int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len);
-int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx);
-
#endif
diff --git a/src/init.cpp b/src/init.cpp
index b9af16a156..7ef3bc5dac 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -4,7 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "init.h"
@@ -31,6 +31,7 @@
#ifndef WIN32
#include <signal.h>
#endif
+#include "compat/sanity.h"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
@@ -115,7 +116,6 @@ void Shutdown()
RenameThread("bitcoin-shutoff");
mempool.AddTransactionsUpdated(1);
StopRPCThreads();
- ShutdownRPCMining();
#ifdef ENABLE_WALLET
if (pwalletMain)
bitdb.Flush(false);
@@ -195,8 +195,9 @@ bool static Bind(const CService &addr, unsigned int flags) {
return true;
}
-std::string HelpMessage(HelpMessageMode hmm)
+std::string HelpMessage(HelpMessageMode mode)
{
+ // When adding new options to the categories, please keep and ensure alphabetical ordering.
string strUsage = _("Options:") + "\n";
strUsage += " -? " + _("This help message") + "\n";
strUsage += " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)") + "\n";
@@ -204,7 +205,7 @@ std::string HelpMessage(HelpMessageMode hmm)
strUsage += " -checkblocks=<n> " + _("How many blocks to check at startup (default: 288, 0 = all)") + "\n";
strUsage += " -checklevel=<n> " + _("How thorough the block verification of -checkblocks is (0-4, default: 3)") + "\n";
strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n";
- if (hmm == HMM_BITCOIND)
+ if (mode == HMM_BITCOIND)
{
#if !defined(WIN32)
strUsage += " -daemon " + _("Run in the background as a daemon and accept commands") + "\n";
@@ -274,12 +275,13 @@ std::string HelpMessage(HelpMessageMode hmm)
strUsage += " -dropmessagestest=<n> " + _("Randomly drop 1 of every <n> network messages") + "\n";
strUsage += " -fuzzmessagestest=<n> " + _("Randomly fuzz 1 of every <n> network messages") + "\n";
strUsage += " -flushwallet " + _("Run a thread to flush wallet periodically (default: 1)") + "\n";
+ strUsage += " -stopafterblockimport " + _("Stop running after importing blocks from disk (default: 0)") + "\n";
}
strUsage += " -debug=<category> " + _("Output debugging information (default: 0, supplying <category> is optional)") + "\n";
strUsage += " " + _("If <category> is not supplied, output all debugging information.") + "\n";
strUsage += " " + _("<category> can be:");
strUsage += " addrman, alert, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below
- if (hmm == HMM_BITCOIN_QT)
+ if (mode == HMM_BITCOIN_QT)
strUsage += ", qt";
strUsage += ".\n";
strUsage += " -gen " + _("Generate coins (default: 0)") + "\n";
@@ -405,6 +407,11 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
LogPrintf("Warning: Could not open blocks file %s\n", path.string());
}
}
+
+ if (GetBoolArg("-stopafterblockimport", false)) {
+ LogPrintf("Stopping after block import\n");
+ StartShutdown();
+ }
}
/** Sanity checks
@@ -418,8 +425,8 @@ bool InitSanityCheck(void)
"information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries");
return false;
}
-
- // TODO: remaining sanity checks, see #4081
+ if (!glibc_sanity_test() || !glibcxx_sanity_test())
+ return false;
return true;
}
@@ -1168,8 +1175,6 @@ bool AppInit2(boost::thread_group& threadGroup)
#endif
StartNode(threadGroup);
- // InitRPCMining is needed here so getwork/getblocktemplate in the GUI debug console works properly.
- InitRPCMining();
if (fServer)
StartRPCThreads();
diff --git a/src/key.cpp b/src/key.cpp
index 4747beffb4..96b1ac439c 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -4,6 +4,8 @@
#include "key.h"
+#include "crypto/sha2.h"
+
#include <openssl/bn.h>
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>
@@ -510,12 +512,10 @@ void static BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, un
num[1] = (nChild >> 16) & 0xFF;
num[2] = (nChild >> 8) & 0xFF;
num[3] = (nChild >> 0) & 0xFF;
- HMAC_SHA512_CTX ctx;
- HMAC_SHA512_Init(&ctx, chainCode, 32);
- HMAC_SHA512_Update(&ctx, &header, 1);
- HMAC_SHA512_Update(&ctx, data, 32);
- HMAC_SHA512_Update(&ctx, num, 4);
- HMAC_SHA512_Final(output, &ctx);
+ CHMAC_SHA512(chainCode, 32).Write(&header, 1)
+ .Write(data, 32)
+ .Write(num, 4)
+ .Finalize(output);
}
bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
@@ -562,13 +562,10 @@ bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
}
void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
- static const char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
- HMAC_SHA512_CTX ctx;
- HMAC_SHA512_Init(&ctx, hashkey, sizeof(hashkey));
- HMAC_SHA512_Update(&ctx, seed, nSeedLen);
+ static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
unsigned char out[64];
LockObject(out);
- HMAC_SHA512_Final(out, &ctx);
+ CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out);
key.Set(&out[0], &out[32], true);
memcpy(vchChainCode, &out[32], 32);
UnlockObject(out);
diff --git a/src/main.cpp b/src/main.cpp
index 98e1741954..d3f04b95fa 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -130,8 +130,8 @@ namespace {
namespace {
struct CMainSignals {
- // Notifies listeners of updated transaction data (passing hash, transaction, and optionally the block it is found in.
- boost::signals2::signal<void (const uint256 &, const CTransaction &, const CBlock *)> SyncTransaction;
+ // Notifies listeners of updated transaction data (transaction, and optionally the block it is found in.
+ boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
// Notifies listeners of an erased transaction (currently disabled, requires transaction replacement).
boost::signals2::signal<void (const uint256 &)> EraseTransaction;
// Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible).
@@ -146,7 +146,7 @@ struct CMainSignals {
}
void RegisterWallet(CWalletInterface* pwalletIn) {
- g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2, _3));
+ g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2));
g_signals.EraseTransaction.connect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1));
g_signals.UpdatedTransaction.connect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.SetBestChain.connect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
@@ -160,7 +160,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn) {
g_signals.SetBestChain.disconnect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
g_signals.UpdatedTransaction.disconnect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.EraseTransaction.disconnect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1));
- g_signals.SyncTransaction.disconnect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2, _3));
+ g_signals.SyncTransaction.disconnect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2));
}
void UnregisterAllWallets() {
@@ -172,8 +172,8 @@ void UnregisterAllWallets() {
g_signals.SyncTransaction.disconnect_all_slots();
}
-void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) {
- g_signals.SyncTransaction(hash, tx, pblock);
+void SyncWithWallets(const CTransaction &tx, const CBlock *pblock) {
+ g_signals.SyncTransaction(tx, pblock);
}
//////////////////////////////////////////////////////////////////////////////
@@ -952,7 +952,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
pool.addUnchecked(hash, entry);
}
- g_signals.SyncTransaction(hash, tx, NULL);
+ g_signals.SyncTransaction(tx, NULL);
return true;
}
@@ -1479,7 +1479,7 @@ void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev)
-void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash)
+void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight)
{
bool ret;
// mark inputs spent
@@ -1494,7 +1494,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
}
// add outputs
- ret = inputs.SetCoins(txhash, CCoins(tx, nHeight));
+ ret = inputs.SetCoins(tx.GetHash(), CCoins(tx, nHeight));
assert(ret);
}
@@ -1767,8 +1767,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
!((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
if (fEnforceBIP30) {
- for (unsigned int i = 0; i < block.vtx.size(); i++) {
- uint256 hash = block.GetTxHash(i);
+ BOOST_FOREACH(const CTransaction& tx, block.vtx) {
+ const uint256& hash = tx.GetHash();
if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned())
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"),
REJECT_INVALID, "bad-txns-BIP30");
@@ -1829,11 +1829,11 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
}
CTxUndo txundo;
- UpdateCoins(tx, state, view, txundo, pindex->nHeight, block.GetTxHash(i));
+ UpdateCoins(tx, state, view, txundo, pindex->nHeight);
if (!tx.IsCoinBase())
blockundo.vtxundo.push_back(txundo);
- vPos.push_back(std::make_pair(block.GetTxHash(i), pos));
+ vPos.push_back(std::make_pair(tx.GetHash(), pos));
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
}
int64_t nTime = GetTimeMicros() - nStart;
@@ -1892,13 +1892,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
assert(ret);
// Watch for transactions paying to me
- for (unsigned int i = 0; i < block.vtx.size(); i++)
- g_signals.SyncTransaction(block.GetTxHash(i), block.vtx[i], &block);
+ BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ g_signals.SyncTransaction(tx, &block);
// Watch for changes to the previous coinbase transaction.
static uint256 hashPrevBestCoinBase;
g_signals.UpdatedTransaction(hashPrevBestCoinBase);
- hashPrevBestCoinBase = block.GetTxHash(0);
+ hashPrevBestCoinBase = block.vtx[0].GetHash();
return true;
}
@@ -1996,7 +1996,7 @@ bool static DisconnectTip(CValidationState &state) {
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- SyncWithWallets(tx.GetHash(), tx, NULL);
+ SyncWithWallets(tx, NULL);
}
return true;
}
@@ -2036,11 +2036,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
// Tell wallet about transactions that went from mempool
// to conflicted:
BOOST_FOREACH(const CTransaction &tx, txConflicted) {
- SyncWithWallets(tx.GetHash(), tx, NULL);
+ SyncWithWallets(tx, NULL);
}
// ... and about transactions that got confirmed:
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- SyncWithWallets(tx.GetHash(), tx, &block);
+ SyncWithWallets(tx, &block);
}
return true;
}
@@ -2351,28 +2351,6 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f
return state.Invalid(error("CheckBlockHeader() : block timestamp too far in the future"),
REJECT_INVALID, "time-too-new");
- CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
- if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0)))
- {
- // Extra checks to prevent "fill up memory by spamming with bogus blocks"
- int64_t deltaTime = block.GetBlockTime() - pcheckpoint->nTime;
- if (deltaTime < 0)
- {
- return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"),
- REJECT_CHECKPOINT, "time-too-old");
- }
- bool fOverflow = false;
- uint256 bnNewBlock;
- bnNewBlock.SetCompact(block.nBits, NULL, &fOverflow);
- uint256 bnRequired;
- bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime));
- if (fOverflow || bnNewBlock > bnRequired)
- {
- return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"),
- REJECT_INVALID, "bad-diffbits");
- }
- }
-
return true;
}
@@ -2403,16 +2381,11 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
if (!CheckTransaction(tx, state))
return error("CheckBlock() : CheckTransaction failed");
- // Build the merkle tree already. We need it anyway later, and it makes the
- // block cache the transaction hashes, which means they don't need to be
- // recalculated many times during this block's validation.
- block.BuildMerkleTree();
-
// Check for duplicate txids. This is caught by ConnectInputs(),
// but catching it earlier avoids a potential DoS attack:
set<uint256> uniqueTx;
- for (unsigned int i = 0; i < block.vtx.size(); i++) {
- uniqueTx.insert(block.GetTxHash(i));
+ BOOST_FOREACH(const CTransaction &tx, block.vtx) {
+ uniqueTx.insert(tx.GetHash());
}
if (uniqueTx.size() != block.vtx.size())
return state.DoS(100, error("CheckBlock() : duplicate transaction"),
@@ -2428,7 +2401,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
REJECT_INVALID, "bad-blk-sigops", true);
// Check merkle root
- if (fCheckMerkleRoot && block.hashMerkleRoot != block.vMerkleTree.back())
+ if (fCheckMerkleRoot && block.hashMerkleRoot != block.BuildMerkleTree())
return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"),
REJECT_INVALID, "bad-txnmrklroot", true);
@@ -2448,6 +2421,28 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex
return state.Invalid(error("AcceptBlock() : block is marked invalid"), 0, "duplicate");
}
+ CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
+ if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0)))
+ {
+ // Extra checks to prevent "fill up memory by spamming with bogus blocks"
+ int64_t deltaTime = block.GetBlockTime() - pcheckpoint->nTime;
+ if (deltaTime < 0)
+ {
+ return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"),
+ REJECT_CHECKPOINT, "time-too-old");
+ }
+ bool fOverflow = false;
+ uint256 bnNewBlock;
+ bnNewBlock.SetCompact(block.nBits, NULL, &fOverflow);
+ uint256 bnRequired;
+ bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime));
+ if (fOverflow || bnNewBlock > bnRequired)
+ {
+ return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"),
+ REJECT_INVALID, "bad-diffbits");
+ }
+ }
+
// Get prev block index
CBlockIndex* pindexPrev = NULL;
int nHeight = 0;
@@ -2682,8 +2677,8 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
- uint256 hash = block.vtx[i].GetHash();
- if (filter.IsRelevantAndUpdate(block.vtx[i], hash))
+ const uint256& hash = block.vtx[i].GetHash();
+ if (filter.IsRelevantAndUpdate(block.vtx[i]))
{
vMatch.push_back(true);
vMatchedTxn.push_back(make_pair(i, hash));
@@ -3832,7 +3827,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
{
mempool.check(pcoinsTip);
- RelayTransaction(tx, inv.hash);
+ RelayTransaction(tx);
mapAlreadyAskedFor.erase(inv);
vWorkQueue.push_back(inv.hash);
vEraseQueue.push_back(inv.hash);
@@ -3862,7 +3857,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2))
{
LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString());
- RelayTransaction(orphanTx, orphanHash);
+ RelayTransaction(orphanTx);
mapAlreadyAskedFor.erase(CInv(MSG_TX, orphanHash));
vWorkQueue.push_back(orphanHash);
vEraseQueue.push_back(orphanHash);
@@ -3947,7 +3942,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CTransaction tx;
bool fInMemPool = mempool.lookup(hash, tx);
if (!fInMemPool) continue; // another thread removed since queryHashes, maybe...
- if ((pfrom->pfilter && pfrom->pfilter->IsRelevantAndUpdate(tx, hash)) ||
+ if ((pfrom->pfilter && pfrom->pfilter->IsRelevantAndUpdate(tx)) ||
(!pfrom->pfilter))
vInv.push_back(inv);
if (vInv.size() == MAX_INV_SZ) {
diff --git a/src/main.h b/src/main.h
index 5a0aedcde1..27041a0026 100644
--- a/src/main.h
+++ b/src/main.h
@@ -7,7 +7,7 @@
#define BITCOIN_MAIN_H
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "chainparams.h"
@@ -113,7 +113,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn);
/** Unregister all wallets from core */
void UnregisterAllWallets();
/** Push an updated transaction to all registered wallets */
-void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL);
+void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL);
/** Register with a network node to receive its signals */
void RegisterNodeSignals(CNodeSignals& nodeSignals);
@@ -294,7 +294,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
std::vector<CScriptCheck> *pvChecks = NULL);
// Apply the effects of this transaction on the UTXO set represented by view
-void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash);
+void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight);
// Context-independent validity checks
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
@@ -1129,7 +1129,7 @@ public:
class CWalletInterface {
protected:
- virtual void SyncTransaction(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) =0;
+ virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) =0;
virtual void EraseFromWallet(const uint256 &hash) =0;
virtual void SetBestChain(const CBlockLocator &locator) =0;
virtual void UpdatedTransaction(const uint256 &hash) =0;
diff --git a/src/miner.cpp b/src/miner.cpp
index 87779efbbd..63ce125067 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -6,6 +6,7 @@
#include "miner.h"
#include "core.h"
+#include "hash.h"
#include "main.h"
#include "net.h"
#ifdef ENABLE_WALLET
@@ -13,47 +14,12 @@
#endif
using namespace std;
+
//////////////////////////////////////////////////////////////////////////////
//
// BitcoinMiner
//
-int static FormatHashBlocks(void* pbuffer, unsigned int len)
-{
- unsigned char* pdata = (unsigned char*)pbuffer;
- unsigned int blocks = 1 + ((len + 8) / 64);
- unsigned char* pend = pdata + 64 * blocks;
- memset(pdata + len, 0, 64 * blocks - len);
- pdata[len] = 0x80;
- unsigned int bits = len * 8;
- pend[-1] = (bits >> 0) & 0xff;
- pend[-2] = (bits >> 8) & 0xff;
- pend[-3] = (bits >> 16) & 0xff;
- pend[-4] = (bits >> 24) & 0xff;
- return blocks;
-}
-
-static const unsigned int pSHA256InitState[8] =
-{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
-
-void SHA256Transform(void* pstate, void* pinput, const void* pinit)
-{
- SHA256_CTX ctx;
- unsigned char data[64];
-
- SHA256_Init(&ctx);
-
- for (int i = 0; i < 16; i++)
- ((uint32_t*)data)[i] = ByteReverse(((uint32_t*)pinput)[i]);
-
- for (int i = 0; i < 8; i++)
- ctx.h[i] = ((uint32_t*)pinit)[i];
-
- SHA256_Update(&ctx, data, sizeof(data));
- for (int i = 0; i < 8; i++)
- ((uint32_t*)pstate)[i] = ctx.h[i];
-}
-
//
// Unconfirmed transactions in the memory pool often depend on other
// transactions in the memory pool. When we select transactions from the
@@ -120,14 +86,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
// Create coinbase tx
- CTransaction txNew;
+ CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vin[0].prevout.SetNull();
txNew.vout.resize(1);
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
- // Add our coinbase tx as first transaction
- pblock->vtx.push_back(txNew);
+ // Add dummy coinbase tx as first transaction
+ pblock->vtx.push_back(CTransaction());
pblocktemplate->vTxFees.push_back(-1); // updated at end
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
@@ -288,8 +254,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
continue;
CTxUndo txundo;
- uint256 hash = tx.GetHash();
- UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash);
+ const uint256& hash = tx.GetHash();
+ UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1);
// Added
pblock->vtx.push_back(tx);
@@ -328,7 +294,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
nLastBlockSize = nBlockSize;
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
- pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
+ // Compute final coinbase transaction.
+ txNew.vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
+ txNew.vin[0].scriptSig = CScript() << OP_0 << OP_0;
+ pblock->vtx[0] = txNew;
pblocktemplate->vTxFees[0] = -nFees;
// Fill in header
@@ -336,7 +305,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
UpdateTime(*pblock, pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
pblock->nNonce = 0;
- pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
CBlockIndex indexDummy(*pblock);
@@ -362,58 +330,15 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
}
++nExtraNonce;
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
- pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
- assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
+ CMutableTransaction txCoinbase(pblock->vtx[0]);
+ txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
+ assert(txCoinbase.vin[0].scriptSig.size() <= 100);
+ pblock->vtx[0] = txCoinbase;
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
}
-void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1)
-{
- //
- // Pre-build hash buffers
- //
- struct
- {
- struct unnamed2
- {
- int nVersion;
- uint256 hashPrevBlock;
- uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
- }
- block;
- unsigned char pchPadding0[64];
- uint256 hash1;
- unsigned char pchPadding1[64];
- }
- tmp;
- memset(&tmp, 0, sizeof(tmp));
-
- tmp.block.nVersion = pblock->nVersion;
- tmp.block.hashPrevBlock = pblock->hashPrevBlock;
- tmp.block.hashMerkleRoot = pblock->hashMerkleRoot;
- tmp.block.nTime = pblock->nTime;
- tmp.block.nBits = pblock->nBits;
- tmp.block.nNonce = pblock->nNonce;
-
- FormatHashBlocks(&tmp.block, sizeof(tmp.block));
- FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
-
- // Byte swap all the input buffer
- for (unsigned int i = 0; i < sizeof(tmp)/4; i++)
- ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
-
- // Precalc the first half of the first hash, which stays constant
- SHA256Transform(pmidstate, &tmp.block, pSHA256InitState);
-
- memcpy(pdata, &tmp.block, 128);
- memcpy(phash1, &tmp.hash1, 64);
-}
-
#ifdef ENABLE_WALLET
//////////////////////////////////////////////////////////////////////////////
//
@@ -424,34 +349,33 @@ int64_t nHPSTimerStart = 0;
//
// ScanHash scans nonces looking for a hash with at least some zero bits.
-// It operates on big endian data. Caller does the byte reversing.
-// All input buffers are 16-byte aligned. nNonce is usually preserved
-// between calls, but periodically or if nNonce is 0xffff0000 or above,
-// the block is rebuilt and nNonce starts over at zero.
+// The nonce is usually preserved between calls, but periodically or if the
+// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
+// zero.
//
-unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
-{
- unsigned int& nNonce = *(unsigned int*)(pdata + 12);
- for (;;)
- {
- // Crypto++ SHA256
- // Hash pdata using pmidstate as the starting state into
- // pre-formatted buffer phash1, then hash phash1 into phash
+bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash) {
+ // Write the first 76 bytes of the block header to a double-SHA256 state.
+ CHash256 hasher;
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss << *pblock;
+ assert(ss.size() == 80);
+ hasher.Write((unsigned char*)&ss[0], 76);
+
+ for (;;) {
nNonce++;
- SHA256Transform(phash1, pdata, pmidstate);
- SHA256Transform(phash, phash1, pSHA256InitState);
+
+ // Write the last 4 bytes of the block header (the nonce) to a copy of
+ // the double-SHA256 state, and compute the result.
+ CHash256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)phash);
// Return the nonce if the hash has at least some zero bits,
// caller will check if it has enough to reach the target
- if (((unsigned short*)phash)[14] == 0)
- return nNonce;
+ if (((uint16_t*)phash)[15] == 0)
+ return true;
// If nothing found after trying for a while, return -1
if ((nNonce & 0xffff) == 0)
- {
- nHashesDone = 0xffff+1;
- return (unsigned int) -1;
- }
+ return false;
if ((nNonce & 0xfff) == 0)
boost::this_thread::interruption_point();
}
@@ -539,45 +463,26 @@ void static BitcoinMiner(CWallet *pwallet)
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
//
- // Pre-build hash buffers
- //
- char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf);
- char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf);
- char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf);
-
- FormatHashBuffers(pblock, pmidstate, pdata, phash1);
-
- unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4);
- unsigned int& nBlockBits = *(unsigned int*)(pdata + 64 + 8);
- unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12);
-
-
- //
// Search
//
int64_t nStart = GetTime();
uint256 hashTarget = uint256().SetCompact(pblock->nBits);
- uint256 hashbuf[2];
- uint256& hash = *alignup<16>(hashbuf);
+ uint256 hash;
+ uint32_t nNonce = 0;
+ uint32_t nOldNonce = 0;
while (true)
{
- unsigned int nHashesDone = 0;
- unsigned int nNonceFound;
-
- // Crypto++ SHA256
- nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1,
- (char*)&hash, nHashesDone);
+ bool fFound = ScanHash(pblock, nNonce, &hash);
+ uint32_t nHashesDone = nNonce - nOldNonce;
+ nOldNonce = nNonce;
// Check if something found
- if (nNonceFound != (unsigned int) -1)
+ if (fFound)
{
- for (unsigned int i = 0; i < sizeof(hash)/4; i++)
- ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]);
-
if (hash <= hashTarget)
{
// Found a solution
- pblock->nNonce = ByteReverse(nNonceFound);
+ pblock->nNonce = nNonce;
assert(hash == pblock->GetHash());
SetThreadPriority(THREAD_PRIORITY_NORMAL);
@@ -626,7 +531,7 @@ void static BitcoinMiner(CWallet *pwallet)
// Regtest mode doesn't require peers
if (vNodes.empty() && Params().MiningRequiresPeers())
break;
- if (nBlockNonce >= 0xffff0000)
+ if (nNonce >= 0xffff0000)
break;
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
break;
@@ -635,11 +540,9 @@ void static BitcoinMiner(CWallet *pwallet)
// Update nTime every few seconds
UpdateTime(*pblock, pindexPrev);
- nBlockTime = ByteReverse(pblock->nTime);
if (Params().AllowMinDifficultyBlocks())
{
// Changing pblock->nTime can change work required on testnet:
- nBlockBits = ByteReverse(pblock->nBits);
hashTarget.SetCompact(pblock->nBits);
}
}
diff --git a/src/miner.h b/src/miner.h
index dcd61d8fd9..1fa499dc5b 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -23,12 +23,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
/** Modify the extranonce in a block */
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
-/** Do mining precalculation */
-void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
/** Check mined block */
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
-/** Base sha256 mining transform */
-void SHA256Transform(void* pstate, void* pinput, const void* pinit);
extern double dHashesPerSec;
extern int64_t nHPSTimerStart;
diff --git a/src/net.cpp b/src/net.cpp
index 757a06aaed..811df43334 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -4,7 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "net.h"
@@ -528,10 +528,6 @@ void CNode::CloseSocketDisconnect()
pnodeSync = NULL;
}
-void CNode::Cleanup()
-{
-}
-
void CNode::PushVersion()
{
int nBestHeight = g_signals.GetHeight().get_value_or(0);
@@ -678,7 +674,6 @@ int CNetMessage::readHeader(const char *pch, unsigned int nBytes)
// switch state to reading message data
in_data = true;
- vRecv.resize(hdr.nMessageSize);
return nCopy;
}
@@ -688,6 +683,11 @@ int CNetMessage::readData(const char *pch, unsigned int nBytes)
unsigned int nRemaining = hdr.nMessageSize - nDataPos;
unsigned int nCopy = std::min(nRemaining, nBytes);
+ if (vRecv.size() < nDataPos + nCopy) {
+ // Allocate up to 256 KiB ahead, but never more than the total message size.
+ vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
+ }
+
memcpy(&vRecv[nDataPos], pch, nCopy);
nDataPos += nCopy;
@@ -773,7 +773,6 @@ void ThreadSocketHandler()
// close socket and cleanup
pnode->CloseSocketDisconnect();
- pnode->Cleanup();
// hold in disconnected pool until all refs are released
if (pnode->fNetworkNode || pnode->fInbound)
@@ -1789,6 +1788,7 @@ public:
delete pnode;
vNodes.clear();
vNodesDisconnected.clear();
+ vhListenSocket.clear();
delete semOutbound;
semOutbound = NULL;
delete pnodeLocalHost;
@@ -1808,17 +1808,17 @@ instance_of_cnetcleanup;
-void RelayTransaction(const CTransaction& tx, const uint256& hash)
+void RelayTransaction(const CTransaction& tx)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(10000);
ss << tx;
- RelayTransaction(tx, hash, ss);
+ RelayTransaction(tx, ss);
}
-void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
+void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
{
- CInv inv(MSG_TX, hash);
+ CInv inv(MSG_TX, tx.GetHash());
{
LOCK(cs_mapRelay);
// Expire old relay messages
@@ -1840,7 +1840,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
LOCK(pnode->cs_filter);
if (pnode->pfilter)
{
- if (pnode->pfilter->IsRelevantAndUpdate(tx, hash))
+ if (pnode->pfilter->IsRelevantAndUpdate(tx))
pnode->PushInventory(inv);
} else
pnode->PushInventory(inv);
diff --git a/src/net.h b/src/net.h
index 14d578a72a..41dc618571 100644
--- a/src/net.h
+++ b/src/net.h
@@ -693,8 +693,6 @@ public:
void Subscribe(unsigned int nChannel, unsigned int nHops=0);
void CancelSubscribe(unsigned int nChannel);
void CloseSocketDisconnect();
- void Cleanup();
-
// Denial-of-service detection/prevention
// The idea is to detect peers that are behaving
@@ -726,8 +724,8 @@ public:
class CTransaction;
-void RelayTransaction(const CTransaction& tx, const uint256& hash);
-void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss);
+void RelayTransaction(const CTransaction& tx);
+void RelayTransaction(const CTransaction& tx, const CDataStream& ss);
/** Access to the (IP) address database (peers.dat) */
class CAddrDB
diff --git a/src/netbase.h b/src/netbase.h
index 23cfb1f158..40a3d25676 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -6,7 +6,7 @@
#define BITCOIN_NETBASE_H
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "compat.h"
diff --git a/src/protocol.h b/src/protocol.h
index 6de5d05a72..1f23274299 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -64,6 +64,14 @@ class CMessageHeader
enum
{
NODE_NETWORK = (1 << 0),
+
+ // Bits 24-31 are reserved for temporary experiments. Just pick a bit that
+ // isn't getting used, or one not being used much, and notify the
+ // bitcoin-development mailing list. Remember that service bits are just
+ // unauthenticated advertisements, so your code must be robust against
+ // collisions and other cases where nodes may be advertising a service they
+ // do not actually support. Other service bits should be allocated via the
+ // BIP process.
};
/** A CService with information about it as peer */
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 2dc56a5107..5df8f19729 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "addressbookpage.h"
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 387f6ede4b..76dddb103c 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "bitcoingui.h"
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 275fa35f39..e7a842df99 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -6,7 +6,7 @@
#define BITCOINGUI_H
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include <QMainWindow>
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 42d6da7d37..c6a6150392 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -440,7 +440,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
// nPayAmount
qint64 nPayAmount = 0;
bool fDust = false;
- CTransaction txDummy;
+ CMutableTransaction txDummy;
foreach(const qint64 &amount, CoinControlDialog::payAmounts)
{
nPayAmount += amount;
@@ -521,7 +521,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority);
// Fee
- int64_t nFee = payTxFee.GetFee(nBytes);
+ int64_t nFee = payTxFee.GetFee(max((unsigned int)1000, nBytes));
// Min Fee
int64_t nMinFee = GetMinFee(txDummy, nBytes, AllowFree(dPriority), GMF_SEND);
@@ -582,6 +582,13 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
l6->setText(sPriorityLabel); // Priority
l7->setText(fDust ? tr("yes") : tr("no")); // Dust
l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change
+ if (nPayFee > 0)
+ {
+ l3->setText("~" + l3->text());
+ l4->setText("~" + l4->text());
+ if (nChange > 0)
+ l8->setText("~" + l8->text());
+ }
// turn labels "red"
l5->setStyleSheet((nBytes >= 1000) ? "color:red;" : ""); // Bytes >= 1000
@@ -599,12 +606,22 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minRelayTxFee.GetFee(546)));
+ // how many satoshis the estimated fee can vary per byte we guess wrong
+ double dFeeVary = (double)std::max(CTransaction::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000;
+ QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
+
+ l3->setToolTip(toolTip4);
+ l4->setToolTip(toolTip4);
l5->setToolTip(toolTip1);
l6->setToolTip(toolTip2);
l7->setToolTip(toolTip3);
+ l8->setToolTip(toolTip4);
+ dialog->findChild<QLabel *>("labelCoinControlFeeText") ->setToolTip(l3->toolTip());
+ dialog->findChild<QLabel *>("labelCoinControlAfterFeeText") ->setToolTip(l4->toolTip());
dialog->findChild<QLabel *>("labelCoinControlBytesText") ->setToolTip(l5->toolTip());
dialog->findChild<QLabel *>("labelCoinControlPriorityText") ->setToolTip(l6->toolTip());
dialog->findChild<QLabel *>("labelCoinControlLowOutputText")->setToolTip(l7->toolTip());
+ dialog->findChild<QLabel *>("labelCoinControlChangeText") ->setToolTip(l8->toolTip());
// Insufficient funds
QLabel *label = dialog->findChild<QLabel *>("labelCoinControlInsuffFunds");
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui
index 1e574e8527..7158b65c2d 100644
--- a/src/qt/forms/rpcconsole.ui
+++ b/src/qt/forms/rpcconsole.ui
@@ -559,7 +559,7 @@
<item>
<widget class="QLabel" name="label_16">
<property name="text">
- <string>In:</string>
+ <string>Received</string>
</property>
</widget>
</item>
@@ -639,7 +639,7 @@
<item>
<widget class="QLabel" name="label_17">
<property name="text">
- <string>Out:</string>
+ <string>Sent</string>
</property>
</widget>
</item>
diff --git a/src/qt/notificator.h b/src/qt/notificator.h
index abab986992..3395e64350 100644
--- a/src/qt/notificator.h
+++ b/src/qt/notificator.h
@@ -6,7 +6,7 @@
#define NOTIFICATOR_H
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include <QIcon>
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index abfd4123e0..12d54dff64 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "optionsdialog.h"
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 4dafd9d2af..6d985abaf8 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "optionsmodel.h"
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index d8dad15c0d..cc2f00916f 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -22,7 +22,7 @@
#endif
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h" /* for USE_QRCODE */
+#include "config/bitcoin-config.h" /* for USE_QRCODE */
#endif
#ifdef USE_QRCODE
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index f7491f4a42..e1f40ddd09 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -231,6 +231,7 @@ RPCConsole::RPCConsole(QWidget *parent) :
startExecutor();
setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
+
ui->detailWidget->hide();
clear();
@@ -581,7 +582,7 @@ void RPCConsole::peerLayoutChanged()
if (fUnselect && selectedRow >= 0)
{
ui->peerWidget->selectionModel()->select(QItemSelection(selectedModelIndex.first(), selectedModelIndex.last()),
- QItemSelectionModel::Deselect);
+ QItemSelectionModel::Deselect);
}
if (fReselect)
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 3fee34d00e..3aeff3eace 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -13,7 +13,6 @@
#include <QDialog>
class ClientModel;
-class CNodeCombinedStats;
QT_BEGIN_NAMESPACE
class QItemSelection;
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 220da28cfe..03a2381c06 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -1,5 +1,5 @@
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#ifdef ENABLE_WALLET
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 0fabc86872..580c6bd5ba 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -438,7 +438,7 @@ Value getblockchaininfo(const Array& params, bool fHelp)
"Returns an object containing various state info regarding block chain processing.\n"
"\nResult:\n"
"{\n"
- " \"chain\": \"xxxx\", (string) current chain (main, testnet3, regtest)\n"
+ " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
" \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
" \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
" \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index 3caf7d89fe..a1410f0e41 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -24,36 +24,6 @@
using namespace json_spirit;
using namespace std;
-#ifdef ENABLE_WALLET
-// Key used by getwork miners.
-// Allocated in InitRPCMining, free'd in ShutdownRPCMining
-static CReserveKey* pMiningKey = NULL;
-
-void InitRPCMining()
-{
- if (!pwalletMain)
- return;
-
- // getwork/getblocktemplate mining rewards paid here:
- pMiningKey = new CReserveKey(pwalletMain);
-}
-
-void ShutdownRPCMining()
-{
- if (!pMiningKey)
- return;
-
- delete pMiningKey; pMiningKey = NULL;
-}
-#else
-void InitRPCMining()
-{
-}
-void ShutdownRPCMining()
-{
-}
-#endif
-
// Return average network hashes per second based on the last 'lookup' blocks,
// or from the last difficulty change if 'lookup' is nonpositive.
// If 'height' is nonnegative, compute the estimate at the time when a given block was found.
@@ -131,9 +101,6 @@ Value getgenerate(const Array& params, bool fHelp)
+ HelpExampleRpc("getgenerate", "")
);
- if (!pMiningKey)
- return false;
-
return GetBoolArg("-gen", false);
}
@@ -253,6 +220,7 @@ Value getmininginfo(const Array& params, bool fHelp)
" \"hashespersec\": n (numeric) The hashes per second of the generation, or 0 if no generation.\n"
" \"pooledtx\": n (numeric) The size of the mem pool\n"
" \"testnet\": true|false (boolean) If using testnet or not\n"
+ " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getmininginfo", "")
@@ -268,7 +236,8 @@ Value getmininginfo(const Array& params, bool fHelp)
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
obj.push_back(Pair("networkhashps", getnetworkhashps(params, false)));
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
- obj.push_back(Pair("testnet", Params().RPCisTestNet()));
+ obj.push_back(Pair("testnet", Params().NetworkID() == CChainParams::TESTNET));
+ obj.push_back(Pair("chain", Params().NetworkIDString()));
#ifdef ENABLE_WALLET
obj.push_back(Pair("generate", getgenerate(params, false)));
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
@@ -277,132 +246,6 @@ Value getmininginfo(const Array& params, bool fHelp)
}
-#ifdef ENABLE_WALLET
-Value getwork(const Array& params, bool fHelp)
-{
- if (fHelp || params.size() > 1)
- throw runtime_error(
- "getwork ( \"data\" )\n"
- "\nIf 'data' is not specified, it returns the formatted hash data to work on.\n"
- "If 'data' is specified, tries to solve the block and returns true if it was successful.\n"
- "\nArguments:\n"
- "1. \"data\" (string, optional) The hex encoded data to solve\n"
- "\nResult (when 'data' is not specified):\n"
- "{\n"
- " \"midstate\" : \"xxxx\", (string) The precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
- " \"data\" : \"xxxxx\", (string) The block data\n"
- " \"hash1\" : \"xxxxx\", (string) The formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
- " \"target\" : \"xxxx\" (string) The little endian hash target\n"
- "}\n"
- "\nResult (when 'data' is specified):\n"
- "true|false (boolean) If solving the block specified in the 'data' was successfull\n"
- "\nExamples:\n"
- + HelpExampleCli("getwork", "")
- + HelpExampleRpc("getwork", "")
- );
-
- if (vNodes.empty())
- throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!");
-
- if (IsInitialBlockDownload())
- throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");
-
- typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
- static mapNewBlock_t mapNewBlock; // FIXME: thread safety
- static vector<CBlockTemplate*> vNewBlockTemplate;
-
- if (params.size() == 0)
- {
- // Update block
- static unsigned int nTransactionsUpdatedLast;
- static CBlockIndex* pindexPrev;
- static int64_t nStart;
- static CBlockTemplate* pblocktemplate;
- if (pindexPrev != chainActive.Tip() ||
- (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60))
- {
- if (pindexPrev != chainActive.Tip())
- {
- // Deallocate old blocks since they're obsolete now
- mapNewBlock.clear();
- BOOST_FOREACH(CBlockTemplate* pblocktemplate, vNewBlockTemplate)
- delete pblocktemplate;
- vNewBlockTemplate.clear();
- }
-
- // Clear pindexPrev so future getworks make a new block, despite any failures from here on
- pindexPrev = NULL;
-
- // Store the pindexBest used before CreateNewBlock, to avoid races
- nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
- CBlockIndex* pindexPrevNew = chainActive.Tip();
- nStart = GetTime();
-
- // Create new block
- pblocktemplate = CreateNewBlockWithKey(*pMiningKey);
- if (!pblocktemplate)
- throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
- vNewBlockTemplate.push_back(pblocktemplate);
-
- // Need to update only after we know CreateNewBlock succeeded
- pindexPrev = pindexPrevNew;
- }
- CBlock* pblock = &pblocktemplate->block; // pointer for convenience
-
- // Update nTime
- UpdateTime(*pblock, pindexPrev);
- pblock->nNonce = 0;
-
- // Update nExtraNonce
- static unsigned int nExtraNonce = 0;
- IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
-
- // Save
- mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
-
- // Pre-build hash buffers
- char pmidstate[32];
- char pdata[128];
- char phash1[64];
- FormatHashBuffers(pblock, pmidstate, pdata, phash1);
-
- uint256 hashTarget = uint256().SetCompact(pblock->nBits);
-
- Object result;
- result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
- result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
- result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
- result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
- return result;
- }
- else
- {
- // Parse parameters
- vector<unsigned char> vchData = ParseHex(params[0].get_str());
- if (vchData.size() != 128)
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
- CBlock* pdata = (CBlock*)&vchData[0];
-
- // Byte reverse
- for (int i = 0; i < 128/4; i++)
- ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
-
- // Get saved block
- if (!mapNewBlock.count(pdata->hashMerkleRoot))
- return false;
- CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
-
- pblock->nTime = pdata->nTime;
- pblock->nNonce = pdata->nNonce;
- pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
- pblock->hashMerkleRoot = pblock->BuildMerkleTree();
-
- assert(pwalletMain != NULL);
- return CheckWork(pblock, *pwalletMain, *pMiningKey);
- }
-}
-#endif
-
Value getblocktemplate(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 1)
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
index 77e0e09ec3..5181aa23d8 100644
--- a/src/rpcmisc.cpp
+++ b/src/rpcmisc.cpp
@@ -73,7 +73,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("testnet", Params().RPCisTestNet()));
+ obj.push_back(Pair("testnet", Params().NetworkID() == CChainParams::TESTNET));
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index 0eca55a472..6fc86eedfb 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -80,7 +80,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
" {\n"
" \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
" \"addrlocal\":\"ip:port\", (string) local address\n"
- " \"services\":\"00000001\", (string) The services\n"
+ " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
" \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
" \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
" \"bytessent\": n, (numeric) The total bytes sent\n"
@@ -115,7 +115,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
obj.push_back(Pair("addr", stats.addrName));
if (!(stats.addrLocal.empty()))
obj.push_back(Pair("addrlocal", stats.addrLocal));
- obj.push_back(Pair("services", strprintf("%08x", stats.nServices)));
+ obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
obj.push_back(Pair("lastsend", stats.nLastSend));
obj.push_back(Pair("lastrecv", stats.nLastRecv));
obj.push_back(Pair("bytessent", stats.nSendBytes));
@@ -344,6 +344,7 @@ Value getnetworkinfo(const Array& params, bool fHelp)
"{\n"
" \"version\": xxxxx, (numeric) the server version\n"
" \"protocolversion\": xxxxx, (numeric) the protocol version\n"
+ " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\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"
@@ -365,6 +366,7 @@ Value getnetworkinfo(const Array& params, bool fHelp)
Object obj;
obj.push_back(Pair("version", (int)CLIENT_VERSION));
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
+ obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
obj.push_back(Pair("timeoffset", GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index dee7daeb2a..9771f8e685 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -349,7 +349,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
Array inputs = params[0].get_array();
Object sendTo = params[1].get_obj();
- CTransaction rawTx;
+ CMutableTransaction rawTx;
BOOST_FOREACH(const Value& input, inputs)
{
@@ -554,11 +554,11 @@ Value signrawtransaction(const Array& params, bool fHelp)
vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
- vector<CTransaction> txVariants;
+ vector<CMutableTransaction> txVariants;
while (!ssData.empty())
{
try {
- CTransaction tx;
+ CMutableTransaction tx;
ssData >> tx;
txVariants.push_back(tx);
}
@@ -572,7 +572,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
// mergedTx will end up with all the signatures; it
// starts as a clone of the rawtx:
- CTransaction mergedTx(txVariants[0]);
+ CMutableTransaction mergedTx(txVariants[0]);
bool fComplete = true;
// Fetch previous transactions (inputs):
@@ -713,7 +713,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
// ... and merge in other signatures:
- BOOST_FOREACH(const CTransaction& txv, txVariants)
+ BOOST_FOREACH(const CMutableTransaction& txv, txVariants)
{
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
}
@@ -770,7 +770,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
catch (std::exception &e) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
}
- uint256 hashTx = tx.GetHash();
+ const uint256 &hashTx = tx.GetHash();
CCoinsViewCache &view = *pcoinsTip;
CCoins existingCoins;
@@ -780,7 +780,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
// push to local node and sync with wallets
CValidationState state;
if (AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees))
- SyncWithWallets(hashTx, tx, NULL);
+ SyncWithWallets(tx, NULL);
else {
if(state.IsInvalid())
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
@@ -790,7 +790,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
} else if (fHaveChain) {
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
}
- RelayTransaction(tx, hashTx);
+ RelayTransaction(tx);
return hashTx.GetHex();
}
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index d4ceb7f995..93da81e429 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -315,7 +315,6 @@ static const CRPCCommand vRPCCommands[] =
/* Wallet-enabled mining */
{ "getgenerate", &getgenerate, true, false, false },
{ "gethashespersec", &gethashespersec, true, false, false },
- { "getwork", &getwork, true, false, true },
{ "setgenerate", &setgenerate, true, true, false },
#endif // ENABLE_WALLET
};
@@ -642,7 +641,6 @@ void StartRPCThreads()
LogPrintf("Binding RPC on address %s port %i (IPv4+IPv6 bind any: %i)\n", bindAddress.to_string(), endpoint.port(), bBindAny);
boost::system::error_code v6_only_error;
boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(*rpc_io_service));
- rpc_acceptors.push_back(acceptor);
try {
acceptor->open(endpoint.protocol());
@@ -658,6 +656,7 @@ void StartRPCThreads()
RPCListen(acceptor, *rpc_ssl_context, fUseSSL);
fListening = true;
+ rpc_acceptors.push_back(acceptor);
// If dual IPv6/IPv4 bind succesful, skip binding to IPv4 separately
if(bBindAny && bindAddress == asio::ip::address_v6::any() && !v6_only_error)
break;
@@ -700,11 +699,20 @@ void StopRPCThreads()
// First, cancel all timers and acceptors
// This is not done automatically by ->stop(), and in some cases the destructor of
// asio::io_service can hang if this is skipped.
+ boost::system::error_code ec;
BOOST_FOREACH(const boost::shared_ptr<ip::tcp::acceptor> &acceptor, rpc_acceptors)
- acceptor->cancel();
+ {
+ acceptor->cancel(ec);
+ if (ec)
+ LogPrintf("%s: Warning: %s when cancelling acceptor", __func__, ec.message());
+ }
rpc_acceptors.clear();
BOOST_FOREACH(const PAIRTYPE(std::string, boost::shared_ptr<deadline_timer>) &timer, deadlineTimers)
- timer.second->cancel();
+ {
+ timer.second->cancel(ec);
+ if (ec)
+ LogPrintf("%s: Warning: %s when cancelling timer", __func__, ec.message());
+ }
deadlineTimers.clear();
rpc_io_service->stop();
@@ -763,7 +771,7 @@ void JSONRequest::parse(const Value& valRequest)
if (valMethod.type() != str_type)
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
strMethod = valMethod.get_str();
- if (strMethod != "getwork" && strMethod != "getblocktemplate")
+ if (strMethod != "getblocktemplate")
LogPrint("rpc", "ThreadRPCServer method=%s\n", strMethod);
// Parse params
diff --git a/src/rpcserver.h b/src/rpcserver.h
index 73e8b9426c..5271542385 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -130,7 +130,6 @@ extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHe
extern json_spirit::Value getnetworkhashps(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value gethashespersec(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp);
-extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value estimatefee(const json_spirit::Array& params, bool fHelp);
diff --git a/src/script.cpp b/src/script.cpp
index 11cdfef950..c83d26885a 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -9,6 +9,9 @@
#include "hash.h"
#include "key.h"
#include "keystore.h"
+#include "crypto/sha1.h"
+#include "crypto/sha2.h"
+#include "crypto/ripemd160.h"
#include "sync.h"
#include "uint256.h"
#include "util.h"
@@ -801,21 +804,15 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
valtype& vch = stacktop(-1);
valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
if (opcode == OP_RIPEMD160)
- RIPEMD160(&vch[0], vch.size(), &vchHash[0]);
+ CRIPEMD160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]);
else if (opcode == OP_SHA1)
- SHA1(&vch[0], vch.size(), &vchHash[0]);
+ CSHA1().Write(&vch[0], vch.size()).Finalize(&vchHash[0]);
else if (opcode == OP_SHA256)
- SHA256(&vch[0], vch.size(), &vchHash[0]);
+ CSHA256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]);
else if (opcode == OP_HASH160)
- {
- uint160 hash160 = Hash160(vch);
- memcpy(&vchHash[0], &hash160, sizeof(hash160));
- }
+ CHash160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]);
else if (opcode == OP_HASH256)
- {
- uint256 hash = Hash(vch.begin(), vch.end());
- memcpy(&vchHash[0], &hash, sizeof(hash));
- }
+ CHash256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]);
popstack(stack);
stack.push_back(vchHash);
}
@@ -1639,7 +1636,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
}
-bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType)
+bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
@@ -1674,7 +1671,7 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransa
return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0);
}
-bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType)
+bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
{
assert(nIn < txTo.vin.size());
CTxIn& txin = txTo.vin[nIn];
@@ -1692,7 +1689,7 @@ static CScript PushAll(const vector<valtype>& values)
return result;
}
-static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
+static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& txTo, unsigned int nIn,
const vector<valtype>& vSolutions,
vector<valtype>& sigs1, vector<valtype>& sigs2)
{
diff --git a/src/script.h b/src/script.h
index a282e7dc04..ea988f0e40 100644
--- a/src/script.h
+++ b/src/script.h
@@ -20,6 +20,7 @@
class CCoins;
class CKeyStore;
class CTransaction;
+class CMutableTransaction;
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
@@ -769,12 +770,12 @@ public:
void Serialize(Stream &s, int nType, int nVersion) const {
std::vector<unsigned char> compr;
if (Compress(compr)) {
- s << CFlatData(&compr[0], &compr[compr.size()]);
+ s << CFlatData(compr);
return;
}
unsigned int nSize = script.size() + nSpecialScripts;
s << VARINT(nSize);
- s << CFlatData(&script[0], &script[script.size()]);
+ s << CFlatData(script);
}
template<typename Stream>
@@ -783,13 +784,13 @@ public:
s >> VARINT(nSize);
if (nSize < nSpecialScripts) {
std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
- s >> REF(CFlatData(&vch[0], &vch[vch.size()]));
+ s >> REF(CFlatData(vch));
Decompress(nSize, vch);
return;
}
nSize -= nSpecialScripts;
script.resize(nSize);
- s >> REF(CFlatData(&script[0], &script[script.size()]));
+ s >> REF(CFlatData(script));
}
};
@@ -805,8 +806,8 @@ bool IsMine(const CKeyStore& keystore, const CTxDestination &dest);
void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys);
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
-bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
-bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
+bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
+bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders,
diff --git a/src/serialize.h b/src/serialize.h
index 1341746592..5ac85554c6 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -37,6 +37,34 @@ inline T& REF(const T& val)
return const_cast<T&>(val);
}
+/** Get begin pointer of vector (non-const version).
+ * @note These functions avoid the undefined case of indexing into an empty
+ * vector, as well as that of indexing after the end of the vector.
+ */
+template <class T, class TAl>
+inline T* begin_ptr(std::vector<T,TAl>& v)
+{
+ return v.empty() ? NULL : &v[0];
+}
+/** Get begin pointer of vector (const version) */
+template <class T, class TAl>
+inline const T* begin_ptr(const std::vector<T,TAl>& v)
+{
+ return v.empty() ? NULL : &v[0];
+}
+/** Get end pointer of vector (non-const version) */
+template <class T, class TAl>
+inline T* end_ptr(std::vector<T,TAl>& v)
+{
+ return v.empty() ? NULL : (&v[0] + v.size());
+}
+/** Get end pointer of vector (const version) */
+template <class T, class TAl>
+inline const T* end_ptr(const std::vector<T,TAl>& v)
+{
+ return v.empty() ? NULL : (&v[0] + v.size());
+}
+
/////////////////////////////////////////////////////////////////
//
// Templates for serializing to anything that looks like a stream,
@@ -318,6 +346,12 @@ protected:
char* pend;
public:
CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
+ template <class T, class TAl>
+ explicit CFlatData(std::vector<T,TAl> &v)
+ {
+ pbegin = (char*)begin_ptr(v);
+ pend = (char*)end_ptr(v);
+ }
char* begin() { return pbegin; }
const char* begin() const { return pbegin; }
char* end() { return pend; }
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index fb06fb3435..3a45844411 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
// 50 orphan transactions:
for (int i = 0; i < 50; i++)
{
- CTransaction tx;
+ CMutableTransaction tx;
tx.vin.resize(1);
tx.vin[0].prevout.n = 0;
tx.vin[0].prevout.hash = GetRandHash();
@@ -184,7 +184,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
{
CTransaction txPrev = RandomOrphan();
- CTransaction tx;
+ CMutableTransaction tx;
tx.vin.resize(1);
tx.vin[0].prevout.n = 0;
tx.vin[0].prevout.hash = txPrev.GetHash();
@@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
{
CTransaction txPrev = RandomOrphan();
- CTransaction tx;
+ CMutableTransaction tx;
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
@@ -242,10 +242,10 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
// 100 orphan transactions:
static const int NPREV=100;
- CTransaction orphans[NPREV];
+ CMutableTransaction orphans[NPREV];
for (int i = 0; i < NPREV; i++)
{
- CTransaction& tx = orphans[i];
+ CMutableTransaction& tx = orphans[i];
tx.vin.resize(1);
tx.vin[0].prevout.n = 0;
tx.vin[0].prevout.hash = GetRandHash();
@@ -258,7 +258,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
}
// Create a transaction that depends on orphans:
- CTransaction tx;
+ CMutableTransaction tx;
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp
index e2a75da349..4bee0f6b6e 100644
--- a/src/test/accounting_tests.cpp
+++ b/src/test/accounting_tests.cpp
@@ -83,13 +83,21 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
wtx.mapValue["comment"] = "y";
- --wtx.nLockTime; // Just to change the hash :)
+ {
+ CMutableTransaction tx(wtx);
+ --tx.nLockTime; // Just to change the hash :)
+ *static_cast<CTransaction*>(&wtx) = CTransaction(tx);
+ }
pwalletMain->AddToWallet(wtx);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[1]->nTimeReceived = (unsigned int)1333333336;
wtx.mapValue["comment"] = "x";
- --wtx.nLockTime; // Just to change the hash :)
+ {
+ CMutableTransaction tx(wtx);
+ --tx.nLockTime; // Just to change the hash :)
+ *static_cast<CTransaction*>(&wtx) = CTransaction(tx);
+ }
pwalletMain->AddToWallet(wtx);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[2]->nTimeReceived = (unsigned int)1333333329;
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index abedd3093c..b56d998be2 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -118,33 +118,33 @@ BOOST_AUTO_TEST_CASE(bloom_match)
CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(uint256("0xb4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b"));
- BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match tx hash");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match tx hash");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
// byte-reversed tx hash
filter.insert(ParseHex("6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4"));
- BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match manually serialized tx hash");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized tx hash");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a01"));
- BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match input signature");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input signature");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339"));
- BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match input pub key");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input pub key");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("04943fdd508053c75000106d3bc6e2754dbcff19"));
- BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match output address");
- BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(spendingTx, spendingTx.GetHash()), "Simple Bloom filter didn't add output");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(spendingTx), "Simple Bloom filter didn't add output");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("a266436d2965547608b9e15d9032a7b9d64fa431"));
- BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match output address");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
- BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match COutPoint");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match COutPoint");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
COutPoint prevOutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0);
@@ -154,23 +154,23 @@ BOOST_AUTO_TEST_CASE(bloom_match)
memcpy(&data[32], &prevOutPoint.n, sizeof(unsigned int));
filter.insert(data);
}
- BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match manually serialized COutPoint");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized COutPoint");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(uint256("00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436"));
- BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched random tx hash");
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random tx hash");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(ParseHex("0000006d2965547608b9e15d9032a7b9d64fa431"));
- BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched random address");
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random address");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 1));
- BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched COutPoint for an output we didn't care about");
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about");
filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
filter.insert(COutPoint(uint256("0x000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
- BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched COutPoint for an output we didn't care about");
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about");
}
BOOST_AUTO_TEST_CASE(merkle_block_1)
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
new file mode 100644
index 0000000000..7bd98fa381
--- /dev/null
+++ b/src/test/crypto_tests.cpp
@@ -0,0 +1,203 @@
+// Copyright (c) 2014 The Bitcoin Core developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "crypto/ripemd160.h"
+#include "crypto/sha1.h"
+#include "crypto/sha2.h"
+#include "util.h"
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE(crypto_tests)
+
+template<typename Hasher, typename In, typename Out>
+void TestVector(const Hasher &h, const In &in, const Out &out) {
+ Out hash;
+ BOOST_CHECK(out.size() == h.OUTPUT_SIZE);
+ hash.resize(out.size());
+ {
+ // Test that writing the whole input string at once works.
+ Hasher(h).Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]);
+ BOOST_CHECK(hash == out);
+ }
+ for (int i=0; i<32; i++) {
+ // Test that writing the string broken up in random pieces works.
+ Hasher hasher(h);
+ size_t pos = 0;
+ while (pos < in.size()) {
+ size_t len = insecure_rand() % ((in.size() - pos + 1) / 2 + 1);
+ hasher.Write((unsigned char*)&in[pos], len);
+ pos += len;
+ if (pos > 0 && pos + 2 * out.size() > in.size()) {
+ // Test that writing the rest at once to a copy of a hasher works.
+ Hasher(hasher).Write((unsigned char*)&in[pos], in.size() - pos).Finalize(&hash[0]);
+ BOOST_CHECK(hash == out);
+ }
+ }
+ hasher.Finalize(&hash[0]);
+ BOOST_CHECK(hash == out);
+ }
+}
+
+void TestSHA1(const std::string &in, const std::string &hexout) { TestVector(CSHA1(), in, ParseHex(hexout));}
+void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(CSHA256(), in, ParseHex(hexout));}
+void TestSHA512(const std::string &in, const std::string &hexout) { TestVector(CSHA512(), in, ParseHex(hexout));}
+void TestRIPEMD160(const std::string &in, const std::string &hexout) { TestVector(CRIPEMD160(), in, ParseHex(hexout));}
+
+void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ TestVector(CHMAC_SHA512(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout));
+}
+
+std::string LongTestString(void) {
+ std::string ret;
+ for (int i=0; i<200000; i++) {
+ ret += (unsigned char)(i);
+ ret += (unsigned char)(i >> 4);
+ ret += (unsigned char)(i >> 8);
+ ret += (unsigned char)(i >> 12);
+ ret += (unsigned char)(i >> 16);
+ }
+ return ret;
+}
+
+const std::string test1 = LongTestString();
+
+BOOST_AUTO_TEST_CASE(ripemd160_testvectors) {
+ TestRIPEMD160("", "9c1185a5c5e9fc54612808977ee8f548b2258d31");
+ TestRIPEMD160("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc");
+ TestRIPEMD160("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36");
+ TestRIPEMD160("secure hash algorithm", "20397528223b6a5f4cbc2808aba0464e645544f9");
+ TestRIPEMD160("RIPEMD160 is considered to be safe", "a7d78608c7af8a8e728778e81576870734122b66");
+ TestRIPEMD160("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "12a053384a9c0c88e405a06c27dcf49ada62eb2b");
+ TestRIPEMD160("For this sample, this 63-byte string will be used as input data",
+ "de90dbfee14b63fb5abf27c2ad4a82aaa5f27a11");
+ TestRIPEMD160("This is exactly 64 bytes long, not counting the terminating byte",
+ "eda31d51d3a623b81e19eb02e24ff65d27d67b37");
+ TestRIPEMD160(std::string(1000000, 'a'), "52783243c1697bdbe16d37f97f68f08325dc1528");
+ TestRIPEMD160(test1, "464243587bd146ea835cdf57bdae582f25ec45f1");
+}
+
+BOOST_AUTO_TEST_CASE(sha1_testvectors) {
+ TestSHA1("", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
+ TestSHA1("abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
+ TestSHA1("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3");
+ TestSHA1("secure hash algorithm", "d4d6d2f0ebe317513bbd8d967d89bac5819c2f60");
+ TestSHA1("SHA1 is considered to be safe", "f2b6650569ad3a8720348dd6ea6c497dee3a842a");
+ TestSHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
+ TestSHA1("For this sample, this 63-byte string will be used as input data",
+ "4f0ea5cd0585a23d028abdc1a6684e5a8094dc49");
+ TestSHA1("This is exactly 64 bytes long, not counting the terminating byte",
+ "fb679f23e7d1ce053313e66e127ab1b444397057");
+ TestSHA1(std::string(1000000, 'a'), "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
+ TestSHA1(test1, "b7755760681cbfd971451668f32af5774f4656b5");
+}
+
+BOOST_AUTO_TEST_CASE(sha256_testvectors) {
+ TestSHA256("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+ TestSHA256("abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
+ TestSHA256("message digest",
+ "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650");
+ TestSHA256("secure hash algorithm",
+ "f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d");
+ TestSHA256("SHA256 is considered to be safe",
+ "6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630");
+ TestSHA256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
+ TestSHA256("For this sample, this 63-byte string will be used as input data",
+ "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342");
+ TestSHA256("This is exactly 64 bytes long, not counting the terminating byte",
+ "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8");
+ TestSHA256("As Bitcoin relies on 80 byte header hashes, we want to have an example for that.",
+ "7406e8de7d6e4fffc573daef05aefb8806e7790f55eab5576f31349743cca743");
+ TestSHA256(std::string(1000000, 'a'),
+ "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
+ TestSHA256(test1, "a316d55510b49662420f49d145d42fb83f31ef8dc016aa4e32df049991a91e26");
+}
+
+BOOST_AUTO_TEST_CASE(sha512_testvectors) {
+ TestSHA512("",
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce"
+ "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
+ TestSHA512("abc",
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
+ "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f");
+ TestSHA512("message digest",
+ "107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f33"
+ "09e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c");
+ TestSHA512("secure hash algorithm",
+ "7746d91f3de30c68cec0dd693120a7e8b04d8073cb699bdce1a3f64127bca7a3"
+ "d5db502e814bb63c063a7a5043b2df87c61133395f4ad1edca7fcf4b30c3236e");
+ TestSHA512("SHA512 is considered to be safe",
+ "099e6468d889e1c79092a89ae925a9499b5408e01b66cb5b0a3bd0dfa51a9964"
+ "6b4a3901caab1318189f74cd8cf2e941829012f2449df52067d3dd5b978456c2");
+ TestSHA512("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335"
+ "96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445");
+ TestSHA512("For this sample, this 63-byte string will be used as input data",
+ "b3de4afbc516d2478fe9b518d063bda6c8dd65fc38402dd81d1eb7364e72fb6e"
+ "6663cf6d2771c8f5a6da09601712fb3d2a36c6ffea3e28b0818b05b0a8660766");
+ TestSHA512("This is exactly 64 bytes long, not counting the terminating byte",
+ "70aefeaa0e7ac4f8fe17532d7185a289bee3b428d950c14fa8b713ca09814a38"
+ "7d245870e007a80ad97c369d193e41701aa07f3221d15f0e65a1ff970cedf030");
+ TestSHA512("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"
+ "ijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
+ "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909");
+ TestSHA512(std::string(1000000, 'a'),
+ "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
+ "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b");
+ TestSHA512(test1,
+ "40cac46c147e6131c5193dd5f34e9d8bb4951395f27b08c558c65ff4ba2de594"
+ "37de8c3ef5459d76a52cedc02dc499a3c9ed9dedbfb3281afd9653b8a112fafc");
+}
+
+BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
+ // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231
+ TestHMACSHA512("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde"
+ "daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854");
+ TestHMACSHA512("4a656665",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554"
+ "9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737");
+ TestHMACSHA512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddddddd",
+ "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39"
+ "bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb");
+ TestHMACSHA512("0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db"
+ "a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd");
+ TestHMACSHA512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579204669727374",
+ "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352"
+ "6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598");
+ TestHMACSHA512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "5468697320697320612074657374207573696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565"
+ "647320746f20626520686173686564206265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c676f726974686d2e",
+ "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944"
+ "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/hmac_tests.cpp b/src/test/hmac_tests.cpp
deleted file mode 100644
index 780ce480ce..0000000000
--- a/src/test/hmac_tests.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright (c) 2013 The Bitcoin Core developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include "hash.h"
-#include "util.h"
-
-#include <boost/test/unit_test.hpp>
-
-using namespace std;
-
-BOOST_AUTO_TEST_SUITE(hmac_tests)
-
-typedef struct {
- const char *pszKey;
- const char *pszData;
- const char *pszMAC;
-} testvec_t;
-
-// test cases 1, 2, 3, 4, 6 and 7 of RFC 4231
-static const testvec_t vtest[] = {
- {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
- "0b0b0b0b",
- "4869205468657265",
- "87aa7cdea5ef619d4ff0b4241a1d6cb0"
- "2379f4e2ce4ec2787ad0b30545e17cde"
- "daa833b7d6b8a702038b274eaea3f4e4"
- "be9d914eeb61f1702e696c203a126854"
- },
- {
- "4a656665",
- "7768617420646f2079612077616e7420"
- "666f72206e6f7468696e673f",
- "164b7a7bfcf819e2e395fbe73b56e0a3"
- "87bd64222e831fd610270cd7ea250554"
- "9758bf75c05a994a6d034f65f8f0e6fd"
- "caeab1a34d4a6b4b636e070a38bce737"
- },
- {
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaa",
- "dddddddddddddddddddddddddddddddd"
- "dddddddddddddddddddddddddddddddd"
- "dddddddddddddddddddddddddddddddd"
- "dddd",
- "fa73b0089d56a284efb0f0756c890be9"
- "b1b5dbdd8ee81a3655f83e33b2279d39"
- "bf3e848279a722c806b485a47e67c807"
- "b946a337bee8942674278859e13292fb"
- },
- {
- "0102030405060708090a0b0c0d0e0f10"
- "111213141516171819",
- "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
- "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
- "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
- "cdcd",
- "b0ba465637458c6990e5a8c5f61d4af7"
- "e576d97ff94b872de76f8050361ee3db"
- "a91ca5c11aa25eb4d679275cc5788063"
- "a5f19741120c4f2de2adebeb10a298dd"
- },
- {
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaa",
- "54657374205573696e67204c61726765"
- "72205468616e20426c6f636b2d53697a"
- "65204b6579202d2048617368204b6579"
- "204669727374",
- "80b24263c7c1a3ebb71493c1dd7be8b4"
- "9b46d1f41b4aeec1121b013783f8f352"
- "6b56d037e05f2598bd0fd2215d6a1e52"
- "95e64f73f63f0aec8b915a985d786598"
- },
- {
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaa",
- "54686973206973206120746573742075"
- "73696e672061206c6172676572207468"
- "616e20626c6f636b2d73697a65206b65"
- "7920616e642061206c61726765722074"
- "68616e20626c6f636b2d73697a652064"
- "6174612e20546865206b6579206e6565"
- "647320746f2062652068617368656420"
- "6265666f7265206265696e6720757365"
- "642062792074686520484d414320616c"
- "676f726974686d2e",
- "e37b6a775dc87dbaa4dfa9f96e5e3ffd"
- "debd71f8867289865df5a32d20cdc944"
- "b6022cac3c4982b10d5eeb55c3e4de15"
- "134676fb6de0446065c97440fa8c6a58"
- }
-};
-
-BOOST_AUTO_TEST_CASE(hmacsha512_testvectors)
-{
- for (unsigned int n=0; n<sizeof(vtest)/sizeof(vtest[0]); n++)
- {
- vector<unsigned char> vchKey = ParseHex(vtest[n].pszKey);
- vector<unsigned char> vchData = ParseHex(vtest[n].pszData);
- vector<unsigned char> vchMAC = ParseHex(vtest[n].pszMAC);
- unsigned char vchTemp[64];
-
- HMAC_SHA512_CTX ctx;
- HMAC_SHA512_Init(&ctx, &vchKey[0], vchKey.size());
- HMAC_SHA512_Update(&ctx, &vchData[0], vchData.size());
- HMAC_SHA512_Final(&vchTemp[0], &ctx);
-
- BOOST_CHECK(memcmp(&vchTemp[0], &vchMAC[0], 64) == 0);
-
- }
-}
-
-BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index b72ba0293f..47977cf295 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -9,8 +9,6 @@
#include <boost/test/unit_test.hpp>
-extern void SHA256Transform(void* pstate, void* pinput, const void* pinit);
-
BOOST_AUTO_TEST_SUITE(miner_tests)
static
@@ -53,7 +51,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
CBlockTemplate *pblocktemplate;
- CTransaction tx,tx2;
+ CMutableTransaction tx,tx2;
CScript script;
uint256 hash;
@@ -70,10 +68,12 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
pblock->nVersion = 1;
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
- pblock->vtx[0].vin[0].scriptSig = CScript();
- pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce);
- pblock->vtx[0].vin[0].scriptSig.push_back(chainActive.Height());
- pblock->vtx[0].vout[0].scriptPubKey = CScript();
+ CMutableTransaction txCoinbase(pblock->vtx[0]);
+ txCoinbase.vin[0].scriptSig = CScript();
+ txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
+ txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
+ txCoinbase.vout[0].scriptPubKey = CScript();
+ pblock->vtx[0] = CTransaction(txCoinbase);
if (txFirst.size() < 2)
txFirst.push_back(new CTransaction(pblock->vtx[0]));
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
@@ -259,30 +259,4 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
}
-BOOST_AUTO_TEST_CASE(sha256transform_equality)
-{
- unsigned int pSHA256InitState[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
-
-
- // unsigned char pstate[32];
- unsigned char pinput[64];
-
- int i;
-
- for (i = 0; i < 32; i++) {
- pinput[i] = i;
- pinput[i+32] = 0;
- }
-
- uint256 hash;
-
- SHA256Transform(&hash, pinput, pSHA256InitState);
-
- BOOST_TEST_MESSAGE(hash.GetHex());
-
- uint256 hash_reference("0x2df5e1c65ef9f8cde240d23cae2ec036d31a15ec64bc68f64be242b1da6631f3");
-
- BOOST_CHECK(hash == hash_reference);
-}
-
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 3775abd633..452cf084a7 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -55,13 +55,13 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
CScript escrow;
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
- CTransaction txFrom; // Funding transaction
+ CMutableTransaction txFrom; // Funding transaction
txFrom.vout.resize(3);
txFrom.vout[0].scriptPubKey = a_and_b;
txFrom.vout[1].scriptPubKey = a_or_b;
txFrom.vout[2].scriptPubKey = escrow;
- CTransaction txTo[3]; // Spending transaction
+ CMutableTransaction txTo[3]; // Spending transaction
for (int i = 0; i < 3; i++)
{
txTo[i].vin.resize(1);
@@ -270,13 +270,13 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
CScript escrow;
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
- CTransaction txFrom; // Funding transaction
+ CMutableTransaction txFrom; // Funding transaction
txFrom.vout.resize(3);
txFrom.vout[0].scriptPubKey = a_and_b;
txFrom.vout[1].scriptPubKey = a_or_b;
txFrom.vout[2].scriptPubKey = escrow;
- CTransaction txTo[3]; // Spending transaction
+ CMutableTransaction txTo[3]; // Spending transaction
for (int i = 0; i < 3; i++)
{
txTo[i].vin.resize(1);
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index 7d7e6681df..9dce4daac6 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -36,9 +36,9 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
// build a block with some dummy transactions
CBlock block;
for (unsigned int j=0; j<nTx; j++) {
- CTransaction tx;
+ CMutableTransaction tx;
tx.nLockTime = rand(); // actual transaction data doesn't matter; just make the nLockTime's unique
- block.vtx.push_back(tx);
+ block.vtx.push_back(CTransaction(tx));
}
// calculate actual merkle root and height
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index 9b1290e0ea..a75593a8b2 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -30,11 +30,11 @@ static bool
Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
{
// Create dummy to/from transactions:
- CTransaction txFrom;
+ CMutableTransaction txFrom;
txFrom.vout.resize(1);
txFrom.vout[0].scriptPubKey = scriptPubKey;
- CTransaction txTo;
+ CMutableTransaction txTo;
txTo.vin.resize(1);
txTo.vout.resize(1);
txTo.vin[0].prevout.n = 0;
@@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(sign)
evalScripts[i].SetDestination(standardScripts[i].GetID());
}
- CTransaction txFrom; // Funding transaction:
+ CMutableTransaction txFrom; // Funding transaction:
string reason;
txFrom.vout.resize(8);
for (int i = 0; i < 4; i++)
@@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(sign)
}
BOOST_CHECK(IsStandardTx(txFrom, reason));
- CTransaction txTo[8]; // Spending transactions
+ CMutableTransaction txTo[8]; // Spending transactions
for (int i = 0; i < 8; i++)
{
txTo[i].vin.resize(1);
@@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE(set)
keystore.AddCScript(inner[i]);
}
- CTransaction txFrom; // Funding transaction:
+ CMutableTransaction txFrom; // Funding transaction:
string reason;
txFrom.vout.resize(4);
for (int i = 0; i < 4; i++)
@@ -183,7 +183,7 @@ BOOST_AUTO_TEST_CASE(set)
}
BOOST_CHECK(IsStandardTx(txFrom, reason));
- CTransaction txTo[4]; // Spending transactions
+ CMutableTransaction txTo[4]; // Spending transactions
for (int i = 0; i < 4; i++)
{
txTo[i].vin.resize(1);
@@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
keys.push_back(key[i].GetPubKey());
}
- CTransaction txFrom;
+ CMutableTransaction txFrom;
txFrom.vout.resize(6);
// First three are standard:
@@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
coins.SetCoins(txFrom.GetHash(), CCoins(txFrom, 0));
- CTransaction txTo;
+ CMutableTransaction txTo;
txTo.vout.resize(1);
txTo.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
@@ -326,7 +326,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txTo.vin[i].scriptSig = t;
}
- CTransaction txToNonStd;
+ CMutableTransaction txToNonStd;
txToNonStd.vout.resize(1);
txToNonStd.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
txToNonStd.vout[0].nValue = 1000;
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 29d518d707..cba582e941 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -240,11 +240,11 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
CScript scriptPubKey12;
scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG;
- CTransaction txFrom12;
+ CMutableTransaction txFrom12;
txFrom12.vout.resize(1);
txFrom12.vout[0].scriptPubKey = scriptPubKey12;
- CTransaction txTo12;
+ CMutableTransaction txTo12;
txTo12.vin.resize(1);
txTo12.vout.resize(1);
txTo12.vin[0].prevout.n = 0;
@@ -274,11 +274,11 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
CScript scriptPubKey23;
scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG;
- CTransaction txFrom23;
+ CMutableTransaction txFrom23;
txFrom23.vout.resize(1);
txFrom23.vout[0].scriptPubKey = scriptPubKey23;
- CTransaction txTo23;
+ CMutableTransaction txTo23;
txTo23.vin.resize(1);
txTo23.vout.resize(1);
txTo23.vin[0].prevout.n = 0;
@@ -345,11 +345,11 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
keystore.AddKey(key);
}
- CTransaction txFrom;
+ CMutableTransaction txFrom;
txFrom.vout.resize(1);
txFrom.vout[0].scriptPubKey.SetDestination(keys[0].GetPubKey().GetID());
CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
- CTransaction txTo;
+ CMutableTransaction txTo;
txTo.vin.resize(1);
txTo.vout.resize(1);
txTo.vin[0].prevout.n = 0;
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 353fd60f7b..423ae4a789 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -28,7 +28,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
return 1;
}
- CTransaction txTmp(txTo);
+ CMutableTransaction txTmp(txTo);
// In case concatenating two scripts ends up with two codeseparators,
// or an extra one at the end, this prevents all those possible incompatibilities.
@@ -90,7 +90,7 @@ void static RandomScript(CScript &script) {
script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
}
-void static RandomTransaction(CTransaction &tx, bool fSingle) {
+void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
tx.nVersion = insecure_rand();
tx.vin.clear();
tx.vout.clear();
@@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(sighash_test)
#endif
for (int i=0; i<nRandomTests; i++) {
int nHashType = insecure_rand();
- CTransaction txTo;
+ CMutableTransaction txTo;
RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
CScript scriptCode;
RandomScript(scriptCode);
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index feba5ee80e..238033f407 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00};
vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
- CTransaction tx;
+ CMutableTransaction tx;
stream >> tx;
CValidationState state;
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid.");
@@ -224,10 +224,10 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
// paid to a TX_PUBKEYHASH.
//
-static std::vector<CTransaction>
+static std::vector<CMutableTransaction>
SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsView & coinsRet)
{
- std::vector<CTransaction> dummyTransactions;
+ std::vector<CMutableTransaction> dummyTransactions;
dummyTransactions.resize(2);
// Add some keys to the keystore:
@@ -261,9 +261,9 @@ BOOST_AUTO_TEST_CASE(test_Get)
CBasicKeyStore keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(coinsDummy);
- std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+ std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
- CTransaction t1;
+ CMutableTransaction t1;
t1.vin.resize(3);
t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
t1.vin[0].prevout.n = 1;
@@ -296,9 +296,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
CBasicKeyStore keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(coinsDummy);
- std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+ std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
- CTransaction t;
+ CMutableTransaction t;
t.vin.resize(1);
t.vin[0].prevout.hash = dummyTransactions[0].GetHash();
t.vin[0].prevout.n = 1;
diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp
index 1993358826..86a83f5163 100644
--- a/src/test/wallet_tests.cpp
+++ b/src/test/wallet_tests.cpp
@@ -31,16 +31,18 @@ static vector<COutput> vCoins;
static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0)
{
static int nextLockTime = 0;
- CTransaction tx;
+ CMutableTransaction tx;
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
tx.vout.resize(nInput+1);
tx.vout[nInput].nValue = nValue;
+ if (fIsFromMe) {
+ // IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(),
+ // so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
+ tx.vin.resize(1);
+ }
CWalletTx* wtx = new CWalletTx(&wallet, tx);
if (fIsFromMe)
{
- // IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(),
- // so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
- wtx->vin.resize(1);
wtx->fDebitCached = true;
wtx->nDebitCached = 1;
}
diff --git a/src/util.h b/src/util.h
index da1810a3d3..5eb6f03826 100644
--- a/src/util.h
+++ b/src/util.h
@@ -7,7 +7,7 @@
#define BITCOIN_UTIL_H
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "compat.h"
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 36e40b1fc8..e74980e9e7 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -603,11 +603,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
// Add a transaction to the wallet, or update it.
// pblock is optional, but should be provided if the transaction is known to be in a block.
// If fUpdate is true, existing transactions will be updated.
-bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
+bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
{
{
AssertLockHeld(cs_wallet);
- bool fExisted = mapWallet.count(hash);
+ bool fExisted = mapWallet.count(tx.GetHash());
if (fExisted && !fUpdate) return false;
if (fExisted || IsMine(tx) || IsFromMe(tx))
{
@@ -621,10 +621,10 @@ bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction&
return false;
}
-void CWallet::SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock)
+void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
{
LOCK2(cs_main, cs_wallet);
- if (!AddToWalletIfInvolvingMe(hash, tx, pblock, true))
+ if (!AddToWalletIfInvolvingMe(tx, pblock, true))
return; // Not one of ours
// If a transaction changes 'conflicted' state, that changes the balance
@@ -870,7 +870,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
ReadBlockFromDisk(block, pindex);
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
- if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
+ if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
ret++;
}
pindex = chainActive.Next(pindex);
@@ -909,9 +909,8 @@ void CWalletTx::RelayWalletTransaction()
if (!IsCoinBase())
{
if (GetDepthInMainChain() == 0) {
- uint256 hash = GetHash();
- LogPrintf("Relaying wtx %s\n", hash.ToString());
- RelayTransaction((CTransaction)*this, hash);
+ LogPrintf("Relaying wtx %s\n", GetHash().ToString());
+ RelayTransaction((CTransaction)*this);
}
}
}
@@ -1028,7 +1027,7 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
vCoins.clear();
{
- LOCK(cs_wallet);
+ LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const uint256& wtxid = it->first;
@@ -1245,6 +1244,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
}
wtxNew.BindWallet(this);
+ CMutableTransaction txNew;
{
LOCK2(cs_main, cs_wallet);
@@ -1252,8 +1252,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
nFeeRet = payTxFee.GetFeePerK();
while (true)
{
- wtxNew.vin.clear();
- wtxNew.vout.clear();
+ txNew.vin.clear();
+ txNew.vout.clear();
wtxNew.fFromMe = true;
int64_t nTotalValue = nValue + nFeeRet;
@@ -1267,7 +1267,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
strFailReason = _("Transaction amount too small");
return false;
}
- wtxNew.vout.push_back(txout);
+ txNew.vout.push_back(txout);
}
// Choose coins to use
@@ -1331,8 +1331,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
else
{
// Insert change txn at random position:
- vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
- wtxNew.vout.insert(position, newTxOut);
+ vector<CTxOut>::iterator position = txNew.vout.begin()+GetRandInt(txNew.vout.size()+1);
+ txNew.vout.insert(position, newTxOut);
}
}
else
@@ -1340,17 +1340,20 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
// Fill vin
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
- wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
+ txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
// Sign
int nIn = 0;
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
- if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
+ if (!SignSignature(*this, *coin.first, txNew, nIn++))
{
strFailReason = _("Signing transaction failed");
return false;
}
+ // Embed the constructed transaction data in wtxNew.
+ *static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
+
// Limit size
unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
if (nBytes >= MAX_STANDARD_TX_SIZE)
diff --git a/src/wallet.h b/src/wallet.h
index b168116f49..8494ce9a34 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -244,8 +244,8 @@ public:
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet=false);
- void SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock);
- bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate);
+ void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
+ bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
void EraseFromWallet(const uint256 &hash);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();