aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--depends/packages/gmp.mk30
-rw-r--r--depends/packages/packages.mk2
-rw-r--r--depends/patches/gmp/arm_gmp_build_fix.patch21
-rw-r--r--depends/patches/gmp/darwin_gmp_build_fix.patch29
-rw-r--r--doc/REST-interface.md24
-rw-r--r--doc/build-osx.md2
-rw-r--r--doc/build-unix.md5
-rw-r--r--doc/release-notes.md29
-rwxr-xr-xqa/pull-tester/rpc-tests.sh3
-rwxr-xr-xqa/rpc-tests/mempool_resurrect_test.py88
-rwxr-xr-xqa/rpc-tests/mempool_spendcoinbase.py69
-rwxr-xr-xqa/rpc-tests/rest.py62
-rw-r--r--qa/rpc-tests/util.py16
-rw-r--r--src/Makefile.am26
-rw-r--r--src/bitcoin-tx.cpp12
-rw-r--r--src/bloom.cpp2
-rw-r--r--src/chain.h2
-rw-r--r--src/chainparams.h2
-rw-r--r--src/coincontrol.h2
-rw-r--r--src/compressor.h2
-rw-r--r--src/core_read.cpp4
-rw-r--r--src/core_write.cpp4
-rw-r--r--src/crypto/hmac_sha256.cpp34
-rw-r--r--src/crypto/hmac_sha256.h32
-rw-r--r--src/crypto/hmac_sha512.cpp34
-rw-r--r--src/crypto/hmac_sha512.h32
-rw-r--r--src/crypto/rfc6979_hmac_sha256.cpp47
-rw-r--r--src/crypto/rfc6979_hmac_sha256.h36
-rw-r--r--src/crypto/sha2.h64
-rw-r--r--src/crypto/sha256.cpp189
-rw-r--r--src/crypto/sha256.h28
-rw-r--r--src/crypto/sha512.cpp (renamed from src/crypto/sha2.cpp)210
-rw-r--r--src/crypto/sha512.h28
-rw-r--r--src/hash.cpp1
-rw-r--r--src/hash.h2
-rw-r--r--src/init.cpp10
-rw-r--r--src/init.h6
-rw-r--r--src/key.cpp32
-rw-r--r--src/key.h8
-rw-r--r--src/main.cpp170
-rw-r--r--src/main.h200
-rw-r--r--src/miner.cpp4
-rw-r--r--src/net.cpp10
-rw-r--r--src/net.h11
-rw-r--r--src/netbase.cpp20
-rw-r--r--src/netbase.h4
-rw-r--r--src/pow.cpp2
-rw-r--r--src/primitives/block.cpp (renamed from src/core/block.cpp)2
-rw-r--r--src/primitives/block.h (renamed from src/core/block.h)8
-rw-r--r--src/primitives/transaction.cpp (renamed from src/core/transaction.cpp)2
-rw-r--r--src/primitives/transaction.h (renamed from src/core/transaction.h)6
-rw-r--r--src/pubkey.cpp1
-rw-r--r--src/qt/bitcoinunits.cpp2
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/rest.cpp93
-rw-r--r--src/rpcblockchain.cpp6
-rw-r--r--src/rpcrawtransaction.cpp2
-rw-r--r--src/rpcserver.cpp2
-rw-r--r--src/script/bitcoinconsensus.cpp2
-rw-r--r--src/script/interpreter.cpp4
-rw-r--r--src/script/sign.cpp2
-rw-r--r--src/secp256k1/.travis.yml2
-rw-r--r--src/secp256k1/Makefile.am3
-rw-r--r--src/secp256k1/build-aux/m4/bitcoin_secp.m48
-rw-r--r--src/secp256k1/configure.ac61
-rw-r--r--src/secp256k1/include/secp256k1.h12
-rw-r--r--src/secp256k1/src/ecdsa.h14
-rw-r--r--src/secp256k1/src/ecdsa_impl.h180
-rw-r--r--src/secp256k1/src/eckey.h5
-rw-r--r--src/secp256k1/src/eckey_impl.h33
-rw-r--r--src/secp256k1/src/ecmult.h2
-rw-r--r--src/secp256k1/src/ecmult_gen_impl.h19
-rw-r--r--src/secp256k1/src/ecmult_impl.h99
-rw-r--r--src/secp256k1/src/field.h18
-rw-r--r--src/secp256k1/src/field_10x26_impl.h45
-rw-r--r--src/secp256k1/src/field_5x52_impl.h38
-rw-r--r--src/secp256k1/src/field_5x52_int128_impl.h84
-rw-r--r--src/secp256k1/src/field_gmp_impl.h21
-rw-r--r--src/secp256k1/src/field_impl.h12
-rw-r--r--src/secp256k1/src/group.h8
-rw-r--r--src/secp256k1/src/group_impl.h86
-rw-r--r--src/secp256k1/src/num.h42
-rw-r--r--src/secp256k1/src/num_gmp_impl.h184
-rw-r--r--src/secp256k1/src/num_impl.h2
-rw-r--r--src/secp256k1/src/scalar.h41
-rw-r--r--src/secp256k1/src/scalar_4x64_impl.h102
-rw-r--r--src/secp256k1/src/scalar_8x32_impl.h126
-rw-r--r--src/secp256k1/src/scalar_impl.h152
-rw-r--r--src/secp256k1/src/secp256k1.c47
-rw-r--r--src/secp256k1/src/tests.c551
-rw-r--r--src/secp256k1/src/util.h17
-rw-r--r--src/test/crypto_tests.cpp83
-rw-r--r--src/test/data/script_invalid.json98
-rw-r--r--src/test/data/script_valid.json94
-rw-r--r--src/test/key_tests.cpp23
-rw-r--r--src/test/main_tests.cpp2
-rw-r--r--src/test/script_tests.cpp37
-rw-r--r--src/test/util_tests.cpp2
-rw-r--r--src/txmempool.h2
-rw-r--r--src/undo.h2
-rw-r--r--src/utilmoneystr.cpp2
-rw-r--r--src/wallet.h4
102 files changed, 2618 insertions, 1529 deletions
diff --git a/depends/packages/gmp.mk b/depends/packages/gmp.mk
deleted file mode 100644
index bcbf50ceae..0000000000
--- a/depends/packages/gmp.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-package=gmp
-$(package)_version=6.0.0a
-$(package)_download_path=https://gmplib.org/download/gmp
-$(package)_file_name=$(package)-$($(package)_version).tar.bz2
-$(package)_sha256_hash=7f8e9a804b9c6d07164cf754207be838ece1219425d64e28cfa3e70d5c759aaf
-$(package)_patches=arm_gmp_build_fix.patch darwin_gmp_build_fix.patch
-
-define $(package)_preprocess_cmds
- patch -p1 < $($(package)_patch_dir)/arm_gmp_build_fix.patch && \
- patch -p1 < $($(package)_patch_dir)/darwin_gmp_build_fix.patch
-endef
-
-define $(package)_set_vars
- $(package)_config_opts=--disable-shared CC_FOR_BUILD=$(build_CC)
- $(package)_config_opts_x86_64_darwin=--with-pic
- $(package)_config_opts_x86_64_linux=--with-pic
- $(package)_config_opts_arm_linux=--with-pic
-endef
-
-define $(package)_config_cmds
- $($(package)_autoconf)
-endef
-
-define $(package)_build_cmds
- $(MAKE)
-endef
-
-define $(package)_stage_cmds
- $(MAKE) DESTDIR=$($(package)_staging_dir) install
-endef
diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk
index 305d21cb2d..bbf53cc2dc 100644
--- a/depends/packages/packages.mk
+++ b/depends/packages/packages.mk
@@ -1,4 +1,4 @@
-packages:=boost openssl gmp
+packages:=boost openssl
native_packages := native_ccache native_comparisontool
qt_native_packages = native_protobuf
diff --git a/depends/patches/gmp/arm_gmp_build_fix.patch b/depends/patches/gmp/arm_gmp_build_fix.patch
deleted file mode 100644
index 666cf58cf6..0000000000
--- a/depends/patches/gmp/arm_gmp_build_fix.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-
-# HG changeset patch
-# User Torbjorn Granlund <tege@gmplib.org>
-# Date 1396602422 -7200
-# Node ID 676e2d0f0e4dd301a7066079d2c9326c25c34a40
-# Parent 0194a75b56b21a9196626430af86c5bd9110c42d
-Conditionalise ARM asm on !__thumb__.
-
-diff -r 0194a75b56b2 -r 676e2d0f0e4d mpn/generic/div_qr_1n_pi1.c
---- a/mpn/generic/div_qr_1n_pi1.c Thu Apr 03 23:58:51 2014 +0200
-+++ b/mpn/generic/div_qr_1n_pi1.c Fri Apr 04 11:07:02 2014 +0200
-@@ -130,7 +130,7 @@
- "%2" ((UDItype)(a0)), "r" ((UDItype)(b0)) __CLOBBER_CC)
- #endif
-
--#if defined (__arm__) && W_TYPE_SIZE == 32
-+#if defined (__arm__) && !defined (__thumb__) && W_TYPE_SIZE == 32
- #define add_mssaaaa(m, sh, sl, ah, al, bh, bl) \
- __asm__ ( "adds %2, %5, %6\n\t" \
- "adcs %1, %3, %4\n\t" \
-
diff --git a/depends/patches/gmp/darwin_gmp_build_fix.patch b/depends/patches/gmp/darwin_gmp_build_fix.patch
deleted file mode 100644
index b9cfd80e77..0000000000
--- a/depends/patches/gmp/darwin_gmp_build_fix.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-
-# HG changeset patch
-# User Torbjorn Granlund <tege@gmplib.org>
-# Date 1396470504 -7200
-# Node ID 1fab0adc5ff7d9ecddcbda96f407da58347bb49c
-# Parent db645603dcdb41afcf78b19b551ecd5a01c3841c
-Workaround for Darwin assembler quirk.
-
-diff -r db645603dcdb -r 1fab0adc5ff7 mpn/x86_64/k8/redc_1.asm
---- a/mpn/x86_64/k8/redc_1.asm Mon Mar 31 23:04:32 2014 +0200
-+++ b/mpn/x86_64/k8/redc_1.asm Wed Apr 02 22:28:24 2014 +0200
-@@ -114,7 +114,7 @@
-
- JUMPTABSECT
- ALIGN(8)
--L(tab): JMPENT( L(0m4), L(tab))
-+L(tab): JMPENT( L(0), L(tab))
- JMPENT( L(1), L(tab))
- JMPENT( L(2), L(tab))
- JMPENT( L(3), L(tab))
-@@ -397,6 +397,7 @@
-
-
- ALIGN(16)
-+L(0):
- L(0m4):
- L(lo0): mov (mp,nneg,8), %rax
- mov nneg, i
-
diff --git a/doc/REST-interface.md b/doc/REST-interface.md
new file mode 100644
index 0000000000..05c532be54
--- /dev/null
+++ b/doc/REST-interface.md
@@ -0,0 +1,24 @@
+Unauthenticated REST Interface
+==============================
+
+The REST API can be enabled with the `-rest` option.
+
+Supported API
+-------------
+`GET /rest/tx/TX-HASH.{bin|hex|json}`
+
+Given a transaction hash,
+Returns a transaction, in binary, hex-encoded binary or JSON formats.
+
+`GET /rest/block/BLOCK-HASH.{bin|hex|json}`
+
+Given a block hash,
+Returns a block, in binary, hex-encoded binary or JSON formats.
+
+The HTTP request and response are both handled entirely in-memory, thus making maximum memory usage at least 2.66MB (1 MB max block, plus hex encoding) per request.
+
+For full TX query capability, one must enable the transaction index via "txindex=1" command line / configuration option.
+
+Risks
+-------------
+Running a webbrowser on the same node with a REST enabled bitcoind can be a risk. Accessing prepared XSS websites could read out tx/block data of your node by placing links like `<script src="http://127.0.0.1:1234/tx/json/1234567890">` which might break the nodes privacy. \ No newline at end of file
diff --git a/doc/build-osx.md b/doc/build-osx.md
index 491c5c4683..c41820f2b1 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -38,7 +38,7 @@ Instructions: Homebrew
#### Install dependencies using Homebrew
- brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt gmp
+ brew install autoconf automake libtool boost miniupnpc openssl pkg-config protobuf qt
#### Installing berkeley-db4 using Homebrew
diff --git a/doc/build-unix.md b/doc/build-unix.md
index e03dc8181a..8ddee3b757 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -33,7 +33,6 @@ These dependencies are required:
------------|------------------|----------------------
libssl | SSL Support | Secure communications
libboost | Boost | C++ Library
- libgmp | secp256k1 | Arbitrary-precision arithmetic (version >= 3.1)
Optional dependencies:
@@ -58,7 +57,7 @@ Dependency Build Instructions: Ubuntu & Debian
----------------------------------------------
Build requirements:
- sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libgmp-dev
+ sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev
for Ubuntu 12.04 and later or Debian 7 and later libboost-all-dev has to be installed:
@@ -106,7 +105,7 @@ To build with Qt 4 you need the following:
For Qt 5 you need the following:
- sudo apt-get install libqt5gui5 libqt5core5 libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler
+ sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler
libqrencode (optional) can be installed with:
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 6aaea67790..f804e8c11b 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -95,3 +95,32 @@ are done, it always returns an immediate error with code -28 to all calls.
This new behaviour can be useful for clients to know that a server is already
started and will be available soon (for instance, so that they do not
have to start it themselves).
+
+Improved signing security
+=========================
+
+For 0.10 the security of signing against unusual attacks has been
+improved by making the signatures constant time and deterministic.
+
+This change is a result of switching signing to use libsecp256k1
+instead of OpenSSL. Libsecp256k1 is a cryptographic library
+optimized for the curve Bitcoin uses which was created by Bitcoin
+Core developer Pieter Wuille.
+
+There exist attacks[1] against most ECC implementations where an
+attacker on shared virtual machine hardware could extract a private
+key if they could cause a target to sign using the same key hundreds
+of times. While using shared hosts and reusing keys are inadvisable
+for other reasons, it's a better practice to avoid the exposure.
+
+OpenSSL has code in their source repository for derandomization
+and reduction in timing leaks, and we've eagerly wanted to use
+it for a long time but this functionality has still not made its
+way into a released version of OpenSSL. Libsecp256k1 achieves
+significantly stronger protection: As far as we're aware this is
+the only deployed implementation of constant time signing for
+the curve Bitcoin uses and we have reason to believe that
+libsecp256k1 is better tested and more thoroughly reviewed
+than the implementation in OpenSSL.
+
+[1] https://eprint.iacr.org/2014/161.pdf
diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh
index 2f1e24b78d..a93b80686b 100755
--- a/qa/pull-tester/rpc-tests.sh
+++ b/qa/pull-tester/rpc-tests.sh
@@ -18,9 +18,12 @@ fi
if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
${BUILDDIR}/qa/rpc-tests/wallet.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/listtransactions.py --srcdir "${BUILDDIR}/src"
+ ${BUILDDIR}/qa/rpc-tests/mempool_resurrect_test.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --mineblock --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/getchaintips.py --srcdir "${BUILDDIR}/src"
+ ${BUILDDIR}/qa/rpc-tests/rest.py --srcdir "${BUILDDIR}/src"
+ ${BUILDDIR}/qa/rpc-tests/mempool_spendcoinbase.py --srcdir "${BUILDDIR}/src"
#${BUILDDIR}/qa/rpc-tests/forknotify.py --srcdir "${BUILDDIR}/src"
else
echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"
diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py
new file mode 100755
index 0000000000..907cbf98f9
--- /dev/null
+++ b/qa/rpc-tests/mempool_resurrect_test.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Test resurrection of mined transactions when
+# the blockchain is re-organized.
+#
+
+from test_framework import BitcoinTestFramework
+from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
+from util import *
+import os
+import shutil
+
+# Create one-input, one-output, no-fee transaction:
+class MempoolCoinbaseTest(BitcoinTestFramework):
+
+ def setup_network(self):
+ # Just need one node for this test
+ args = ["-checkmempool", "-debug=mempool"]
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, args))
+ self.is_network_split = False
+
+ def create_tx(self, from_txid, to_address, amount):
+ inputs = [{ "txid" : from_txid, "vout" : 0}]
+ outputs = { to_address : amount }
+ rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
+ signresult = self.nodes[0].signrawtransaction(rawtx)
+ assert_equal(signresult["complete"], True)
+ return signresult["hex"]
+
+ def run_test(self):
+ node0_address = self.nodes[0].getnewaddress()
+
+ # Spend block 1/2/3's coinbase transactions
+ # Mine a block.
+ # Create three more transactions, spending the spends
+ # Mine another block.
+ # ... make sure all the transactions are confirmed
+ # Invalidate both blocks
+ # ... make sure all the transactions are put back in the mempool
+ # Mine a new block
+ # ... make sure all the transactions are confirmed again.
+
+ b = [ self.nodes[0].getblockhash(n) for n in range(1, 4) ]
+ coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
+ spends1_raw = [ self.create_tx(txid, node0_address, 50) for txid in coinbase_txids ]
+ spends1_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw ]
+
+ blocks = []
+ blocks.extend(self.nodes[0].setgenerate(True, 1))
+
+ spends2_raw = [ self.create_tx(txid, node0_address, 49.99) for txid in spends1_id ]
+ spends2_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw ]
+
+ blocks.extend(self.nodes[0].setgenerate(True, 1))
+
+ # mempool should be empty, all txns confirmed
+ assert_equal(set(self.nodes[0].getrawmempool()), set())
+ for txid in spends1_id+spends2_id:
+ tx = self.nodes[0].gettransaction(txid)
+ assert(tx["confirmations"] > 0)
+
+ # Use invalidateblock to re-org back; all transactions should
+ # end up unconfirmed and back in the mempool
+ for node in self.nodes:
+ node.invalidateblock(blocks[0])
+
+ # mempool should be empty, all txns confirmed
+ assert_equal(set(self.nodes[0].getrawmempool()), set(spends1_id+spends2_id))
+ for txid in spends1_id+spends2_id:
+ tx = self.nodes[0].gettransaction(txid)
+ assert(tx["confirmations"] == 0)
+
+ # Generate another block, they should all get mined
+ self.nodes[0].setgenerate(True, 1)
+ # mempool should be empty, all txns confirmed
+ assert_equal(set(self.nodes[0].getrawmempool()), set())
+ for txid in spends1_id+spends2_id:
+ tx = self.nodes[0].gettransaction(txid)
+ assert(tx["confirmations"] > 0)
+
+
+if __name__ == '__main__':
+ MempoolCoinbaseTest().main()
diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py
new file mode 100755
index 0000000000..0fc7c8577e
--- /dev/null
+++ b/qa/rpc-tests/mempool_spendcoinbase.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Test spending coinbase transactions.
+# The coinbase transaction in block N can appear in block
+# N+100... so is valid in the mempool when the best block
+# height is N+99.
+# This test makes sure coinbase spends that will be mature
+# in the next block are accepted into the memory pool,
+# but less mature coinbase spends are NOT.
+#
+
+from test_framework import BitcoinTestFramework
+from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
+from util import *
+import os
+import shutil
+
+# Create one-input, one-output, no-fee transaction:
+class MempoolSpendCoinbaseTest(BitcoinTestFramework):
+
+ def setup_network(self):
+ # Just need one node for this test
+ args = ["-checkmempool", "-debug=mempool"]
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, args))
+ self.is_network_split = False
+
+ def create_tx(self, from_txid, to_address, amount):
+ inputs = [{ "txid" : from_txid, "vout" : 0}]
+ outputs = { to_address : amount }
+ rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
+ signresult = self.nodes[0].signrawtransaction(rawtx)
+ assert_equal(signresult["complete"], True)
+ return signresult["hex"]
+
+ def run_test(self):
+ chain_height = self.nodes[0].getblockcount()
+ assert_equal(chain_height, 200)
+ node0_address = self.nodes[0].getnewaddress()
+
+ # Coinbase at height chain_height-100+1 ok in mempool, should
+ # get mined. Coinbase at height chain_height-100+2 is
+ # is too immature to spend.
+ b = [ self.nodes[0].getblockhash(n) for n in range(101, 103) ]
+ coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
+ spends_raw = [ self.create_tx(txid, node0_address, 50) for txid in coinbase_txids ]
+
+ spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0])
+
+ # coinbase at height 102 should be too immature to spend
+ assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, spends_raw[1])
+
+ # mempool should have just spend_101:
+ assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ])
+
+ # mine a block, spend_101 should get confirmed
+ self.nodes[0].setgenerate(True, 1)
+ assert_equal(set(self.nodes[0].getrawmempool()), set())
+
+ # ... and now height 102 can be spent:
+ spend_102_id = self.nodes[0].sendrawtransaction(spends_raw[1])
+ assert_equal(self.nodes[0].getrawmempool(), [ spend_102_id ])
+
+if __name__ == '__main__':
+ MempoolSpendCoinbaseTest().main()
diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py
new file mode 100755
index 0000000000..2d301bf4f8
--- /dev/null
+++ b/qa/rpc-tests/rest.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Test REST interface
+#
+
+from test_framework import BitcoinTestFramework
+from util import *
+import json
+
+try:
+ import http.client as httplib
+except ImportError:
+ import httplib
+try:
+ import urllib.parse as urlparse
+except ImportError:
+ import urlparse
+
+def http_get_call(host, port, path, response_object = 0):
+ conn = httplib.HTTPConnection(host, port)
+ conn.request('GET', path)
+
+ if response_object:
+ return conn.getresponse()
+
+ return conn.getresponse().read()
+
+
+class RESTTest (BitcoinTestFramework):
+ FORMAT_SEPARATOR = "."
+
+ def run_test(self):
+ url = urlparse.urlparse(self.nodes[0].url)
+ bb_hash = self.nodes[0].getbestblockhash()
+
+ # check binary format
+ response = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"bin", True)
+ assert_equal(response.status, 200)
+ assert_greater_than(int(response.getheader('content-length')), 10)
+
+ # check json format
+ json_string = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+'json')
+ json_obj = json.loads(json_string)
+ assert_equal(json_obj['hash'], bb_hash)
+
+ # do tx test
+ tx_hash = json_obj['tx'][0];
+ json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"json")
+ json_obj = json.loads(json_string)
+ assert_equal(json_obj['txid'], tx_hash)
+
+ # check hex format response
+ hex_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"hex", True)
+ assert_equal(response.status, 200)
+ assert_greater_than(int(response.getheader('content-length')), 10)
+
+if __name__ == '__main__':
+ RESTTest ().main ()
diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py
index bed7fed8ca..ec65f783e8 100644
--- a/qa/rpc-tests/util.py
+++ b/qa/rpc-tests/util.py
@@ -163,7 +163,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None):
Start a bitcoind and return RPC connection to it
"""
datadir = os.path.join(dirname, "node"+str(i))
- args = [ os.getenv("BITCOIND", "bitcoind"), "-datadir="+datadir, "-keypool=1", "-discover=0" ]
+ args = [ os.getenv("BITCOIND", "bitcoind"), "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
if extra_args is not None: args.extend(extra_args)
bitcoind_processes[i] = subprocess.Popen(args)
devnull = open("/dev/null", "w+")
@@ -327,3 +327,17 @@ def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants):
def assert_equal(thing1, thing2):
if thing1 != thing2:
raise AssertionError("%s != %s"%(str(thing1),str(thing2)))
+
+def assert_greater_than(thing1, thing2):
+ if thing1 <= thing2:
+ raise AssertionError("%s <= %s"%(str(thing1),str(thing2)))
+
+def assert_raises(exc, fun, *args, **kwds):
+ try:
+ fun(*args, **kwds)
+ except exc:
+ pass
+ except Exception as e:
+ raise AssertionError("Unexpected exception raised: "+type(e).__name__)
+ else:
+ raise AssertionError("No exception raised")
diff --git a/src/Makefile.am b/src/Makefile.am
index 3ec9e2f85d..69b3a6d4f1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -87,8 +87,8 @@ BITCOIN_CORE_H = \
coins.h \
compat.h \
compressor.h \
- core/block.h \
- core/transaction.h \
+ primitives/block.h \
+ primitives/transaction.h \
core_io.h \
crypter.h \
db.h \
@@ -203,10 +203,18 @@ libbitcoin_wallet_a_SOURCES = \
crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES)
crypto_libbitcoin_crypto_a_SOURCES = \
crypto/sha1.cpp \
- crypto/sha2.cpp \
+ crypto/sha256.cpp \
+ crypto/sha512.cpp \
+ crypto/hmac_sha256.cpp \
+ crypto/rfc6979_hmac_sha256.cpp \
+ crypto/hmac_sha512.cpp \
crypto/ripemd160.cpp \
crypto/common.h \
- crypto/sha2.h \
+ crypto/sha256.h \
+ crypto/sha512.h \
+ crypto/hmac_sha256.h \
+ crypto/rfc6979_hmac_sha256.h \
+ crypto/hmac_sha512.h \
crypto/sha1.h \
crypto/ripemd160.h
@@ -227,8 +235,8 @@ libbitcoin_common_a_SOURCES = \
chainparams.cpp \
coins.cpp \
compressor.cpp \
- core/block.cpp \
- core/transaction.cpp \
+ primitives/block.cpp \
+ primitives/transaction.cpp \
core_read.cpp \
core_write.cpp \
eccryptoverify.cpp \
@@ -342,9 +350,11 @@ bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if BUILD_BITCOIN_LIBS
include_HEADERS = script/bitcoinconsensus.h
libbitcoinconsensus_la_SOURCES = \
- core/transaction.cpp \
+ primitives/transaction.cpp \
+ crypto/hmac_sha512.cpp \
crypto/sha1.cpp \
- crypto/sha2.cpp \
+ crypto/sha256.cpp \
+ crypto/sha512.cpp \
crypto/ripemd160.cpp \
eccryptoverify.cpp \
ecwrapper.cpp \
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index c0d21ed36f..23eaebed64 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -4,7 +4,7 @@
#include "base58.h"
#include "clientversion.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "core_io.h"
#include "keystore.h"
#include "main.h" // for MAX_BLOCK_SIZE
@@ -57,6 +57,7 @@ static bool AppInitRawTx(int argc, char* argv[])
strUsage += " -? " + _("This help message") + "\n";
strUsage += " -create " + _("Create new, empty TX.") + "\n";
strUsage += " -json " + _("Select JSON output") + "\n";
+ strUsage += " -txid " + _("Output only the hex-encoded transaction id of the resultant transaction.") + "\n";
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n";
strUsage += " -testnet " + _("Use the test network") + "\n";
strUsage += "\n";
@@ -488,6 +489,13 @@ static void OutputTxJSON(const CTransaction& tx)
fprintf(stdout, "%s\n", jsonOutput.c_str());
}
+static void OutputTxHash(const CTransaction& tx)
+{
+ string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id)
+
+ fprintf(stdout, "%s\n", strHexHash.c_str());
+}
+
static void OutputTxHex(const CTransaction& tx)
{
string strHex = EncodeHexTx(tx);
@@ -499,6 +507,8 @@ static void OutputTx(const CTransaction& tx)
{
if (GetBoolArg("-json", false))
OutputTxJSON(tx);
+ else if (GetBoolArg("-txid", false))
+ OutputTxHash(tx);
else
OutputTxHex(tx);
}
diff --git a/src/bloom.cpp b/src/bloom.cpp
index 07b8f2c0ae..da30e6f355 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -4,7 +4,7 @@
#include "bloom.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "hash.h"
#include "script/script.h"
#include "script/standard.h"
diff --git a/src/chain.h b/src/chain.h
index c01240665d..d834790f06 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -6,7 +6,7 @@
#ifndef BITCOIN_CHAIN_H
#define BITCOIN_CHAIN_H
-#include "core/block.h"
+#include "primitives/block.h"
#include "pow.h"
#include "tinyformat.h"
#include "uint256.h"
diff --git a/src/chainparams.h b/src/chainparams.h
index 9f24b70a26..5d1ee1d3c6 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -8,7 +8,7 @@
#include "chainparamsbase.h"
#include "checkpoints.h"
-#include "core/block.h"
+#include "primitives/block.h"
#include "protocol.h"
#include "uint256.h"
diff --git a/src/coincontrol.h b/src/coincontrol.h
index c8bdd3b39d..cf61998723 100644
--- a/src/coincontrol.h
+++ b/src/coincontrol.h
@@ -5,7 +5,7 @@
#ifndef BITCOIN_COINCONTROL_H
#define BITCOIN_COINCONTROL_H
-#include "core/transaction.h"
+#include "primitives/transaction.h"
/** Coin Control Features. */
class CCoinControl
diff --git a/src/compressor.h b/src/compressor.h
index d9cde5de7a..efb8119d01 100644
--- a/src/compressor.h
+++ b/src/compressor.h
@@ -6,7 +6,7 @@
#ifndef BITCOIN_COMPRESSOR_H
#define BITCOIN_COMPRESSOR_H
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "script/script.h"
#include "serialize.h"
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 42e2f8d200..65c3a08c55 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -4,8 +4,8 @@
#include "core_io.h"
-#include "core/block.h"
-#include "core/transaction.h"
+#include "primitives/block.h"
+#include "primitives/transaction.h"
#include "script/script.h"
#include "serialize.h"
#include "streams.h"
diff --git a/src/core_write.cpp b/src/core_write.cpp
index a3ae8eec07..760b6a71bf 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -5,7 +5,7 @@
#include "core_io.h"
#include "base58.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "script/script.h"
#include "script/standard.h"
#include "serialize.h"
@@ -129,4 +129,6 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
if (hashBlock != 0)
entry.pushKV("blockhash", hashBlock.GetHex());
+
+ entry.pushKV("hex", EncodeHexTx(tx)); // the hex-encoded transaction. used the name "hex" to be consistent with the verbose output of "getrawtransaction".
}
diff --git a/src/crypto/hmac_sha256.cpp b/src/crypto/hmac_sha256.cpp
new file mode 100644
index 0000000000..435896538b
--- /dev/null
+++ b/src/crypto/hmac_sha256.cpp
@@ -0,0 +1,34 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "crypto/hmac_sha256.h"
+
+#include <string.h>
+
+CHMAC_SHA256::CHMAC_SHA256(const unsigned char* key, size_t keylen)
+{
+ unsigned char rkey[64];
+ if (keylen <= 64) {
+ memcpy(rkey, key, keylen);
+ memset(rkey + keylen, 0, 64 - keylen);
+ } else {
+ CSHA256().Write(key, keylen).Finalize(rkey);
+ memset(rkey + 32, 0, 32);
+ }
+
+ for (int n = 0; n < 64; n++)
+ rkey[n] ^= 0x5c;
+ outer.Write(rkey, 64);
+
+ for (int n = 0; n < 64; n++)
+ rkey[n] ^= 0x5c ^ 0x36;
+ inner.Write(rkey, 64);
+}
+
+void CHMAC_SHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
+{
+ unsigned char temp[32];
+ inner.Finalize(temp);
+ outer.Write(temp, 32).Finalize(hash);
+}
diff --git a/src/crypto/hmac_sha256.h b/src/crypto/hmac_sha256.h
new file mode 100644
index 0000000000..1fdee5a7cd
--- /dev/null
+++ b/src/crypto/hmac_sha256.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CRYPTO_HMAC_SHA256_H
+#define BITCOIN_CRYPTO_HMAC_SHA256_H
+
+#include "crypto/sha256.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** A hasher class for HMAC-SHA-512. */
+class CHMAC_SHA256
+{
+private:
+ CSHA256 outer;
+ CSHA256 inner;
+
+public:
+ static const size_t OUTPUT_SIZE = 32;
+
+ CHMAC_SHA256(const unsigned char* key, size_t keylen);
+ CHMAC_SHA256& Write(const unsigned char* data, size_t len)
+ {
+ inner.Write(data, len);
+ return *this;
+ }
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+};
+
+#endif // BITCOIN_CRYPTO_HMAC_SHA256_H
diff --git a/src/crypto/hmac_sha512.cpp b/src/crypto/hmac_sha512.cpp
new file mode 100644
index 0000000000..940a93277c
--- /dev/null
+++ b/src/crypto/hmac_sha512.cpp
@@ -0,0 +1,34 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "crypto/hmac_sha512.h"
+
+#include <string.h>
+
+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/hmac_sha512.h b/src/crypto/hmac_sha512.h
new file mode 100644
index 0000000000..17d75021aa
--- /dev/null
+++ b/src/crypto/hmac_sha512.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CRYPTO_HMAC_SHA512_H
+#define BITCOIN_CRYPTO_HMAC_SHA512_H
+
+#include "crypto/sha512.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** 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 // BITCOIN_CRYPTO_HMAC_SHA512_H
diff --git a/src/crypto/rfc6979_hmac_sha256.cpp b/src/crypto/rfc6979_hmac_sha256.cpp
new file mode 100644
index 0000000000..3f935abfea
--- /dev/null
+++ b/src/crypto/rfc6979_hmac_sha256.cpp
@@ -0,0 +1,47 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "crypto/rfc6979_hmac_sha256.h"
+
+#include <string.h>
+
+#include <algorithm>
+
+static const unsigned char zero[1] = {0x00};
+static const unsigned char one[1] = {0x01};
+
+RFC6979_HMAC_SHA256::RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen) : retry(false)
+{
+ memset(V, 0x01, sizeof(V));
+ memset(K, 0x00, sizeof(K));
+
+ CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Write(key, keylen).Write(msg, msglen).Finalize(K);
+ CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
+ CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(one, sizeof(one)).Write(key, keylen).Write(msg, msglen).Finalize(K);
+ CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
+}
+
+RFC6979_HMAC_SHA256::~RFC6979_HMAC_SHA256()
+{
+ memset(V, 0x01, sizeof(V));
+ memset(K, 0x00, sizeof(K));
+}
+
+void RFC6979_HMAC_SHA256::Generate(unsigned char* output, size_t outputlen)
+{
+ if (retry) {
+ CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Finalize(K);
+ CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
+ }
+
+ while (outputlen > 0) {
+ CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V);
+ size_t len = std::min(outputlen, sizeof(V));
+ memcpy(output, V, len);
+ output += len;
+ outputlen -= len;
+ }
+
+ retry = true;
+}
diff --git a/src/crypto/rfc6979_hmac_sha256.h b/src/crypto/rfc6979_hmac_sha256.h
new file mode 100644
index 0000000000..e67ddcf8fe
--- /dev/null
+++ b/src/crypto/rfc6979_hmac_sha256.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_RFC6979_HMAC_SHA256_H
+#define BITCOIN_RFC6979_HMAC_SHA256_H
+
+#include "crypto/hmac_sha256.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** The RFC 6979 PRNG using HMAC-SHA256. */
+class RFC6979_HMAC_SHA256
+{
+private:
+ unsigned char V[CHMAC_SHA256::OUTPUT_SIZE];
+ unsigned char K[CHMAC_SHA256::OUTPUT_SIZE];
+ bool retry;
+
+public:
+ /**
+ * Construct a new RFC6979 PRNG, using the given key and message.
+ * The message is assumed to be already hashed.
+ */
+ RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen);
+
+ /**
+ * Generate a byte array.
+ */
+ void Generate(unsigned char* output, size_t outputlen);
+
+ ~RFC6979_HMAC_SHA256();
+};
+
+#endif // BITCOIN_RFC6979_HMAC_SHA256_H
diff --git a/src/crypto/sha2.h b/src/crypto/sha2.h
deleted file mode 100644
index 329c6675ab..0000000000
--- a/src/crypto/sha2.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2014 The Bitcoin developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_CRYPTO_SHA2_H
-#define BITCOIN_CRYPTO_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 // BITCOIN_CRYPTO_SHA2_H
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
new file mode 100644
index 0000000000..8410e59305
--- /dev/null
+++ b/src/crypto/sha256.cpp
@@ -0,0 +1,189 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "crypto/sha256.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
+} // 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;
+}
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
new file mode 100644
index 0000000000..bde1a59bed
--- /dev/null
+++ b/src/crypto/sha256.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CRYPTO_SHA256_H
+#define BITCOIN_CRYPTO_SHA256_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();
+};
+
+#endif // BITCOIN_CRYPTO_SHA256_H
diff --git a/src/crypto/sha2.cpp b/src/crypto/sha512.cpp
index 613aac2d71..22c3103bed 100644
--- a/src/crypto/sha2.cpp
+++ b/src/crypto/sha512.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "crypto/sha2.h"
+#include "crypto/sha512.h"
#include "crypto/common.h"
@@ -11,124 +11,6 @@
// 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
{
@@ -249,8 +131,8 @@ void Transform(uint64_t* s, const unsigned char* chunk)
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));
+ 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;
@@ -267,63 +149,6 @@ void Transform(uint64_t* s, const unsigned char* chunk)
} // 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)
@@ -380,32 +205,3 @@ CSHA512& CSHA512::Reset()
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/sha512.h b/src/crypto/sha512.h
new file mode 100644
index 0000000000..5566d5db3e
--- /dev/null
+++ b/src/crypto/sha512.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CRYPTO_SHA512_H
+#define BITCOIN_CRYPTO_SHA512_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** 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();
+};
+
+#endif // BITCOIN_CRYPTO_SHA512_H
diff --git a/src/hash.cpp b/src/hash.cpp
index 2cca06ae23..aaca00ea2d 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "hash.h"
+#include "crypto/hmac_sha512.h"
inline uint32_t ROTL32(uint32_t x, int8_t r)
{
diff --git a/src/hash.h b/src/hash.h
index 75695160e6..5a34cdc5c3 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -7,7 +7,7 @@
#define BITCOIN_HASH_H
#include "crypto/ripemd160.h"
-#include "crypto/sha2.h"
+#include "crypto/sha256.h"
#include "serialize.h"
#include "uint256.h"
#include "version.h"
diff --git a/src/init.cpp b/src/init.cpp
index 7b6ebb1b30..11329c16aa 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
@@ -60,7 +60,7 @@ bool fFeeEstimatesInitialized = false;
#define MIN_CORE_FILEDESCRIPTORS 150
#endif
-// Used to pass flags to the Bind() function
+/** Used to pass flags to the Bind() function */
enum BindFlags {
BF_NONE = 0,
BF_EXPLICIT = (1U << 0),
@@ -175,9 +175,9 @@ void Shutdown()
LogPrintf("%s: done\n", __func__);
}
-//
-// Signal handlers are very limited in what they are allowed to do, so:
-//
+/**
+ * Signal handlers are very limited in what they are allowed to do, so:
+ */
void HandleSIGTERM(int)
{
fRequestShutdown = true;
diff --git a/src/init.h b/src/init.h
index aaf8c07e6e..f2f7ac6747 100644
--- a/src/init.h
+++ b/src/init.h
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2013 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_INIT_H
@@ -22,7 +22,7 @@ bool ShutdownRequested();
void Shutdown();
bool AppInit2(boost::thread_group& threadGroup);
-/* The help message mode determines what help message to show */
+/** The help message mode determines what help message to show */
enum HelpMessageMode {
HMM_BITCOIND,
HMM_BITCOIN_QT
diff --git a/src/key.cpp b/src/key.cpp
index a91ed1cc1d..acf62360a4 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -4,7 +4,8 @@
#include "key.h"
-#include "crypto/sha2.h"
+#include "crypto/hmac_sha512.h"
+#include "crypto/rfc6979_hmac_sha256.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "random.h"
@@ -71,19 +72,23 @@ CPubKey CKey::GetPubKey() const {
return result;
}
-bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
+bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
if (!fValid)
return false;
vchSig.resize(72);
- int nSigLen = 72;
- CKey nonce;
+ RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
do {
- nonce.MakeNewKey(true);
- if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin()))
- break;
+ uint256 nonce;
+ prng.Generate((unsigned char*)&nonce, 32);
+ nonce += test_case;
+ int nSigLen = 72;
+ int ret = secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), (unsigned char*)&nonce);
+ nonce = 0;
+ if (ret) {
+ vchSig.resize(nSigLen);
+ return true;
+ }
} while(true);
- vchSig.resize(nSigLen);
- return true;
}
bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
@@ -105,10 +110,13 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
return false;
vchSig.resize(65);
int rec = -1;
- CKey nonce;
+ RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
do {
- nonce.MakeNewKey(true);
- if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec))
+ uint256 nonce;
+ prng.Generate((unsigned char*)&nonce, 32);
+ int ret = secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), (unsigned char*)&nonce, &rec);
+ nonce = 0;
+ if (ret)
break;
} while(true);
assert(rec != -1);
diff --git a/src/key.h b/src/key.h
index 228cc42449..d85abe095c 100644
--- a/src/key.h
+++ b/src/key.h
@@ -122,8 +122,12 @@ public:
*/
CPubKey GetPubKey() const;
- //! Create a DER-serialized signature.
- bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig) const;
+ /**
+ * Create a DER-serialized signature.
+ * The test_case parameter tweaks the deterministic nonce, and is only for
+ * testing. It should be zero for normal use.
+ */
+ bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const;
/**
* Create a compact signature (65 bytes), which allows reconstructing the used public key.
diff --git a/src/main.cpp b/src/main.cpp
index 0515eeb156..60e1db6647 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "main.h"
@@ -33,9 +33,9 @@ using namespace std;
# error "Bitcoin cannot be compiled without assertions."
#endif
-//
-// Global state
-//
+/**
+ * Global state
+ */
CCriticalSection cs_main;
@@ -66,7 +66,7 @@ map<uint256, COrphanTx> mapOrphanTransactions;
map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
void EraseOrphansFor(NodeId peer);
-// Constant stuff for coinbase transactions we create:
+/** Constant stuff for coinbase transactions we create: */
CScript COINBASE_FLAGS;
const string strMessageMagic = "Bitcoin Signed Message:\n";
@@ -97,44 +97,49 @@ namespace {
CBlockIndex *pindexBestInvalid;
- // The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least
- // as good as our current tip. Entries may be failed, though.
+ /**
+ * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least
+ * as good as our current tip. Entries may be failed, though.
+ */
set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
- // Number of nodes with fSyncStarted.
+ /** Number of nodes with fSyncStarted. */
int nSyncStarted = 0;
- // All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions.
+ /** All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. */
multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
CCriticalSection cs_LastBlockFile;
std::vector<CBlockFileInfo> vinfoBlockFile;
int nLastBlockFile = 0;
- // Every received block is assigned a unique and increasing identifier, so we
- // know which one to give priority in case of a fork.
+ /**
+ * Every received block is assigned a unique and increasing identifier, so we
+ * know which one to give priority in case of a fork.
+ */
CCriticalSection cs_nBlockSequenceId;
- // Blocks loaded from disk are assigned id 0, so start the counter at 1.
+ /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
uint32_t nBlockSequenceId = 1;
- // Sources of received blocks, to be able to send them reject messages or ban
- // them, if processing happens afterwards. Protected by cs_main.
+ /**
+ * Sources of received blocks, to be able to send them reject messages or ban
+ * them, if processing happens afterwards. Protected by cs_main.
+ */
map<uint256, NodeId> mapBlockSource;
- // Blocks that are in flight, and that are in the queue to be downloaded.
- // Protected by cs_main.
+ /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
struct QueuedBlock {
uint256 hash;
- CBlockIndex *pindex; // Optional.
- int64_t nTime; // Time of "getdata" request in microseconds.
+ CBlockIndex *pindex; //! Optional.
+ int64_t nTime; //! Time of "getdata" request in microseconds.
};
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
- // Number of preferrable block download peers.
+ /** Number of preferable block download peers. */
int nPreferredDownload = 0;
- // Dirty block index entries.
+ /** Dirty block index entries. */
set<CBlockIndex*> setDirtyBlockIndex;
- // Dirty block file entries.
+ /** Dirty block file entries. */
set<int> setDirtyFileInfo;
} // anon namespace
@@ -148,19 +153,19 @@ namespace {
namespace {
struct CMainSignals {
- // Notifies listeners of updated transaction data (transaction, and optionally the block it is found in.
+ /** 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).
+ /** 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).
+ /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
boost::signals2::signal<void (const uint256 &)> UpdatedTransaction;
- // Notifies listeners of a new active block chain.
+ /** Notifies listeners of a new active block chain. */
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
- // Notifies listeners about an inventory item being seen on the network.
+ /** Notifies listeners about an inventory item being seen on the network. */
boost::signals2::signal<void (const uint256 &)> Inventory;
- // Tells listeners to broadcast their data.
+ /** Tells listeners to broadcast their data. */
boost::signals2::signal<void ()> Broadcast;
- // Notifies listeners of a block validation result
+ /** Notifies listeners of a block validation result */
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
} g_signals;
@@ -213,32 +218,34 @@ struct CBlockReject {
uint256 hashBlock;
};
-// Maintain validation-specific state about nodes, protected by cs_main, instead
-// by CNode's own locks. This simplifies asynchronous operation, where
-// processing of incoming data is done after the ProcessMessage call returns,
-// and we're no longer holding the node's locks.
+/**
+ * Maintain validation-specific state about nodes, protected by cs_main, instead
+ * by CNode's own locks. This simplifies asynchronous operation, where
+ * processing of incoming data is done after the ProcessMessage call returns,
+ * and we're no longer holding the node's locks.
+ */
struct CNodeState {
- // Accumulated misbehaviour score for this peer.
+ //! Accumulated misbehaviour score for this peer.
int nMisbehavior;
- // Whether this peer should be disconnected and banned (unless whitelisted).
+ //! Whether this peer should be disconnected and banned (unless whitelisted).
bool fShouldBan;
- // String name of this peer (debugging/logging purposes).
+ //! String name of this peer (debugging/logging purposes).
std::string name;
- // List of asynchronously-determined block rejections to notify this peer about.
+ //! List of asynchronously-determined block rejections to notify this peer about.
std::vector<CBlockReject> rejects;
- // The best known block we know this peer has announced.
+ //! The best known block we know this peer has announced.
CBlockIndex *pindexBestKnownBlock;
- // The hash of the last unknown block this peer has announced.
+ //! The hash of the last unknown block this peer has announced.
uint256 hashLastUnknownBlock;
- // The last full block we both have.
+ //! The last full block we both have.
CBlockIndex *pindexLastCommonBlock;
- // Whether we've started headers synchronization with this peer.
+ //! Whether we've started headers synchronization with this peer.
bool fSyncStarted;
- // Since when we're stalling block download progress (in microseconds), or 0.
+ //! Since when we're stalling block download progress (in microseconds), or 0.
int64_t nStallingSince;
list<QueuedBlock> vBlocksInFlight;
int nBlocksInFlight;
- // Whether we consider this a preferred download peer.
+ //! Whether we consider this a preferred download peer.
bool fPreferredDownload;
CNodeState() {
@@ -254,7 +261,7 @@ struct CNodeState {
}
};
-// Map maintaining per-node state. Requires cs_main.
+/** Map maintaining per-node state. Requires cs_main. */
map<NodeId, CNodeState> mapNodeState;
// Requires cs_main.
@@ -708,15 +715,15 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true;
}
-//
-// Check transaction inputs to mitigate two
-// potential denial-of-service attacks:
-//
-// 1. scriptSigs with extra data stuffed into them,
-// not consumed by scriptPubKey (or P2SH script)
-// 2. P2SH scripts with a crazy number of expensive
-// CHECKSIG/CHECKMULTISIG operations
-//
+/**
+ * Check transaction inputs to mitigate two
+ * potential denial-of-service attacks:
+ *
+ * 1. scriptSigs with extra data stuffed into them,
+ * not consumed by scriptPubKey (or P2SH script)
+ * 2. P2SH scripts with a crazy number of expensive
+ * CHECKSIG/CHECKMULTISIG operations
+ */
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{
if (tx.IsCoinBase())
@@ -1054,7 +1061,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return true;
}
-// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
+/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
{
CBlockIndex *pindexSlow = NULL;
@@ -1181,7 +1188,7 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
CAmount GetBlockValue(int nHeight, const CAmount& nFees)
{
- int64_t nSubsidy = 50 * COIN;
+ CAmount nSubsidy = 50 * COIN;
int halvings = nHeight / Params().SubsidyHalvingInterval();
// Force block reward to zero when right shift is undefined.
@@ -1327,7 +1334,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
if (state.IsInvalid(nDoS)) {
std::map<uint256, NodeId>::iterator it = mapBlockSource.find(pindex->GetBlockHash());
if (it != mapBlockSource.end() && State(it->second)) {
- CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason(), pindex->GetBlockHash()};
+ CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()};
State(it->second)->rejects.push_back(reject);
if (nDoS > 0)
Misbehaving(it->second, nDoS);
@@ -1357,10 +1364,11 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight);
}
-bool CScriptCheck::operator()() const {
+bool CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
- if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore)))
- return error("CScriptCheck() : %s:%d VerifySignature failed", ptxTo->GetHash().ToString(), nIn);
+ if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore), &error)) {
+ return ::error("CScriptCheck() : %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error));
+ }
return true;
}
@@ -1448,7 +1456,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
CScriptCheck check(*coins, tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore);
if (check())
- return state.Invalid(false, REJECT_NONSTANDARD, "non-mandatory-script-verify-flag");
+ return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
}
// Failures of other flags indicate a transaction that is
// invalid in new blocks, e.g. a invalid P2SH. We DoS ban
@@ -1457,7 +1465,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// as to the correct behavior - we may want to continue
// peering with non-upgraded nodes even after a soft-fork
// super-majority vote has passed.
- return state.DoS(100,false, REJECT_INVALID, "mandatory-script-verify-flag-failed");
+ return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
}
}
}
@@ -1818,7 +1826,7 @@ void FlushStateToDisk() {
FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
}
-// Update chainActive and related internal data structures.
+/** Update chainActive and related internal data structures. */
void static UpdateTip(CBlockIndex *pindexNew) {
chainActive.SetTip(pindexNew);
@@ -1857,7 +1865,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
}
}
-// Disconnect chainActive's tip.
+/** Disconnect chainActive's tip. */
bool static DisconnectTip(CValidationState &state) {
CBlockIndex *pindexDelete = chainActive.Tip();
assert(pindexDelete);
@@ -1904,8 +1912,10 @@ static int64_t nTimeFlush = 0;
static int64_t nTimeChainState = 0;
static int64_t nTimePostConnect = 0;
-// Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
-// corresponding to pindexNew, to bypass loading it again from disk.
+/**
+ * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
+ * corresponding to pindexNew, to bypass loading it again from disk.
+ */
bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) {
assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip);
@@ -1965,8 +1975,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
return true;
}
-// Return the tip of the chain with the most work in it, that isn't
-// known to be invalid (it's however far from certain to be valid).
+/**
+ * Return the tip of the chain with the most work in it, that isn't
+ * known to be invalid (it's however far from certain to be valid).
+ */
static CBlockIndex* FindMostWorkChain() {
do {
CBlockIndex *pindexNew = NULL;
@@ -2007,7 +2019,7 @@ static CBlockIndex* FindMostWorkChain() {
} while(true);
}
-// Delete all entries in setBlockIndexCandidates that are worse than the current tip.
+/** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */
static void PruneBlockIndexCandidates() {
// Note that we can't delete the current block itself, as we may need to return to it later in case a
// reorganization to a better block fails.
@@ -2019,8 +2031,10 @@ static void PruneBlockIndexCandidates() {
assert(!setBlockIndexCandidates.empty());
}
-// Try to make some progress towards making pindexMostWork the active block.
-// pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
+/**
+ * Try to make some progress towards making pindexMostWork the active block.
+ * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
+ */
static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) {
AssertLockHeld(cs_main);
bool fInvalidFound = false;
@@ -2085,9 +2099,11 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
return true;
}
-// Make the best chain active, in multiple steps. The result is either failure
-// or an activated best chain. pblock is either NULL or a pointer to a block
-// that is already loaded (to avoid loading it again from disk).
+/**
+ * Make the best chain active, in multiple steps. The result is either failure
+ * or an activated best chain. pblock is either NULL or a pointer to a block
+ * that is already loaded (to avoid loading it again from disk).
+ */
bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
CBlockIndex *pindexNewTip = NULL;
CBlockIndex *pindexMostWork = NULL;
@@ -2236,7 +2252,7 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
return pindexNew;
}
-// Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS).
+/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos)
{
pindexNew->nTx = block.vtx.size();
@@ -2745,7 +2761,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve
} else {
// calculate left hash
uint256 left = CalcHash(height-1, pos*2, vTxid), right;
- // calculate right hash if not beyong the end of the array - copy left hash otherwise1
+ // calculate right hash if not beyond the end of the array - copy left hash otherwise1
if (pos*2+1 < CalcTreeWidth(height-1))
right = CalcHash(height-1, pos*2+1, vTxid);
else
@@ -3975,7 +3991,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->id, pfrom->cleanSubVer,
state.GetRejectReason());
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
- state.GetRejectReason(), inv.hash);
+ state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS);
}
@@ -4049,7 +4065,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
int nDoS;
if (state.IsInvalid(nDoS)) {
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
- state.GetRejectReason(), inv.hash);
+ state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0) {
LOCK(cs_main);
Misbehaving(pfrom->GetId(), nDoS);
@@ -4256,7 +4272,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (fDebug) {
try {
string strMsg; unsigned char ccode; string strReason;
- vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, 111);
+ vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, MAX_REJECT_MESSAGE_LENGTH);
ostringstream ss;
ss << strMsg << " code " << itostr(ccode) << ": " << strReason;
diff --git a/src/main.h b/src/main.h
index caf8331ee1..f3d30fafb3 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MAIN_H
@@ -14,8 +14,8 @@
#include "chain.h"
#include "chainparams.h"
#include "coins.h"
-#include "core/block.h"
-#include "core/transaction.h"
+#include "primitives/block.h"
+#include "primitives/transaction.h"
#include "net.h"
#include "pow.h"
#include "script/script.h"
@@ -60,7 +60,7 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000;
static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
/** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
-/** Maxiumum number of signature check operations in an IsStandard() P2SH script */
+/** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */
static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
@@ -96,8 +96,10 @@ static const unsigned int MAX_HEADERS_RESULTS = 2000;
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
/** Time to wait (in seconds) between writing blockchain state to disk. */
static const unsigned int DATABASE_WRITE_INTERVAL = 3600;
+/** Maximum length of reject messages. */
+static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
-/** "reject" message codes **/
+/** "reject" message codes */
static const unsigned char REJECT_MALFORMED = 0x01;
static const unsigned char REJECT_INVALID = 0x10;
static const unsigned char REJECT_OBSOLETE = 0x11;
@@ -131,10 +133,10 @@ extern bool fIsBareMultisigStd;
extern unsigned int nCoinCacheSize;
extern CFeeRate minRelayTxFee;
-// Best header we've seen so far (used for getheaders queries' starting points).
+/** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex *pindexBestHeader;
-// Minimum disk space required - used in CheckDiskSpace()
+/** Minimum disk space required - used in CheckDiskSpace() */
static const uint64_t nMinDiskSpace = 52428800;
/** Register a wallet to receive updates from core */
@@ -151,15 +153,17 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
/** Unregister a network node */
void UnregisterNodeSignals(CNodeSignals& nodeSignals);
-/** Process an incoming block. This only returns after the best known valid
- block is made active. Note that it does not, however, guarantee that the
- specific block passed to it has been checked for validity!
- @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state iff pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation.
- @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
- @param[in] pblock The block we want to process.
- @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
- @return True if state.IsValid()
-*/
+/**
+ * Process an incoming block. This only returns after the best known valid
+ * block is made active. Note that it does not, however, guarantee that the
+ * specific block passed to it has been checked for validity!
+ *
+ * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation.
+ * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
+ * @param[in] pblock The block we want to process.
+ * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
+ * @return True if state.IsValid()
+ */
bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
/** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
@@ -245,54 +249,59 @@ struct CDiskTxPos : public CDiskBlockPos
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
-//
-// Check transaction inputs, and make sure any
-// pay-to-script-hash transactions are evaluating IsStandard scripts
-//
-// Why bother? To avoid denial-of-service attacks; an attacker
-// can submit a standard HASH... OP_EQUAL transaction,
-// which will get accepted into blocks. The redemption
-// script can be anything; an attacker could use a very
-// expensive-to-check-upon-redemption script like:
-// DUP CHECKSIG DROP ... repeated 100 times... OP_1
-//
+/**
+ * Check transaction inputs, and make sure any
+ * pay-to-script-hash transactions are evaluating IsStandard scripts
+ *
+ * Why bother? To avoid denial-of-service attacks; an attacker
+ * can submit a standard HASH... OP_EQUAL transaction,
+ * which will get accepted into blocks. The redemption
+ * script can be anything; an attacker could use a very
+ * expensive-to-check-upon-redemption script like:
+ * DUP CHECKSIG DROP ... repeated 100 times... OP_1
+ */
-/** Check for standard transaction types
- @param[in] mapInputs Map of previous transactions that have outputs we're spending
- @return True if all inputs (scriptSigs) use only standard transaction forms
-*/
+/**
+ * Check for standard transaction types
+ * @param[in] mapInputs Map of previous transactions that have outputs we're spending
+ * @return True if all inputs (scriptSigs) use only standard transaction forms
+ */
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
-/** Count ECDSA signature operations the old-fashioned (pre-0.6) way
- @return number of sigops this transaction's outputs will produce when spent
- @see CTransaction::FetchInputs
-*/
+/**
+ * Count ECDSA signature operations the old-fashioned (pre-0.6) way
+ * @return number of sigops this transaction's outputs will produce when spent
+ * @see CTransaction::FetchInputs
+ */
unsigned int GetLegacySigOpCount(const CTransaction& tx);
-/** Count ECDSA signature operations in pay-to-script-hash inputs.
-
- @param[in] mapInputs Map of previous transactions that have outputs we're spending
- @return maximum number of sigops required to validate this transaction's inputs
- @see CTransaction::FetchInputs
+/**
+ * Count ECDSA signature operations in pay-to-script-hash inputs.
+ *
+ * @param[in] mapInputs Map of previous transactions that have outputs we're spending
+ * @return maximum number of sigops required to validate this transaction's inputs
+ * @see CTransaction::FetchInputs
*/
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
-// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
-// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
-// instead of being performed inline.
+/**
+ * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
+ * This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
+ * instead of being performed inline.
+ */
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks,
unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL);
-// Apply the effects of this transaction on the UTXO set represented by view
+/** 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);
-// Context-independent validity checks
+/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
/** Check for standard transaction types
- @return True if all outputs (scriptPubKeys) use only standard transaction forms
-*/
+ * @return True if all outputs (scriptPubKeys) use only standard transaction forms
+ */
bool IsStandardTx(const CTransaction& tx, std::string& reason);
bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0);
@@ -315,8 +324,10 @@ public:
};
-/** Closure representing one script verification
- * Note that this stores references to the spending transaction */
+/**
+ * Closure representing one script verification
+ * Note that this stores references to the spending transaction
+ */
class CScriptCheck
{
private:
@@ -325,14 +336,15 @@ private:
unsigned int nIn;
unsigned int nFlags;
bool cacheStore;
+ ScriptError error;
public:
- CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false) {}
+ CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) :
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
- ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn) { }
+ ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { }
- bool operator()() const;
+ bool operator()();
void swap(CScriptCheck &check) {
scriptPubKey.swap(check.scriptPubKey);
@@ -340,12 +352,15 @@ public:
std::swap(nIn, check.nIn);
std::swap(nFlags, check.nFlags);
std::swap(cacheStore, check.cacheStore);
+ std::swap(error, check.error);
}
+
+ ScriptError GetScriptError() const { return error; }
};
/** Data structure that represents a partial merkle tree.
*
- * It respresents a subset of the txid's of a known block, in a way that
+ * It represents a subset of the txid's of a known block, in a way that
* allows recovery of the list of txid's and the merkle root, in an
* authenticated way.
*
@@ -380,36 +395,38 @@ public:
class CPartialMerkleTree
{
protected:
- // the total number of transactions in the block
+ /** the total number of transactions in the block */
unsigned int nTransactions;
- // node-is-parent-of-matched-txid bits
+ /** node-is-parent-of-matched-txid bits */
std::vector<bool> vBits;
- // txids and internal hashes
+ /** txids and internal hashes */
std::vector<uint256> vHash;
- // flag set when encountering invalid data
+ /** flag set when encountering invalid data */
bool fBad;
- // helper function to efficiently calculate the number of nodes at given height in the merkle tree
+ /** helper function to efficiently calculate the number of nodes at given height in the merkle tree */
unsigned int CalcTreeWidth(int height) {
return (nTransactions+(1 << height)-1) >> height;
}
- // calculate the hash of a node in the merkle tree (at leaf level: the txid's themself)
+ /** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */
uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid);
- // recursive function that traverses tree nodes, storing the data as bits and hashes
+ /** recursive function that traverses tree nodes, storing the data as bits and hashes */
void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
- // recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
- // it returns the hash of the respective node.
+ /**
+ * recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
+ * it returns the hash of the respective node.
+ */
uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch);
public:
- // serialization implementation
+ /** serialization implementation */
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
@@ -432,13 +449,15 @@ public:
}
}
- // Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them
+ /** Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them */
CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
CPartialMerkleTree();
- // extract the matching txid's represented by this partial merkle tree.
- // returns the merkle root, or 0 in case of failure
+ /**
+ * extract the matching txid's represented by this partial merkle tree.
+ * returns the merkle root, or 0 in case of failure
+ */
uint256 ExtractMatches(std::vector<uint256> &vMatch);
};
@@ -458,22 +477,21 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
* of problems. Note that in any case, coins may be modified. */
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL);
-// Apply the effects of this block (with given index) on the UTXO set represented by coins
+/** Apply the effects of this block (with given index) on the UTXO set represented by coins */
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
-// Context-independent validity checks
+/** Context-independent validity checks */
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
-// Context-dependent validity checks
+/** Context-dependent validity checks */
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev);
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev);
-// Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held)
+/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
-// Store block on disk
-// if dbp is provided, the file is known to already reside on disk
+/** Store block on disk. If dbp is provided, the file is known to already reside on disk */
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL);
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL);
@@ -482,13 +500,13 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
class CBlockFileInfo
{
public:
- unsigned int nBlocks; // number of blocks stored in file
- unsigned int nSize; // number of used bytes of block file
- unsigned int nUndoSize; // number of used bytes in the undo file
- unsigned int nHeightFirst; // lowest height of block in file
- unsigned int nHeightLast; // highest height of block in file
- uint64_t nTimeFirst; // earliest time of block in file
- uint64_t nTimeLast; // latest time of block in file
+ unsigned int nBlocks; //! number of blocks stored in file
+ unsigned int nSize; //! number of used bytes of block file
+ unsigned int nUndoSize; //! number of used bytes in the undo file
+ unsigned int nHeightFirst; //! lowest height of block in file
+ unsigned int nHeightLast; //! highest height of block in file
+ uint64_t nTimeFirst; //! earliest time of block in file
+ uint64_t nTimeLast; //! latest time of block in file
ADD_SERIALIZE_METHODS;
@@ -519,7 +537,7 @@ public:
std::string ToString() const;
- // update statistics (does not update nSize)
+ /** update statistics (does not update nSize) */
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) {
if (nBlocks==0 || nHeightFirst > nHeightIn)
nHeightFirst = nHeightIn;
@@ -537,9 +555,9 @@ public:
class CValidationState {
private:
enum mode_state {
- MODE_VALID, // everything ok
- MODE_INVALID, // network rule violation (DoS value may be set)
- MODE_ERROR, // run-time error
+ MODE_VALID, //! everything ok
+ MODE_INVALID, //! network rule violation (DoS value may be set)
+ MODE_ERROR, //! run-time error
} mode;
int nDoS;
std::string strRejectReason;
@@ -634,24 +652,26 @@ struct CBlockTemplate
-/** Used to relay blocks as header + vector<merkle branch>
+/**
+ * Used to relay blocks as header + vector<merkle branch>
* to filtered nodes.
*/
class CMerkleBlock
{
public:
- // Public only for unit testing
+ /** Public only for unit testing */
CBlockHeader header;
CPartialMerkleTree txn;
public:
- // Public only for unit testing and relay testing
- // (not relayed)
+ /** Public only for unit testing and relay testing (not relayed) */
std::vector<std::pair<unsigned int, uint256> > vMatchedTxn;
- // Create from a CBlock, filtering transactions according to filter
- // Note that this will call IsRelevantAndUpdate on the filter for each transaction,
- // thus the filter will likely be modified.
+ /**
+ * Create from a CBlock, filtering transactions according to filter
+ * Note that this will call IsRelevantAndUpdate on the filter for each transaction,
+ * thus the filter will likely be modified.
+ */
CMerkleBlock(const CBlock& block, CBloomFilter& filter);
ADD_SERIALIZE_METHODS;
diff --git a/src/miner.cpp b/src/miner.cpp
index 660173f35b..ad29431421 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -6,8 +6,8 @@
#include "miner.h"
#include "amount.h"
-#include "core/block.h"
-#include "core/transaction.h"
+#include "primitives/block.h"
+#include "primitives/transaction.h"
#include "hash.h"
#include "main.h"
#include "net.h"
diff --git a/src/net.cpp b/src/net.cpp
index 6bf72d22c5..42b3c30fb7 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -12,7 +12,7 @@
#include "addrman.h"
#include "chainparams.h"
#include "clientversion.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "ui_interface.h"
#ifdef WIN32
@@ -399,7 +399,9 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
// Connect
SOCKET hSocket;
- if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
+ bool proxyConnectionFailed = false;
+ if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort(), nConnectTimeout, &proxyConnectionFailed) :
+ ConnectSocket(addrConnect, hSocket, nConnectTimeout, &proxyConnectionFailed))
{
addrman.Attempt(addrConnect);
@@ -415,6 +417,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
pnode->nTimeConnected = GetTime();
return pnode;
+ } else if (!proxyConnectionFailed) {
+ // If connecting to the node failed, and failure is not caused by a problem connecting to
+ // the proxy, mark this as an attempt.
+ addrman.Attempt(addrConnect);
}
return NULL;
diff --git a/src/net.h b/src/net.h
index e48acf5644..a475be0b33 100644
--- a/src/net.h
+++ b/src/net.h
@@ -44,6 +44,8 @@ static const int PING_INTERVAL = 2 * 60;
static const int TIMEOUT_INTERVAL = 20 * 60;
/** The maximum number of entries in an 'inv' protocol message */
static const unsigned int MAX_INV_SZ = 50000;
+/** The maximum number of new addresses to accumulate before announcing. */
+static const unsigned int MAX_ADDR_TO_SEND = 1000;
/** -listen default */
static const bool DEFAULT_LISTEN = true;
/** -upnp default */
@@ -368,8 +370,13 @@ public:
// Known checking here is only to save space from duplicates.
// SendMessages will filter it again for knowns that were added
// after addresses were pushed.
- if (addr.IsValid() && !setAddrKnown.count(addr))
- vAddrToSend.push_back(addr);
+ if (addr.IsValid() && !setAddrKnown.count(addr)) {
+ if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
+ vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr;
+ } else {
+ vAddrToSend.push_back(addr);
+ }
+ }
}
diff --git a/src/netbase.cpp b/src/netbase.cpp
index aca5a107fe..053c645a1b 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -519,9 +519,11 @@ bool IsProxy(const CNetAddr &addr) {
return false;
}
-bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
+bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
{
proxyType proxy;
+ if (outProxyConnectionFailed)
+ *outProxyConnectionFailed = false;
// no proxy needed (none set for target network)
if (!GetProxy(addrDest.GetNetwork(), proxy))
return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
@@ -529,8 +531,11 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
SOCKET hSocket = INVALID_SOCKET;
// first connect to proxy server
- if (!ConnectSocketDirectly(proxy, hSocket, nTimeout))
+ if (!ConnectSocketDirectly(proxy, hSocket, nTimeout)) {
+ if (outProxyConnectionFailed)
+ *outProxyConnectionFailed = true;
return false;
+ }
// do socks negotiation
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
return false;
@@ -539,10 +544,14 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
return true;
}
-bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout)
+bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
{
string strDest;
int port = portDefault;
+
+ if (outProxyConnectionFailed)
+ *outProxyConnectionFailed = false;
+
SplitHostPort(string(pszDest), port, strDest);
SOCKET hSocket = INVALID_SOCKET;
@@ -561,8 +570,11 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
if (!HaveNameProxy())
return false;
// first connect to name proxy server
- if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout))
+ if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout)) {
+ if (outProxyConnectionFailed)
+ *outProxyConnectionFailed = true;
return false;
+ }
// do socks negotiation
if (!Socks5(strDest, (unsigned short)port, hSocket))
return false;
diff --git a/src/netbase.h b/src/netbase.h
index 9d8697dcc6..09fe094946 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -182,8 +182,8 @@ bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nM
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0);
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
-bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);
-bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout);
+bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);
+bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);
/** Return readable error string for a network error code */
std::string NetworkErrorString(int err);
/** Close socket and set hSocket to INVALID_SOCKET */
diff --git a/src/pow.cpp b/src/pow.cpp
index e07e7ff770..bdcfa852f4 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -7,7 +7,7 @@
#include "chain.h"
#include "chainparams.h"
-#include "core/block.h"
+#include "primitives/block.h"
#include "uint256.h"
#include "util.h"
diff --git a/src/core/block.cpp b/src/primitives/block.cpp
index 2010d44dac..225bb80be8 100644
--- a/src/core/block.cpp
+++ b/src/primitives/block.cpp
@@ -3,7 +3,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "core/block.h"
+#include "primitives/block.h"
#include "hash.h"
#include "tinyformat.h"
diff --git a/src/core/block.h b/src/primitives/block.h
index 6e119c3699..e663c91e84 100644
--- a/src/core/block.h
+++ b/src/primitives/block.h
@@ -3,10 +3,10 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_CORE_BLOCK_H
-#define BITCOIN_CORE_BLOCK_H
+#ifndef BITCOIN_PRIMITIVES_BLOCK_H
+#define BITCOIN_PRIMITIVES_BLOCK_H
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "serialize.h"
#include "uint256.h"
@@ -165,4 +165,4 @@ struct CBlockLocator
}
};
-#endif // BITCOIN_CORE_BLOCK_H
+#endif // BITCOIN_PRIMITIVES_BLOCK_H
diff --git a/src/core/transaction.cpp b/src/primitives/transaction.cpp
index f835bafb9f..336151905c 100644
--- a/src/core/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "hash.h"
#include "tinyformat.h"
diff --git a/src/core/transaction.h b/src/primitives/transaction.h
index 724348020a..a7a1e013ed 100644
--- a/src/core/transaction.h
+++ b/src/primitives/transaction.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_CORE_TRANSACTION_H
-#define BITCOIN_CORE_TRANSACTION_H
+#ifndef BITCOIN_PRIMITIVES_TRANSACTION_H
+#define BITCOIN_PRIMITIVES_TRANSACTION_H
#include "amount.h"
#include "script/script.h"
@@ -273,4 +273,4 @@ struct CMutableTransaction
uint256 GetHash() const;
};
-#endif // BITCOIN_CORE_TRANSACTION_H
+#endif // BITCOIN_PRIMITIVES_TRANSACTION_H
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
index 9c6f536f21..91979ff4dc 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -4,7 +4,6 @@
#include "pubkey.h"
-#include "crypto/sha2.h"
#include "eccryptoverify.h"
#ifdef USE_SECP256K1
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index 75e1f9ae78..5c542b59ae 100644
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -4,7 +4,7 @@
#include "bitcoinunits.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include <QStringList>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 22a1f019e9..a1ae756c43 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -9,7 +9,7 @@
#include "qvalidatedlineedit.h"
#include "walletmodel.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "init.h"
#include "main.h"
#include "protocol.h"
diff --git a/src/rest.cpp b/src/rest.cpp
index 4953d7e717..6285784af5 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "core/block.h"
-#include "core/transaction.h"
+#include "primitives/block.h"
+#include "primitives/transaction.h"
#include "main.h"
#include "rpcserver.h"
#include "streams.h"
@@ -18,6 +18,7 @@ using namespace std;
using namespace json_spirit;
enum RetFormat {
+ RF_UNDEF,
RF_BINARY,
RF_HEX,
RF_JSON,
@@ -25,14 +26,16 @@ enum RetFormat {
static const struct {
enum RetFormat rf;
- const char *name;
+ const char* name;
} rf_names[] = {
- { RF_BINARY, "binary" }, // default, if match not found
- { RF_HEX, "hex" },
- { RF_JSON, "json" },
+ {RF_UNDEF, ""},
+ {RF_BINARY, "bin"},
+ {RF_HEX, "hex"},
+ {RF_JSON, "json"},
};
-class RestErr {
+class RestErr
+{
public:
enum HTTPStatusCode status;
string message;
@@ -49,15 +52,34 @@ static RestErr RESTERR(enum HTTPStatusCode status, string message)
return re;
}
-static enum RetFormat ParseDataFormat(const string& format)
+static enum RetFormat ParseDataFormat(vector<string>& params, const string strReq)
{
- for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
- if (format == rf_names[i].name)
- return rf_names[i].rf;
+ boost::split(params, strReq, boost::is_any_of("."));
+ if (params.size() > 1) {
+ for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
+ if (params[1] == rf_names[i].name)
+ return rf_names[i].rf;
+ }
return rf_names[0].rf;
}
+static string AvailableDataFormatsString()
+{
+ string formats = "";
+ for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
+ if (strlen(rf_names[i].name) > 0) {
+ formats.append(".");
+ formats.append(rf_names[i].name);
+ formats.append(", ");
+ }
+
+ if (formats.length() > 0)
+ return formats.substr(0, formats.length() - 2);
+
+ return formats;
+}
+
static bool ParseHashStr(const string& strReq, uint256& v)
{
if (!IsHex(strReq) || (strReq.size() != 64))
@@ -67,15 +89,13 @@ static bool ParseHashStr(const string& strReq, uint256& v)
return true;
}
-static bool rest_block(AcceptedConnection *conn,
+static bool rest_block(AcceptedConnection* conn,
string& strReq,
map<string, string>& mapHeaders,
bool fRun)
{
vector<string> params;
- boost::split(params, strReq, boost::is_any_of("/"));
-
- enum RetFormat rf = ParseDataFormat(params.size() > 1 ? params[1] : string(""));
+ enum RetFormat rf = ParseDataFormat(params, strReq);
string hashStr = params[0];
uint256 hash;
@@ -105,7 +125,7 @@ static bool rest_block(AcceptedConnection *conn,
}
case RF_HEX: {
- string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";;
+ string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";
conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush;
return true;
}
@@ -115,22 +135,24 @@ static bool rest_block(AcceptedConnection *conn,
string strJSON = write_string(Value(objBlock), false) + "\n";
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
return true;
- }
+ }
+
+ default: {
+ throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
+ }
}
// not reached
- return true; // continue to process further HTTP reqs on this cxn
+ return true; // continue to process further HTTP reqs on this cxn
}
-static bool rest_tx(AcceptedConnection *conn,
+static bool rest_tx(AcceptedConnection* conn,
string& strReq,
map<string, string>& mapHeaders,
bool fRun)
{
vector<string> params;
- boost::split(params, strReq, boost::is_any_of("/"));
-
- enum RetFormat rf = ParseDataFormat(params.size() > 1 ? params[1] : string(""));
+ enum RetFormat rf = ParseDataFormat(params, strReq);
string hashStr = params[0];
uint256 hash;
@@ -153,7 +175,7 @@ static bool rest_tx(AcceptedConnection *conn,
}
case RF_HEX: {
- string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";;
+ string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";
conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush;
return true;
}
@@ -165,33 +187,37 @@ static bool rest_tx(AcceptedConnection *conn,
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
return true;
}
+
+ default: {
+ throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
+ }
}
// not reached
- return true; // continue to process further HTTP reqs on this cxn
+ return true; // continue to process further HTTP reqs on this cxn
}
static const struct {
- const char *prefix;
- bool (*handler)(AcceptedConnection *conn,
+ const char* prefix;
+ bool (*handler)(AcceptedConnection* conn,
string& strURI,
map<string, string>& mapHeaders,
bool fRun);
} uri_prefixes[] = {
- { "/rest/tx/", rest_tx },
- { "/rest/block/", rest_block },
+ {"/rest/tx/", rest_tx},
+ {"/rest/block/", rest_block},
};
-bool HTTPReq_REST(AcceptedConnection *conn,
+bool HTTPReq_REST(AcceptedConnection* conn,
string& strURI,
map<string, string>& mapHeaders,
bool fRun)
{
try {
std::string statusmessage;
- if(RPCIsInWarmup(&statusmessage))
- throw RESTERR(HTTP_SERVICE_UNAVAILABLE, "Service temporarily unavailable: "+statusmessage);
-
+ if (RPCIsInWarmup(&statusmessage))
+ throw RESTERR(HTTP_SERVICE_UNAVAILABLE, "Service temporarily unavailable: " + statusmessage);
+
for (unsigned int i = 0; i < ARRAYLEN(uri_prefixes); i++) {
unsigned int plen = strlen(uri_prefixes[i].prefix);
if (strURI.substr(0, plen) == uri_prefixes[i].prefix) {
@@ -199,8 +225,7 @@ bool HTTPReq_REST(AcceptedConnection *conn,
return uri_prefixes[i].handler(conn, strReq, mapHeaders, fRun);
}
}
- }
- catch (RestErr& re) {
+ } catch (RestErr& re) {
conn->stream() << HTTPReply(re.status, re.message + "\r\n", false, false, "text/plain") << std::flush;
return false;
}
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 045cd90ef6..924f416904 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -505,6 +505,12 @@ Value getchaintips(const Array& params, bool fHelp)
" \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
" }\n"
"]\n"
+ "Possible values for status:\n"
+ "1. \"invalid\" This branch contains at least one invalid block\n"
+ "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
+ "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
+ "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
+ "5. \"active\" This is the tip of the active main chain, which is certainly valid\n"
"\nExamples:\n"
+ HelpExampleCli("getchaintips", "")
+ HelpExampleRpc("getchaintips", "")
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 25734f4930..8de15ff9e2 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -4,7 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "core_io.h"
#include "init.h"
#include "keystore.h"
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 8512212185..90695611f2 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -269,6 +269,8 @@ static const CRPCCommand vRPCCommands[] =
{ "blockchain", "gettxout", &gettxout, true, false, false },
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
{ "blockchain", "verifychain", &verifychain, true, false, false },
+ { "blockchain", "invalidateblock", &invalidateblock, true, true, false },
+ { "blockchain", "reconsiderblock", &reconsiderblock, true, true, false },
/* Mining */
{ "mining", "getblocktemplate", &getblocktemplate, true, false, false },
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index 4faa760ad7..d4fd2ad7d9 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -5,7 +5,7 @@
#include "bitcoinconsensus.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "script/interpreter.h"
#include "version.h"
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index a10cefcc0b..3231f2e74e 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -5,10 +5,10 @@
#include "interpreter.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
-#include "crypto/sha2.h"
+#include "crypto/sha256.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "script/script.h"
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 7dfed751b6..03c33ad9b5 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -5,7 +5,7 @@
#include "script/sign.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "key.h"
#include "keystore.h"
#include "script/standard.h"
diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml
index 24a86b561b..3a85e8cba0 100644
--- a/src/secp256k1/.travis.yml
+++ b/src/secp256k1/.travis.yml
@@ -18,6 +18,8 @@ env:
- FIELD=64bit ENDOMORPHISM=yes
- FIELD=32bit
- FIELD=32bit ENDOMORPHISM=yes
+ - BIGNUM=none
+ - BIGNUM=none ENDOMORPHISM=yes
- BUILD=distcheck
- EXTRAFLAGS=CFLAGS=-DDETERMINISTIC
before_script: ./autogen.sh
diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am
index d527da6b77..dbf1790f34 100644
--- a/src/secp256k1/Makefile.am
+++ b/src/secp256k1/Makefile.am
@@ -68,12 +68,13 @@ bench_sign_LDFLAGS = -static
bench_inv_SOURCES = src/bench_inv.c
bench_inv_LDADD = $(COMMON_LIB) $(SECP_LIBS)
bench_inv_LDFLAGS = -static
+bench_inv_CPPFLAGS = $(SECP_INCLUDES)
endif
if USE_TESTS
noinst_PROGRAMS += tests
tests_SOURCES = src/tests.c
-tests_CPPFLAGS = -DVERIFY $(SECP_TEST_INCLUDES)
+tests_CPPFLAGS = -DVERIFY $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
tests_LDADD = $(COMMON_LIB) $(SECP_LIBS) $(SECP_TEST_LIBS)
tests_LDFLAGS = -static
TESTS = tests
diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
index e6f3470ed7..4ca28f99cf 100644
--- a/src/secp256k1/build-aux/m4/bitcoin_secp.m4
+++ b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
@@ -78,7 +78,13 @@ fi
dnl
AC_DEFUN([SECP_GMP_CHECK],[
if test x"$has_gmp" != x"yes"; then
- AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS=-lgmp; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])])
+ CPPFLAGS_TEMP="$CPPFLAGS"
+ CPPFLAGS="$GMP_CPPFLAGS $CPPFLAGS"
+ LIBS_TEMP="$LIBS"
+ LIBS="$GMP_LIBS $LIBS"
+ AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS="$GMP_LIBS -lgmp"; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])])
+ CPPFLAGS="$CPPFLAGS_TEMP"
+ LIBS="$LIBS_TEMP"
fi
if test x"$set_field" = x"gmp" && test x"$has_gmp" != x"yes"; then
AC_MSG_ERROR([$set_field field support explicitly requested but libgmp was not found])
diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac
index 2da5709834..6e6fccd7fd 100644
--- a/src/secp256k1/configure.ac
+++ b/src/secp256k1/configure.ac
@@ -33,10 +33,35 @@ case $host in
esac
case $host_os in
- darwin*)
- CPPFLAGS="$CPPFLAGS -I/opt/local/include"
- LDFLAGS="$LDFLAGS -L/opt/local/lib"
- ;;
+ *darwin*)
+ if test x$cross_compiling != xyes; then
+ AC_PATH_PROG([BREW],brew,)
+ if test x$BREW != x; then
+ dnl These Homebrew packages may be keg-only, meaning that they won't be found
+ dnl in expected paths because they may conflict with system files. Ask
+ dnl Homebrew where each one is located, then adjust paths accordingly.
+
+ openssl_prefix=`$BREW --prefix openssl 2>/dev/null`
+ gmp_prefix=`$BREW --prefix gmp 2>/dev/null`
+ if test x$openssl_prefix != x; then
+ PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH"
+ export PKG_CONFIG_PATH
+ fi
+ if test x$gmp_prefix != x; then
+ GMP_CPPFLAGS="-I$gmp_prefix/include"
+ GMP_LIBS="-L$gmp_prefix/lib"
+ fi
+ else
+ AC_PATH_PROG([PORT],port,)
+ dnl if homebrew isn't installed and macports is, add the macports default paths
+ dnl as a last resort.
+ if test x$PORT != x; then
+ CPPFLAGS="$CPPFLAGS -isystem /opt/local/include"
+ LDFLAGS="$LDFLAGS -L/opt/local/lib"
+ fi
+ fi
+ fi
+ ;;
esac
CFLAGS="$CFLAGS -W"
@@ -70,7 +95,7 @@ AC_ARG_ENABLE(endomorphism,
AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=gmp|64bit|64bit_asm|32bit|auto],
[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto])
-AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|auto],
+AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|none|auto],
[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto])
AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto],
@@ -154,7 +179,7 @@ if test x"$req_bignum" = x"auto"; then
fi
if test x"$set_bignum" = x; then
- AC_MSG_ERROR([no working bignum implementation found])
+ set_bignum=none
fi
else
set_bignum=$req_bignum
@@ -162,8 +187,7 @@ else
gmp)
SECP_GMP_CHECK
;;
- openssl)
- SECP_OPENSSL_CHECK
+ none)
;;
*)
AC_MSG_ERROR([invalid bignum implementation selection])
@@ -196,9 +220,15 @@ esac
# select bignum implementation
case $set_bignum in
gmp)
- AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])
- AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation])
- AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the USE_FIELD_INV_NUM implementation])
+ AC_DEFINE(HAVE_LIBGMP, 1, [Define this symbol if libgmp is installed])
+ AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation for num])
+ AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the num-based field inverse implementation])
+ AC_DEFINE(USE_SCALAR_INV_NUM, 1, [Define this symbol to use the num-based scalar inverse implementation])
+ ;;
+none)
+ AC_DEFINE(USE_NUM_NONE, 1, [Define this symbol to use no num implementation])
+ AC_DEFINE(USE_FIELD_INV_BUILTIN, 1, [Define this symbol to use the native field inverse implementation])
+ AC_DEFINE(USE_SCALAR_INV_BUILTIN, 1, [Define this symbol to use the native scalar inverse implementation])
;;
*)
AC_MSG_ERROR([invalid bignum implementation])
@@ -236,10 +266,11 @@ fi
if test x"$set_field" = x"gmp" || test x"$set_bignum" = x"gmp"; then
SECP_LIBS="$SECP_LIBS $GMP_LIBS"
+ SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS"
fi
if test x"$use_endomorphism" = x"yes"; then
- AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism])
+ AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization])
fi
AC_MSG_NOTICE([Using field implementation: $set_field])
@@ -256,4 +287,10 @@ AC_SUBST(YASM_BINFMT)
AM_CONDITIONAL([USE_ASM], [test x"$set_field" == x"64bit_asm"])
AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"])
AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" != x"no"])
+
+dnl make sure nothing new is exported so that we don't break the cache
+PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH"
+unset PKG_CONFIG_PATH
+PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP"
+
AC_OUTPUT
diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h
index 932bf0279f..94a6ef483f 100644
--- a/src/secp256k1/include/secp256k1.h
+++ b/src/secp256k1/include/secp256k1.h
@@ -15,18 +15,6 @@ extern "C" {
# endif
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
-# if SECP256K1_GNUC_PREREQ(3,0)
-# define SECP256K1_RESTRICT __restrict__
-# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
-# define SECP256K1_RESTRICT __restrict
-# else
-# define SECP256K1_RESTRICT
-# endif
-# else
-# define SECP256K1_RESTRICT restrict
-# endif
-
-# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
# if SECP256K1_GNUC_PREREQ(2,7)
# define SECP256K1_INLINE __inline__
# elif (defined(_MSC_VER))
diff --git a/src/secp256k1/src/ecdsa.h b/src/secp256k1/src/ecdsa.h
index 3b1e0484ea..5fc5230c36 100644
--- a/src/secp256k1/src/ecdsa.h
+++ b/src/secp256k1/src/ecdsa.h
@@ -7,17 +7,21 @@
#ifndef _SECP256K1_ECDSA_
#define _SECP256K1_ECDSA_
-#include "num.h"
+#include "scalar.h"
+#include "group.h"
+
+static void secp256k1_ecsda_start(void);
+static void secp256k1_ecdsa_stop(void);
typedef struct {
- secp256k1_num_t r, s;
+ secp256k1_scalar_t r, s;
} secp256k1_ecdsa_sig_t;
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size);
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a);
-static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message);
+static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
-static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid);
-static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s);
+static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
+static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s);
#endif
diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h
index 4c05ec39f8..a951d0b4ad 100644
--- a/src/secp256k1/src/ecdsa_impl.h
+++ b/src/secp256k1/src/ecdsa_impl.h
@@ -8,13 +8,51 @@
#ifndef _SECP256K1_ECDSA_IMPL_H_
#define _SECP256K1_ECDSA_IMPL_H_
-#include "num.h"
+#include "scalar.h"
#include "field.h"
#include "group.h"
#include "ecmult.h"
#include "ecmult_gen.h"
#include "ecdsa.h"
+typedef struct {
+ secp256k1_fe_t order_as_fe;
+ secp256k1_fe_t p_minus_order;
+} secp256k1_ecdsa_consts_t;
+
+static const secp256k1_ecdsa_consts_t *secp256k1_ecdsa_consts = NULL;
+
+static void secp256k1_ecdsa_start(void) {
+ if (secp256k1_ecdsa_consts != NULL)
+ return;
+
+ /* Allocate. */
+ secp256k1_ecdsa_consts_t *ret = (secp256k1_ecdsa_consts_t*)malloc(sizeof(secp256k1_ecdsa_consts_t));
+
+ static const unsigned char order[] = {
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+ 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
+ 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41
+ };
+
+ secp256k1_fe_set_b32(&ret->order_as_fe, order);
+ secp256k1_fe_negate(&ret->p_minus_order, &ret->order_as_fe, 1);
+ secp256k1_fe_normalize(&ret->p_minus_order);
+
+ /* Set the global pointer. */
+ secp256k1_ecdsa_consts = ret;
+}
+
+static void secp256k1_ecdsa_stop(void) {
+ if (secp256k1_ecdsa_consts == NULL)
+ return;
+
+ secp256k1_ecdsa_consts_t *c = (secp256k1_ecdsa_consts_t*)secp256k1_ecdsa_consts;
+ secp256k1_ecdsa_consts = NULL;
+ free(c);
+}
+
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) {
if (sig[0] != 0x30) return 0;
int lenr = sig[3];
@@ -26,18 +64,37 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned ch
if (lenr == 0) return 0;
if (sig[lenr+4] != 0x02) return 0;
if (lens == 0) return 0;
- secp256k1_num_set_bin(&r->r, sig+4, lenr);
- secp256k1_num_set_bin(&r->s, sig+6+lenr, lens);
+ const unsigned char *sp = sig + 6 + lenr;
+ while (lens > 0 && sp[0] == 0) {
+ lens--;
+ sp++;
+ }
+ if (lens > 32) return 0;
+ const unsigned char *rp = sig + 4;
+ while (lenr > 0 && rp[0] == 0) {
+ lenr--;
+ rp++;
+ }
+ if (lenr > 32) return 0;
+ unsigned char ra[32] = {0}, sa[32] = {0};
+ memcpy(ra + 32 - lenr, rp, lenr);
+ memcpy(sa + 32 - lens, sp, lens);
+ int overflow = 0;
+ secp256k1_scalar_set_b32(&r->r, ra, &overflow);
+ if (overflow) return 0;
+ secp256k1_scalar_set_b32(&r->s, sa, &overflow);
+ if (overflow) return 0;
return 1;
}
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) {
- int lenR = (secp256k1_num_bits(&a->r) + 7)/8;
- if (lenR == 0 || secp256k1_num_get_bit(&a->r, lenR*8-1))
- lenR++;
- int lenS = (secp256k1_num_bits(&a->s) + 7)/8;
- if (lenS == 0 || secp256k1_num_get_bit(&a->s, lenS*8-1))
- lenS++;
+ unsigned char r[33] = {0}, s[33] = {0};
+ secp256k1_scalar_get_b32(&r[1], &a->r);
+ secp256k1_scalar_get_b32(&s[1], &a->s);
+ unsigned char *rp = r, *sp = s;
+ int lenR = 33, lenS = 33;
+ while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; }
+ while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; }
if (*size < 6+lenS+lenR)
return 0;
*size = 6 + lenS + lenR;
@@ -45,98 +102,67 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se
sig[1] = 4 + lenS + lenR;
sig[2] = 0x02;
sig[3] = lenR;
- secp256k1_num_get_bin(sig+4, lenR, &a->r);
+ memcpy(sig+4, rp, lenR);
sig[4+lenR] = 0x02;
sig[5+lenR] = lenS;
- secp256k1_num_get_bin(sig+lenR+6, lenS, &a->s);
+ memcpy(sig+lenR+6, sp, lenS);
return 1;
}
-static int secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) {
- const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
-
- if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s))
- return 0;
- if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s))
- return 0;
- if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0)
+static int secp256k1_ecdsa_sig_recompute(secp256k1_scalar_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
+ if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
return 0;
int ret = 0;
- secp256k1_num_t sn, u1, u2;
- secp256k1_num_init(&sn);
- secp256k1_num_init(&u1);
- secp256k1_num_init(&u2);
- secp256k1_num_mod_inverse(&sn, &sig->s, &c->order);
- secp256k1_num_mod_mul(&u1, &sn, message, &c->order);
- secp256k1_num_mod_mul(&u2, &sn, &sig->r, &c->order);
+ secp256k1_scalar_t sn, u1, u2;
+ secp256k1_scalar_inverse_var(&sn, &sig->s);
+ secp256k1_scalar_mul(&u1, &sn, message);
+ secp256k1_scalar_mul(&u2, &sn, &sig->r);
secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey);
secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
if (!secp256k1_gej_is_infinity(&pr)) {
secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr);
secp256k1_fe_normalize(&xr);
unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr);
- secp256k1_num_set_bin(r2, xrb, 32);
- secp256k1_num_mod(r2, &c->order);
+ secp256k1_scalar_set_b32(r2, xrb, NULL);
ret = 1;
}
- secp256k1_num_free(&sn);
- secp256k1_num_free(&u1);
- secp256k1_num_free(&u2);
return ret;
}
-static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid) {
- const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
-
- if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s))
- return 0;
- if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s))
- return 0;
- if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0)
+static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
+ if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
return 0;
- secp256k1_num_t rx;
- secp256k1_num_init(&rx);
- secp256k1_num_copy(&rx, &sig->r);
+ unsigned char brx[32];
+ secp256k1_scalar_get_b32(brx, &sig->r);
+ secp256k1_fe_t fx;
+ VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* brx comes from a scalar, so is less than the order; certainly less than p */
if (recid & 2) {
- secp256k1_num_add(&rx, &rx, &c->order);
- if (secp256k1_num_cmp(&rx, &secp256k1_fe_consts->p) >= 0)
+ if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_consts->p_minus_order) >= 0)
return 0;
+ secp256k1_fe_add(&fx, &secp256k1_ecdsa_consts->order_as_fe);
}
- unsigned char brx[32];
- secp256k1_num_get_bin(brx, 32, &rx);
- secp256k1_num_free(&rx);
- secp256k1_fe_t fx;
- secp256k1_fe_set_b32(&fx, brx);
secp256k1_ge_t x;
if (!secp256k1_ge_set_xo(&x, &fx, recid & 1))
return 0;
secp256k1_gej_t xj;
secp256k1_gej_set_ge(&xj, &x);
- secp256k1_num_t rn, u1, u2;
- secp256k1_num_init(&rn);
- secp256k1_num_init(&u1);
- secp256k1_num_init(&u2);
- secp256k1_num_mod_inverse(&rn, &sig->r, &c->order);
- secp256k1_num_mod_mul(&u1, &rn, message, &c->order);
- secp256k1_num_sub(&u1, &c->order, &u1);
- secp256k1_num_mod_mul(&u2, &rn, &sig->s, &c->order);
+ secp256k1_scalar_t rn, u1, u2;
+ secp256k1_scalar_inverse_var(&rn, &sig->r);
+ secp256k1_scalar_mul(&u1, &rn, message);
+ secp256k1_scalar_negate(&u1, &u1);
+ secp256k1_scalar_mul(&u2, &rn, &sig->s);
secp256k1_gej_t qj;
secp256k1_ecmult(&qj, &xj, &u2, &u1);
secp256k1_ge_set_gej_var(pubkey, &qj);
- secp256k1_num_free(&rn);
- secp256k1_num_free(&u1);
- secp256k1_num_free(&u2);
return !secp256k1_gej_is_infinity(&qj);
}
-static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) {
- secp256k1_num_t r2;
- secp256k1_num_init(&r2);
+static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
+ secp256k1_scalar_t r2;
int ret = 0;
- ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_num_cmp(&sig->r, &r2) == 0;
- secp256k1_num_free(&r2);
+ ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_scalar_eq(&sig->r, &r2);
return ret;
}
@@ -150,34 +176,30 @@ static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_
secp256k1_fe_normalize(&r.y);
secp256k1_fe_get_b32(b, &r.x);
int overflow = 0;
- secp256k1_scalar_t sigr;
- secp256k1_scalar_set_b32(&sigr, b, &overflow);
+ secp256k1_scalar_set_b32(&sig->r, b, &overflow);
if (recid)
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
secp256k1_scalar_t n;
- secp256k1_scalar_mul(&n, &sigr, seckey);
+ secp256k1_scalar_mul(&n, &sig->r, seckey);
secp256k1_scalar_add(&n, &n, message);
- secp256k1_scalar_t sigs;
- secp256k1_scalar_inverse(&sigs, nonce);
- secp256k1_scalar_mul(&sigs, &sigs, &n);
+ secp256k1_scalar_inverse(&sig->s, nonce);
+ secp256k1_scalar_mul(&sig->s, &sig->s, &n);
secp256k1_scalar_clear(&n);
secp256k1_gej_clear(&rp);
secp256k1_ge_clear(&r);
- if (secp256k1_scalar_is_zero(&sigs))
+ if (secp256k1_scalar_is_zero(&sig->s))
return 0;
- if (secp256k1_scalar_is_high(&sigs)) {
- secp256k1_scalar_negate(&sigs, &sigs);
+ if (secp256k1_scalar_is_high(&sig->s)) {
+ secp256k1_scalar_negate(&sig->s, &sig->s);
if (recid)
*recid ^= 1;
}
- secp256k1_scalar_get_num(&sig->s, &sigs);
- secp256k1_scalar_get_num(&sig->r, &sigr);
return 1;
}
-static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s) {
- secp256k1_num_copy(&sig->r, r);
- secp256k1_num_copy(&sig->s, s);
+static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s) {
+ sig->r = *r;
+ sig->s = *s;
}
#endif
diff --git a/src/secp256k1/src/eckey.h b/src/secp256k1/src/eckey.h
index 024c8b821b..6de5dc0a59 100644
--- a/src/secp256k1/src/eckey.h
+++ b/src/secp256k1/src/eckey.h
@@ -9,7 +9,6 @@
#include "group.h"
#include "scalar.h"
-#include "num.h"
static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size);
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed);
@@ -18,8 +17,8 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned
static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed);
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
-static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak);
+static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
-static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak);
+static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak);
#endif
diff --git a/src/secp256k1/src/eckey_impl.h b/src/secp256k1/src/eckey_impl.h
index 290b1f0900..0f218ced9e 100644
--- a/src/secp256k1/src/eckey_impl.h
+++ b/src/secp256k1/src/eckey_impl.h
@@ -9,7 +9,7 @@
#include "eckey.h"
-#include "num.h"
+#include "scalar.h"
#include "field.h"
#include "group.h"
#include "ecmult_gen.h"
@@ -17,12 +17,12 @@
static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) {
if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) {
secp256k1_fe_t x;
- secp256k1_fe_set_b32(&x, pub+1);
- return secp256k1_ge_set_xo(elem, &x, pub[0] == 0x03);
+ return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo(elem, &x, pub[0] == 0x03);
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) {
secp256k1_fe_t x, y;
- secp256k1_fe_set_b32(&x, pub+1);
- secp256k1_fe_set_b32(&y, pub+33);
+ if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) {
+ return 0;
+ }
secp256k1_ge_set_xy(elem, &x, &y);
if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07))
return 0;
@@ -154,17 +154,12 @@ static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp
return 1;
}
-static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak) {
- if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0)
- return 0;
-
+static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
secp256k1_gej_t pt;
secp256k1_gej_set_ge(&pt, key);
- secp256k1_num_t one;
- secp256k1_num_init(&one);
- secp256k1_num_set_int(&one, 1);
+ secp256k1_scalar_t one;
+ secp256k1_scalar_set_int(&one, 1);
secp256k1_ecmult(&pt, &pt, &one, tweak);
- secp256k1_num_free(&one);
if (secp256k1_gej_is_infinity(&pt))
return 0;
@@ -180,19 +175,15 @@ static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp
return 1;
}
-static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak) {
- if (secp256k1_num_is_zero(tweak))
- return 0;
- if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0)
+static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
+ if (secp256k1_scalar_is_zero(tweak))
return 0;
- secp256k1_num_t zero;
- secp256k1_num_init(&zero);
- secp256k1_num_set_int(&zero, 0);
+ secp256k1_scalar_t zero;
+ secp256k1_scalar_set_int(&zero, 0);
secp256k1_gej_t pt;
secp256k1_gej_set_ge(&pt, key);
secp256k1_ecmult(&pt, &pt, tweak, &zero);
- secp256k1_num_free(&zero);
secp256k1_ge_set_gej(key, &pt);
return 1;
}
diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h
index e3cf18b680..15a7100a4a 100644
--- a/src/secp256k1/src/ecmult.h
+++ b/src/secp256k1/src/ecmult.h
@@ -14,6 +14,6 @@ static void secp256k1_ecmult_start(void);
static void secp256k1_ecmult_stop(void);
/** Double multiply: R = na*A + ng*G */
-static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng);
+static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng);
#endif
diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h
index 07859ab04b..af0ead522d 100644
--- a/src/secp256k1/src/ecmult_gen_impl.h
+++ b/src/secp256k1/src/ecmult_gen_impl.h
@@ -23,8 +23,8 @@ typedef struct {
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63).
* None of the resulting prec group elements have a known scalar, and neither do any of
* the intermediate sums while computing a*G.
- * To make memory access uniform, the bytes of prec(i, n_i) are sliced per value of n_i. */
- unsigned char prec[64][sizeof(secp256k1_ge_t)][16]; /* prec[j][k][i] = k'th byte of (16^j * i * G + U_i) */
+ */
+ secp256k1_fe_t prec[64][16][2]; /* prec[j][i] = (16^j * i * G + U_i).{x,y} */
} secp256k1_ecmult_gen_consts_t;
static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL;
@@ -45,7 +45,7 @@ static void secp256k1_ecmult_gen_start(void) {
{
static const unsigned char nums_b32[32] = "The scalar for this x is unknown";
secp256k1_fe_t nums_x;
- secp256k1_fe_set_b32(&nums_x, nums_b32);
+ VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32));
secp256k1_ge_t nums_ge;
VERIFY_CHECK(secp256k1_ge_set_xo(&nums_ge, &nums_x, 0));
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
@@ -81,9 +81,9 @@ static void secp256k1_ecmult_gen_start(void) {
}
for (int j=0; j<64; j++) {
for (int i=0; i<16; i++) {
- const unsigned char* raw = (const unsigned char*)(&prec[j*16 + i]);
- for (size_t k=0; k<sizeof(secp256k1_ge_t); k++)
- ret->prec[j][k][i] = raw[k];
+ VERIFY_CHECK(!secp256k1_ge_is_infinity(&prec[j*16 + i]));
+ ret->prec[j][i][0] = prec[j*16 + i].x;
+ ret->prec[j][i][1] = prec[j*16 + i].y;
}
}
@@ -104,11 +104,14 @@ static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *g
const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts;
secp256k1_gej_set_infinity(r);
secp256k1_ge_t add;
+ add.infinity = 0;
int bits;
for (int j=0; j<64; j++) {
bits = secp256k1_scalar_get_bits(gn, j * 4, 4);
- for (size_t k=0; k<sizeof(secp256k1_ge_t); k++)
- ((unsigned char*)(&add))[k] = c->prec[j][k][bits];
+ for (int i=0; i<16; i++) {
+ secp256k1_fe_cmov(&add.x, &c->prec[j][i][0], i == bits);
+ secp256k1_fe_cmov(&add.y, &c->prec[j][i][1], i == bits);
+ }
secp256k1_gej_add_ge(r, r, &add);
}
bits = 0;
diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h
index 508902564e..445b81593f 100644
--- a/src/secp256k1/src/ecmult_impl.h
+++ b/src/secp256k1/src/ecmult_impl.h
@@ -7,8 +7,8 @@
#ifndef _SECP256K1_ECMULT_IMPL_H_
#define _SECP256K1_ECMULT_IMPL_H_
-#include "num.h"
#include "group.h"
+#include "scalar.h"
#include "ecmult.h"
/* optimal for 128-bit and 256-bit exponents. */
@@ -16,7 +16,11 @@
/** larger numbers may result in slightly better performance, at the cost of
exponentially larger precomputed tables. WINDOW_G == 14 results in 640 KiB. */
+#ifdef USE_ENDOMORPHISM
#define WINDOW_G 14
+#else
+#define WINDOW_G 15
+#endif
/** Fill a table 'pre' with precomputed odd multiples of a. W determines the size of the table.
* pre will contains the values [1*a,3*a,5*a,...,(2^(w-1)-1)*a], so it needs place for
@@ -69,7 +73,9 @@ static void secp256k1_ecmult_table_precomp_ge_var(secp256k1_ge_t *pre, const sec
typedef struct {
/* For accelerating the computation of a*P + b*G: */
secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of the generator */
+#ifdef USE_ENDOMORPHISM
secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of 2^128*generator */
+#endif
} secp256k1_ecmult_consts_t;
static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL;
@@ -85,14 +91,18 @@ static void secp256k1_ecmult_start(void) {
const secp256k1_ge_t *g = &secp256k1_ge_consts->g;
secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g);
+#ifdef USE_ENDOMORPHISM
/* calculate 2^128*generator */
secp256k1_gej_t g_128j = gj;
for (int i=0; i<128; i++)
secp256k1_gej_double_var(&g_128j, &g_128j);
+#endif
/* precompute the tables with odd multiples */
secp256k1_ecmult_table_precomp_ge_var(ret->pre_g, &gj, WINDOW_G);
+#ifdef USE_ENDOMORPHISM
secp256k1_ecmult_table_precomp_ge_var(ret->pre_g_128, &g_128j, WINDOW_G);
+#endif
/* Set the global pointer to the precomputation table. */
secp256k1_ecmult_consts = ret;
@@ -111,56 +121,62 @@ static void secp256k1_ecmult_stop(void) {
* with the following guarantees:
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
* - two non-zero entries in wnaf are separated by at least w-1 zeroes.
- * - the index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where
- * bits is the number of bits necessary to represent the absolute value of the input.
+ * - the number of set values in wnaf is returned. This number is at most 256, and at most one more
+ * - than the number of bits in the (absolute value) of the input.
*/
-static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) {
- int ret = 0;
- int zeroes = 0;
- secp256k1_num_t x;
- secp256k1_num_copy(&x, a);
+static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) {
+ secp256k1_scalar_t s = *a;
+
int sign = 1;
- if (secp256k1_num_is_neg(&x)) {
+ if (secp256k1_scalar_get_bits(&s, 255, 1)) {
+ secp256k1_scalar_negate(&s, &s);
sign = -1;
- secp256k1_num_negate(&x);
}
- while (!secp256k1_num_is_zero(&x)) {
- while (!secp256k1_num_is_odd(&x)) {
- zeroes++;
- secp256k1_num_shift(&x, 1);
+
+ int set_bits = 0;
+ int bit = 0;
+ while (bit < 256) {
+ if (secp256k1_scalar_get_bits(&s, bit, 1) == 0) {
+ bit++;
+ continue;
+ }
+ while (set_bits < bit) {
+ wnaf[set_bits++] = 0;
}
- int word = secp256k1_num_shift(&x, w);
- while (zeroes) {
- wnaf[ret++] = 0;
- zeroes--;
+ int now = w;
+ if (bit + now > 256) {
+ now = 256 - bit;
}
+ int word = secp256k1_scalar_get_bits_var(&s, bit, now);
if (word & (1 << (w-1))) {
- secp256k1_num_inc(&x);
- wnaf[ret++] = sign * (word - (1 << w));
+ secp256k1_scalar_add_bit(&s, bit + w);
+ wnaf[set_bits++] = sign * (word - (1 << w));
} else {
- wnaf[ret++] = sign * word;
+ wnaf[set_bits++] = sign * word;
}
- zeroes = w-1;
+ bit += now;
}
- return ret;
+ return set_bits;
}
-static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) {
+static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) {
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
#ifdef USE_ENDOMORPHISM
- secp256k1_num_t na_1, na_lam;
+ secp256k1_scalar_t na_1, na_lam;
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
- secp256k1_gej_split_exp_var(&na_1, &na_lam, na);
+ secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na);
/* build wnaf representation for na_1 and na_lam. */
- int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
- int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A);
+ int wnaf_na_1[130]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
+ int wnaf_na_lam[130]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A);
+ VERIFY_CHECK(bits_na_1 <= 130);
+ VERIFY_CHECK(bits_na_lam <= 130);
int bits = bits_na_1;
if (bits_na_lam > bits) bits = bits_na_lam;
#else
/* build wnaf representation for na. */
- int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
+ int wnaf_na[256]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
int bits = bits_na;
#endif
@@ -172,19 +188,22 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
for (int i=0; i<ECMULT_TABLE_SIZE(WINDOW_A); i++)
secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]);
-#endif
/* Splitted G factors. */
- secp256k1_num_t ng_1, ng_128;
+ secp256k1_scalar_t ng_1, ng_128;
/* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */
- secp256k1_num_split(&ng_1, &ng_128, ng, 128);
+ secp256k1_scalar_split_128(&ng_1, &ng_128, ng);
/* Build wnaf representation for ng_1 and ng_128 */
int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G);
int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G);
if (bits_ng_1 > bits) bits = bits_ng_1;
if (bits_ng_128 > bits) bits = bits_ng_128;
+#else
+ int wnaf_ng[257]; int bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, ng, WINDOW_G);
+ if (bits_ng > bits) bits = bits_ng;
+#endif
secp256k1_gej_set_infinity(r);
secp256k1_gej_t tmpj;
@@ -202,12 +221,6 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A);
secp256k1_gej_add_var(r, r, &tmpj);
}
-#else
- if (i < bits_na && (n = wnaf_na[i])) {
- ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A);
- secp256k1_gej_add_var(r, r, &tmpj);
- }
-#endif
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G);
secp256k1_gej_add_ge_var(r, r, &tmpa);
@@ -216,6 +229,16 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G);
secp256k1_gej_add_ge_var(r, r, &tmpa);
}
+#else
+ if (i < bits_na && (n = wnaf_na[i])) {
+ ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A);
+ secp256k1_gej_add_var(r, r, &tmpj);
+ }
+ if (i < bits_ng && (n = wnaf_ng[i])) {
+ ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G);
+ secp256k1_gej_add_ge_var(r, r, &tmpa);
+ }
+#endif
}
}
diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h
index c7feead900..0cdf0fb479 100644
--- a/src/secp256k1/src/field.h
+++ b/src/secp256k1/src/field.h
@@ -33,7 +33,10 @@
#endif
typedef struct {
+#ifndef USE_NUM_NONE
secp256k1_num_t p;
+#endif
+ secp256k1_fe_t order;
} secp256k1_fe_consts_t;
static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL;
@@ -59,8 +62,11 @@ static int secp256k1_fe_is_odd(const secp256k1_fe_t *a);
/** Compare two field elements. Requires both inputs to be normalized */
static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b);
-/** Set a field element equal to 32-byte big endian value. Resulting field element is normalized. */
-static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a);
+/** Compare two field elements. Requires both inputs to be normalized */
+static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b);
+
+/** Set a field element equal to 32-byte big endian value. If succesful, the resulting field element is normalized. */
+static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a);
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a);
@@ -78,7 +84,7 @@ static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a);
/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
* The output magnitude is 1 (but not guaranteed to be normalized). */
-static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b);
+static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t * SECP256K1_RESTRICT b);
/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
* The output magnitude is 1 (but not guaranteed to be normalized). */
@@ -104,11 +110,13 @@ static void secp256k1_fe_inv_all(size_t len, secp256k1_fe_t r[len], const secp25
/** Potentially faster version of secp256k1_fe_inv_all, without constant-time guarantee. */
static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t r[len], const secp256k1_fe_t a[len]);
-
/** Convert a field element to a hexadecimal string. */
static void secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a);
/** Convert a hexadecimal string to a field element. */
-static void secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen);
+static int secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen);
+
+/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
+static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag);
#endif
diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h
index c0f1be0b2d..c4403fba22 100644
--- a/src/secp256k1/src/field_10x26_impl.h
+++ b/src/secp256k1/src/field_10x26_impl.h
@@ -152,7 +152,21 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const se
| (t[5]^u[5]) | (t[6]^u[6]) | (t[7]^u[7]) | (t[8]^u[8]) | (t[9]^u[9])) == 0;
}
-static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
+static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+#ifdef VERIFY
+ VERIFY_CHECK(a->normalized);
+ VERIFY_CHECK(b->normalized);
+ secp256k1_fe_verify(a);
+ secp256k1_fe_verify(b);
+#endif
+ for (int i = 9; i >= 0; i--) {
+ if (a->n[i] > b->n[i]) return 1;
+ if (a->n[i] < b->n[i]) return -1;
+ }
+ return 0;
+}
+
+static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
for (int i=0; i<32; i++) {
@@ -162,11 +176,15 @@ static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift;
}
}
+ if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) {
+ return 0;
+ }
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
+ return 1;
}
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
@@ -253,7 +271,7 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1
#define VERIFY_BITS(x, n) do { } while(0)
#endif
-SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uint32_t *b, uint32_t *r) {
+SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b, uint32_t *r) {
VERIFY_BITS(a[0], 30);
VERIFY_BITS(a[1], 30);
VERIFY_BITS(a[2], 30);
@@ -853,12 +871,13 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint32_t *a, uint32_t
}
-static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t * SECP256K1_RESTRICT b) {
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= 8);
VERIFY_CHECK(b->magnitude <= 8);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
+ VERIFY_CHECK(r != b);
#endif
secp256k1_fe_mul_inner(a->n, b->n, r->n);
#ifdef VERIFY
@@ -881,4 +900,24 @@ static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
#endif
}
+static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag) {
+ uint32_t mask0 = flag + ~((uint32_t)0), mask1 = ~mask0;
+ r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
+ r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
+ r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
+ r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
+ r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
+ r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1);
+ r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1);
+ r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1);
+ r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1);
+ r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1);
+#ifdef VERIFY
+ if (flag) {
+ r->magnitude = a->magnitude;
+ r->normalized = a->normalized;
+ }
+#endif
+}
+
#endif
diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h
index d1b06d05a4..75b210eaf6 100644
--- a/src/secp256k1/src/field_5x52_impl.h
+++ b/src/secp256k1/src/field_5x52_impl.h
@@ -150,7 +150,21 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const se
return ((t[0]^u[0]) | (t[1]^u[1]) | (t[2]^u[2]) | (t[3]^u[3]) | (t[4]^u[4])) == 0;
}
-static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
+static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+#ifdef VERIFY
+ VERIFY_CHECK(a->normalized);
+ VERIFY_CHECK(b->normalized);
+ secp256k1_fe_verify(a);
+ secp256k1_fe_verify(b);
+#endif
+ for (int i = 4; i >= 0; i--) {
+ if (a->n[i] > b->n[i]) return 1;
+ if (a->n[i] < b->n[i]) return -1;
+ }
+ return 0;
+}
+
+static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
for (int i=0; i<32; i++) {
for (int j=0; j<2; j++) {
@@ -159,11 +173,15 @@ static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift;
}
}
+ if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) {
+ return 0;
+ }
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
+ return 1;
}
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
@@ -229,12 +247,13 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1
#endif
}
-static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t * SECP256K1_RESTRICT b) {
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= 8);
VERIFY_CHECK(b->magnitude <= 8);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
+ VERIFY_CHECK(r != b);
#endif
secp256k1_fe_mul_inner(a->n, b->n, r->n);
#ifdef VERIFY
@@ -257,4 +276,19 @@ static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
#endif
}
+static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag) {
+ uint64_t mask0 = flag + ~((uint64_t)0), mask1 = ~mask0;
+ r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
+ r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
+ r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
+ r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
+ r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
+#ifdef VERIFY
+ if (flag) {
+ r->magnitude = a->magnitude;
+ r->normalized = a->normalized;
+ }
+#endif
+}
+
#endif
diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h
index c476428672..e552fb4319 100644
--- a/src/secp256k1/src/field_5x52_int128_impl.h
+++ b/src/secp256k1/src/field_5x52_int128_impl.h
@@ -15,7 +15,7 @@
#define VERIFY_BITS(x, n) do { } while(0)
#endif
-SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r) {
+SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b, uint64_t *r) {
VERIFY_BITS(a[0], 56);
VERIFY_BITS(a[1], 56);
VERIFY_BITS(a[2], 56);
@@ -26,6 +26,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uin
VERIFY_BITS(b[2], 56);
VERIFY_BITS(b[3], 56);
VERIFY_BITS(b[4], 52);
+ VERIFY_CHECK(r != b);
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
/* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n.
@@ -33,15 +34,17 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uin
* Note that [x 0 0 0 0 0] = [x*R].
*/
+ uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
+
__int128 c, d;
- d = (__int128)a[0] * b[3]
- + (__int128)a[1] * b[2]
- + (__int128)a[2] * b[1]
- + (__int128)a[3] * b[0];
+ d = (__int128)a0 * b[3]
+ + (__int128)a1 * b[2]
+ + (__int128)a2 * b[1]
+ + (__int128)a3 * b[0];
VERIFY_BITS(d, 114);
/* [d 0 0 0] = [p3 0 0 0] */
- c = (__int128)a[4] * b[4];
+ c = (__int128)a4 * b[4];
VERIFY_BITS(c, 112);
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
d += (c & M) * R; c >>= 52;
@@ -53,11 +56,11 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uin
VERIFY_BITS(d, 63);
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
- d += (__int128)a[0] * b[4]
- + (__int128)a[1] * b[3]
- + (__int128)a[2] * b[2]
- + (__int128)a[3] * b[1]
- + (__int128)a[4] * b[0];
+ d += (__int128)a0 * b[4]
+ + (__int128)a1 * b[3]
+ + (__int128)a2 * b[2]
+ + (__int128)a3 * b[1]
+ + (__int128)a4 * b[0];
VERIFY_BITS(d, 115);
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
d += c * R;
@@ -72,13 +75,13 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uin
VERIFY_BITS(t4, 48);
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
- c = (__int128)a[0] * b[0];
+ c = (__int128)a0 * b[0];
VERIFY_BITS(c, 112);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
- d += (__int128)a[1] * b[4]
- + (__int128)a[2] * b[3]
- + (__int128)a[3] * b[2]
- + (__int128)a[4] * b[1];
+ d += (__int128)a1 * b[4]
+ + (__int128)a2 * b[3]
+ + (__int128)a3 * b[2]
+ + (__int128)a4 * b[1];
VERIFY_BITS(d, 115);
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
uint64_t u0 = d & M; d >>= 52;
@@ -92,48 +95,43 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uin
c += (__int128)u0 * (R >> 4);
VERIFY_BITS(c, 115);
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
- uint64_t t0 = c & M; c >>= 52;
- VERIFY_BITS(t0, 52);
+ r[0] = c & M; c >>= 52;
+ VERIFY_BITS(r[0], 52);
VERIFY_BITS(c, 61);
- /* [d 0 t4 t3 0 c t0] = [p8 0 0 p5 p4 p3 0 0 p0] */
+ /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
- c += (__int128)a[0] * b[1]
- + (__int128)a[1] * b[0];
+ c += (__int128)a0 * b[1]
+ + (__int128)a1 * b[0];
VERIFY_BITS(c, 114);
- /* [d 0 t4 t3 0 c t0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
- d += (__int128)a[2] * b[4]
- + (__int128)a[3] * b[3]
- + (__int128)a[4] * b[2];
+ /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
+ d += (__int128)a2 * b[4]
+ + (__int128)a3 * b[3]
+ + (__int128)a4 * b[2];
VERIFY_BITS(d, 114);
- /* [d 0 t4 t3 0 c t0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
+ /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
c += (d & M) * R; d >>= 52;
VERIFY_BITS(c, 115);
VERIFY_BITS(d, 62);
- /* [d 0 0 t4 t3 0 c t0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- uint64_t t1 = c & M; c >>= 52;
- VERIFY_BITS(t1, 52);
+ /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
+ r[1] = c & M; c >>= 52;
+ VERIFY_BITS(r[1], 52);
VERIFY_BITS(c, 63);
- /* [d 0 0 t4 t3 c t1 t0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
+ /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
- c += (__int128)a[0] * b[2]
- + (__int128)a[1] * b[1]
- + (__int128)a[2] * b[0];
+ c += (__int128)a0 * b[2]
+ + (__int128)a1 * b[1]
+ + (__int128)a2 * b[0];
VERIFY_BITS(c, 114);
- /* [d 0 0 t4 t3 c t1 t0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
- d += (__int128)a[3] * b[4]
- + (__int128)a[4] * b[3];
+ /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
+ d += (__int128)a3 * b[4]
+ + (__int128)a4 * b[3];
VERIFY_BITS(d, 114);
- /* [d 0 0 t4 t3 c t1 t0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
+ /* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
c += (d & M) * R; d >>= 52;
VERIFY_BITS(c, 115);
VERIFY_BITS(d, 62);
- /* [d 0 0 0 t4 t3 c t1 t0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
+ /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[0] = t0;
- VERIFY_BITS(r[0], 52);
- /* [d 0 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
- r[1] = t1;
- VERIFY_BITS(r[1], 52);
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[2] = c & M; c >>= 52;
VERIFY_BITS(r[2], 52);
diff --git a/src/secp256k1/src/field_gmp_impl.h b/src/secp256k1/src/field_gmp_impl.h
index af4728e5b4..8af7dd68f8 100644
--- a/src/secp256k1/src/field_gmp_impl.h
+++ b/src/secp256k1/src/field_gmp_impl.h
@@ -75,7 +75,15 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const se
return ret;
}
-static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
+SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+ for (int i=FIELD_LIMBS; i>=0; i--) {
+ if (a->n[i] > b->n[i]) return 1;
+ if (a->n[i] < b->n[i]) return -1;
+ }
+ return 0;
+}
+
+static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
for (int i=0; i<FIELD_LIMBS+1; i++)
r->n[i] = 0;
for (int i=0; i<256; i++) {
@@ -83,6 +91,7 @@ static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
int shift = i%GMP_NUMB_BITS;
r->n[limb] |= (mp_limb_t)((a[31-i/8] >> (i%8)) & 0x1) << shift;
}
+ return (mpn_cmp(r->n, secp256k1_field_p, FIELD_LIMBS) < 0);
}
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
@@ -142,7 +151,8 @@ static void secp256k1_fe_reduce(secp256k1_fe_t *r, mp_limb_t *tmp) {
r->n[FIELD_LIMBS] = mpn_add(r->n, tmp, FIELD_LIMBS, q, 1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS);
}
-static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t * SECP256K1_RESTRICT b) {
+ VERIFY_CHECK(r != b);
secp256k1_fe_t ac = *a;
secp256k1_fe_t bc = *b;
secp256k1_fe_normalize(&ac);
@@ -160,4 +170,11 @@ static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
secp256k1_fe_reduce(r, tmp);
}
+static void secp256k1_fe_cmov(secp256k1_fe_t *r, const secp256k1_fe_t *a, int flag) {
+ mp_limb_t mask0 = flag + ~((mp_limb_t)0), mask1 = ~mask0;
+ for (int i = 0; i <= FIELD_LIMBS; i++) {
+ r->n[i] = (r->n[i] & mask0) | (a->n[i] & mask1);
+ }
+}
+
#endif
diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h
index 3a31e1844e..4d25e53715 100644
--- a/src/secp256k1/src/field_impl.h
+++ b/src/secp256k1/src/field_impl.h
@@ -41,7 +41,7 @@ static void secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a) {
r[64] = 0x00;
}
-static void secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
+static int secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
unsigned char tmp[32] = {};
static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
@@ -63,7 +63,7 @@ static void secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
if (alen > i*2)
tmp[32 - alen/2 + i] = (cvt[(unsigned char)a[2*i]] << 4) + cvt[(unsigned char)a[2*i+1]];
}
- secp256k1_fe_set_b32(r, tmp);
+ return secp256k1_fe_set_b32(r, tmp);
}
static int secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
@@ -197,7 +197,7 @@ static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
for (int j=0; j<3; j++) secp256k1_fe_sqr(&t1, &t1);
secp256k1_fe_mul(&t1, &t1, &x2);
for (int j=0; j<2; j++) secp256k1_fe_sqr(&t1, &t1);
- secp256k1_fe_mul(r, &t1, a);
+ secp256k1_fe_mul(r, a, &t1);
}
static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
@@ -212,7 +212,7 @@ static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
secp256k1_num_set_bin(&n, b, 32);
secp256k1_num_mod_inverse(&n, &n, &secp256k1_fe_consts->p);
secp256k1_num_get_bin(b, 32, &n);
- secp256k1_fe_set_b32(r, b);
+ VERIFY_CHECK(secp256k1_fe_set_b32(r, b));
#else
#error "Please select field inverse implementation"
#endif
@@ -267,16 +267,20 @@ static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t r[len], const se
}
static void secp256k1_fe_start(void) {
+#ifndef USE_NUM_NONE
static const unsigned char secp256k1_fe_consts_p[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
};
+#endif
if (secp256k1_fe_consts == NULL) {
secp256k1_fe_inner_start();
secp256k1_fe_consts_t *ret = (secp256k1_fe_consts_t*)malloc(sizeof(secp256k1_fe_consts_t));
+#ifndef USE_NUM_NONE
secp256k1_num_set_bin(&ret->p, secp256k1_fe_consts_p, sizeof(secp256k1_fe_consts_p));
+#endif
secp256k1_fe_consts = ret;
}
}
diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h
index ba02549821..0f14bd25f3 100644
--- a/src/secp256k1/src/group.h
+++ b/src/secp256k1/src/group.h
@@ -27,14 +27,11 @@ typedef struct {
/** Global constants related to the group */
typedef struct {
- secp256k1_num_t order; /* the order of the curve (= order of its generator) */
- secp256k1_num_t half_order; /* half the order of the curve (= order of its generator) */
secp256k1_ge_t g; /* the generator point */
#ifdef USE_ENDOMORPHISM
/* constants related to secp256k1's efficiently computable endomorphism */
secp256k1_fe_t beta;
- secp256k1_num_t lambda, a1b2, b1, a2;
#endif
} secp256k1_ge_consts_t;
@@ -112,10 +109,6 @@ static void secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a);
#ifdef USE_ENDOMORPHISM
/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */
static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a);
-
-/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (given that a is
- not more than 256 bits). */
-static void secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a);
#endif
/** Clear a secp256k1_gej_t to prevent leaking sensitive information. */
@@ -124,5 +117,4 @@ static void secp256k1_gej_clear(secp256k1_gej_t *r);
/** Clear a secp256k1_ge_t to prevent leaking sensitive information. */
static void secp256k1_ge_clear(secp256k1_ge_t *r);
-
#endif
diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h
index 1edbc6e099..cbd0d8c4fc 100644
--- a/src/secp256k1/src/group_impl.h
+++ b/src/secp256k1/src/group_impl.h
@@ -208,29 +208,25 @@ static int secp256k1_ge_is_valid(const secp256k1_ge_t *a) {
}
static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a) {
- if (a->infinity) {
- r->infinity = 1;
- return;
- }
-
- secp256k1_fe_t t5 = a->y;
- secp256k1_fe_normalize(&t5);
- if (secp256k1_fe_is_zero(&t5)) {
- r->infinity = 1;
+ // For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity,
+ // Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have
+ // y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p.
+ r->infinity = a->infinity;
+ if (r->infinity) {
return;
}
secp256k1_fe_t t1,t2,t3,t4;
- secp256k1_fe_mul(&r->z, &t5, &a->z);
+ secp256k1_fe_mul(&r->z, &a->z, &a->y);
secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */
secp256k1_fe_sqr(&t1, &a->x);
secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */
secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */
- secp256k1_fe_sqr(&t3, &t5);
+ secp256k1_fe_sqr(&t3, &a->y);
secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */
secp256k1_fe_sqr(&t4, &t3);
secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */
- secp256k1_fe_mul(&t3, &a->x, &t3); /* T3 = 2*X*Y^2 (1) */
+ secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */
r->x = t3;
secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */
secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */
@@ -241,7 +237,6 @@ static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *
secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */
secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */
secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */
- r->infinity = 0;
}
static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b) {
@@ -342,7 +337,7 @@ static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c
*
* Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives:
* U1 = X1*Z2^2, U2 = X2*Z1^2
- * S1 = X1*Z2^3, S2 = X2*Z2^3
+ * S1 = Y1*Z2^3, S2 = Y2*Z1^3
* Z = Z1*Z2
* T = U1+U2
* M = S1+S2
@@ -414,40 +409,9 @@ static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *
*r = *a;
secp256k1_fe_mul(&r->x, &r->x, beta);
}
-
-static void secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a) {
- const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
- secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2;
-
- secp256k1_num_copy(&bnn2, &c->order);
- secp256k1_num_shift(&bnn2, 1);
-
- secp256k1_num_mul(&bnc1, a, &c->a1b2);
- secp256k1_num_add(&bnc1, &bnc1, &bnn2);
- secp256k1_num_div(&bnc1, &bnc1, &c->order);
-
- secp256k1_num_mul(&bnc2, a, &c->b1);
- secp256k1_num_add(&bnc2, &bnc2, &bnn2);
- secp256k1_num_div(&bnc2, &bnc2, &c->order);
-
- secp256k1_num_mul(&bnt1, &bnc1, &c->a1b2);
- secp256k1_num_mul(&bnt2, &bnc2, &c->a2);
- secp256k1_num_add(&bnt1, &bnt1, &bnt2);
- secp256k1_num_sub(r1, a, &bnt1);
- secp256k1_num_mul(&bnt1, &bnc1, &c->b1);
- secp256k1_num_mul(&bnt2, &bnc2, &c->a1b2);
- secp256k1_num_sub(r2, &bnt1, &bnt2);
-}
#endif
-
static void secp256k1_ge_start(void) {
- static const unsigned char secp256k1_ge_consts_order[] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
- 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
- 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41
- };
static const unsigned char secp256k1_ge_consts_g_x[] = {
0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,
0x55,0xA0,0x62,0x95,0xCE,0x87,0x0B,0x07,
@@ -462,47 +426,21 @@ static void secp256k1_ge_start(void) {
};
#ifdef USE_ENDOMORPHISM
/* properties of secp256k1's efficiently computable endomorphism */
- static const unsigned char secp256k1_ge_consts_lambda[] = {
- 0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,
- 0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
- 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,
- 0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72
- };
static const unsigned char secp256k1_ge_consts_beta[] = {
0x7a,0xe9,0x6a,0x2b,0x65,0x7c,0x07,0x10,
0x6e,0x64,0x47,0x9e,0xac,0x34,0x34,0xe9,
0x9c,0xf0,0x49,0x75,0x12,0xf5,0x89,0x95,
0xc1,0x39,0x6c,0x28,0x71,0x95,0x01,0xee
};
- static const unsigned char secp256k1_ge_consts_a1b2[] = {
- 0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,
- 0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15
- };
- static const unsigned char secp256k1_ge_consts_b1[] = {
- 0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,
- 0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3
- };
- static const unsigned char secp256k1_ge_consts_a2[] = {
- 0x01,
- 0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,
- 0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8
- };
#endif
if (secp256k1_ge_consts == NULL) {
secp256k1_ge_consts_t *ret = (secp256k1_ge_consts_t*)malloc(sizeof(secp256k1_ge_consts_t));
- secp256k1_num_set_bin(&ret->order, secp256k1_ge_consts_order, sizeof(secp256k1_ge_consts_order));
- secp256k1_num_copy(&ret->half_order, &ret->order);
- secp256k1_num_shift(&ret->half_order, 1);
#ifdef USE_ENDOMORPHISM
- secp256k1_num_set_bin(&ret->lambda, secp256k1_ge_consts_lambda, sizeof(secp256k1_ge_consts_lambda));
- secp256k1_num_set_bin(&ret->a1b2, secp256k1_ge_consts_a1b2, sizeof(secp256k1_ge_consts_a1b2));
- secp256k1_num_set_bin(&ret->a2, secp256k1_ge_consts_a2, sizeof(secp256k1_ge_consts_a2));
- secp256k1_num_set_bin(&ret->b1, secp256k1_ge_consts_b1, sizeof(secp256k1_ge_consts_b1));
- secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta);
+ VERIFY_CHECK(secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta));
#endif
secp256k1_fe_t g_x, g_y;
- secp256k1_fe_set_b32(&g_x, secp256k1_ge_consts_g_x);
- secp256k1_fe_set_b32(&g_y, secp256k1_ge_consts_g_y);
+ VERIFY_CHECK(secp256k1_fe_set_b32(&g_x, secp256k1_ge_consts_g_x));
+ VERIFY_CHECK(secp256k1_fe_set_b32(&g_y, secp256k1_ge_consts_g_y));
secp256k1_ge_set_xy(&ret->g, &g_x, &g_y);
secp256k1_ge_consts = ret;
}
diff --git a/src/secp256k1/src/num.h b/src/secp256k1/src/num.h
index c86f847858..339b6bb6ec 100644
--- a/src/secp256k1/src/num.h
+++ b/src/secp256k1/src/num.h
@@ -7,6 +7,8 @@
#ifndef _SECP256K1_NUM_
#define _SECP256K1_NUM_
+#ifndef USE_NUM_NONE
+
#if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h"
#endif
@@ -17,9 +19,6 @@
#error "Please select num implementation"
#endif
-/** Clear a number to prevent the leak of sensitive data. */
-static void secp256k1_num_clear(secp256k1_num_t *r);
-
/** Copy a number. */
static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a);
@@ -30,15 +29,9 @@ static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const sec
/** Set a number to the value of a binary big-endian string. */
static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen);
-/** Set a number equal to a (signed) integer. */
-static void secp256k1_num_set_int(secp256k1_num_t *r, int a);
-
/** Compute a modular inverse. The input must be less than the modulus. */
static void secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m);
-/** Multiply two numbers modulo another. */
-static void secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m);
-
/** Compare the absolute value of two numbers. */
static int secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b);
@@ -54,47 +47,22 @@ static void secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, cons
/** Multiply two (signed) numbers. */
static void secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
-/** Divide two (signed) numbers. */
-static void secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
-
/** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1,
even if r was negative. */
static void secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m);
-/** Calculate the number of bits in (the absolute value of) a number. */
-static int secp256k1_num_bits(const secp256k1_num_t *a);
-
-/** Right-shift the passed number by bits bits, and return those bits. */
-static int secp256k1_num_shift(secp256k1_num_t *r, int bits);
+/** Right-shift the passed number by bits bits. */
+static void secp256k1_num_shift(secp256k1_num_t *r, int bits);
/** Check whether a number is zero. */
static int secp256k1_num_is_zero(const secp256k1_num_t *a);
-/** Check whether a number is odd. */
-static int secp256k1_num_is_odd(const secp256k1_num_t *a);
-
/** Check whether a number is strictly negative. */
static int secp256k1_num_is_neg(const secp256k1_num_t *a);
-/** Check whether a particular bit is set in a number. */
-static int secp256k1_num_get_bit(const secp256k1_num_t *a, int pos);
-
-/** Increase a number by 1. */
-static void secp256k1_num_inc(secp256k1_num_t *r);
-
-/** Set a number equal to the value of a hex string (unsigned). */
-static void secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen);
-
-/** Convert (the absolute value of) a number to a hexadecimal string. */
-static void secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a);
-
-/** Split a number into a low and high part. */
-static void secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits);
-
/** Change a number's sign. */
static void secp256k1_num_negate(secp256k1_num_t *r);
-/** Get a bunch of bits from a number. */
-static int secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count);
+#endif
#endif
diff --git a/src/secp256k1/src/num_gmp_impl.h b/src/secp256k1/src/num_gmp_impl.h
index e45a59e0cd..19d474e59f 100644
--- a/src/secp256k1/src/num_gmp_impl.h
+++ b/src/secp256k1/src/num_gmp_impl.h
@@ -22,35 +22,10 @@ static void secp256k1_num_sanity(const secp256k1_num_t *a) {
#define secp256k1_num_sanity(a) do { } while(0)
#endif
-static void secp256k1_num_init(secp256k1_num_t *r) {
- r->neg = 0;
- r->limbs = 1;
- r->data[0] = 0;
-}
-
-static void secp256k1_num_clear(secp256k1_num_t *r) {
- memset(r, 0, sizeof(*r));
-}
-
-static void secp256k1_num_free(secp256k1_num_t *r) {
- (void)r;
-}
-
static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
*r = *a;
}
-static int secp256k1_num_bits(const secp256k1_num_t *a) {
- int ret=(a->limbs-1)*GMP_NUMB_BITS;
- mp_limb_t x=a->data[a->limbs-1];
- while (x) {
- x >>= 1;
- ret++;
- }
- return ret;
-}
-
-
static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) {
unsigned char tmp[65];
int len = 0;
@@ -71,18 +46,16 @@ static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, un
VERIFY_CHECK(alen > 0);
VERIFY_CHECK(alen <= 64);
int len = mpn_set_str(r->data, a, alen, 256);
+ if (len == 0) {
+ r->data[0] = 0;
+ len = 1;
+ }
VERIFY_CHECK(len <= NUM_LIMBS*2);
r->limbs = len;
r->neg = 0;
while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
}
-static void secp256k1_num_set_int(secp256k1_num_t *r, int a) {
- r->limbs = 1;
- r->neg = (a < 0);
- r->data[0] = (a < 0) ? -a : a;
-}
-
static void secp256k1_num_add_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs);
r->limbs = a->limbs;
@@ -161,10 +134,6 @@ static int secp256k1_num_is_zero(const secp256k1_num_t *a) {
return (a->limbs == 1 && a->data[0] == 0);
}
-static int secp256k1_num_is_odd(const secp256k1_num_t *a) {
- return a->data[0] & 1;
-}
-
static int secp256k1_num_is_neg(const secp256k1_num_t *a) {
return (a->limbs > 1 || a->data[0] != 0) && a->neg;
}
@@ -237,140 +206,27 @@ static void secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, cons
memset(tmp, 0, sizeof(tmp));
}
-static void secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
- secp256k1_num_sanity(a);
- secp256k1_num_sanity(b);
- if (b->limbs > a->limbs) {
- r->limbs = 1;
- r->data[0] = 0;
- r->neg = 0;
- return;
- }
-
- mp_limb_t quo[2*NUM_LIMBS+1];
- mp_limb_t rem[2*NUM_LIMBS+1];
- mpn_tdiv_qr(quo, rem, 0, a->data, a->limbs, b->data, b->limbs);
- mpn_copyi(r->data, quo, a->limbs - b->limbs + 1);
- r->limbs = a->limbs - b->limbs + 1;
- while (r->limbs > 1 && r->data[r->limbs - 1]==0) r->limbs--;
- r->neg = a->neg ^ b->neg;
-}
-
-static void secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) {
- secp256k1_num_mul(r, a, b);
- secp256k1_num_mod(r, m);
-}
-
-
-static int secp256k1_num_shift(secp256k1_num_t *r, int bits) {
- VERIFY_CHECK(bits <= GMP_NUMB_BITS);
- mp_limb_t ret = mpn_rshift(r->data, r->data, r->limbs, bits);
- if (r->limbs>1 && r->data[r->limbs-1]==0) r->limbs--;
- ret >>= (GMP_NUMB_BITS - bits);
- return ret;
-}
-
-static int secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) {
- return (a->limbs*GMP_NUMB_BITS > pos) && ((a->data[pos/GMP_NUMB_BITS] >> (pos % GMP_NUMB_BITS)) & 1);
-}
-
-static void secp256k1_num_inc(secp256k1_num_t *r) {
- mp_limb_t ret = mpn_add_1(r->data, r->data, r->limbs, (mp_limb_t)1);
- if (ret) {
- VERIFY_CHECK(r->limbs < 2*NUM_LIMBS);
- r->data[r->limbs++] = ret;
- }
-}
-
-static void secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) {
- static const unsigned char cvt[256] = {
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0,
- 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
- 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0
- };
- unsigned char num[257] = {};
- for (int i=0; i<alen; i++) {
- num[i] = cvt[(unsigned char)a[i]];
- }
- r->limbs = mpn_set_str(r->data, num, alen, 16);
- r->neg = 0;
- while (r->limbs > 1 && r->data[r->limbs-1] == 0) r->limbs--;
-}
-
-static void secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) {
- static const unsigned char cvt[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
- unsigned char *tmp = malloc(257);
- mp_size_t len = mpn_get_str(tmp, 16, (mp_limb_t*)a->data, a->limbs);
- VERIFY_CHECK(len <= rlen);
- for (int i=0; i<len; i++) {
- VERIFY_CHECK(rlen-len+i >= 0);
- VERIFY_CHECK(rlen-len+i < rlen);
- VERIFY_CHECK(tmp[i] < 16);
- r[rlen-len+i] = cvt[tmp[i]];
- }
- for (int i=0; i<rlen-len; i++) {
- VERIFY_CHECK(i >= 0);
- VERIFY_CHECK(i < rlen);
- r[i] = cvt[0];
- }
- free(tmp);
-}
-
-static void secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) {
- VERIFY_CHECK(bits > 0);
- rh->neg = a->neg;
- if (bits >= a->limbs * GMP_NUMB_BITS) {
- *rl = *a;
- rh->limbs = 1;
- rh->data[0] = 0;
- return;
- }
- rl->limbs = 0;
- rl->neg = a->neg;
- int left = bits;
- while (left >= GMP_NUMB_BITS) {
- rl->data[rl->limbs] = a->data[rl->limbs];
- rl->limbs++;
- left -= GMP_NUMB_BITS;
- }
- if (left == 0) {
- mpn_copyi(rh->data, a->data + rl->limbs, a->limbs - rl->limbs);
- rh->limbs = a->limbs - rl->limbs;
- } else {
- mpn_rshift(rh->data, a->data + rl->limbs, a->limbs - rl->limbs, left);
- rh->limbs = a->limbs - rl->limbs;
- while (rh->limbs>1 && rh->data[rh->limbs-1]==0) rh->limbs--;
- }
- if (left > 0) {
- rl->data[rl->limbs] = a->data[rl->limbs] & ((((mp_limb_t)1) << left) - 1);
- rl->limbs++;
+static void secp256k1_num_shift(secp256k1_num_t *r, int bits) {
+ if (bits % GMP_NUMB_BITS) {
+ // Shift within limbs.
+ mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS);
+ }
+ if (bits >= GMP_NUMB_BITS) {
+ // Shift full limbs.
+ for (int i = 0; i < r->limbs; i++) {
+ int index = i + (bits / GMP_NUMB_BITS);
+ if (index < r->limbs && index < 2*NUM_LIMBS) {
+ r->data[i] = r->data[index];
+ } else {
+ r->data[i] = 0;
+ }
+ }
}
- while (rl->limbs>1 && rl->data[rl->limbs-1]==0) rl->limbs--;
+ while (r->limbs>1 && r->data[r->limbs-1]==0) r->limbs--;
}
static void secp256k1_num_negate(secp256k1_num_t *r) {
r->neg ^= 1;
}
-static int secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count) {
- int ret = 0;
- for (int i = 0; i < count; i++) {
- ret |= ((a->data[(offset + i) / GMP_NUMB_BITS] >> ((offset + i) % GMP_NUMB_BITS)) & 1) << i;
- }
- return ret;
-}
-
#endif
diff --git a/src/secp256k1/src/num_impl.h b/src/secp256k1/src/num_impl.h
index f73d3ceea8..0b0e3a072a 100644
--- a/src/secp256k1/src/num_impl.h
+++ b/src/secp256k1/src/num_impl.h
@@ -15,6 +15,8 @@
#if defined(USE_NUM_GMP)
#include "num_gmp_impl.h"
+#elif defined(USE_NUM_NONE)
+/* Nothing. */
#else
#error "Please select num implementation"
#endif
diff --git a/src/secp256k1/src/scalar.h b/src/secp256k1/src/scalar.h
index 3baacb3721..2f5ba0d447 100644
--- a/src/secp256k1/src/scalar.h
+++ b/src/secp256k1/src/scalar.h
@@ -21,20 +21,32 @@
#error "Please select scalar implementation"
#endif
+static void secp256k1_scalar_start(void);
+static void secp256k1_scalar_stop(void);
+
/** Clear a scalar to prevent the leak of sensitive data. */
static void secp256k1_scalar_clear(secp256k1_scalar_t *r);
-/** Access bits from a scalar. */
-static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count);
+/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */
+static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count);
+
+/** Access bits from a scalar. Not constant time. */
+static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count);
/** Set a scalar from a big endian byte array. */
static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *bin, int *overflow);
+/** Set a scalar to an unsigned integer. */
+static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v);
+
/** Convert a scalar to a byte array. */
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_t* a);
-/** Add two scalars together (modulo the group order). */
-static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
+/** Add two scalars together (modulo the group order). Returns whether it overflowed. */
+static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
+
+/** Add a power of two to a scalar. The result is not allowed to overflow. */
+static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit);
/** Multiply two scalars (modulo the group order). */
static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
@@ -45,6 +57,9 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t
/** Compute the inverse of a scalar (modulo the group order). */
static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *a);
+/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */
+static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a);
+
/** Compute the complement of a scalar (modulo the group order). */
static void secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a);
@@ -57,7 +72,25 @@ static int secp256k1_scalar_is_one(const secp256k1_scalar_t *a);
/** Check whether a scalar is higher than the group order divided by 2. */
static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a);
+#ifndef USE_NUM_NONE
/** Convert a scalar to a number. */
static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a);
+/** Get the order of the group as a number. */
+static void secp256k1_scalar_order_get_num(secp256k1_num_t *r);
+#endif
+
+/** Compare two scalars. */
+static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
+
+static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
+
+#ifdef USE_ENDOMORPHISM
+/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */
+static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a);
+#endif
+
+/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
+static void secp256k1_scalar_mul_shift_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b, unsigned int shift);
+
#endif
diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h
index f78718234f..d144775220 100644
--- a/src/secp256k1/src/scalar_4x64_impl.h
+++ b/src/secp256k1/src/scalar_4x64_impl.h
@@ -33,9 +33,27 @@ SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar_t *r) {
r->d[3] = 0;
}
-SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count) {
- VERIFY_CHECK((offset + count - 1) / 64 == offset / 64);
- return (a->d[offset / 64] >> (offset % 64)) & ((((uint64_t)1) << count) - 1);
+SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v) {
+ r->d[0] = v;
+ r->d[1] = 0;
+ r->d[2] = 0;
+ r->d[3] = 0;
+}
+
+SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) {
+ VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6);
+ return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1);
+}
+
+SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) {
+ VERIFY_CHECK(count < 32);
+ VERIFY_CHECK(offset + count <= 256);
+ if ((offset + count - 1) >> 6 == offset >> 6) {
+ return secp256k1_scalar_get_bits(a, offset, count);
+ } else {
+ VERIFY_CHECK((offset >> 6) + 1 < 4);
+ return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1);
+ }
}
SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *a) {
@@ -63,7 +81,7 @@ SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar_t *r, unsig
return overflow;
}
-static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
uint128_t t = (uint128_t)a->d[0] + b->d[0];
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
t += (uint128_t)a->d[1] + b->d[1];
@@ -72,7 +90,26 @@ static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t
r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
t += (uint128_t)a->d[3] + b->d[3];
r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
- secp256k1_scalar_reduce(r, t + secp256k1_scalar_check_overflow(r));
+ int overflow = t + secp256k1_scalar_check_overflow(r);
+ VERIFY_CHECK(overflow == 0 || overflow == 1);
+ secp256k1_scalar_reduce(r, overflow);
+ return overflow;
+}
+
+static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
+ VERIFY_CHECK(bit < 256);
+ uint128_t t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
+ r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
+ t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
+ r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
+ t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F));
+ r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
+ t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F));
+ r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL;
+#ifdef VERIFY
+ VERIFY_CHECK((t >> 64) == 0);
+ VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
+#endif
}
static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) {
@@ -280,13 +317,11 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint64_t *l
secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r));
}
-static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
/* 160 bit accumulator. */
uint64_t c0 = 0, c1 = 0;
uint32_t c2 = 0;
- uint64_t l[8];
-
/* l[0..7] = a[0..3] * b[0..3]. */
muladd_fast(a->d[0], b->d[0]);
extract_fast(l[0]);
@@ -313,17 +348,13 @@ static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t
extract_fast(l[6]);
VERIFY_CHECK(c1 <= 0);
l[7] = c0;
-
- secp256k1_scalar_reduce_512(r, l);
}
-static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) {
+static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar_t *a) {
/* 160 bit accumulator. */
uint64_t c0 = 0, c1 = 0;
uint32_t c2 = 0;
- uint64_t l[8];
-
/* l[0..7] = a[0..3] * b[0..3]. */
muladd_fast(a->d[0], a->d[0]);
extract_fast(l[0]);
@@ -344,8 +375,6 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t
extract_fast(l[6]);
VERIFY_CHECK(c1 == 0);
l[7] = c0;
-
- secp256k1_scalar_reduce_512(r, l);
}
#undef sumadd
@@ -356,4 +385,47 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t
#undef extract
#undef extract_fast
+static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+ uint64_t l[8];
+ secp256k1_scalar_mul_512(l, a, b);
+ secp256k1_scalar_reduce_512(r, l);
+}
+
+static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) {
+ uint64_t l[8];
+ secp256k1_scalar_sqr_512(l, a);
+ secp256k1_scalar_reduce_512(r, l);
+}
+
+static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
+ r1->d[0] = a->d[0];
+ r1->d[1] = a->d[1];
+ r1->d[2] = 0;
+ r1->d[3] = 0;
+ r2->d[0] = a->d[2];
+ r2->d[1] = a->d[3];
+ r2->d[2] = 0;
+ r2->d[3] = 0;
+}
+
+SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+ return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0;
+}
+
+SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b, unsigned int shift) {
+ VERIFY_CHECK(shift >= 256);
+ uint64_t l[8];
+ secp256k1_scalar_mul_512(l, a, b);
+ unsigned int shiftlimbs = shift >> 6;
+ unsigned int shiftlow = shift & 0x3F;
+ unsigned int shifthigh = 64 - shiftlow;
+ r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0;
+ if ((l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1) {
+ secp256k1_scalar_add_bit(r, 0);
+ }
+}
+
#endif
diff --git a/src/secp256k1/src/scalar_8x32_impl.h b/src/secp256k1/src/scalar_8x32_impl.h
index e58be1365f..915cbcddbe 100644
--- a/src/secp256k1/src/scalar_8x32_impl.h
+++ b/src/secp256k1/src/scalar_8x32_impl.h
@@ -45,9 +45,31 @@ SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar_t *r) {
r->d[7] = 0;
}
-SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count) {
- VERIFY_CHECK((offset + count - 1) / 32 == offset / 32);
- return (a->d[offset / 32] >> (offset % 32)) & ((1 << count) - 1);
+SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v) {
+ r->d[0] = v;
+ r->d[1] = 0;
+ r->d[2] = 0;
+ r->d[3] = 0;
+ r->d[4] = 0;
+ r->d[5] = 0;
+ r->d[6] = 0;
+ r->d[7] = 0;
+}
+
+SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) {
+ VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5);
+ return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1);
+}
+
+SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count) {
+ VERIFY_CHECK(count < 32);
+ VERIFY_CHECK(offset + count <= 256);
+ if ((offset + count - 1) >> 5 == offset >> 5) {
+ return secp256k1_scalar_get_bits(a, offset, count);
+ } else {
+ VERIFY_CHECK((offset >> 5) + 1 < 8);
+ return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1);
+ }
}
SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *a) {
@@ -89,7 +111,7 @@ SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar_t *r, uint3
return overflow;
}
-static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
uint64_t t = (uint64_t)a->d[0] + b->d[0];
r->d[0] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)a->d[1] + b->d[1];
@@ -106,7 +128,34 @@ static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t
r->d[6] = t & 0xFFFFFFFFULL; t >>= 32;
t += (uint64_t)a->d[7] + b->d[7];
r->d[7] = t & 0xFFFFFFFFULL; t >>= 32;
- secp256k1_scalar_reduce(r, t + secp256k1_scalar_check_overflow(r));
+ int overflow = t + secp256k1_scalar_check_overflow(r);
+ VERIFY_CHECK(overflow == 0 || overflow == 1);
+ secp256k1_scalar_reduce(r, overflow);
+ return overflow;
+}
+
+static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit) {
+ VERIFY_CHECK(bit < 256);
+ uint64_t t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F));
+ r->d[0] = t & 0xFFFFFFFFULL; t >>= 32;
+ t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F));
+ r->d[1] = t & 0xFFFFFFFFULL; t >>= 32;
+ t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F));
+ r->d[2] = t & 0xFFFFFFFFULL; t >>= 32;
+ t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F));
+ r->d[3] = t & 0xFFFFFFFFULL; t >>= 32;
+ t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F));
+ r->d[4] = t & 0xFFFFFFFFULL; t >>= 32;
+ t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F));
+ r->d[5] = t & 0xFFFFFFFFULL; t >>= 32;
+ t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F));
+ r->d[6] = t & 0xFFFFFFFFULL; t >>= 32;
+ t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F));
+ r->d[7] = t & 0xFFFFFFFFULL;
+#ifdef VERIFY
+ VERIFY_CHECK((t >> 32) == 0);
+ VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
+#endif
}
static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) {
@@ -405,12 +454,10 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint32_t *l
secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r));
}
-static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+static void secp256k1_scalar_mul_512(uint32_t l[16], const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
/* 96 bit accumulator. */
uint32_t c0 = 0, c1 = 0, c2 = 0;
- uint32_t l[16];
-
/* l[0..15] = a[0..7] * b[0..7]. */
muladd_fast(a->d[0], b->d[0]);
extract_fast(l[0]);
@@ -493,16 +540,12 @@ static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t
extract_fast(l[14]);
VERIFY_CHECK(c1 == 0);
l[15] = c0;
-
- secp256k1_scalar_reduce_512(r, l);
}
-static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) {
+static void secp256k1_scalar_sqr_512(uint32_t l[16], const secp256k1_scalar_t *a) {
/* 96 bit accumulator. */
uint32_t c0 = 0, c1 = 0, c2 = 0;
- uint32_t l[16];
-
/* l[0..15] = a[0..7]^2. */
muladd_fast(a->d[0], a->d[0]);
extract_fast(l[0]);
@@ -557,8 +600,6 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t
extract_fast(l[14]);
VERIFY_CHECK(c1 == 0);
l[15] = c0;
-
- secp256k1_scalar_reduce_512(r, l);
}
#undef sumadd
@@ -569,4 +610,59 @@ static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t
#undef extract
#undef extract_fast
+static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+ uint32_t l[16];
+ secp256k1_scalar_mul_512(l, a, b);
+ secp256k1_scalar_reduce_512(r, l);
+}
+
+static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) {
+ uint32_t l[16];
+ secp256k1_scalar_sqr_512(l, a);
+ secp256k1_scalar_reduce_512(r, l);
+}
+
+static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
+ r1->d[0] = a->d[0];
+ r1->d[1] = a->d[1];
+ r1->d[2] = a->d[2];
+ r1->d[3] = a->d[3];
+ r1->d[4] = 0;
+ r1->d[5] = 0;
+ r1->d[6] = 0;
+ r1->d[7] = 0;
+ r2->d[0] = a->d[4];
+ r2->d[1] = a->d[5];
+ r2->d[2] = a->d[6];
+ r2->d[3] = a->d[7];
+ r2->d[4] = 0;
+ r2->d[5] = 0;
+ r2->d[6] = 0;
+ r2->d[7] = 0;
+}
+
+SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
+ return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0;
+}
+
+SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b, unsigned int shift) {
+ VERIFY_CHECK(shift >= 256);
+ uint32_t l[16];
+ secp256k1_scalar_mul_512(l, a, b);
+ unsigned int shiftlimbs = shift >> 5;
+ unsigned int shiftlow = shift & 0x1F;
+ unsigned int shifthigh = 32 - shiftlow;
+ r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 480 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[1] = shift < 480 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[2] = shift < 448 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 416 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[3] = shift < 416 ? (l[3 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[4 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[4] = shift < 384 ? (l[4 + shiftlimbs] >> shiftlow | (shift < 352 && shiftlow ? (l[5 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0;
+ r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0;
+ if ((l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1) {
+ secp256k1_scalar_add_bit(r, 0);
+ }
+}
+
#endif
diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h
index ddc5061c76..7fc159df77 100644
--- a/src/secp256k1/src/scalar_impl.h
+++ b/src/secp256k1/src/scalar_impl.h
@@ -9,6 +9,7 @@
#include <string.h>
+#include "group.h"
#include "scalar.h"
#if defined HAVE_CONFIG_H
@@ -23,12 +24,132 @@
#error "Please select scalar implementation"
#endif
+typedef struct {
+#ifndef USE_NUM_NONE
+ secp256k1_num_t order;
+#endif
+#ifdef USE_ENDOMORPHISM
+ secp256k1_scalar_t minus_lambda, minus_b1, minus_b2, g1, g2;
+#endif
+} secp256k1_scalar_consts_t;
+
+static const secp256k1_scalar_consts_t *secp256k1_scalar_consts = NULL;
+
+static void secp256k1_scalar_start(void) {
+ if (secp256k1_scalar_consts != NULL)
+ return;
+
+ /* Allocate. */
+ secp256k1_scalar_consts_t *ret = (secp256k1_scalar_consts_t*)malloc(sizeof(secp256k1_scalar_consts_t));
+
+#ifndef USE_NUM_NONE
+ static const unsigned char secp256k1_scalar_consts_order[] = {
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+ 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
+ 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41
+ };
+ secp256k1_num_set_bin(&ret->order, secp256k1_scalar_consts_order, sizeof(secp256k1_scalar_consts_order));
+#endif
+#ifdef USE_ENDOMORPHISM
+ /**
+ * Lambda is a scalar which has the property for secp256k1 that point multiplication by
+ * it is efficiently computable (see secp256k1_gej_mul_lambda). */
+ static const unsigned char secp256k1_scalar_consts_lambda[32] = {
+ 0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,
+ 0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
+ 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,
+ 0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72
+ };
+ /**
+ * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm
+ * (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1
+ * and k2 have a small size.
+ * It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are:
+ *
+ * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
+ * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3}
+ * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8}
+ * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
+ *
+ * The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives
+ * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and
+ * compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2.
+ *
+ * g1, g2 are precomputed constants used to replace division with a rounded multiplication
+ * when decomposing the scalar for an endomorphism-based point multiplication.
+ *
+ * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve
+ * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5.
+ *
+ * The derivation is described in the paper "Efficient Software Implementation of Public-Key
+ * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez),
+ * Section 4.3 (here we use a somewhat higher-precision estimate):
+ * d = a1*b2 - b1*a2
+ * g1 = round((2^272)*b2/d)
+ * g2 = round((2^272)*b1/d)
+ *
+ * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found
+ * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda').
+ */
+ static const unsigned char secp256k1_scalar_consts_minus_b1[32] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,
+ 0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3
+ };
+ static const unsigned char secp256k1_scalar_consts_b2[32] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,
+ 0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15
+ };
+ static const unsigned char secp256k1_scalar_consts_g1[32] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x86,
+ 0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,
+ 0x90,0xe4,0x92,0x84,0xeb,0x15,0x3d,0xab
+ };
+ static const unsigned char secp256k1_scalar_consts_g2[32] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x43,
+ 0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,
+ 0x7f,0xa9,0x0a,0xbf,0xe4,0xc4,0x22,0x12
+ };
+
+ secp256k1_scalar_set_b32(&ret->minus_lambda, secp256k1_scalar_consts_lambda, NULL);
+ secp256k1_scalar_negate(&ret->minus_lambda, &ret->minus_lambda);
+ secp256k1_scalar_set_b32(&ret->minus_b1, secp256k1_scalar_consts_minus_b1, NULL);
+ secp256k1_scalar_set_b32(&ret->minus_b2, secp256k1_scalar_consts_b2, NULL);
+ secp256k1_scalar_negate(&ret->minus_b2, &ret->minus_b2);
+ secp256k1_scalar_set_b32(&ret->g1, secp256k1_scalar_consts_g1, NULL);
+ secp256k1_scalar_set_b32(&ret->g2, secp256k1_scalar_consts_g2, NULL);
+#endif
+
+ /* Set the global pointer. */
+ secp256k1_scalar_consts = ret;
+}
+
+static void secp256k1_scalar_stop(void) {
+ if (secp256k1_scalar_consts == NULL)
+ return;
+
+ secp256k1_scalar_consts_t *c = (secp256k1_scalar_consts_t*)secp256k1_scalar_consts;
+ secp256k1_scalar_consts = NULL;
+ free(c);
+}
+
+#ifndef USE_NUM_NONE
static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a) {
unsigned char c[32];
secp256k1_scalar_get_b32(c, a);
secp256k1_num_set_bin(r, c, 32);
}
+static void secp256k1_scalar_order_get_num(secp256k1_num_t *r) {
+ *r = secp256k1_scalar_consts->order;
+}
+#endif
static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *x) {
/* First compute x ^ (2^N - 1) for some values of N. */
@@ -181,4 +302,35 @@ static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scal
secp256k1_scalar_mul(r, t, &x6); /* 111111 */
}
+static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *x) {
+#if defined(USE_SCALAR_INV_BUILTIN)
+ secp256k1_scalar_inverse(r, x);
+#elif defined(USE_SCALAR_INV_NUM)
+ unsigned char b[32];
+ secp256k1_scalar_get_b32(b, x);
+ secp256k1_num_t n;
+ secp256k1_num_set_bin(&n, b, 32);
+ secp256k1_num_mod_inverse(&n, &n, &secp256k1_scalar_consts->order);
+ secp256k1_num_get_bin(b, 32, &n);
+ secp256k1_scalar_set_b32(r, b, NULL);
+#else
+#error "Please select scalar inverse implementation"
+#endif
+}
+
+#ifdef USE_ENDOMORPHISM
+static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a) {
+ VERIFY_CHECK(r1 != a);
+ VERIFY_CHECK(r2 != a);
+ secp256k1_scalar_t c1, c2;
+ secp256k1_scalar_mul_shift_var(&c1, a, &secp256k1_scalar_consts->g1, 272);
+ secp256k1_scalar_mul_shift_var(&c2, a, &secp256k1_scalar_consts->g2, 272);
+ secp256k1_scalar_mul(&c1, &c1, &secp256k1_scalar_consts->minus_b1);
+ secp256k1_scalar_mul(&c2, &c2, &secp256k1_scalar_consts->minus_b2);
+ secp256k1_scalar_add(r2, &c1, &c2);
+ secp256k1_scalar_mul(r1, r2, &secp256k1_scalar_consts->minus_lambda);
+ secp256k1_scalar_add(r1, r1, a);
+}
+#endif
+
#endif
diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c
index 1ab5b3722c..20fc27df74 100644
--- a/src/secp256k1/src/secp256k1.c
+++ b/src/secp256k1/src/secp256k1.c
@@ -21,6 +21,8 @@
void secp256k1_start(unsigned int flags) {
secp256k1_fe_start();
secp256k1_ge_start();
+ secp256k1_scalar_start();
+ secp256k1_ecdsa_start();
if (flags & SECP256K1_START_SIGN) {
secp256k1_ecmult_gen_start();
}
@@ -32,6 +34,8 @@ void secp256k1_start(unsigned int flags) {
void secp256k1_stop(void) {
secp256k1_ecmult_stop();
secp256k1_ecmult_gen_stop();
+ secp256k1_ecdsa_stop();
+ secp256k1_scalar_stop();
secp256k1_ge_stop();
secp256k1_fe_stop();
}
@@ -43,11 +47,13 @@ int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned
DEBUG_CHECK(sig != NULL);
DEBUG_CHECK(pubkey != NULL);
+ unsigned char msg32[32] = {0};
+ memcpy(msg32 + 32 - msglen, msg, msglen);
int ret = -3;
- secp256k1_num_t m;
+ secp256k1_scalar_t m;
secp256k1_ecdsa_sig_t s;
secp256k1_ge_t q;
- secp256k1_num_set_bin(&m, msg, msglen);
+ secp256k1_scalar_set_b32(&m, msg32, NULL);
if (!secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) {
ret = -1;
@@ -123,8 +129,8 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u
ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid);
}
if (ret) {
- secp256k1_num_get_bin(sig64, 32, &sig.r);
- secp256k1_num_get_bin(sig64 + 32, 32, &sig.s);
+ secp256k1_scalar_get_b32(sig64, &sig.r);
+ secp256k1_scalar_get_b32(sig64 + 32, &sig.s);
}
secp256k1_scalar_clear(&msg);
secp256k1_scalar_clear(&non);
@@ -142,11 +148,20 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const
DEBUG_CHECK(recid >= 0 && recid <= 3);
int ret = 0;
- secp256k1_num_t m;
+ unsigned char msg32[32] = {0};
+ memcpy(msg32 + 32 - msglen, msg, msglen);
+ secp256k1_scalar_t m;
secp256k1_ecdsa_sig_t sig;
- secp256k1_num_set_bin(&sig.r, sig64, 32);
- secp256k1_num_set_bin(&sig.s, sig64 + 32, 32);
- secp256k1_num_set_bin(&m, msg, msglen);
+ int overflow = 0;
+ secp256k1_scalar_set_b32(&sig.r, sig64, &overflow);
+ if (overflow) {
+ return 0;
+ }
+ secp256k1_scalar_set_b32(&sig.s, sig64 + 32, &overflow);
+ if (overflow) {
+ return 0;
+ }
+ secp256k1_scalar_set_b32(&m, msg32, NULL);
secp256k1_ge_t q;
if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) {
@@ -224,8 +239,12 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);
- secp256k1_num_t term;
- secp256k1_num_set_bin(&term, tweak, 32);
+ secp256k1_scalar_t term;
+ int overflow = 0;
+ secp256k1_scalar_set_b32(&term, tweak, &overflow);
+ if (overflow) {
+ return 0;
+ }
secp256k1_ge_t p;
int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
if (ret) {
@@ -264,8 +283,12 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);
- secp256k1_num_t factor;
- secp256k1_num_set_bin(&factor, tweak, 32);
+ secp256k1_scalar_t factor;
+ int overflow = 0;
+ secp256k1_scalar_set_b32(&factor, tweak, &overflow);
+ if (overflow) {
+ return 0;
+ }
secp256k1_ge_t p;
int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
if (ret) {
diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c
index 5d9b8344d9..78cdd67f27 100644
--- a/src/secp256k1/src/tests.c
+++ b/src/secp256k1/src/tests.c
@@ -23,23 +23,13 @@
static int count = 64;
-/***** NUM TESTS *****/
-
-void random_num_negate(secp256k1_num_t *num) {
- if (secp256k1_rand32() & 1)
- secp256k1_num_negate(num);
-}
-
void random_field_element_test(secp256k1_fe_t *fe) {
do {
unsigned char b32[32];
secp256k1_rand256_test(b32);
- secp256k1_num_t num;
- secp256k1_num_set_bin(&num, b32, 32);
- if (secp256k1_num_cmp(&num, &secp256k1_fe_consts->p) >= 0)
- continue;
- secp256k1_fe_set_b32(fe, b32);
- break;
+ if (secp256k1_fe_set_b32(fe, b32)) {
+ break;
+ }
} while(1);
}
@@ -75,19 +65,6 @@ void random_group_element_jacobian_test(secp256k1_gej_t *gej, const secp256k1_ge
gej->infinity = ge->infinity;
}
-void random_num_order_test(secp256k1_num_t *num) {
- do {
- unsigned char b32[32];
- secp256k1_rand256_test(b32);
- secp256k1_num_set_bin(num, b32, 32);
- if (secp256k1_num_is_zero(num))
- continue;
- if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0)
- continue;
- break;
- } while(1);
-}
-
void random_scalar_order_test(secp256k1_scalar_t *num) {
do {
unsigned char b32[32];
@@ -100,82 +77,36 @@ void random_scalar_order_test(secp256k1_scalar_t *num) {
} while(1);
}
-void random_num_order(secp256k1_num_t *num) {
+void random_scalar_order(secp256k1_scalar_t *num) {
do {
unsigned char b32[32];
secp256k1_rand256(b32);
- secp256k1_num_set_bin(num, b32, 32);
- if (secp256k1_num_is_zero(num))
- continue;
- if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0)
+ int overflow = 0;
+ secp256k1_scalar_set_b32(num, b32, &overflow);
+ if (overflow || secp256k1_scalar_is_zero(num))
continue;
break;
} while(1);
}
-void test_num_copy_inc_cmp(void) {
- secp256k1_num_t n1,n2;
- random_num_order(&n1);
- secp256k1_num_copy(&n2, &n1);
- CHECK(secp256k1_num_eq(&n1, &n2));
- CHECK(secp256k1_num_eq(&n2, &n1));
- secp256k1_num_inc(&n2);
- CHECK(!secp256k1_num_eq(&n1, &n2));
- CHECK(!secp256k1_num_eq(&n2, &n1));
-}
-
+/***** NUM TESTS *****/
-void test_num_get_set_hex(void) {
- secp256k1_num_t n1,n2;
- random_num_order_test(&n1);
- char c[64];
- secp256k1_num_get_hex(c, 64, &n1);
- secp256k1_num_set_hex(&n2, c, 64);
- CHECK(secp256k1_num_eq(&n1, &n2));
- for (int i=0; i<64; i++) {
- /* check whether the lower 4 bits correspond to the last hex character */
- int low1 = secp256k1_num_shift(&n1, 4);
- int lowh = c[63];
- int low2 = ((lowh>>6)*9+(lowh-'0'))&15;
- CHECK(low1 == low2);
- /* shift bits off the hex representation, and compare */
- memmove(c+1, c, 63);
- c[0] = '0';
- secp256k1_num_set_hex(&n2, c, 64);
- CHECK(secp256k1_num_eq(&n1, &n2));
- }
+#ifndef USE_NUM_NONE
+void random_num_negate(secp256k1_num_t *num) {
+ if (secp256k1_rand32() & 1)
+ secp256k1_num_negate(num);
}
-void test_num_get_set_bin(void) {
- secp256k1_num_t n1,n2;
- random_num_order_test(&n1);
- unsigned char c[32];
- secp256k1_num_get_bin(c, 32, &n1);
- secp256k1_num_set_bin(&n2, c, 32);
- CHECK(secp256k1_num_eq(&n1, &n2));
- for (int i=0; i<32; i++) {
- /* check whether the lower 8 bits correspond to the last byte */
- int low1 = secp256k1_num_shift(&n1, 8);
- int low2 = c[31];
- CHECK(low1 == low2);
- /* shift bits off the byte representation, and compare */
- memmove(c+1, c, 31);
- c[0] = 0;
- secp256k1_num_set_bin(&n2, c, 32);
- CHECK(secp256k1_num_eq(&n1, &n2));
- }
+void random_num_order_test(secp256k1_num_t *num) {
+ secp256k1_scalar_t sc;
+ random_scalar_order_test(&sc);
+ secp256k1_scalar_get_num(num, &sc);
}
-void run_num_int(void) {
- secp256k1_num_t n1;
- for (int i=-255; i<256; i++) {
- unsigned char c1[3] = {};
- c1[2] = abs(i);
- unsigned char c2[3] = {0x11,0x22,0x33};
- secp256k1_num_set_int(&n1, i);
- secp256k1_num_get_bin(c2, 3, &n1);
- CHECK(memcmp(c1, c2, 3) == 0);
- }
+void random_num_order(secp256k1_num_t *num) {
+ secp256k1_scalar_t sc;
+ random_scalar_order(&sc);
+ secp256k1_scalar_get_num(num, &sc);
}
void test_num_negate(void) {
@@ -229,82 +160,84 @@ void test_num_add_sub(void) {
void run_num_smalltests(void) {
for (int i=0; i<100*count; i++) {
- test_num_copy_inc_cmp();
- test_num_get_set_hex();
- test_num_get_set_bin();
test_num_negate();
test_num_add_sub();
}
- run_num_int();
}
+#endif
/***** SCALAR TESTS *****/
-int secp256k1_scalar_eq(const secp256k1_scalar_t *s1, const secp256k1_scalar_t *s2) {
- secp256k1_scalar_t t;
- secp256k1_scalar_negate(&t, s2);
- secp256k1_scalar_add(&t, &t, s1);
- int ret = secp256k1_scalar_is_zero(&t);
- return ret;
-}
-
void scalar_test(void) {
unsigned char c[32];
/* Set 's' to a random scalar, with value 'snum'. */
- secp256k1_rand256_test(c);
secp256k1_scalar_t s;
- secp256k1_scalar_set_b32(&s, c, NULL);
- secp256k1_num_t snum;
- secp256k1_num_set_bin(&snum, c, 32);
- secp256k1_num_mod(&snum, &secp256k1_ge_consts->order);
+ random_scalar_order_test(&s);
/* Set 's1' to a random scalar, with value 's1num'. */
- secp256k1_rand256_test(c);
secp256k1_scalar_t s1;
- secp256k1_scalar_set_b32(&s1, c, NULL);
- secp256k1_num_t s1num;
- secp256k1_num_set_bin(&s1num, c, 32);
- secp256k1_num_mod(&s1num, &secp256k1_ge_consts->order);
+ random_scalar_order_test(&s1);
/* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */
- secp256k1_rand256_test(c);
secp256k1_scalar_t s2;
- int overflow = 0;
- secp256k1_scalar_set_b32(&s2, c, &overflow);
- secp256k1_num_t s2num;
- secp256k1_num_set_bin(&s2num, c, 32);
- secp256k1_num_mod(&s2num, &secp256k1_ge_consts->order);
+ random_scalar_order_test(&s2);
+ secp256k1_scalar_get_b32(c, &s2);
+
+#ifndef USE_NUM_NONE
+ secp256k1_num_t snum, s1num, s2num;
+ secp256k1_scalar_get_num(&snum, &s);
+ secp256k1_scalar_get_num(&s1num, &s1);
+ secp256k1_scalar_get_num(&s2num, &s2);
+
+ secp256k1_num_t order;
+ secp256k1_scalar_order_get_num(&order);
+ secp256k1_num_t half_order = order;
+ secp256k1_num_shift(&half_order, 1);
+#endif
{
/* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */
- secp256k1_num_t n, t, m;
- secp256k1_num_set_int(&n, 0);
- secp256k1_num_set_int(&m, 16);
+ secp256k1_scalar_t n;
+ secp256k1_scalar_set_int(&n, 0);
for (int i = 0; i < 256; i += 4) {
- secp256k1_num_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4));
- secp256k1_num_mul(&n, &n, &m);
- secp256k1_num_add(&n, &n, &t);
+ secp256k1_scalar_t t;
+ secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4));
+ for (int j = 0; j < 4; j++) {
+ secp256k1_scalar_add(&n, &n, &n);
+ }
+ secp256k1_scalar_add(&n, &n, &t);
}
- CHECK(secp256k1_num_eq(&n, &snum));
+ CHECK(secp256k1_scalar_eq(&n, &s));
}
{
- /* Test that get_b32 returns the same as get_bin on the number. */
- unsigned char r1[32];
- secp256k1_scalar_get_b32(r1, &s2);
- unsigned char r2[32];
- secp256k1_num_get_bin(r2, 32, &s2num);
- CHECK(memcmp(r1, r2, 32) == 0);
- /* If no overflow occurred when assigning, it should also be equal to the original byte array. */
- CHECK((memcmp(r1, c, 32) == 0) == (overflow == 0));
+ /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */
+ secp256k1_scalar_t n;
+ secp256k1_scalar_set_int(&n, 0);
+ int i = 0;
+ while (i < 256) {
+ int now = (secp256k1_rand32() % 15) + 1;
+ if (now + i > 256) {
+ now = 256 - i;
+ }
+ secp256k1_scalar_t t;
+ secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now));
+ for (int j = 0; j < now; j++) {
+ secp256k1_scalar_add(&n, &n, &n);
+ }
+ secp256k1_scalar_add(&n, &n, &t);
+ i += now;
+ }
+ CHECK(secp256k1_scalar_eq(&n, &s));
}
+#ifndef USE_NUM_NONE
{
/* Test that adding the scalars together is equal to adding their numbers together modulo the order. */
secp256k1_num_t rnum;
secp256k1_num_add(&rnum, &snum, &s2num);
- secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order);
+ secp256k1_num_mod(&rnum, &order);
secp256k1_scalar_t r;
secp256k1_scalar_add(&r, &s, &s2);
secp256k1_num_t r2num;
@@ -316,7 +249,7 @@ void scalar_test(void) {
/* Test that multipying the scalars is equal to multiplying their numbers modulo the order. */
secp256k1_num_t rnum;
secp256k1_num_mul(&rnum, &snum, &s2num);
- secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order);
+ secp256k1_num_mod(&rnum, &order);
secp256k1_scalar_t r;
secp256k1_scalar_mul(&r, &s, &s2);
secp256k1_num_t r2num;
@@ -333,14 +266,14 @@ void scalar_test(void) {
/* Check that comparison with zero matches comparison with zero on the number. */
CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s));
/* Check that comparison with the half order is equal to testing for high scalar. */
- CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &secp256k1_ge_consts->half_order) > 0));
+ CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &half_order) > 0));
secp256k1_scalar_t neg;
secp256k1_scalar_negate(&neg, &s);
secp256k1_num_t negnum;
- secp256k1_num_sub(&negnum, &secp256k1_ge_consts->order, &snum);
- secp256k1_num_mod(&negnum, &secp256k1_ge_consts->order);
+ secp256k1_num_sub(&negnum, &order, &snum);
+ secp256k1_num_mod(&negnum, &order);
/* Check that comparison with the half order is equal to testing for high scalar after negation. */
- CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &secp256k1_ge_consts->half_order) > 0));
+ CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &half_order) > 0));
/* Negating should change the high property, unless the value was already zero. */
CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s));
secp256k1_num_t negnum2;
@@ -356,15 +289,36 @@ void scalar_test(void) {
}
{
+ /* Test secp256k1_scalar_mul_shift_var. */
+ secp256k1_scalar_t r;
+ unsigned int shift = 256 + (secp256k1_rand32() % 257);
+ secp256k1_scalar_mul_shift_var(&r, &s1, &s2, shift);
+ secp256k1_num_t rnum;
+ secp256k1_num_mul(&rnum, &s1num, &s2num);
+ secp256k1_num_shift(&rnum, shift - 1);
+ secp256k1_num_t one;
+ unsigned char cone[1] = {0x01};
+ secp256k1_num_set_bin(&one, cone, 1);
+ secp256k1_num_add(&rnum, &rnum, &one);
+ secp256k1_num_shift(&rnum, 1);
+ secp256k1_num_t rnum2;
+ secp256k1_scalar_get_num(&rnum2, &r);
+ CHECK(secp256k1_num_eq(&rnum, &rnum2));
+ }
+#endif
+
+ {
/* Test that scalar inverses are equal to the inverse of their number modulo the order. */
if (!secp256k1_scalar_is_zero(&s)) {
secp256k1_scalar_t inv;
secp256k1_scalar_inverse(&inv, &s);
+#ifndef USE_NUM_NONE
secp256k1_num_t invnum;
- secp256k1_num_mod_inverse(&invnum, &snum, &secp256k1_ge_consts->order);
+ secp256k1_num_mod_inverse(&invnum, &snum, &order);
secp256k1_num_t invnum2;
secp256k1_scalar_get_num(&invnum2, &inv);
CHECK(secp256k1_num_eq(&invnum, &invnum2));
+#endif
secp256k1_scalar_mul(&inv, &inv, &s);
/* Multiplying a scalar with its inverse must result in one. */
CHECK(secp256k1_scalar_is_one(&inv));
@@ -383,6 +337,23 @@ void scalar_test(void) {
}
{
+ /* Test add_bit. */
+ int bit = secp256k1_rand32() % 256;
+ secp256k1_scalar_t b;
+ secp256k1_scalar_set_int(&b, 1);
+ CHECK(secp256k1_scalar_is_one(&b));
+ for (int i = 0; i < bit; i++) {
+ secp256k1_scalar_add(&b, &b, &b);
+ }
+ secp256k1_scalar_t r1 = s1, r2 = s1;
+ if (!secp256k1_scalar_add(&r1, &r1, &b)) {
+ /* No overflow happened. */
+ secp256k1_scalar_add_bit(&r2, bit);
+ CHECK(secp256k1_scalar_eq(&r1, &r2));
+ }
+ }
+
+ {
/* Test commutativity of mul. */
secp256k1_scalar_t r1, r2;
secp256k1_scalar_mul(&r1, &s1, &s2);
@@ -428,20 +399,49 @@ void scalar_test(void) {
secp256k1_scalar_mul(&r2, &s1, &s1);
CHECK(secp256k1_scalar_eq(&r1, &r2));
}
+
}
void run_scalar_tests(void) {
for (int i = 0; i < 128 * count; i++) {
scalar_test();
}
+
+ {
+ /* (-1)+1 should be zero. */
+ secp256k1_scalar_t s, o;
+ secp256k1_scalar_set_int(&s, 1);
+ secp256k1_scalar_negate(&o, &s);
+ secp256k1_scalar_add(&o, &o, &s);
+ CHECK(secp256k1_scalar_is_zero(&o));
+ }
+
+#ifndef USE_NUM_NONE
+ {
+ /* A scalar with value of the curve order should be 0. */
+ secp256k1_num_t order;
+ secp256k1_scalar_order_get_num(&order);
+ unsigned char bin[32];
+ secp256k1_num_get_bin(bin, 32, &order);
+ secp256k1_scalar_t zero;
+ int overflow = 0;
+ secp256k1_scalar_set_b32(&zero, bin, &overflow);
+ CHECK(overflow == 1);
+ CHECK(secp256k1_scalar_is_zero(&zero));
+ }
+#endif
}
/***** FIELD TESTS *****/
void random_fe(secp256k1_fe_t *x) {
unsigned char bin[32];
- secp256k1_rand256(bin);
- secp256k1_fe_set_b32(x, bin);
+ do {
+ secp256k1_rand256(bin);
+ if (secp256k1_fe_set_b32(x, bin)) {
+ return;
+ }
+ } while(1);
}
void random_fe_non_zero(secp256k1_fe_t *nz) {
@@ -617,9 +617,17 @@ void gej_equals_gej(const secp256k1_gej_t *a, const secp256k1_gej_t *b) {
}
void test_ge(void) {
+ char ca[135];
+ char cb[68];
+ int rlen;
secp256k1_ge_t a, b, i, n;
random_group_element_test(&a);
random_group_element_test(&b);
+ rlen = sizeof(ca);
+ secp256k1_ge_get_hex(ca,&rlen,&a);
+ CHECK(rlen > 4 && rlen <= (int)sizeof(ca));
+ rlen = sizeof(cb);
+ secp256k1_ge_get_hex(cb,&rlen,&b); /* Intentionally undersized buffer. */
n = a;
secp256k1_fe_normalize(&a.y);
secp256k1_fe_negate(&n.y, &a.y, 1);
@@ -697,39 +705,51 @@ void run_ge(void) {
void run_ecmult_chain(void) {
/* random starting point A (on the curve) */
- secp256k1_fe_t ax; secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64);
- secp256k1_fe_t ay; secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64);
+ secp256k1_fe_t ax; VERIFY_CHECK(secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64));
+ secp256k1_fe_t ay; VERIFY_CHECK(secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64));
secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay);
/* two random initial factors xn and gn */
- secp256k1_num_t xn;
- secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64);
- secp256k1_num_t gn;
- secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64);
+ static const unsigned char xni[32] = {
+ 0x84, 0xcc, 0x54, 0x52, 0xf7, 0xfd, 0xe1, 0xed,
+ 0xb4, 0xd3, 0x8a, 0x8c, 0xe9, 0xb1, 0xb8, 0x4c,
+ 0xce, 0xf3, 0x1f, 0x14, 0x6e, 0x56, 0x9b, 0xe9,
+ 0x70, 0x5d, 0x35, 0x7a, 0x42, 0x98, 0x54, 0x07
+ };
+ secp256k1_scalar_t xn;
+ secp256k1_scalar_set_b32(&xn, xni, NULL);
+ static const unsigned char gni[32] = {
+ 0xa1, 0xe5, 0x8d, 0x22, 0x55, 0x3d, 0xcd, 0x42,
+ 0xb2, 0x39, 0x80, 0x62, 0x5d, 0x4c, 0x57, 0xa9,
+ 0x6e, 0x93, 0x23, 0xd4, 0x2b, 0x31, 0x52, 0xe5,
+ 0xca, 0x2c, 0x39, 0x90, 0xed, 0xc7, 0xc9, 0xde
+ };
+ secp256k1_scalar_t gn;
+ secp256k1_scalar_set_b32(&gn, gni, NULL);
/* two small multipliers to be applied to xn and gn in every iteration: */
- secp256k1_num_t xf;
- secp256k1_num_set_hex(&xf, "1337", 4);
- secp256k1_num_t gf;
- secp256k1_num_set_hex(&gf, "7113", 4);
+ static const unsigned char xfi[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x13,0x37};
+ secp256k1_scalar_t xf;
+ secp256k1_scalar_set_b32(&xf, xfi, NULL);
+ static const unsigned char gfi[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x71,0x13};
+ secp256k1_scalar_t gf;
+ secp256k1_scalar_set_b32(&gf, gfi, NULL);
/* accumulators with the resulting coefficients to A and G */
- secp256k1_num_t ae;
- secp256k1_num_set_int(&ae, 1);
- secp256k1_num_t ge;
- secp256k1_num_set_int(&ge, 0);
+ secp256k1_scalar_t ae;
+ secp256k1_scalar_set_int(&ae, 1);
+ secp256k1_scalar_t ge;
+ secp256k1_scalar_set_int(&ge, 0);
/* the point being computed */
secp256k1_gej_t x = a;
- const secp256k1_num_t *order = &secp256k1_ge_consts->order;
for (int i=0; i<200*count; i++) {
/* in each iteration, compute X = xn*X + gn*G; */
secp256k1_ecmult(&x, &x, &xn, &gn);
/* also compute ae and ge: the actual accumulated factors for A and G */
/* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */
- secp256k1_num_mod_mul(&ae, &ae, &xn, order);
- secp256k1_num_mod_mul(&ge, &ge, &xn, order);
- secp256k1_num_add(&ge, &ge, &gn);
- secp256k1_num_mod(&ge, order);
+ secp256k1_scalar_mul(&ae, &ae, &xn);
+ secp256k1_scalar_mul(&ge, &ge, &xn);
+ secp256k1_scalar_add(&ge, &ge, &gn);
/* modify xn and gn */
- secp256k1_num_mod_mul(&xn, &xn, &xf, order);
- secp256k1_num_mod_mul(&gn, &gn, &gf, order);
+ secp256k1_scalar_mul(&xn, &xn, &xf);
+ secp256k1_scalar_mul(&gn, &gn, &gf);
/* verify */
if (i == 19999) {
@@ -749,17 +769,25 @@ void run_ecmult_chain(void) {
}
void test_point_times_order(const secp256k1_gej_t *point) {
- /* multiplying a point by the order results in O */
- const secp256k1_num_t *order = &secp256k1_ge_consts->order;
- secp256k1_num_t zero;
- secp256k1_num_set_int(&zero, 0);
- secp256k1_gej_t res;
- secp256k1_ecmult(&res, point, order, order); /* calc res = order * point + order * G; */
- CHECK(secp256k1_gej_is_infinity(&res));
+ /* X * (point + G) + (order-X) * (pointer + G) = 0 */
+ secp256k1_scalar_t x;
+ random_scalar_order_test(&x);
+ secp256k1_scalar_t nx;
+ secp256k1_scalar_negate(&nx, &x);
+ secp256k1_gej_t res1, res2;
+ secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */
+ secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
+ secp256k1_gej_add_var(&res1, &res1, &res2);
+ CHECK(secp256k1_gej_is_infinity(&res1));
+ CHECK(secp256k1_gej_is_valid(&res1) == 0);
+ secp256k1_ge_t res3;
+ secp256k1_ge_set_gej(&res3, &res1);
+ CHECK(secp256k1_ge_is_infinity(&res3));
+ CHECK(secp256k1_ge_is_valid(&res3) == 0);
}
void run_point_times_order(void) {
- secp256k1_fe_t x; secp256k1_fe_set_hex(&x, "02", 2);
+ secp256k1_fe_t x; VERIFY_CHECK(secp256k1_fe_set_hex(&x, "02", 2));
for (int i=0; i<500; i++) {
secp256k1_ge_t p;
if (secp256k1_ge_set_xo(&p, &x, 1)) {
@@ -776,15 +804,16 @@ void run_point_times_order(void) {
CHECK(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0);
}
-void test_wnaf(const secp256k1_num_t *number, int w) {
- secp256k1_num_t x, two, t;
- secp256k1_num_set_int(&x, 0);
- secp256k1_num_set_int(&two, 2);
- int wnaf[257];
+void test_wnaf(const secp256k1_scalar_t *number, int w) {
+ secp256k1_scalar_t x, two, t;
+ secp256k1_scalar_set_int(&x, 0);
+ secp256k1_scalar_set_int(&two, 2);
+ int wnaf[256];
int bits = secp256k1_ecmult_wnaf(wnaf, number, w);
+ CHECK(bits <= 256);
int zeroes = -1;
for (int i=bits-1; i>=0; i--) {
- secp256k1_num_mul(&x, &x, &two);
+ secp256k1_scalar_mul(&x, &x, &two);
int v = wnaf[i];
if (v) {
CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */
@@ -796,18 +825,23 @@ void test_wnaf(const secp256k1_num_t *number, int w) {
CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */
zeroes++;
}
- secp256k1_num_set_int(&t, v);
- secp256k1_num_add(&x, &x, &t);
+ if (v >= 0) {
+ secp256k1_scalar_set_int(&t, v);
+ } else {
+ secp256k1_scalar_set_int(&t, -v);
+ secp256k1_scalar_negate(&t, &t);
+ }
+ secp256k1_scalar_add(&x, &x, &t);
}
- CHECK(secp256k1_num_eq(&x, number)); /* check that wnaf represents number */
+ CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */
}
void run_wnaf(void) {
- secp256k1_num_t n;
+ secp256k1_scalar_t n;
for (int i=0; i<count; i++) {
- random_num_order(&n);
+ random_scalar_order(&n);
if (i % 1)
- secp256k1_num_negate(&n);
+ secp256k1_scalar_negate(&n, &n);
test_wnaf(&n, 4+(i%10));
}
}
@@ -820,18 +854,22 @@ void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *key, cons
}
void test_ecdsa_sign_verify(void) {
+ int recid;
+ int getrec;
secp256k1_scalar_t msg, key;
random_scalar_order_test(&msg);
random_scalar_order_test(&key);
secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key);
secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj);
secp256k1_ecdsa_sig_t sig;
- random_sign(&sig, &key, &msg, NULL);
- secp256k1_num_t msg_num;
- secp256k1_scalar_get_num(&msg_num, &msg);
- CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num));
- secp256k1_num_inc(&msg_num);
- CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num));
+ getrec = secp256k1_rand32()&1;
+ random_sign(&sig, &key, &msg, getrec?&recid:NULL);
+ if (getrec) CHECK(recid >= 0 && recid < 4);
+ CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
+ secp256k1_scalar_t one;
+ secp256k1_scalar_set_int(&one, 1);
+ secp256k1_scalar_add(&msg, &msg, &one);
+ CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
}
void run_ecdsa_sign_verify(void) {
@@ -846,11 +884,11 @@ void test_ecdsa_end_to_end(void) {
/* Generate a random key and message. */
{
- secp256k1_num_t msg, key;
- random_num_order_test(&msg);
- random_num_order_test(&key);
- secp256k1_num_get_bin(privkey, 32, &key);
- secp256k1_num_get_bin(message, 32, &msg);
+ secp256k1_scalar_t msg, key;
+ random_scalar_order_test(&msg);
+ random_scalar_order_test(&key);
+ secp256k1_scalar_get_b32(privkey, &key);
+ secp256k1_scalar_get_b32(message, &msg);
}
/* Construct and verify corresponding public key. */
@@ -935,7 +973,8 @@ void run_ecdsa_end_to_end(void) {
}
}
-void test_ecdsa_infinity(void) {
+/* Tests several edge cases. */
+void test_ecdsa_edge_cases(void) {
const unsigned char msg32[32] = {
'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
'a', ' ', 'v', 'e', 'r', 'y', ' ', 's',
@@ -943,8 +982,8 @@ void test_ecdsa_infinity(void) {
's', 's', 'a', 'g', 'e', '.', '.', '.'
};
const unsigned char sig64[64] = {
- // Generated by signing the above message with nonce 'This is the nonce we will use...'
- // and secret key 0 (which is not valid), resulting in recid 0.
+ /* Generated by signing the above message with nonce 'This is the nonce we will use...'
+ * and secret key 0 (which is not valid), resulting in recid 0. */
0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8,
0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96,
0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63,
@@ -960,10 +999,93 @@ void test_ecdsa_infinity(void) {
CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 1));
CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 2));
CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 3));
+
+ /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */
+ const unsigned char sigb64[64] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ };
+ unsigned char pubkeyb[33];
+ int pubkeyblen = 33;
+ for (int recid = 0; recid < 4; recid++) {
+ /* (4,4) encoded in DER. */
+ unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04};
+ /* (order + r,4) encoded in DER. */
+ unsigned char sigbderlong[40] = {
+ 0x30, 0x26, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC,
+ 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E,
+ 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04
+ };
+ CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigb64, pubkeyb, &pubkeyblen, 1, recid));
+ CHECK(secp256k1_ecdsa_verify(msg32, 32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 1);
+ for (int recid2 = 0; recid2 < 4; recid2++) {
+ unsigned char pubkey2b[33];
+ int pubkey2blen = 33;
+ CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigb64, pubkey2b, &pubkey2blen, 1, recid2));
+ /* Verifying with (order + r,4) should always fail. */
+ CHECK(secp256k1_ecdsa_verify(msg32, 32, sigbderlong, sizeof(sigbderlong), pubkey2b, pubkey2blen) != 1);
+ }
+ /* Damage signature. */
+ sigbder[7]++;
+ CHECK(secp256k1_ecdsa_verify(msg32, 32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 0);
+ }
+
+ /* Test the case where ECDSA recomputes a point that is infinity. */
+ {
+ secp256k1_ecdsa_sig_t sig;
+ secp256k1_scalar_set_int(&sig.s, 1);
+ secp256k1_scalar_negate(&sig.s, &sig.s);
+ secp256k1_scalar_inverse(&sig.s, &sig.s);
+ secp256k1_scalar_set_int(&sig.r, 1);
+ secp256k1_gej_t keyj;
+ secp256k1_ecmult_gen(&keyj, &sig.r);
+ secp256k1_ge_t key;
+ secp256k1_ge_set_gej(&key, &keyj);
+ secp256k1_scalar_t msg = sig.s;
+ CHECK(secp256k1_ecdsa_sig_verify(&sig, &key, &msg) == 0);
+ }
+
+ /* Test r/s equal to zero */
+ {
+ /* (1,1) encoded in DER. */
+ unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01};
+ unsigned char sigc64[64] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ };
+ unsigned char pubkeyc[65];
+ int pubkeyclen = 65;
+ CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigc64, pubkeyc, &pubkeyclen, 0, 0) == 1);
+ CHECK(secp256k1_ecdsa_verify(msg32, 32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 1);
+ sigcder[4] = 0;
+ sigc64[31] = 0;
+ CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigc64, pubkeyb, &pubkeyblen, 1, 0) == 0);
+ CHECK(secp256k1_ecdsa_verify(msg32, 32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 0);
+ sigcder[4] = 1;
+ sigcder[7] = 0;
+ sigc64[31] = 1;
+ sigc64[63] = 0;
+ CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigc64, pubkeyb, &pubkeyblen, 1, 0) == 0);
+ CHECK(secp256k1_ecdsa_verify(msg32, 32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 0);
+ }
}
-void run_ecdsa_infinity(void) {
- test_ecdsa_infinity();
+void run_ecdsa_edge_cases(void) {
+ test_ecdsa_edge_cases();
}
#ifdef ENABLE_OPENSSL_TESTS
@@ -996,11 +1118,12 @@ void test_ecdsa_openssl(void) {
CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
secp256k1_ecdsa_sig_t sig;
CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize));
- secp256k1_num_t msg_num;
- secp256k1_scalar_get_num(&msg_num, &msg);
- CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num));
- secp256k1_num_inc(&sig.r);
- CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num));
+ CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
+ secp256k1_scalar_t one;
+ secp256k1_scalar_set_int(&one, 1);
+ secp256k1_scalar_t msg2;
+ secp256k1_scalar_add(&msg2, &msg, &one);
+ CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg2));
random_sign(&sig, &key, &msg, NULL);
int secp_sigsize = 80;
@@ -1042,8 +1165,19 @@ int main(int argc, char **argv) {
/* initialize */
secp256k1_start(SECP256K1_START_SIGN | SECP256K1_START_VERIFY);
+ /* initializing a second time shouldn't cause any harm or memory leaks. */
+ secp256k1_start(SECP256K1_START_SIGN | SECP256K1_START_VERIFY);
+
+ /* Likewise, re-running the internal init functions should be harmless. */
+ secp256k1_fe_start();
+ secp256k1_ge_start();
+ secp256k1_scalar_start();
+ secp256k1_ecdsa_start();
+
+#ifndef USE_NUM_NONE
/* num tests */
run_num_smalltests();
+#endif
/* scalar tests */
run_scalar_tests();
@@ -1067,7 +1201,7 @@ int main(int argc, char **argv) {
/* ecdsa tests */
run_ecdsa_sign_verify();
run_ecdsa_end_to_end();
- run_ecdsa_infinity();
+ run_ecdsa_edge_cases();
#ifdef ENABLE_OPENSSL_TESTS
run_ecdsa_openssl();
#endif
@@ -1076,5 +1210,14 @@ int main(int argc, char **argv) {
/* shutdown */
secp256k1_stop();
+
+ /* shutting down twice shouldn't cause any double frees. */
+ secp256k1_stop();
+
+ /* Same for the internal shutdown functions. */
+ secp256k1_fe_stop();
+ secp256k1_ge_stop();
+ secp256k1_scalar_stop();
+ secp256k1_ecdsa_stop();
return 0;
}
diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h
index 96b47057c0..08b23a9d38 100644
--- a/src/secp256k1/src/util.h
+++ b/src/secp256k1/src/util.h
@@ -61,4 +61,21 @@
#define VERIFY_CHECK(cond) do { (void)(cond); } while(0)
#endif
+/* Macro for restrict, when available and not in a VERIFY build. */
+#if defined(SECP256K1_BUILD) && defined(VERIFY)
+# define SECP256K1_RESTRICT
+#else
+# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+# if SECP256K1_GNUC_PREREQ(3,0)
+# define SECP256K1_RESTRICT __restrict__
+# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
+# define SECP256K1_RESTRICT __restrict
+# else
+# define SECP256K1_RESTRICT
+# endif
+# else
+# define SECP256K1_RESTRICT restrict
+# endif
+#endif
+
#endif
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 68232a2ff1..26708f5071 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -2,14 +2,19 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "crypto/rfc6979_hmac_sha256.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
-#include "crypto/sha2.h"
+#include "crypto/sha256.h"
+#include "crypto/sha512.h"
+#include "crypto/hmac_sha256.h"
+#include "crypto/hmac_sha512.h"
#include "random.h"
#include "utilstrencodings.h"
#include <vector>
+#include <boost/assign/list_of.hpp>
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(crypto_tests)
@@ -48,6 +53,11 @@ void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(C
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 TestHMACSHA256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ TestVector(CHMAC_SHA256(&key[0], key.size()), ParseHex(hexin), 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));
@@ -158,6 +168,43 @@ BOOST_AUTO_TEST_CASE(sha512_testvectors) {
"37de8c3ef5459d76a52cedc02dc499a3c9ed9dedbfb3281afd9653b8a112fafc");
}
+BOOST_AUTO_TEST_CASE(hmac_sha256_testvectors) {
+ // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231
+ TestHMACSHA256("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
+ TestHMACSHA256("4a656665",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
+ TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddddddd",
+ "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe");
+ TestHMACSHA256("0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b");
+ TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579204669727374",
+ "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54");
+ TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "5468697320697320612074657374207573696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565"
+ "647320746f20626520686173686564206265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c676f726974686d2e",
+ "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2");
+}
+
BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
// test cases 1, 2, 3, 4, 6 and 7 of RFC 4231
TestHMACSHA512("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
@@ -201,4 +248,38 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
"b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58");
}
+void TestRFC6979(const std::string& hexkey, const std::string& hexmsg, const std::vector<std::string>& hexout)
+{
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ std::vector<unsigned char> msg = ParseHex(hexmsg);
+ RFC6979_HMAC_SHA256 rng(&key[0], key.size(), &msg[0], msg.size());
+
+ for (unsigned int i = 0; i < hexout.size(); i++) {
+ std::vector<unsigned char> out = ParseHex(hexout[i]);
+ std::vector<unsigned char> gen;
+ gen.resize(out.size());
+ rng.Generate(&gen[0], gen.size());
+ BOOST_CHECK(out == gen);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(rfc6979_hmac_sha256)
+{
+ TestRFC6979(
+ "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f00",
+ "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a",
+ boost::assign::list_of
+ ("4fe29525b2086809159acdf0506efb86b0ec932c7ba44256ab321e421e67e9fb")
+ ("2bf0fff1d3c378a22dc5de1d856522325c65b504491a0cbd01cb8f3aa67ffd4a")
+ ("f528b410cb541f77000d7afb6c5b53c5c471eab43e466d9ac5190c39c82fd82e"));
+
+ TestRFC6979(
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ boost::assign::list_of
+ ("9c236c165b82ae0cd590659e100b6bab3036e7ba8b06749baf6981e16f1a2b95")
+ ("df471061625bc0ea14b682feee2c9c02f235da04204c1d62a1536c6e17aed7a9")
+ ("7597887cbd76321f32e30440679a22cf7f8d9d2eac390e581fea091ce202ba94"));
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json
index 71e757714c..c454b52976 100644
--- a/src/test/data/script_invalid.json
+++ b/src/test/data/script_invalid.json
@@ -496,177 +496,177 @@ nSequences are max.
["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA"],
+["
+Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of
+pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded
+signatures and pubkeys.
+"],
+[
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT",
+ "STRICTENC",
+ "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded."
+],
[
- "0x47 0x30440220304eff7556bba9560df47873275e64db45f3cd735998ce3f00d2e57b1bb5f31302205c0c9d14b8b80d43e2ac9b87532f1af6d8a3271262bc694ec4e14068392bb0a001",
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0",
+ "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
+ "STRICTENC",
+ "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid."
+],
+
+["Automatically generated test cases"],
+[
+ "0x47 0x3044022053205076a7bb12d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801",
"0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"",
"P2PK, bad sig"
],
[
- "0x47 0x3044022037fcdb8e08f41e27588de8bc036d2c4b16eb3d09c1ba53b8f47a0a9c27722a39022058664b7a53b507e71dfafb77193e3786c3f0c119d78ce9104480ee7ece04f09301 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
+ "0x47 0x30440220151ea78fa148b59f399b23731b634645ebc142f299ee9838d46fb78cf7e0bc0102200d62327dcd54ac6bcfb1516b035b1bf8eaea438c52c62d3450d1f3a8f030e0de01 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
"DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG",
"",
"P2PKH, bad pubkey"
],
[
- "0x47 0x3044022035e5b6742d299861c84cebaf2ea64145ee427a95facab39e2594d6deebb0c1d602200acb16778faa2e467a59006f342f2535b1418d55ba63a8605b387b7f9ac86d9a01",
+ "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"",
"P2PK anyonecanpay marked with normal hashtype"
],
[
- "0x47 0x3044022029b2b8765ca950cf75a69e80b73b7ddfcaa8b27080c2db4c23b36aae60688e790220598ff368e17872ee065aa54d7d3a590682ca5204325b23b31d7da3c4a21ae67901 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ "0x47 0x304402202166fcd5e607de452d3c6f15e059505cf21654346592f9650ba906b9e8be88fa022005d976d28eb8de477102feba28807b3ad361e7fa24796d259c9d61452f7c318c01 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
"HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
"P2SH",
"P2SH(P2PK), bad redeemscript"
],
[
- "0x47 0x30440220647f906e63890df5ef1d3fed47ba892b31976c634281079e2bd38504fb54a1fb022021e8811f38fbe90efb6b74cb78da01d9badbac3bafdf70a861d7538a220d0b2601 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+ "0x47 0x3044022064cc90ca89ad721384b231653b945579359a24b928ef8539b331172628c9cc6102203e238869ab5dac3fc293db53c12e7dd3079e86cfde9024b689efc7227e4d671001 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
"HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
"P2SH",
"P2SH(P2PKH), bad sig"
],
[
- "0 0x47 0x304402203ef170402f8887f2ac183f31b1f503b0bc60bfc968dd469b097ea6124aefac5002200612febadc4e4cacc086982cb85830a17af3680c1b6a3cf77c1708af7621cf1301 0 0x47 0x304402207821838251a24a2234844f68e7169e6d11945cdf052ea12bd3e4e37457aceb4402200b6b46c81361e314c740ae5133c072af5fa5c209d65d2db1679e1716f19a538101",
+ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"",
"3-of-3, 2 sigs"
],
[
- "0 0 0x47 0x304402204661f7795e8db7be3132e8974e9a76d1d24b31f23df94c6fbcea07d1c205789102203f5e45a1c0b085279b58d11b36d5fea5449c3cf16f844ad10124e9b65e8777d201 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
+ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
"HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
"P2SH",
"P2SH(2-of-3), 1 sig"
],
[
- "0x47 0x304402200052bc1600ca45c71f3538720fe62a5e8548dffd137af04467598c98466e9c0a0220789318ddbc9991ee477974089220a2feb6a6298a7c93d5ff6c25a92a2f4b48d501",
+ "0x47 0x30440220001d6702bfa4f49c3a2542af9b1c2844a2eaac55f86f310f42d26a5dd17d6a8002202cdadbe608c00b50dd951c6ba0877d5b07a970f3e265c18697bc413a0a86f69901",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "STRICTENC",
+ "DERSIG",
"P2PK with too much R padding"
],
[
- "0x48 0x304502206eb7b92628bfb3c4d2a04b65b986987bcbb1af4fceedb144d5a0437b7ee410590221005f57a52df4aa26366742eed0db182fce51fbcd7159011b0644a7c05943eb228901",
+ "0x48 0x304502207d2b258e959605e2ea50b46fea1325b7391ffb0c14a5b58ef8ad3851da3644380221007e75136df5f2e38216c4338b31c97e8307102edb97d611e06914e1f8fba68ead01",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "STRICTENC",
+ "DERSIG",
"P2PK with too much S padding"
],
[
- "0x47 0x30440220d8ad1efd55a3d2b8896495c38aba72056e1b3ca4a6ca15760e843eb1a9b9907602203eb0e8f3d6bec998262dfd03eaeb0f31c4e5105965436dec77550724b3771f3201",
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "STRICTENC",
+ "DERSIG",
"P2PK with too little R padding"
],
[
- "0x47 0x30440220001d0f82c127470cb38316c96b1719b33382353687a1146a776dee8259606905022062cd1fc8eacef819d68f0f41cc9ae9fdc2e29b70c3c7ad2c6c18f39b4e35c42701",
+ "0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
"P2PK NOT with bad sig with too much R padding"
],
[
- "0x47 0x30440220005d727e2a82d6e8a98a6da6fbc281325644d1a40455e386fdb17883a8e6bc4d02202d15cca42ce136047a980d288e60c679d7e84cce18c3ceffb6bc81b9e9ba517801",
+ "0x47 0x30440220003040725f724a0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"",
"P2PK NOT with too much R padding but no DERSIG"
],
[
- "0x47 0x30440220006e8bc4f82032b12bd594847c16d8b2986de734aa3b0528bd89d664d41e6d1c02200cfd582694891bcfa2e630e899bda257486eba00a007222fae71144dba07dc2901",
+ "0x47 0x30440220003040725f724a0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
"P2PK NOT with too much R padding"
],
[
- "0x48 0x304502206c43e065c8a8db3bbe69015afb86a51fb2fc8870defd41d436da2a197d9d6c12022100fcec35816ee2d84ec271ad159fcabf5dd712157051169e48ac328a7818cdb51e01",
+ "0x49 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef05101",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
- "LOW_S,STRICTENC",
+ "LOW_S",
"P2PK with high S"
],
[
- "0x47 0x304402203aab50cd7c30cc1e1475dee615b295bcee6ccf8aa8a7f6cda6b696c70d79cbb40220558e43fe7596c31146e2d077698d5a9c38351d8ba567549a2ae43ca97231c39501",
+ "0x47 0x30440220745d63eb70d45652128b450aa5ca7d9b513439963f261cb1c40a60f0785e7ee402204877785b38945ca9dbec78e1c1d4dd12148cc25c868bd27480023b49ae0f310501",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"STRICTENC",
"P2PK with hybrid pubkey"
],
[
- "0x47 0x304402205745e8f846110c185ee1185c01843a108588b81463d2c34d4a3f2445529f12fe02206ee6a2657bbc4e2bb74bfc44c3a5c4f410ed6356ca68982465de6ca807c807c201",
+ "0x47 0x30440220606f6f9f6cebc94ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"",
"P2PK NOT with hybrid pubkey but no STRICTENC"
],
[
- "0x47 0x3044022078033e4227aa05ded69d8da579966578e230d8a7fb44d5f1a0620c3853c24f78022006a2e3f4d872ac8dfdc529110aa37301d65a76255a4b6cce2992adacd4d2c4e201",
+ "0x47 0x30440220606f6f9f6cebc94ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"STRICTENC",
"P2PK NOT with hybrid pubkey"
],
[
- "0x47 0x304402207592427de20e315d644839754f2a5cca5b978b983a15e6da82109ede01722baa022032ceaf78590faa3f7743821e1b47b897ed1a57f6ee1c8a7519d23774d8de3c4401",
+ "0x47 0x30440220606f6f9f6cebc84ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"STRICTENC",
"P2PK NOT with invalid hybrid pubkey"
],
[
- "0 0x47 0x304402206797289d3dc81692edae58430276d04641ea5d86967be557163f8494da32fd78022006fc6ab77aaed4ac11ea69cd878ab26e3e24290f47a43e9adf34075d52b7142c01",
+ "0 0x47 0x304402203cdcf66792fe97e3955655ede5dad004950e58b369831ffa7743132c507b272c022031fbcfb4a72b3e00217abf2f5557585f1f9891f12827d2f0a2ae2978e7f9f11001",
"1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG",
"STRICTENC",
"1-of-2 with the first 1 hybrid pubkey"
],
[
- "0x47 0x304402201f82b99a813c9c48c8dee8d2c43b8f637b72353fe9bdcc084537bc17e2ab770402200c43b96a5f7e115f0114eabda32e068145965cb6c7b5ef64833bb4fcf9fc1b3b05",
+ "0x47 0x304402201c215cb13e4954e60ce4f6de74941904c771f998de7b1d9627e82a1949fde517022031c2197455f3dbecbb78321201308d7b039424e38d480772d7cd4eb465a083f405",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"STRICTENC",
"P2PK with undefined hashtype"
],
-
-["
-Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of
-pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded
-signatures and pubkeys.
-"],
-[
- "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
- "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT",
- "STRICTENC",
- "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded."
-],
-[
- "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0",
- "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
- "STRICTENC",
- "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid."
-],
-
[
- "0x47 0x30440220166848cd5b82a32b5944d90de3c35249354b43773c2ece1844ee8d1103e2f6c602203b6b046da4243c77adef80ada9201b27bbfdf7f9d5428f40434b060432afd62005",
+ "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
"STRICTENC",
"P2PK NOT with invalid sig and undefined hashtype"
],
[
- "0x01 0x01 0x47 0x304402200e48ba1cf4d7182db94ffb57bd72ea31b5545dc0d1c512e665779b4fb2badc52022054b8388dfc074c708a75b62359b7be46402751ee40c0a111aef38a837b6ed09801 0x47 0x304402201c9820f59c49107bb30e6175cfc9ec95f897b03beb628b4bc854d2b80392aa0602200235d986ae418bcd111b8814f4c26a0ab5f475fb542a44884fc14912a97a252301 0x47 0x304402204cd7894c6f10a871f5b0c1f9c13228f8cdd4050248f0d0f498ee86be69ee3080022051bd2932c7d585eb600c7194235c74da820935f0d67972fd9545673aa1fd023301",
+ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"NULLDUMMY",
"3-of-3 with nonzero dummy"
],
[
- "0x01 0x01 0x47 0x304402201847fc3b8f7597768e7f543c58da1fca6e8e35eb28979431e6b637572ce6eaa4022048dd58608e040841d0bf52a70cfb70e1a9c8d2826fad068f4e9d2bf5c87766a501 0x47 0x30440220711311a72516affed73363763983d05c3d6a06a2eadf5d76b90b4354162ba94302204841a69e5955a7dc8e4ab3105fd0c86040c1dac6016297a51ddbf5079c28756801 0x47 0x30440220267e331a378191e7282fd10d61c97bf74bc97c233c5833d677936424ac08dee502201eee83d88b91988e1c4d9b979df2404aa190e0987a8ca09c4e5cd61da1d48ecc01",
+ "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
"NULLDUMMY",
"3-of-3 NOT with invalid sig with nonzero dummy"
],
[
- "0 0x47 0x3044022035341cc377b19138f944f90c45772cb06338c6d56a4c0c31a65bf1a8a105fadc022046dd232850b6bacb25879c9da82a7a628982aa19d055f1753468f68047662e0301 DUP",
+ "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 DUP",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"SIGPUSHONLY",
"2-of-2 with two identical keys and sigs pushed using OP_DUP"
],
[
- "0x47 0x304402204d8b99eea2f53382fd67e0dbc8ed0596bd614aa0dad6bc6843c7860c79b901c3022062f022a71993013e3d9b22302a8e4b40109d7bb057aeb250b9aab2197b3e96b801 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+ "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
"",
"P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY"
],
[
- "0x47 0x30440220078c887c33abc67fbbd827ceb3f661c1c459e78218161b652f23e3ca76cfabbd022047df245eacb8a88d8c5ca7b5228e3b4d070c102d2f542433362d3f443cd24eda01 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+ "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
"SIGPUSHONLY",
"P2SH(P2PK) with non-push scriptSig"
diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json
index ada45a64ed..af0f6939c6 100644
--- a/src/test/data/script_valid.json
+++ b/src/test/data/script_valid.json
@@ -664,160 +664,158 @@ nSequences are max.
["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", ""],
["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", ""],
+["
+CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and
+pubkeys in a specific order, and will exit early if the number of signatures
+left to check is greater than the number of keys left. As STRICTENC fails the
+script when it reaches an invalidly encoded signature or pubkey, we can use it
+to test the exact order in which signatures and pubkeys are evaluated by
+distinguishing CHECKMULTISIG returning false on the stack and the script as a
+whole failing.
+See also the corresponding inverted versions of these tests in script_invalid.json
+"],
+[
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
+ "STRICTENC",
+ "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey."
+],
+[
+ "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
+ "STRICTENC",
+ "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature."
+],
+["Automatically generated test cases"],
[
- "0x47 0x3044022007415aa37ce7eaa6146001ac8bdefca0ddcba0e37c5dc08c4ac99392124ebac802207d382307fd53f65778b07b9c63b6e196edeadf0be719130c5db21ff1e700d67501",
+ "0x47 0x3044022053205076a7bb13d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801",
"0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"",
"P2PK"
],
[
- "0x47 0x3044022069d40999786aeb2fd874f9eb2636461a062dc963471627ed8390a3a5f9556f640220350132a52415ce622f2aadd07f791c591500917ec1f8c5edbc5381ef7942534d01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508",
+ "0x47 0x304402206e05a6fe23c59196ffe176c9ddc31e73a9885638f9d1328d47c0c703863b8876022076feb53811aa5b04e0e79f938eb19906cc5e67548bc555a8e8b8b0fc603d840c01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508",
"DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG",
"",
"P2PKH"
],
[
- "0x47 0x30440220519f2a6632ffa134c7811ea2819e9dcc951f0c7baf461f2dffdd09133f3b080a02203ec6bab5eb6619ed7f41b8701d7c6d70cfc83bb26c5c97f54b2ca6e304fc2bb581",
+ "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"",
"P2PK anyonecanpay"
],
[
- "0x47 0x30440220279dad2170ffb5639f0a1ea71fc462ee37d75d420d86f84c978bac523c09b7f20220683b2789f5c5528a9e0a0d78f6e40db3f616cf1adb5a5fdef117d5974795cfe201 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ "0x47 0x304402202166fcd5e607de452d3c6f15e059505cf21654346592f9650ba906b9e8be88fa022005d976d28eb8de477102feba28807b3ad361e7fa24796d259c9d61452f7c318c01 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
"HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
"P2SH",
"P2SH(P2PK)"
],
[
- "0x47 0x3044022066acbfb5ac96b7cbf3f05a2aaf358c32438c45d1d7359dee9fc1ee636940735f02205606a03fd8cbf6a6fcbcba60c8abb1e385c0b5753cb57a97538159106fd3684e01 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+ "0x47 0x3044022064cc90ca89ad721384b231653b945579359a24b928ef8539b331172628c9cc6102203e238869ab5dac3fc293db53c12e7dd3079e86cfde9024b689efc7227e4d671001 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
"HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
"",
"P2SH(P2PKH), bad sig but no VERIFY_P2SH"
],
[
- "0 0x47 0x3044022004e791dd30a64c70e55e84e150c002af9feb3ce0ab1f20e86c53d1209003927502205a60453987fcd72aebaaacebc8ce4b15449cdd79e54cc82cefb83e69dbcfeabf01 0x47 0x304402201d021808ce93dd8574cc4f99ae4f11b44305528b0aecbd9f156f08315173643802200944a0ea5c884bd86180aef76d8b1e444860776b251e47d2d6c651a1c6f9930801 0x47 0x30440220446336d7b7de05ebb5683b82b05248ec7d78e88ae8d6125985f5776c887a4cf90220674ab2b2c2f954ba1cf35457d273c90d0c0c1c224d0ae128628740e81129486801",
+ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"",
"3-of-3"
],
[
- "0 0x47 0x30440220288b06d057cf0eac434ed0c3be9257cc0ca144dd99c11cc8f1a49467a37d8e8002203c496c72253c528e6bc81c42e683aba974d46041a96ef7b00915c863eb2a702901 0x47 0x304402207ffb4da33f40cac839a43000a187bd76a1ee5bf95e46dc1534b38bb7bd0321db022038c078f29d1831f8eb68ffdc2634c654fb01c3467b6457b98ad220653bb2478501 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
+ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x304402204511cf05e85c2be07c6c176c5338a08ed3cb34212667f39613340881169986c002207cc48b27aa3691a20706a5773ec9923cadd20fedffd00c24457d85f83f0b51fe01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
"HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
"P2SH",
"P2SH(2-of-3)"
],
[
- "0x47 0x30440220001fff8863c84c0efc8eea5bffb7f388313f966f23a00ad3c0acc30ff5339684022016e6d78f51a3a1c362745931ca40b24f71cba2903dbfe5a6d392a9189127d83701",
+ "0x47 0x30440220001d6702bfa4f49c3a2542af9b1c2844a2eaac55f86f310f42d26a5dd17d6a8002202cdadbe608c00b50dd951c6ba0877d5b07a970f3e265c18697bc413a0a86f69901",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"",
"P2PK with too much R padding but no DERSIG"
],
[
- "0x48 0x304502202323d56f293842b544cacedd06baafb999196dfa1c2975314848c158ac606655022100514bd98186b8a3a1cc87f4aff76aed797781389f13f50d87bf95b2df6e488fcc01",
+ "0x48 0x304502207d2b258e959605e2ea50b46fea1325b7391ffb0c14a5b58ef8ad3851da3644380221007e75136df5f2e38216c4338b31c97e8307102edb97d611e06914e1f8fba68ead01",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"",
"P2PK with too much S padding but no DERSIG"
],
[
- "0x47 0x30440220d31c24bb6c08a496e7698a08fd41975115d7b55bfaa31cb2d573e09481e59a6702206a691239996434076b78a4e1cf46fc8e993b468a9c77fb1832186aa8040a61a201",
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"",
"P2PK with too little R padding but no DERSIG"
],
[
- "0x47 0x30440220007c2cc7aef1801c2937447703c87ef2a3744209ad98da2abadd4ba8bb2e3ea00220503a275582c9f9e9ff30260c81b7f64b8b696f22105605cc8241fb76a797316201",
+ "0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"",
"P2PK NOT with bad sig with too much R padding but no DERSIG"
],
[
- "0x48 0x3045022021bf9184d94f208ac9f4757ebca9b1cbebf008cfc244fe5be1360b1b9aba0e92022100e55074f72f3a1bfddf2ea4ea7ba984f78822e136fe04c8f9c1363238e0233bd801",
+ "0x49 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef05101",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
- "STRICTENC",
+ "",
"P2PK with high S but no LOW_S"
],
[
- "0x47 0x304402202163bc732c21b7de0251297d3c6c2ece182782e85fc5e19d6036f1130a79051e022033827811634924ebba68767537d78dd7bd9109ae2a89a60587927abdc25eb06401",
+ "0x47 0x30440220745d63eb70d45652128b450aa5ca7d9b513439963f261cb1c40a60f0785e7ee402204877785b38945ca9dbec78e1c1d4dd12148cc25c868bd27480023b49ae0f310501",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"",
"P2PK with hybrid pubkey but no STRICTENC"
],
[
- "0x47 0x3044022078d6c447887e88dcbe1bc5b613645280df6f4e5935648bc226e9d91da71b3216022047d6b7ef0949b228fc1b359afb8d50500268711354298217b983c26970790c7601",
+ "0x47 0x30440220606f6f9f6cebc84ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"",
"P2PK NOT with invalid hybrid pubkey but no STRICTENC"
],
[
- "0 0x47 0x304402203b269b9fbc0936877bf855b5fb41757218d9548b246370d991442a5f5bd1c3440220235268a4eaa8c67e543c6e37da81dd36d3b1be2de6b4fef04113389ca6ddc04501",
+ "0 0x47 0x304402203a5ee39032637c431af0a3ac42e32e0627390bd44f6f98c9c04e6d714635ad0202207b42fcd889c3ae8a1b515608f38535f1f9be815176ee8d1b65a27c767cf37aed01",
"1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"",
"1-of-2 with the second 1 hybrid pubkey and no STRICTENC"
],
[
- "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "0 0x47 0x304402203a5ee39032637c431af0a3ac42e32e0627390bd44f6f98c9c04e6d714635ad0202207b42fcd889c3ae8a1b515608f38535f1f9be815176ee8d1b65a27c767cf37aed01",
"1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"STRICTENC",
"1-of-2 with the second 1 hybrid pubkey"
],
-
-["
-CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and
-pubkeys in a specific order, and will exit early if the number of signatures
-left to check is greater than the number of keys left. As STRICTENC fails the
-script when it reaches an invalidly encoded signature or pubkey, we can use it
-to test the exact order in which signatures and pubkeys are evaluated by
-distinguishing CHECKMULTISIG returning false on the stack and the script as a
-whole failing.
-
-See also the corresponding inverted versions of these tests in script_invalid.json
-"],
-[
- "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
- "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
- "STRICTENC",
- "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey."
-],
-[
- "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
- "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
- "STRICTENC",
- "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature."
-],
-
[
- "0x47 0x304402204649e9517ef0377a8f8270bd423053fd98ddff62d74ea553e9579558abbb75e4022044a2b2344469c12e35ed898987711272b634733dd0f5e051288eceb04bd4669e05",
+ "0x47 0x304402201c215cb13e4954e60ce4f6de74941904c771f998de7b1d9627e82a1949fde517022031c2197455f3dbecbb78321201308d7b039424e38d480772d7cd4eb465a083f405",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"",
"P2PK with undefined hashtype but no STRICTENC"
],
[
- "0x47 0x304402207f1cf1866a2df0bb4b8d84d0ade72aa3abb6aaab0639d608b23d9e10ead0c48202203caa97f22c3439443eea4b89f7f6729854df0f567a8184d6ecc6e8b6c68c3e9d05",
+ "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
"",
"P2PK NOT with invalid sig and undefined hashtype but no STRICTENC"
],
[
- "1 0x47 0x3044022046ce33d1771b0127dd4c4cef8fdc3218ebdfa60e3793ed700292d8ebd93fb1f402201029d47a414db83e96e31443c2d8b552f971469c4800f5eff7df2f0648521aed01 0x47 0x304402205c53911ad55b054920043962bbda98cf6e57e2db1cd5611138251490baabaa8702201dc80dfceae6007e7772dc13ff6e7ca66a983cb017fe5d46d30118462d83bcf801 0x47 0x304402201937e44a4ec12364f9d32f9d25e7ecbc68aee9ef90069af80efef4c05f6ace9602206c515101c00c75710b32ff7ff8dbaf7c9a0be6e86ed14a0755b47626604f31fd01",
+ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"",
"3-of-3 with nonzero dummy but no NULLDUMMY"
],
[
- "1 0x47 0x30440220195038dbc6b2ae1199f86a6777824f7c5149789d85f655a3534a4422b8fba38c02204df9db87d2eb9fe06edc66870d9ac4c9ce673459f9d43cee0347ce4ffb02ee5a01 0x47 0x3044022010a45f30c6fa97a186eba9e6b595ab87d3dfcbf05dcaf1f1b8e3e7bf39515bb802203474e78d3d372e5f5c0f8c257ce8300c4bb8f37c51d4a894e11a91b5817da6ed01 0x47 0x30440220039cffd8e39850f95112662b1220b14b3c0d3d8a2772e13c947bfbf96345a64e02204154bfa77e2c0134d5434353bed82141e5da1cc479954aa288d5f0671480a04b01",
+ "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
"",
"3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY"
],
[
- "0 0x47 0x3044022002a27769ee33db258bdf7a3792e7da4143ec4001b551f73e6a190b8d1bde449d02206742c56ccd94a7a2e16ca52fc1ae4a0aa122b0014a867a80de104f9cb18e472c01 DUP",
+ "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 DUP",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"",
"2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY"
],
[
- "0 0x47 0x304402203acf75dd59bbef171aeeedae4f1020b824195820db82575c2b323b8899f95de9022067df297d3a5fad049ba0bb81255d0e495643cbcf9abae9e396988618bc0c6dfe01 0x47 0x304402205f8b859230c1cab7d4e8de38ff244d2ebe046b64e8d3f4219b01e483c203490a022071bdc488e31b557f7d9e5c8a8bec90dc92289ca70fa317685f4f140e38b30c4601",
+ "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"SIGPUSHONLY",
"2-of-2 with two identical keys and sigs pushed"
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index f9e35e0166..43b18ce61e 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -8,6 +8,7 @@
#include "script/script.h"
#include "uint256.h"
#include "util.h"
+#include "utilstrencodings.h"
#include <string>
#include <vector>
@@ -162,6 +163,28 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK(rkey1C == pubkey1C);
BOOST_CHECK(rkey2C == pubkey2C);
}
+
+ // test deterministic signing
+
+ std::vector<unsigned char> detsig, detsigc;
+ string strMsg = "Very deterministic message";
+ uint256 hashMsg = Hash(strMsg.begin(), strMsg.end());
+ BOOST_CHECK(key1.Sign(hashMsg, detsig));
+ BOOST_CHECK(key1C.Sign(hashMsg, detsigc));
+ BOOST_CHECK(detsig == detsigc);
+ BOOST_CHECK(detsig == ParseHex("304402205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d022014ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
+ BOOST_CHECK(key2.Sign(hashMsg, detsig));
+ BOOST_CHECK(key2C.Sign(hashMsg, detsigc));
+ BOOST_CHECK(detsig == detsigc);
+ BOOST_CHECK(detsig == ParseHex("3044022052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd5022061d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
+ BOOST_CHECK(key1.SignCompact(hashMsg, detsig));
+ BOOST_CHECK(key1C.SignCompact(hashMsg, detsigc));
+ BOOST_CHECK(detsig == ParseHex("1c5dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
+ BOOST_CHECK(detsigc == ParseHex("205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
+ BOOST_CHECK(key2.SignCompact(hashMsg, detsig));
+ BOOST_CHECK(key2C.SignCompact(hashMsg, detsigc));
+ BOOST_CHECK(detsig == ParseHex("1c52d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
+ BOOST_CHECK(detsigc == ParseHex("2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp
index 78c4181409..bf57dd81d9 100644
--- a/src/test/main_tests.cpp
+++ b/src/test/main_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "main.h"
#include <boost/test/unit_test.hpp>
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 6952f4c584..4d2a9aff45 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -248,8 +248,9 @@ public:
{
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType);
std::vector<unsigned char> vchSig, r, s;
+ uint32_t iter = 0;
do {
- key.Sign(hash, vchSig);
+ key.Sign(hash, vchSig, iter++);
if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) {
NegateSignatureS(vchSig);
}
@@ -490,24 +491,18 @@ BOOST_AUTO_TEST_CASE(script_build)
).Num(0).PushSig(keys.key1).PushSig(keys.key1));
- std::map<std::string, Array> tests_good;
- std::map<std::string, Array> tests_bad;
+ std::set<std::string> tests_good;
+ std::set<std::string> tests_bad;
{
Array json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
Array json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
BOOST_FOREACH(Value& tv, json_good) {
- Array test = tv.get_array();
- if (test.size() >= 4) {
- tests_good[test[3].get_str()] = test;
- }
+ tests_good.insert(write_string(Value(tv.get_array()), true));
}
BOOST_FOREACH(Value& tv, json_bad) {
- Array test = tv.get_array();
- if (test.size() >= 4) {
- tests_bad[test[3].get_str()] = test;
- }
+ tests_bad.insert(write_string(Value(tv.get_array()), true));
}
}
@@ -516,27 +511,23 @@ BOOST_AUTO_TEST_CASE(script_build)
BOOST_FOREACH(TestBuilder& test, good) {
test.Test(true);
- if (tests_good.count(test.GetComment()) == 0) {
+ std::string str = write_string(Value(test.GetJSON()), true);
#ifndef UPDATE_JSON_TESTS
+ if (tests_good.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment());
-#endif
- strGood += write_string(Value(test.GetJSON()), true) + ",\n";
- } else {
- BOOST_CHECK_MESSAGE(ParseScript(tests_good[test.GetComment()][1].get_str()) == test.GetScriptPubKey(), "ScriptPubKey mismatch in auto script_valid test: " + test.GetComment());
- strGood += write_string(Value(tests_good[test.GetComment()]), true) + ",\n";
}
+#endif
+ strGood += str + ",\n";
}
BOOST_FOREACH(TestBuilder& test, bad) {
test.Test(false);
- if (tests_bad.count(test.GetComment()) == 0) {
+ std::string str = write_string(Value(test.GetJSON()), true);
#ifndef UPDATE_JSON_TESTS
+ if (tests_bad.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_invalid test: " + test.GetComment());
-#endif
- strBad += write_string(Value(test.GetJSON()), true) + ",\n";
- } else {
- BOOST_CHECK_MESSAGE(ParseScript(tests_bad[test.GetComment()][1].get_str()) == test.GetScriptPubKey(), "ScriptPubKey mismatch in auto script_invalid test: " + test.GetComment());
- strBad += write_string(Value(tests_bad[test.GetComment()]), true) + ",\n";
}
+#endif
+ strBad += str + ",\n";
}
#ifdef UPDATE_JSON_TESTS
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 67d50fccf4..10f77e3a5b 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -5,7 +5,7 @@
#include "util.h"
#include "clientversion.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "random.h"
#include "sync.h"
#include "utilstrencodings.h"
diff --git a/src/txmempool.h b/src/txmempool.h
index e68b218154..d00bdd0616 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -10,7 +10,7 @@
#include "amount.h"
#include "coins.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "sync.h"
class CAutoFile;
diff --git a/src/undo.h b/src/undo.h
index 4f5f4047dd..2301bd8b43 100644
--- a/src/undo.h
+++ b/src/undo.h
@@ -7,7 +7,7 @@
#define BITCOIN_UNDO_H
#include "compressor.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "serialize.h"
/** Undo information for a CTxIn
diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp
index 085adae85e..3e076a0266 100644
--- a/src/utilmoneystr.cpp
+++ b/src/utilmoneystr.cpp
@@ -5,7 +5,7 @@
#include "utilmoneystr.h"
-#include "core/transaction.h"
+#include "primitives/transaction.h"
#include "tinyformat.h"
#include "utilstrencodings.h"
diff --git a/src/wallet.h b/src/wallet.h
index 0244ce2368..70d274c2d5 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -7,8 +7,8 @@
#define BITCOIN_WALLET_H
#include "amount.h"
-#include "core/block.h"
-#include "core/transaction.h"
+#include "primitives/block.h"
+#include "primitives/transaction.h"
#include "crypter.h"
#include "key.h"
#include "keystore.h"