diff options
Diffstat (limited to 'src')
32 files changed, 814 insertions, 417 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3ec9e2f85d..4c4f9f6937 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 @@ -343,8 +351,10 @@ if BUILD_BITCOIN_LIBS include_HEADERS = script/bitcoinconsensus.h libbitcoinconsensus_la_SOURCES = \ core/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/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 63e72c66d2..7b6ebb1b30 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -330,8 +330,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; if (GetBoolArg("-help-debug", false)) { - strUsage += " -printblock=<hash> " + _("Print block on startup, if found in block index") + "\n"; - strUsage += " -printblocktree " + strprintf(_("Print block tree on startup (default: %u)"), 0) + "\n"; strUsage += " -printpriority " + strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0) + "\n"; strUsage += " -privdb " + strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1) + "\n"; strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; @@ -1048,34 +1046,6 @@ bool AppInit2(boost::thread_group& threadGroup) } LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); - if (GetBoolArg("-printblockindex", false) || GetBoolArg("-printblocktree", false)) - { - PrintBlockTree(); - return false; - } - - if (mapArgs.count("-printblock")) - { - string strMatch = mapArgs["-printblock"]; - int nFound = 0; - for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) - { - uint256 hash = (*mi).first; - if (boost::algorithm::starts_with(hash.ToString(), strMatch)) - { - CBlockIndex* pindex = (*mi).second; - CBlock block; - ReadBlockFromDisk(block, pindex); - block.BuildMerkleTree(); - LogPrintf("%s\n", block.ToString()); - nFound++; - } - } - if (nFound == 0) - LogPrintf("No blocks matching %s were found\n", strMatch); - return false; - } - boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); // Allowed to fail as this file IS missing on first startup. 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); @@ -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 bda2ee7f7b..0515eeb156 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1199,15 +1199,14 @@ bool IsInitialBlockDownload() LOCK(cs_main); if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate()) return true; - static int64_t nLastUpdate; - static CBlockIndex* pindexLastBest; - if (chainActive.Tip() != pindexLastBest) - { - pindexLastBest = chainActive.Tip(); - nLastUpdate = GetTime(); - } - return (GetTime() - nLastUpdate < 10 && - chainActive.Tip()->GetBlockTime() < GetTime() - 24 * 60 * 60); + static bool lockIBDState = false; + if (lockIBDState) + return false; + bool state = (chainActive.Height() < pindexBestHeader->nHeight - 24 * 6 || + pindexBestHeader->GetBlockTime() < GetTime() - 24 * 60 * 60); + if (!state) + lockIBDState = true; + return state; } bool fLargeWorkForkFound = false; @@ -2136,6 +2135,73 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { return true; } +bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { + AssertLockHeld(cs_main); + + // Mark the block itself as invalid. + pindex->nStatus |= BLOCK_FAILED_VALID; + setDirtyBlockIndex.insert(pindex); + setBlockIndexCandidates.erase(pindex); + + while (chainActive.Contains(pindex)) { + CBlockIndex *pindexWalk = chainActive.Tip(); + pindexWalk->nStatus |= BLOCK_FAILED_CHILD; + setDirtyBlockIndex.insert(pindexWalk); + setBlockIndexCandidates.erase(pindexWalk); + // ActivateBestChain considers blocks already in chainActive + // unconditionally valid already, so force disconnect away from it. + if (!DisconnectTip(state)) { + return false; + } + } + + // The resulting new best tip may not be in setBlockIndexCandidates anymore, so + // add them again. + BlockMap::iterator it = mapBlockIndex.begin(); + while (it != mapBlockIndex.end()) { + if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) { + setBlockIndexCandidates.insert(pindex); + } + it++; + } + + InvalidChainFound(pindex); + return true; +} + +bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex) { + AssertLockHeld(cs_main); + + int nHeight = pindex->nHeight; + + // Remove the invalidity flag from this block and all its descendants. + BlockMap::iterator it = mapBlockIndex.begin(); + while (it != mapBlockIndex.end()) { + if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) { + it->second->nStatus &= ~BLOCK_FAILED_MASK; + setDirtyBlockIndex.insert(it->second); + if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) { + setBlockIndexCandidates.insert(it->second); + } + if (it->second == pindexBestInvalid) { + // Reset invalid block marker if it was pointing to one of those. + pindexBestInvalid = NULL; + } + } + it++; + } + + // Remove the invalidity flag from all ancestors too. + while (pindex != NULL) { + if (pindex->nStatus & BLOCK_FAILED_MASK) { + pindex->nStatus &= ~BLOCK_FAILED_MASK; + setDirtyBlockIndex.insert(pindex); + } + pindex = pindex->pprev; + } + return true; +} + CBlockIndex* AddToBlockIndex(const CBlockHeader& block) { // Check for duplicate @@ -3114,75 +3180,6 @@ bool InitBlockIndex() { -void PrintBlockTree() -{ - AssertLockHeld(cs_main); - // pre-compute tree structure - map<CBlockIndex*, vector<CBlockIndex*> > mapNext; - for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) - { - CBlockIndex* pindex = (*mi).second; - mapNext[pindex->pprev].push_back(pindex); - // test - //while (rand() % 3 == 0) - // mapNext[pindex->pprev].push_back(pindex); - } - - vector<pair<int, CBlockIndex*> > vStack; - vStack.push_back(make_pair(0, chainActive.Genesis())); - - int nPrevCol = 0; - while (!vStack.empty()) - { - int nCol = vStack.back().first; - CBlockIndex* pindex = vStack.back().second; - vStack.pop_back(); - - // print split or gap - if (nCol > nPrevCol) - { - for (int i = 0; i < nCol-1; i++) - LogPrintf("| "); - LogPrintf("|\\\n"); - } - else if (nCol < nPrevCol) - { - for (int i = 0; i < nCol; i++) - LogPrintf("| "); - LogPrintf("|\n"); - } - nPrevCol = nCol; - - // print columns - for (int i = 0; i < nCol; i++) - LogPrintf("| "); - - // print item - CBlock block; - ReadBlockFromDisk(block, pindex); - LogPrintf("%d (blk%05u.dat:0x%x) %s tx %u\n", - pindex->nHeight, - pindex->GetBlockPos().nFile, pindex->GetBlockPos().nPos, - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()), - block.vtx.size()); - - // put the main time-chain first - vector<CBlockIndex*>& vNext = mapNext[pindex]; - for (unsigned int i = 0; i < vNext.size(); i++) - { - if (chainActive.Next(vNext[i])) - { - swap(vNext[0], vNext[i]); - break; - } - } - - // iterate children - for (unsigned int i = 0; i < vNext.size(); i++) - vStack.push_back(make_pair(nCol+i, vNext[i])); - } -} - bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) { // Map of disk positions for blocks with unknown parent (only used for reindex) diff --git a/src/main.h b/src/main.h index c0d6412528..caf8331ee1 100644 --- a/src/main.h +++ b/src/main.h @@ -177,8 +177,6 @@ bool InitBlockIndex(); bool LoadBlockIndex(); /** Unload database information */ void UnloadBlockIndex(); -/** Print the loaded block tree */ -void PrintBlockTree(); /** Process protocol messages received from a given node */ bool ProcessMessages(CNode* pfrom); /** Send queued protocol messages to be sent to a give node */ @@ -609,6 +607,12 @@ public: /** Find the last common block between the parameter chain and a locator. */ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); +/** Mark a block as invalid. */ +bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex); + +/** Remove invalidity status from a block and its descendants. */ +bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); + /** The currently-connected chain of blocks. */ extern CChain chainActive; diff --git a/src/net.cpp b/src/net.cpp index a66875a894..6bf72d22c5 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1559,7 +1559,7 @@ void static Discover(boost::thread_group& threadGroup) #ifdef WIN32 // Get local host IP - char pszHostName[1000] = ""; + char pszHostName[256] = ""; if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) { vector<CNetAddr> vaddr; @@ -1567,7 +1567,8 @@ void static Discover(boost::thread_group& threadGroup) { BOOST_FOREACH (const CNetAddr &addr, vaddr) { - AddLocal(addr, LOCAL_IF); + if (AddLocal(addr, LOCAL_IF)) + LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString()); } } } @@ -1587,20 +1588,19 @@ void static Discover(boost::thread_group& threadGroup) struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr); CNetAddr addr(s4->sin_addr); if (AddLocal(addr, LOCAL_IF)) - LogPrintf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString()); + LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToString()); } else if (ifa->ifa_addr->sa_family == AF_INET6) { struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr); CNetAddr addr(s6->sin6_addr); if (AddLocal(addr, LOCAL_IF)) - LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString()); + LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToString()); } } freeifaddrs(myaddrs); } #endif - } void StartNode(boost::thread_group& threadGroup) diff --git a/src/netbase.cpp b/src/netbase.cpp index ea05b8766f..aca5a107fe 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifdef HAVE_CONFIG_H -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "netbase.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 c85f569fd3..75e1f9ae78 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -106,10 +106,8 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator QString quotient_str = QString::number(quotient); QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0'); - // Use SI-stule separators as these are locale indendent and can't be - // confused with the decimal marker. Rule is to use a thin space every - // three digits on *both* sides of the decimal point - but only if there - // are five or more digits + // Use SI-style thin space separators as these are locale independent and can't be + // confused with the decimal marker. QChar thin_sp(THIN_SP_CP); int q_size = quotient_str.size(); if (separators == separatorAlways || (separators == separatorStandard && q_size > 4)) diff --git a/src/random.h b/src/random.h index ec73d910c4..aa55ca2b6f 100644 --- a/src/random.h +++ b/src/random.h @@ -26,7 +26,7 @@ uint256 GetRandHash(); /** * Seed insecure_rand using the random pool. - * @param Deterministic Use a determinstic seed + * @param Deterministic Use a deterministic seed */ void seed_insecure_rand(bool fDeterministic = false); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index e8b0f62a83..045cd90ef6 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -496,11 +496,13 @@ Value getchaintips(const Array& params, bool fHelp) " \"height\": xxxx, (numeric) height of the chain tip\n" " \"hash\": \"xxxx\", (string) block hash of the tip\n" " \"branchlen\": 0 (numeric) zero for main chain\n" + " \"status\": \"active\" (string) \"active\" for the main chain\n" " },\n" " {\n" " \"height\": xxxx,\n" " \"hash\": \"xxxx\",\n" " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" + " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" " }\n" "]\n" "\nExamples:\n" @@ -521,6 +523,9 @@ Value getchaintips(const Array& params, bool fHelp) setTips.erase(pprev); } + // Always report the currently active tip. + setTips.insert(chainActive.Tip()); + /* Construct the output array. */ Array res; BOOST_FOREACH(const CBlockIndex* block, setTips) @@ -532,6 +537,28 @@ Value getchaintips(const Array& params, bool fHelp) const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight; obj.push_back(Pair("branchlen", branchLen)); + string status; + if (chainActive.Contains(block)) { + // This block is part of the currently active chain. + status = "active"; + } else if (block->nStatus & BLOCK_FAILED_MASK) { + // This block or one of its ancestors is invalid. + status = "invalid"; + } else if (block->nChainTx == 0) { + // This block cannot be connected because full block data for it or one of its parents is missing. + status = "headers-only"; + } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) { + // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized. + status = "valid-fork"; + } else if (block->IsValid(BLOCK_VALID_TREE)) { + // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain. + status = "valid-headers"; + } else { + // No clue. + status = "unknown"; + } + obj.push_back(Pair("status", status)); + res.push_back(obj); } @@ -561,3 +588,79 @@ Value getmempoolinfo(const Array& params, bool fHelp) return ret; } +Value invalidateblock(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "invalidateblock \"hash\"\n" + "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the block to mark as invalid\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("invalidateblock", "\"blockhash\"") + + HelpExampleRpc("invalidateblock", "\"blockhash\"") + ); + + std::string strHash = params[0].get_str(); + uint256 hash(strHash); + CValidationState state; + + { + LOCK(cs_main); + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockindex = mapBlockIndex[hash]; + InvalidateBlock(state, pblockindex); + } + + if (state.IsValid()) { + ActivateBestChain(state); + } + + if (!state.IsValid()) { + throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); + } + + return Value::null; +} + +Value reconsiderblock(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "reconsiderblock \"hash\"\n" + "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" + "This can be used to undo the effects of invalidateblock.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the block to reconsider\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("reconsiderblock", "\"blockhash\"") + + HelpExampleRpc("reconsiderblock", "\"blockhash\"") + ); + + std::string strHash = params[0].get_str(); + uint256 hash(strHash); + CValidationState state; + + { + LOCK(cs_main); + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockindex = mapBlockIndex[hash]; + ReconsiderBlock(state, pblockindex); + } + + if (state.IsValid()) { + ActivateBestChain(state); + } + + if (!state.IsValid()) { + throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); + } + + return Value::null; +} diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index b03016a508..8512212185 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -160,7 +160,7 @@ string CRPCTable::help(string strCommand) const // We already filter duplicates, but these deprecated screw up the sort order if (strMethod.find("label") != string::npos) continue; - if (strCommand != "" && strMethod != strCommand) + if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand) continue; #ifdef ENABLE_WALLET if (pcmd->reqWallet && !pwalletMain) @@ -246,7 +246,6 @@ static const CRPCCommand vRPCCommands[] = { "control", "getinfo", &getinfo, true, false, false }, /* uses wallet if enabled */ { "control", "help", &help, true, true, false }, { "control", "stop", &stop, true, true, false }, - { "control", "setmocktime", &setmocktime, true, false, false }, /* P2P networking */ { "network", "getnetworkinfo", &getnetworkinfo, true, false, false }, @@ -300,6 +299,11 @@ static const CRPCCommand vRPCCommands[] = { "util", "estimatefee", &estimatefee, true, true, false }, { "util", "estimatepriority", &estimatepriority, true, true, false }, + /* Not shown in help */ + { "hidden", "invalidateblock", &invalidateblock, true, true, false }, + { "hidden", "reconsiderblock", &reconsiderblock, true, true, false }, + { "hidden", "setmocktime", &setmocktime, true, false, false }, + #ifdef ENABLE_WALLET /* Wallet */ { "wallet", "addmultisigaddress", &addmultisigaddress, true, false, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index b0e437057b..2b2428445d 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -222,6 +222,8 @@ extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getchaintips(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value invalidateblock(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value reconsiderblock(const json_spirit::Array& params, bool fHelp); // in rest.cpp extern bool HTTPReq_REST(AcceptedConnection *conn, diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index a10cefcc0b..237c712870 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -8,7 +8,7 @@ #include "core/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/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/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/script_tests.cpp b/src/test/script_tests.cpp index 6952f4c584..53411190eb 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); } diff --git a/src/wallet.cpp b/src/wallet.cpp index 000a088b97..27dbf61c2b 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -2030,7 +2030,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings() set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const { - AssertLockHeld(cs_wallet); // mapWallet + LOCK(cs_wallet); set<CTxDestination> result; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook) { |