aboutsummaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
authorNoodleDoodleNoodleDoodleNoodleDoodleNoo <xeven77@outlook.com>2014-06-16 03:32:09 -0700
committerNoodleDoodleNoodleDoodleNoodleDoodleNoo <xeven77@outlook.com>2014-06-16 03:32:09 -0700
commit8fc42a21fc8ff4528c59e206b24d974982332964 (patch)
treea0d9934ca8675afe4bbe5594f2b9694867eb73b6 /src/crypto
parentRevert "Update slow-hash.c" (diff)
parentMerge pull request #33 from mikezackles/arch_linux_build_fixes (diff)
downloadmonero-8fc42a21fc8ff4528c59e206b24d974982332964.tar.xz
Merge branch 'master' of https://github.com/monero-project/bitmonero
Diffstat (limited to '')
-rw-r--r--src/crypto/aesb.c177
-rw-r--r--src/crypto/crypto.cpp25
-rw-r--r--src/crypto/crypto.h8
-rw-r--r--src/crypto/electrum-words.cpp110
-rw-r--r--src/crypto/electrum-words.h3280
-rw-r--r--src/crypto/oaes_config.h6
-rw-r--r--src/crypto/oaes_lib.c25
-rw-r--r--src/crypto/oaes_lib.h25
-rw-r--r--src/crypto/slow-hash.c344
-rw-r--r--src/cryptonote_config.h8
-rw-r--r--src/cryptonote_core/account.cpp16
-rw-r--r--src/cryptonote_core/account.h2
-rw-r--r--src/cryptonote_core/blockchain_storage.cpp139
-rw-r--r--src/cryptonote_core/blockchain_storage.h12
-rw-r--r--src/cryptonote_core/checkpoints.cpp26
-rw-r--r--src/cryptonote_core/checkpoints.h3
-rw-r--r--src/cryptonote_core/checkpoints_create.h3
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp25
-rw-r--r--src/cryptonote_core/cryptonote_core.h10
-rw-r--r--src/cryptonote_core/cryptonote_format_utils.cpp7
-rw-r--r--src/cryptonote_core/miner.cpp19
-rw-r--r--src/cryptonote_core/miner.h19
-rw-r--r--src/cryptonote_core/tx_extra.h52
-rw-r--r--src/cryptonote_core/tx_pool.cpp79
-rw-r--r--src/cryptonote_core/tx_pool.h10
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h4
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl30
27 files changed, 4207 insertions, 257 deletions
diff --git a/src/crypto/aesb.c b/src/crypto/aesb.c
new file mode 100644
index 000000000..ba48313da
--- /dev/null
+++ b/src/crypto/aesb.c
@@ -0,0 +1,177 @@
+/*
+---------------------------------------------------------------------------
+Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
+
+The redistribution and use of this software (with or without changes)
+is allowed without the payment of fees or royalties provided that:
+
+ source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation.
+
+This software is provided 'as is' with no explicit or implied warranties
+in respect of its operation, including, but not limited to, correctness
+and fitness for purpose.
+---------------------------------------------------------------------------
+Issue Date: 20/12/2007
+*/
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+#define TABLE_ALIGN 32
+#define WPOLY 0x011b
+#define N_COLS 4
+#define AES_BLOCK_SIZE 16
+#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2))
+
+#if defined(_MSC_VER)
+#define ALIGN __declspec(align(TABLE_ALIGN))
+#elif defined(__GNUC__)
+#define ALIGN __attribute__ ((aligned(16)))
+#else
+#define ALIGN
+#endif
+
+#define rf1(r,c) (r)
+#define word_in(x,c) (*((uint32_t*)(x)+(c)))
+#define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = (v))
+
+#define s(x,c) x[c]
+#define si(y,x,c) (s(y,c) = word_in(x, c))
+#define so(y,x,c) word_out(y, c, s(x,c))
+#define state_in(y,x) si(y,x,0); si(y,x,1); si(y,x,2); si(y,x,3)
+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
+#define to_byte(x) ((x) & 0xff)
+#define bval(x,n) to_byte((x) >> (8 * (n)))
+
+#define fwd_var(x,r,c)\
+ ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
+ : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
+ : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
+ : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
+
+#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
+
+#define sb_data(w) {\
+ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
+ w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
+ w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
+ w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
+ w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
+ w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
+ w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
+ w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
+ w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
+ w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
+ w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
+ w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
+ w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
+ w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
+ w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
+ w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
+ w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
+ w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
+ w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
+ w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
+ w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
+ w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
+ w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
+ w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
+ w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
+ w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
+ w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
+ w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
+ w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
+ w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
+ w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
+ w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
+
+#define rc_data(w) {\
+ w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\
+ w(0x1b), w(0x36) }
+
+#define bytes2word(b0, b1, b2, b3) (((uint32_t)(b3) << 24) | \
+ ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
+
+#define h0(x) (x)
+#define w0(p) bytes2word(p, 0, 0, 0)
+#define w1(p) bytes2word(0, p, 0, 0)
+#define w2(p) bytes2word(0, 0, p, 0)
+#define w3(p) bytes2word(0, 0, 0, p)
+
+#define u0(p) bytes2word(f2(p), p, p, f3(p))
+#define u1(p) bytes2word(f3(p), f2(p), p, p)
+#define u2(p) bytes2word(p, f3(p), f2(p), p)
+#define u3(p) bytes2word(p, p, f3(p), f2(p))
+
+#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p))
+#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p))
+#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p))
+#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p))
+
+#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY))
+#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))
+#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) ^ (((x>>5) & 4) * WPOLY))
+#define f3(x) (f2(x) ^ x)
+#define f9(x) (f8(x) ^ x)
+#define fb(x) (f8(x) ^ f2(x) ^ x)
+#define fd(x) (f8(x) ^ f4(x) ^ x)
+#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
+
+#define t_dec(m,n) t_##m##n
+#define t_set(m,n) t_##m##n
+#define t_use(m,n) t_##m##n
+
+#define d_4(t,n,b,e,f,g,h) ALIGN const t n[4][256] = { b(e), b(f), b(g), b(h) }
+
+#define four_tables(x,tab,vf,rf,c) \
+ (tab[0][bval(vf(x,0,c),rf(0,c))] \
+ ^ tab[1][bval(vf(x,1,c),rf(1,c))] \
+ ^ tab[2][bval(vf(x,2,c),rf(2,c))] \
+ ^ tab[3][bval(vf(x,3,c),rf(3,c))])
+
+d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3);
+
+void aesb_single_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
+{
+ uint32_t b0[4], b1[4];
+ const uint32_t *kp = (uint32_t *) expandedKey;
+ state_in(b0, in);
+
+ round(fwd_rnd, b1, b0, kp);
+
+ state_out(out, b1);
+}
+
+void aesb_pseudo_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
+{
+ uint32_t b0[4], b1[4];
+ const uint32_t *kp = (uint32_t *) expandedKey;
+ state_in(b0, in);
+
+ round(fwd_rnd, b1, b0, kp);
+ round(fwd_rnd, b0, b1, kp + 1 * N_COLS);
+ round(fwd_rnd, b1, b0, kp + 2 * N_COLS);
+ round(fwd_rnd, b0, b1, kp + 3 * N_COLS);
+ round(fwd_rnd, b1, b0, kp + 4 * N_COLS);
+ round(fwd_rnd, b0, b1, kp + 5 * N_COLS);
+ round(fwd_rnd, b1, b0, kp + 6 * N_COLS);
+ round(fwd_rnd, b0, b1, kp + 7 * N_COLS);
+ round(fwd_rnd, b1, b0, kp + 8 * N_COLS);
+ round(fwd_rnd, b0, b1, kp + 9 * N_COLS);
+
+ state_out(out, b0);
+}
+
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp
index f5f525700..98a17a3e4 100644
--- a/src/crypto/crypto.cpp
+++ b/src/crypto/crypto.cpp
@@ -50,6 +50,7 @@ namespace crypto {
return &reinterpret_cast<const unsigned char &>(scalar);
}
+ /* generate a random 32-byte (256-bit) integer and copy it to res */
static inline void random_scalar(ec_scalar &res) {
unsigned char tmp[64];
generate_random_bytes(64, tmp);
@@ -62,12 +63,32 @@ namespace crypto {
sc_reduce32(&res);
}
- void crypto_ops::generate_keys(public_key &pub, secret_key &sec) {
+ /*
+ * generate public and secret keys from a random 256-bit integer
+ * TODO: allow specifiying random value (for wallet recovery)
+ *
+ */
+ secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) {
lock_guard<mutex> lock(random_lock);
ge_p3 point;
- random_scalar(sec);
+
+ secret_key rng;
+
+ if (recover)
+ {
+ rng = recovery_key;
+ }
+ else
+ {
+ random_scalar(rng);
+ }
+ sec = rng;
+ sc_reduce32(&sec); // reduce in case second round of keys (sendkeys)
+
ge_scalarmult_base(&point, &sec);
ge_p3_tobytes(&pub, &point);
+
+ return rng;
}
bool crypto_ops::check_key(const public_key &key) {
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 61641fbcf..024713df1 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -62,8 +62,8 @@ namespace crypto {
void operator=(const crypto_ops &);
~crypto_ops();
- static void generate_keys(public_key &, secret_key &);
- friend void generate_keys(public_key &, secret_key &);
+ static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
+ friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
static bool check_key(const public_key &);
friend bool check_key(const public_key &);
static bool secret_key_to_public_key(const secret_key &, public_key &);
@@ -102,8 +102,8 @@ namespace crypto {
/* Generate a new key pair
*/
- inline void generate_keys(public_key &pub, secret_key &sec) {
- crypto_ops::generate_keys(pub, sec);
+ inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
+ return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
}
/* Check a public key. Returns true if it is valid, false otherwise.
diff --git a/src/crypto/electrum-words.cpp b/src/crypto/electrum-words.cpp
new file mode 100644
index 000000000..96a392d04
--- /dev/null
+++ b/src/crypto/electrum-words.cpp
@@ -0,0 +1,110 @@
+/*
+ * This file and its header file are for translating Electrum-style word lists
+ * into their equivalent byte representations for cross-compatibility with
+ * that method of "backing up" one's wallet keys.
+ */
+
+#include <string>
+#include <cassert>
+#include <map>
+#include <cstdint>
+#include <vector>
+#include <boost/algorithm/string.hpp>
+#include "crypto/crypto.h" // for declaration of crypto::secret_key
+
+#include "crypto/electrum-words.h"
+
+namespace crypto
+{
+ namespace ElectrumWords
+ {
+
+ /* convert words to bytes, 3 words -> 4 bytes
+ * returns:
+ * false if not a multiple of 3 words, or if a words is not in the
+ * words list
+ *
+ * true otherwise
+ */
+ bool words_to_bytes(const std::string& words, crypto::secret_key& dst)
+ {
+ int n = NUMWORDS; // hardcoded because this is what electrum uses
+
+ std::vector<std::string> wlist;
+
+ boost::split(wlist, words, boost::is_any_of(" "));
+
+ // error on non-compliant word list
+ if (wlist.size() != 12 && wlist.size() != 24) return false;
+
+ for (unsigned int i=0; i < wlist.size() / 3; i++)
+ {
+ uint32_t val;
+ uint32_t w1, w2, w3;
+
+ // verify all three words exist in the word list
+ if (wordsMap.count(wlist[i*3]) == 0 ||
+ wordsMap.count(wlist[i*3 + 1]) == 0 ||
+ wordsMap.count(wlist[i*3 + 2]) == 0)
+ {
+ return false;
+ }
+
+ w1 = wordsMap.at(wlist[i*3]);
+ w2 = wordsMap.at(wlist[i*3 + 1]);
+ w3 = wordsMap.at(wlist[i*3 + 2]);
+
+ val = w1 + n * (((n - w1) + w2) % n) + n * n * (((n - w2) + w3) % n);
+
+ if (!(val % n == w1)) return false;
+
+ memcpy(dst.data + i * 4, &val, 4); // copy 4 bytes to position
+ }
+
+ std::string wlist_copy = words;
+ if (wlist.size() == 12)
+ {
+ memcpy(dst.data, dst.data + 16, 16); // if electrum 12-word seed, duplicate
+ wlist_copy += ' ';
+ wlist_copy += words;
+ }
+
+ return true;
+ }
+
+ /* convert bytes to words, 4 bytes-> 3 words
+ * returns:
+ * false if wrong number of bytes (shouldn't be possible)
+ * true otherwise
+ */
+ bool bytes_to_words(const crypto::secret_key& src, std::string& words)
+ {
+ int n = NUMWORDS; // hardcoded because this is what electrum uses
+
+ if (sizeof(src.data) % 4 != 0) return false;
+
+ // 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
+ for (unsigned int i=0; i < sizeof(src.data)/4; i++, words += ' ')
+ {
+ uint32_t w1, w2, w3;
+
+ uint32_t val;
+
+ memcpy(&val, (src.data) + (i * 4), 4);
+
+ w1 = val % n;
+ w2 = ((val / n) + w1) % n;
+ w3 = (((val / n) / n) + w2) % n;
+
+ words += wordsArray[w1];
+ words += ' ';
+ words += wordsArray[w2];
+ words += ' ';
+ words += wordsArray[w3];
+ }
+ return false;
+ }
+
+ } // namespace ElectrumWords
+
+} // namespace crypto
diff --git a/src/crypto/electrum-words.h b/src/crypto/electrum-words.h
new file mode 100644
index 000000000..a533299bd
--- /dev/null
+++ b/src/crypto/electrum-words.h
@@ -0,0 +1,3280 @@
+/*
+ * This file and its cpp file are for translating Electrum-style word lists
+ * into their equivalent byte representations for cross-compatibility with
+ * that method of "backing up" one's wallet keys.
+ */
+
+#include <string>
+#include <cstdint>
+#include <map>
+#include "crypto/crypto.h" // for declaration of crypto::secret_key
+
+namespace crypto
+{
+ namespace ElectrumWords
+ {
+
+ const int NUMWORDS = 1626;
+
+ bool words_to_bytes(const std::string& words, crypto::secret_key& dst);
+ bool bytes_to_words(const crypto::secret_key& src, std::string& words);
+
+ const std::map<std::string,uint32_t> wordsMap = {
+ {"like", 0},
+ {"just", 1},
+ {"love", 2},
+ {"know", 3},
+ {"never", 4},
+ {"want", 5},
+ {"time", 6},
+ {"out", 7},
+ {"there", 8},
+ {"make", 9},
+ {"look", 10},
+ {"eye", 11},
+ {"down", 12},
+ {"only", 13},
+ {"think", 14},
+ {"heart", 15},
+ {"back", 16},
+ {"then", 17},
+ {"into", 18},
+ {"about", 19},
+ {"more", 20},
+ {"away", 21},
+ {"still", 22},
+ {"them", 23},
+ {"take", 24},
+ {"thing", 25},
+ {"even", 26},
+ {"through", 27},
+ {"long", 28},
+ {"always", 29},
+ {"world", 30},
+ {"too", 31},
+ {"friend", 32},
+ {"tell", 33},
+ {"try", 34},
+ {"hand", 35},
+ {"thought", 36},
+ {"over", 37},
+ {"here", 38},
+ {"other", 39},
+ {"need", 40},
+ {"smile", 41},
+ {"again", 42},
+ {"much", 43},
+ {"cry", 44},
+ {"been", 45},
+ {"night", 46},
+ {"ever", 47},
+ {"little", 48},
+ {"said", 49},
+ {"end", 50},
+ {"some", 51},
+ {"those", 52},
+ {"around", 53},
+ {"mind", 54},
+ {"people", 55},
+ {"girl", 56},
+ {"leave", 57},
+ {"dream", 58},
+ {"left", 59},
+ {"turn", 60},
+ {"myself", 61},
+ {"give", 62},
+ {"nothing", 63},
+ {"really", 64},
+ {"off", 65},
+ {"before", 66},
+ {"something", 67},
+ {"find", 68},
+ {"walk", 69},
+ {"wish", 70},
+ {"good", 71},
+ {"once", 72},
+ {"place", 73},
+ {"ask", 74},
+ {"stop", 75},
+ {"keep", 76},
+ {"watch", 77},
+ {"seem", 78},
+ {"everything", 79},
+ {"wait", 80},
+ {"got", 81},
+ {"yet", 82},
+ {"made", 83},
+ {"remember", 84},
+ {"start", 85},
+ {"alone", 86},
+ {"run", 87},
+ {"hope", 88},
+ {"maybe", 89},
+ {"believe", 90},
+ {"body", 91},
+ {"hate", 92},
+ {"after", 93},
+ {"close", 94},
+ {"talk", 95},
+ {"stand", 96},
+ {"own", 97},
+ {"each", 98},
+ {"hurt", 99},
+ {"help", 100},
+ {"home", 101},
+ {"god", 102},
+ {"soul", 103},
+ {"new", 104},
+ {"many", 105},
+ {"two", 106},
+ {"inside", 107},
+ {"should", 108},
+ {"true", 109},
+ {"first", 110},
+ {"fear", 111},
+ {"mean", 112},
+ {"better", 113},
+ {"play", 114},
+ {"another", 115},
+ {"gone", 116},
+ {"change", 117},
+ {"use", 118},
+ {"wonder", 119},
+ {"someone", 120},
+ {"hair", 121},
+ {"cold", 122},
+ {"open", 123},
+ {"best", 124},
+ {"any", 125},
+ {"behind", 126},
+ {"happen", 127},
+ {"water", 128},
+ {"dark", 129},
+ {"laugh", 130},
+ {"stay", 131},
+ {"forever", 132},
+ {"name", 133},
+ {"work", 134},
+ {"show", 135},
+ {"sky", 136},
+ {"break", 137},
+ {"came", 138},
+ {"deep", 139},
+ {"door", 140},
+ {"put", 141},
+ {"black", 142},
+ {"together", 143},
+ {"upon", 144},
+ {"happy", 145},
+ {"such", 146},
+ {"great", 147},
+ {"white", 148},
+ {"matter", 149},
+ {"fill", 150},
+ {"past", 151},
+ {"please", 152},
+ {"burn", 153},
+ {"cause", 154},
+ {"enough", 155},
+ {"touch", 156},
+ {"moment", 157},
+ {"soon", 158},
+ {"voice", 159},
+ {"scream", 160},
+ {"anything", 161},
+ {"stare", 162},
+ {"sound", 163},
+ {"red", 164},
+ {"everyone", 165},
+ {"hide", 166},
+ {"kiss", 167},
+ {"truth", 168},
+ {"death", 169},
+ {"beautiful", 170},
+ {"mine", 171},
+ {"blood", 172},
+ {"broken", 173},
+ {"very", 174},
+ {"pass", 175},
+ {"next", 176},
+ {"forget", 177},
+ {"tree", 178},
+ {"wrong", 179},
+ {"air", 180},
+ {"mother", 181},
+ {"understand", 182},
+ {"lip", 183},
+ {"hit", 184},
+ {"wall", 185},
+ {"memory", 186},
+ {"sleep", 187},
+ {"free", 188},
+ {"high", 189},
+ {"realize", 190},
+ {"school", 191},
+ {"might", 192},
+ {"skin", 193},
+ {"sweet", 194},
+ {"perfect", 195},
+ {"blue", 196},
+ {"kill", 197},
+ {"breath", 198},
+ {"dance", 199},
+ {"against", 200},
+ {"fly", 201},
+ {"between", 202},
+ {"grow", 203},
+ {"strong", 204},
+ {"under", 205},
+ {"listen", 206},
+ {"bring", 207},
+ {"sometimes", 208},
+ {"speak", 209},
+ {"pull", 210},
+ {"person", 211},
+ {"become", 212},
+ {"family", 213},
+ {"begin", 214},
+ {"ground", 215},
+ {"real", 216},
+ {"small", 217},
+ {"father", 218},
+ {"sure", 219},
+ {"feet", 220},
+ {"rest", 221},
+ {"young", 222},
+ {"finally", 223},
+ {"land", 224},
+ {"across", 225},
+ {"today", 226},
+ {"different", 227},
+ {"guy", 228},
+ {"line", 229},
+ {"fire", 230},
+ {"reason", 231},
+ {"reach", 232},
+ {"second", 233},
+ {"slowly", 234},
+ {"write", 235},
+ {"eat", 236},
+ {"smell", 237},
+ {"mouth", 238},
+ {"step", 239},
+ {"learn", 240},
+ {"three", 241},
+ {"floor", 242},
+ {"promise", 243},
+ {"breathe", 244},
+ {"darkness", 245},
+ {"push", 246},
+ {"earth", 247},
+ {"guess", 248},
+ {"save", 249},
+ {"song", 250},
+ {"above", 251},
+ {"along", 252},
+ {"both", 253},
+ {"color", 254},
+ {"house", 255},
+ {"almost", 256},
+ {"sorry", 257},
+ {"anymore", 258},
+ {"brother", 259},
+ {"okay", 260},
+ {"dear", 261},
+ {"game", 262},
+ {"fade", 263},
+ {"already", 264},
+ {"apart", 265},
+ {"warm", 266},
+ {"beauty", 267},
+ {"heard", 268},
+ {"notice", 269},
+ {"question", 270},
+ {"shine", 271},
+ {"began", 272},
+ {"piece", 273},
+ {"whole", 274},
+ {"shadow", 275},
+ {"secret", 276},
+ {"street", 277},
+ {"within", 278},
+ {"finger", 279},
+ {"point", 280},
+ {"morning", 281},
+ {"whisper", 282},
+ {"child", 283},
+ {"moon", 284},
+ {"green", 285},
+ {"story", 286},
+ {"glass", 287},
+ {"kid", 288},
+ {"silence", 289},
+ {"since", 290},
+ {"soft", 291},
+ {"yourself", 292},
+ {"empty", 293},
+ {"shall", 294},
+ {"angel", 295},
+ {"answer", 296},
+ {"baby", 297},
+ {"bright", 298},
+ {"dad", 299},
+ {"path", 300},
+ {"worry", 301},
+ {"hour", 302},
+ {"drop", 303},
+ {"follow", 304},
+ {"power", 305},
+ {"war", 306},
+ {"half", 307},
+ {"flow", 308},
+ {"heaven", 309},
+ {"act", 310},
+ {"chance", 311},
+ {"fact", 312},
+ {"least", 313},
+ {"tired", 314},
+ {"children", 315},
+ {"near", 316},
+ {"quite", 317},
+ {"afraid", 318},
+ {"rise", 319},
+ {"sea", 320},
+ {"taste", 321},
+ {"window", 322},
+ {"cover", 323},
+ {"nice", 324},
+ {"trust", 325},
+ {"lot", 326},
+ {"sad", 327},
+ {"cool", 328},
+ {"force", 329},
+ {"peace", 330},
+ {"return", 331},
+ {"blind", 332},
+ {"easy", 333},
+ {"ready", 334},
+ {"roll", 335},
+ {"rose", 336},
+ {"drive", 337},
+ {"held", 338},
+ {"music", 339},
+ {"beneath", 340},
+ {"hang", 341},
+ {"mom", 342},
+ {"paint", 343},
+ {"emotion", 344},
+ {"quiet", 345},
+ {"clear", 346},
+ {"cloud", 347},
+ {"few", 348},
+ {"pretty", 349},
+ {"bird", 350},
+ {"outside", 351},
+ {"paper", 352},
+ {"picture", 353},
+ {"front", 354},
+ {"rock", 355},
+ {"simple", 356},
+ {"anyone", 357},
+ {"meant", 358},
+ {"reality", 359},
+ {"road", 360},
+ {"sense", 361},
+ {"waste", 362},
+ {"bit", 363},
+ {"leaf", 364},
+ {"thank", 365},
+ {"happiness", 366},
+ {"meet", 367},
+ {"men", 368},
+ {"smoke", 369},
+ {"truly", 370},
+ {"decide", 371},
+ {"self", 372},
+ {"age", 373},
+ {"book", 374},
+ {"form", 375},
+ {"alive", 376},
+ {"carry", 377},
+ {"escape", 378},
+ {"damn", 379},
+ {"instead", 380},
+ {"able", 381},
+ {"ice", 382},
+ {"minute", 383},
+ {"throw", 384},
+ {"catch", 385},
+ {"leg", 386},
+ {"ring", 387},
+ {"course", 388},
+ {"goodbye", 389},
+ {"lead", 390},
+ {"poem", 391},
+ {"sick", 392},
+ {"corner", 393},
+ {"desire", 394},
+ {"known", 395},
+ {"problem", 396},
+ {"remind", 397},
+ {"shoulder", 398},
+ {"suppose", 399},
+ {"toward", 400},
+ {"wave", 401},
+ {"drink", 402},
+ {"jump", 403},
+ {"woman", 404},
+ {"pretend", 405},
+ {"sister", 406},
+ {"week", 407},
+ {"human", 408},
+ {"joy", 409},
+ {"crack", 410},
+ {"grey", 411},
+ {"pray", 412},
+ {"surprise", 413},
+ {"dry", 414},
+ {"knee", 415},
+ {"less", 416},
+ {"search", 417},
+ {"bleed", 418},
+ {"caught", 419},
+ {"clean", 420},
+ {"embrace", 421},
+ {"future", 422},
+ {"king", 423},
+ {"son", 424},
+ {"sorrow", 425},
+ {"chest", 426},
+ {"hug", 427},
+ {"remain", 428},
+ {"sat", 429},
+ {"worth", 430},
+ {"blow", 431},
+ {"daddy", 432},
+ {"final", 433},
+ {"parent", 434},
+ {"tight", 435},
+ {"also", 436},
+ {"create", 437},
+ {"lonely", 438},
+ {"safe", 439},
+ {"cross", 440},
+ {"dress", 441},
+ {"evil", 442},
+ {"silent", 443},
+ {"bone", 444},
+ {"fate", 445},
+ {"perhaps", 446},
+ {"anger", 447},
+ {"class", 448},
+ {"scar", 449},
+ {"snow", 450},
+ {"tiny", 451},
+ {"tonight", 452},
+ {"continue", 453},
+ {"control", 454},
+ {"dog", 455},
+ {"edge", 456},
+ {"mirror", 457},
+ {"month", 458},
+ {"suddenly", 459},
+ {"comfort", 460},
+ {"given", 461},
+ {"loud", 462},
+ {"quickly", 463},
+ {"gaze", 464},
+ {"plan", 465},
+ {"rush", 466},
+ {"stone", 467},
+ {"town", 468},
+ {"battle", 469},
+ {"ignore", 470},
+ {"spirit", 471},
+ {"stood", 472},
+ {"stupid", 473},
+ {"yours", 474},
+ {"brown", 475},
+ {"build", 476},
+ {"dust", 477},
+ {"hey", 478},
+ {"kept", 479},
+ {"pay", 480},
+ {"phone", 481},
+ {"twist", 482},
+ {"although", 483},
+ {"ball", 484},
+ {"beyond", 485},
+ {"hidden", 486},
+ {"nose", 487},
+ {"taken", 488},
+ {"fail", 489},
+ {"float", 490},
+ {"pure", 491},
+ {"somehow", 492},
+ {"wash", 493},
+ {"wrap", 494},
+ {"angry", 495},
+ {"cheek", 496},
+ {"creature", 497},
+ {"forgotten", 498},
+ {"heat", 499},
+ {"rip", 500},
+ {"single", 501},
+ {"space", 502},
+ {"special", 503},
+ {"weak", 504},
+ {"whatever", 505},
+ {"yell", 506},
+ {"anyway", 507},
+ {"blame", 508},
+ {"job", 509},
+ {"choose", 510},
+ {"country", 511},
+ {"curse", 512},
+ {"drift", 513},
+ {"echo", 514},
+ {"figure", 515},
+ {"grew", 516},
+ {"laughter", 517},
+ {"neck", 518},
+ {"suffer", 519},
+ {"worse", 520},
+ {"yeah", 521},
+ {"disappear", 522},
+ {"foot", 523},
+ {"forward", 524},
+ {"knife", 525},
+ {"mess", 526},
+ {"somewhere", 527},
+ {"stomach", 528},
+ {"storm", 529},
+ {"beg", 530},
+ {"idea", 531},
+ {"lift", 532},
+ {"offer", 533},
+ {"breeze", 534},
+ {"field", 535},
+ {"five", 536},
+ {"often", 537},
+ {"simply", 538},
+ {"stuck", 539},
+ {"win", 540},
+ {"allow", 541},
+ {"confuse", 542},
+ {"enjoy", 543},
+ {"except", 544},
+ {"flower", 545},
+ {"seek", 546},
+ {"strength", 547},
+ {"calm", 548},
+ {"grin", 549},
+ {"gun", 550},
+ {"heavy", 551},
+ {"hill", 552},
+ {"large", 553},
+ {"ocean", 554},
+ {"shoe", 555},
+ {"sigh", 556},
+ {"straight", 557},
+ {"summer", 558},
+ {"tongue", 559},
+ {"accept", 560},
+ {"crazy", 561},
+ {"everyday", 562},
+ {"exist", 563},
+ {"grass", 564},
+ {"mistake", 565},
+ {"sent", 566},
+ {"shut", 567},
+ {"surround", 568},
+ {"table", 569},
+ {"ache", 570},
+ {"brain", 571},
+ {"destroy", 572},
+ {"heal", 573},
+ {"nature", 574},
+ {"shout", 575},
+ {"sign", 576},
+ {"stain", 577},
+ {"choice", 578},
+ {"doubt", 579},
+ {"glance", 580},
+ {"glow", 581},
+ {"mountain", 582},
+ {"queen", 583},
+ {"stranger", 584},
+ {"throat", 585},
+ {"tomorrow", 586},
+ {"city", 587},
+ {"either", 588},
+ {"fish", 589},
+ {"flame", 590},
+ {"rather", 591},
+ {"shape", 592},
+ {"spin", 593},
+ {"spread", 594},
+ {"ash", 595},
+ {"distance", 596},
+ {"finish", 597},
+ {"image", 598},
+ {"imagine", 599},
+ {"important", 600},
+ {"nobody", 601},
+ {"shatter", 602},
+ {"warmth", 603},
+ {"became", 604},
+ {"feed", 605},
+ {"flesh", 606},
+ {"funny", 607},
+ {"lust", 608},
+ {"shirt", 609},
+ {"trouble", 610},
+ {"yellow", 611},
+ {"attention", 612},
+ {"bare", 613},
+ {"bite", 614},
+ {"money", 615},
+ {"protect", 616},
+ {"amaze", 617},
+ {"appear", 618},
+ {"born", 619},
+ {"choke", 620},
+ {"completely", 621},
+ {"daughter", 622},
+ {"fresh", 623},
+ {"friendship", 624},
+ {"gentle", 625},
+ {"probably", 626},
+ {"six", 627},
+ {"deserve", 628},
+ {"expect", 629},
+ {"grab", 630},
+ {"middle", 631},
+ {"nightmare", 632},
+ {"river", 633},
+ {"thousand", 634},
+ {"weight", 635},
+ {"worst", 636},
+ {"wound", 637},
+ {"barely", 638},
+ {"bottle", 639},
+ {"cream", 640},
+ {"regret", 641},
+ {"relationship", 642},
+ {"stick", 643},
+ {"test", 644},
+ {"crush", 645},
+ {"endless", 646},
+ {"fault", 647},
+ {"itself", 648},
+ {"rule", 649},
+ {"spill", 650},
+ {"art", 651},
+ {"circle", 652},
+ {"join", 653},
+ {"kick", 654},
+ {"mask", 655},
+ {"master", 656},
+ {"passion", 657},
+ {"quick", 658},
+ {"raise", 659},
+ {"smooth", 660},
+ {"unless", 661},
+ {"wander", 662},
+ {"actually", 663},
+ {"broke", 664},
+ {"chair", 665},
+ {"deal", 666},
+ {"favorite", 667},
+ {"gift", 668},
+ {"note", 669},
+ {"number", 670},
+ {"sweat", 671},
+ {"box", 672},
+ {"chill", 673},
+ {"clothes", 674},
+ {"lady", 675},
+ {"mark", 676},
+ {"park", 677},
+ {"poor", 678},
+ {"sadness", 679},
+ {"tie", 680},
+ {"animal", 681},
+ {"belong", 682},
+ {"brush", 683},
+ {"consume", 684},
+ {"dawn", 685},
+ {"forest", 686},
+ {"innocent", 687},
+ {"pen", 688},
+ {"pride", 689},
+ {"stream", 690},
+ {"thick", 691},
+ {"clay", 692},
+ {"complete", 693},
+ {"count", 694},
+ {"draw", 695},
+ {"faith", 696},
+ {"press", 697},
+ {"silver", 698},
+ {"struggle", 699},
+ {"surface", 700},
+ {"taught", 701},
+ {"teach", 702},
+ {"wet", 703},
+ {"bless", 704},
+ {"chase", 705},
+ {"climb", 706},
+ {"enter", 707},
+ {"letter", 708},
+ {"melt", 709},
+ {"metal", 710},
+ {"movie", 711},
+ {"stretch", 712},
+ {"swing", 713},
+ {"vision", 714},
+ {"wife", 715},
+ {"beside", 716},
+ {"crash", 717},
+ {"forgot", 718},
+ {"guide", 719},
+ {"haunt", 720},
+ {"joke", 721},
+ {"knock", 722},
+ {"plant", 723},
+ {"pour", 724},
+ {"prove", 725},
+ {"reveal", 726},
+ {"steal", 727},
+ {"stuff", 728},
+ {"trip", 729},
+ {"wood", 730},
+ {"wrist", 731},
+ {"bother", 732},
+ {"bottom", 733},
+ {"crawl", 734},
+ {"crowd", 735},
+ {"fix", 736},
+ {"forgive", 737},
+ {"frown", 738},
+ {"grace", 739},
+ {"loose", 740},
+ {"lucky", 741},
+ {"party", 742},
+ {"release", 743},
+ {"surely", 744},
+ {"survive", 745},
+ {"teacher", 746},
+ {"gently", 747},
+ {"grip", 748},
+ {"speed", 749},
+ {"suicide", 750},
+ {"travel", 751},
+ {"treat", 752},
+ {"vein", 753},
+ {"written", 754},
+ {"cage", 755},
+ {"chain", 756},
+ {"conversation", 757},
+ {"date", 758},
+ {"enemy", 759},
+ {"however", 760},
+ {"interest", 761},
+ {"million", 762},
+ {"page", 763},
+ {"pink", 764},
+ {"proud", 765},
+ {"sway", 766},
+ {"themselves", 767},
+ {"winter", 768},
+ {"church", 769},
+ {"cruel", 770},
+ {"cup", 771},
+ {"demon", 772},
+ {"experience", 773},
+ {"freedom", 774},
+ {"pair", 775},
+ {"pop", 776},
+ {"purpose", 777},
+ {"respect", 778},
+ {"shoot", 779},
+ {"softly", 780},
+ {"state", 781},
+ {"strange", 782},
+ {"bar", 783},
+ {"birth", 784},
+ {"curl", 785},
+ {"dirt", 786},
+ {"excuse", 787},
+ {"lord", 788},
+ {"lovely", 789},
+ {"monster", 790},
+ {"order", 791},
+ {"pack", 792},
+ {"pants", 793},
+ {"pool", 794},
+ {"scene", 795},
+ {"seven", 796},
+ {"shame", 797},
+ {"slide", 798},
+ {"ugly", 799},
+ {"among", 800},
+ {"blade", 801},
+ {"blonde", 802},
+ {"closet", 803},
+ {"creek", 804},
+ {"deny", 805},
+ {"drug", 806},
+ {"eternity", 807},
+ {"gain", 808},
+ {"grade", 809},
+ {"handle", 810},
+ {"key", 811},
+ {"linger", 812},
+ {"pale", 813},
+ {"prepare", 814},
+ {"swallow", 815},
+ {"swim", 816},
+ {"tremble", 817},
+ {"wheel", 818},
+ {"won", 819},
+ {"cast", 820},
+ {"cigarette", 821},
+ {"claim", 822},
+ {"college", 823},
+ {"direction", 824},
+ {"dirty", 825},
+ {"gather", 826},
+ {"ghost", 827},
+ {"hundred", 828},
+ {"loss", 829},
+ {"lung", 830},
+ {"orange", 831},
+ {"present", 832},
+ {"swear", 833},
+ {"swirl", 834},
+ {"twice", 835},
+ {"wild", 836},
+ {"bitter", 837},
+ {"blanket", 838},
+ {"doctor", 839},
+ {"everywhere", 840},
+ {"flash", 841},
+ {"grown", 842},
+ {"knowledge", 843},
+ {"numb", 844},
+ {"pressure", 845},
+ {"radio", 846},
+ {"repeat", 847},
+ {"ruin", 848},
+ {"spend", 849},
+ {"unknown", 850},
+ {"buy", 851},
+ {"clock", 852},
+ {"devil", 853},
+ {"early", 854},
+ {"false", 855},
+ {"fantasy", 856},
+ {"pound", 857},
+ {"precious", 858},
+ {"refuse", 859},
+ {"sheet", 860},
+ {"teeth", 861},
+ {"welcome", 862},
+ {"add", 863},
+ {"ahead", 864},
+ {"block", 865},
+ {"bury", 866},
+ {"caress", 867},
+ {"content", 868},
+ {"depth", 869},
+ {"despite", 870},
+ {"distant", 871},
+ {"marry", 872},
+ {"purple", 873},
+ {"threw", 874},
+ {"whenever", 875},
+ {"bomb", 876},
+ {"dull", 877},
+ {"easily", 878},
+ {"grasp", 879},
+ {"hospital", 880},
+ {"innocence", 881},
+ {"normal", 882},
+ {"receive", 883},
+ {"reply", 884},
+ {"rhyme", 885},
+ {"shade", 886},
+ {"someday", 887},
+ {"sword", 888},
+ {"toe", 889},
+ {"visit", 890},
+ {"asleep", 891},
+ {"bought", 892},
+ {"center", 893},
+ {"consider", 894},
+ {"flat", 895},
+ {"hero", 896},
+ {"history", 897},
+ {"ink", 898},
+ {"insane", 899},
+ {"muscle", 900},
+ {"mystery", 901},
+ {"pocket", 902},
+ {"reflection", 903},
+ {"shove", 904},
+ {"silently", 905},
+ {"smart", 906},
+ {"soldier", 907},
+ {"spot", 908},
+ {"stress", 909},
+ {"train", 910},
+ {"type", 911},
+ {"view", 912},
+ {"whether", 913},
+ {"bus", 914},
+ {"energy", 915},
+ {"explain", 916},
+ {"holy", 917},
+ {"hunger", 918},
+ {"inch", 919},
+ {"magic", 920},
+ {"mix", 921},
+ {"noise", 922},
+ {"nowhere", 923},
+ {"prayer", 924},
+ {"presence", 925},
+ {"shock", 926},
+ {"snap", 927},
+ {"spider", 928},
+ {"study", 929},
+ {"thunder", 930},
+ {"trail", 931},
+ {"admit", 932},
+ {"agree", 933},
+ {"bag", 934},
+ {"bang", 935},
+ {"bound", 936},
+ {"butterfly", 937},
+ {"cute", 938},
+ {"exactly", 939},
+ {"explode", 940},
+ {"familiar", 941},
+ {"fold", 942},
+ {"further", 943},
+ {"pierce", 944},
+ {"reflect", 945},
+ {"scent", 946},
+ {"selfish", 947},
+ {"sharp", 948},
+ {"sink", 949},
+ {"spring", 950},
+ {"stumble", 951},
+ {"universe", 952},
+ {"weep", 953},
+ {"women", 954},
+ {"wonderful", 955},
+ {"action", 956},
+ {"ancient", 957},
+ {"attempt", 958},
+ {"avoid", 959},
+ {"birthday", 960},
+ {"branch", 961},
+ {"chocolate", 962},
+ {"core", 963},
+ {"depress", 964},
+ {"drunk", 965},
+ {"especially", 966},
+ {"focus", 967},
+ {"fruit", 968},
+ {"honest", 969},
+ {"match", 970},
+ {"palm", 971},
+ {"perfectly", 972},
+ {"pillow", 973},
+ {"pity", 974},
+ {"poison", 975},
+ {"roar", 976},
+ {"shift", 977},
+ {"slightly", 978},
+ {"thump", 979},
+ {"truck", 980},
+ {"tune", 981},
+ {"twenty", 982},
+ {"unable", 983},
+ {"wipe", 984},
+ {"wrote", 985},
+ {"coat", 986},
+ {"constant", 987},
+ {"dinner", 988},
+ {"drove", 989},
+ {"egg", 990},
+ {"eternal", 991},
+ {"flight", 992},
+ {"flood", 993},
+ {"frame", 994},
+ {"freak", 995},
+ {"gasp", 996},
+ {"glad", 997},
+ {"hollow", 998},
+ {"motion", 999},
+ {"peer", 1000},
+ {"plastic", 1001},
+ {"root", 1002},
+ {"screen", 1003},
+ {"season", 1004},
+ {"sting", 1005},
+ {"strike", 1006},
+ {"team", 1007},
+ {"unlike", 1008},
+ {"victim", 1009},
+ {"volume", 1010},
+ {"warn", 1011},
+ {"weird", 1012},
+ {"attack", 1013},
+ {"await", 1014},
+ {"awake", 1015},
+ {"built", 1016},
+ {"charm", 1017},
+ {"crave", 1018},
+ {"despair", 1019},
+ {"fought", 1020},
+ {"grant", 1021},
+ {"grief", 1022},
+ {"horse", 1023},
+ {"limit", 1024},
+ {"message", 1025},
+ {"ripple", 1026},
+ {"sanity", 1027},
+ {"scatter", 1028},
+ {"serve", 1029},
+ {"split", 1030},
+ {"string", 1031},
+ {"trick", 1032},
+ {"annoy", 1033},
+ {"blur", 1034},
+ {"boat", 1035},
+ {"brave", 1036},
+ {"clearly", 1037},
+ {"cling", 1038},
+ {"connect", 1039},
+ {"fist", 1040},
+ {"forth", 1041},
+ {"imagination", 1042},
+ {"iron", 1043},
+ {"jock", 1044},
+ {"judge", 1045},
+ {"lesson", 1046},
+ {"milk", 1047},
+ {"misery", 1048},
+ {"nail", 1049},
+ {"naked", 1050},
+ {"ourselves", 1051},
+ {"poet", 1052},
+ {"possible", 1053},
+ {"princess", 1054},
+ {"sail", 1055},
+ {"size", 1056},
+ {"snake", 1057},
+ {"society", 1058},
+ {"stroke", 1059},
+ {"torture", 1060},
+ {"toss", 1061},
+ {"trace", 1062},
+ {"wise", 1063},
+ {"bloom", 1064},
+ {"bullet", 1065},
+ {"cell", 1066},
+ {"check", 1067},
+ {"cost", 1068},
+ {"darling", 1069},
+ {"during", 1070},
+ {"footstep", 1071},
+ {"fragile", 1072},
+ {"hallway", 1073},
+ {"hardly", 1074},
+ {"horizon", 1075},
+ {"invisible", 1076},
+ {"journey", 1077},
+ {"midnight", 1078},
+ {"mud", 1079},
+ {"nod", 1080},
+ {"pause", 1081},
+ {"relax", 1082},
+ {"shiver", 1083},
+ {"sudden", 1084},
+ {"value", 1085},
+ {"youth", 1086},
+ {"abuse", 1087},
+ {"admire", 1088},
+ {"blink", 1089},
+ {"breast", 1090},
+ {"bruise", 1091},
+ {"constantly", 1092},
+ {"couple", 1093},
+ {"creep", 1094},
+ {"curve", 1095},
+ {"difference", 1096},
+ {"dumb", 1097},
+ {"emptiness", 1098},
+ {"gotta", 1099},
+ {"honor", 1100},
+ {"plain", 1101},
+ {"planet", 1102},
+ {"recall", 1103},
+ {"rub", 1104},
+ {"ship", 1105},
+ {"slam", 1106},
+ {"soar", 1107},
+ {"somebody", 1108},
+ {"tightly", 1109},
+ {"weather", 1110},
+ {"adore", 1111},
+ {"approach", 1112},
+ {"bond", 1113},
+ {"bread", 1114},
+ {"burst", 1115},
+ {"candle", 1116},
+ {"coffee", 1117},
+ {"cousin", 1118},
+ {"crime", 1119},
+ {"desert", 1120},
+ {"flutter", 1121},
+ {"frozen", 1122},
+ {"grand", 1123},
+ {"heel", 1124},
+ {"hello", 1125},
+ {"language", 1126},
+ {"level", 1127},
+ {"movement", 1128},
+ {"pleasure", 1129},
+ {"powerful", 1130},
+ {"random", 1131},
+ {"rhythm", 1132},
+ {"settle", 1133},
+ {"silly", 1134},
+ {"slap", 1135},
+ {"sort", 1136},
+ {"spoken", 1137},
+ {"steel", 1138},
+ {"threaten", 1139},
+ {"tumble", 1140},
+ {"upset", 1141},
+ {"aside", 1142},
+ {"awkward", 1143},
+ {"bee", 1144},
+ {"blank", 1145},
+ {"board", 1146},
+ {"button", 1147},
+ {"card", 1148},
+ {"carefully", 1149},
+ {"complain", 1150},
+ {"crap", 1151},
+ {"deeply", 1152},
+ {"discover", 1153},
+ {"drag", 1154},
+ {"dread", 1155},
+ {"effort", 1156},
+ {"entire", 1157},
+ {"fairy", 1158},
+ {"giant", 1159},
+ {"gotten", 1160},
+ {"greet", 1161},
+ {"illusion", 1162},
+ {"jeans", 1163},
+ {"leap", 1164},
+ {"liquid", 1165},
+ {"march", 1166},
+ {"mend", 1167},
+ {"nervous", 1168},
+ {"nine", 1169},
+ {"replace", 1170},
+ {"rope", 1171},
+ {"spine", 1172},
+ {"stole", 1173},
+ {"terror", 1174},
+ {"accident", 1175},
+ {"apple", 1176},
+ {"balance", 1177},
+ {"boom", 1178},
+ {"childhood", 1179},
+ {"collect", 1180},
+ {"demand", 1181},
+ {"depression", 1182},
+ {"eventually", 1183},
+ {"faint", 1184},
+ {"glare", 1185},
+ {"goal", 1186},
+ {"group", 1187},
+ {"honey", 1188},
+ {"kitchen", 1189},
+ {"laid", 1190},
+ {"limb", 1191},
+ {"machine", 1192},
+ {"mere", 1193},
+ {"mold", 1194},
+ {"murder", 1195},
+ {"nerve", 1196},
+ {"painful", 1197},
+ {"poetry", 1198},
+ {"prince", 1199},
+ {"rabbit", 1200},
+ {"shelter", 1201},
+ {"shore", 1202},
+ {"shower", 1203},
+ {"soothe", 1204},
+ {"stair", 1205},
+ {"steady", 1206},
+ {"sunlight", 1207},
+ {"tangle", 1208},
+ {"tease", 1209},
+ {"treasure", 1210},
+ {"uncle", 1211},
+ {"begun", 1212},
+ {"bliss", 1213},
+ {"canvas", 1214},
+ {"cheer", 1215},
+ {"claw", 1216},
+ {"clutch", 1217},
+ {"commit", 1218},
+ {"crimson", 1219},
+ {"crystal", 1220},
+ {"delight", 1221},
+ {"doll", 1222},
+ {"existence", 1223},
+ {"express", 1224},
+ {"fog", 1225},
+ {"football", 1226},
+ {"gay", 1227},
+ {"goose", 1228},
+ {"guard", 1229},
+ {"hatred", 1230},
+ {"illuminate", 1231},
+ {"mass", 1232},
+ {"math", 1233},
+ {"mourn", 1234},
+ {"rich", 1235},
+ {"rough", 1236},
+ {"skip", 1237},
+ {"stir", 1238},
+ {"student", 1239},
+ {"style", 1240},
+ {"support", 1241},
+ {"thorn", 1242},
+ {"tough", 1243},
+ {"yard", 1244},
+ {"yearn", 1245},
+ {"yesterday", 1246},
+ {"advice", 1247},
+ {"appreciate", 1248},
+ {"autumn", 1249},
+ {"bank", 1250},
+ {"beam", 1251},
+ {"bowl", 1252},
+ {"capture", 1253},
+ {"carve", 1254},
+ {"collapse", 1255},
+ {"confusion", 1256},
+ {"creation", 1257},
+ {"dove", 1258},
+ {"feather", 1259},
+ {"girlfriend", 1260},
+ {"glory", 1261},
+ {"government", 1262},
+ {"harsh", 1263},
+ {"hop", 1264},
+ {"inner", 1265},
+ {"loser", 1266},
+ {"moonlight", 1267},
+ {"neighbor", 1268},
+ {"neither", 1269},
+ {"peach", 1270},
+ {"pig", 1271},
+ {"praise", 1272},
+ {"screw", 1273},
+ {"shield", 1274},
+ {"shimmer", 1275},
+ {"sneak", 1276},
+ {"stab", 1277},
+ {"subject", 1278},
+ {"throughout", 1279},
+ {"thrown", 1280},
+ {"tower", 1281},
+ {"twirl", 1282},
+ {"wow", 1283},
+ {"army", 1284},
+ {"arrive", 1285},
+ {"bathroom", 1286},
+ {"bump", 1287},
+ {"cease", 1288},
+ {"cookie", 1289},
+ {"couch", 1290},
+ {"courage", 1291},
+ {"dim", 1292},
+ {"guilt", 1293},
+ {"howl", 1294},
+ {"hum", 1295},
+ {"husband", 1296},
+ {"insult", 1297},
+ {"led", 1298},
+ {"lunch", 1299},
+ {"mock", 1300},
+ {"mostly", 1301},
+ {"natural", 1302},
+ {"nearly", 1303},
+ {"needle", 1304},
+ {"nerd", 1305},
+ {"peaceful", 1306},
+ {"perfection", 1307},
+ {"pile", 1308},
+ {"price", 1309},
+ {"remove", 1310},
+ {"roam", 1311},
+ {"sanctuary", 1312},
+ {"serious", 1313},
+ {"shiny", 1314},
+ {"shook", 1315},
+ {"sob", 1316},
+ {"stolen", 1317},
+ {"tap", 1318},
+ {"vain", 1319},
+ {"void", 1320},
+ {"warrior", 1321},
+ {"wrinkle", 1322},
+ {"affection", 1323},
+ {"apologize", 1324},
+ {"blossom", 1325},
+ {"bounce", 1326},
+ {"bridge", 1327},
+ {"cheap", 1328},
+ {"crumble", 1329},
+ {"decision", 1330},
+ {"descend", 1331},
+ {"desperately", 1332},
+ {"dig", 1333},
+ {"dot", 1334},
+ {"flip", 1335},
+ {"frighten", 1336},
+ {"heartbeat", 1337},
+ {"huge", 1338},
+ {"lazy", 1339},
+ {"lick", 1340},
+ {"odd", 1341},
+ {"opinion", 1342},
+ {"process", 1343},
+ {"puzzle", 1344},
+ {"quietly", 1345},
+ {"retreat", 1346},
+ {"score", 1347},
+ {"sentence", 1348},
+ {"separate", 1349},
+ {"situation", 1350},
+ {"skill", 1351},
+ {"soak", 1352},
+ {"square", 1353},
+ {"stray", 1354},
+ {"taint", 1355},
+ {"task", 1356},
+ {"tide", 1357},
+ {"underneath", 1358},
+ {"veil", 1359},
+ {"whistle", 1360},
+ {"anywhere", 1361},
+ {"bedroom", 1362},
+ {"bid", 1363},
+ {"bloody", 1364},
+ {"burden", 1365},
+ {"careful", 1366},
+ {"compare", 1367},
+ {"concern", 1368},
+ {"curtain", 1369},
+ {"decay", 1370},
+ {"defeat", 1371},
+ {"describe", 1372},
+ {"double", 1373},
+ {"dreamer", 1374},
+ {"driver", 1375},
+ {"dwell", 1376},
+ {"evening", 1377},
+ {"flare", 1378},
+ {"flicker", 1379},
+ {"grandma", 1380},
+ {"guitar", 1381},
+ {"harm", 1382},
+ {"horrible", 1383},
+ {"hungry", 1384},
+ {"indeed", 1385},
+ {"lace", 1386},
+ {"melody", 1387},
+ {"monkey", 1388},
+ {"nation", 1389},
+ {"object", 1390},
+ {"obviously", 1391},
+ {"rainbow", 1392},
+ {"salt", 1393},
+ {"scratch", 1394},
+ {"shown", 1395},
+ {"shy", 1396},
+ {"stage", 1397},
+ {"stun", 1398},
+ {"third", 1399},
+ {"tickle", 1400},
+ {"useless", 1401},
+ {"weakness", 1402},
+ {"worship", 1403},
+ {"worthless", 1404},
+ {"afternoon", 1405},
+ {"beard", 1406},
+ {"boyfriend", 1407},
+ {"bubble", 1408},
+ {"busy", 1409},
+ {"certain", 1410},
+ {"chin", 1411},
+ {"concrete", 1412},
+ {"desk", 1413},
+ {"diamond", 1414},
+ {"doom", 1415},
+ {"drawn", 1416},
+ {"due", 1417},
+ {"felicity", 1418},
+ {"freeze", 1419},
+ {"frost", 1420},
+ {"garden", 1421},
+ {"glide", 1422},
+ {"harmony", 1423},
+ {"hopefully", 1424},
+ {"hunt", 1425},
+ {"jealous", 1426},
+ {"lightning", 1427},
+ {"mama", 1428},
+ {"mercy", 1429},
+ {"peel", 1430},
+ {"physical", 1431},
+ {"position", 1432},
+ {"pulse", 1433},
+ {"punch", 1434},
+ {"quit", 1435},
+ {"rant", 1436},
+ {"respond", 1437},
+ {"salty", 1438},
+ {"sane", 1439},
+ {"satisfy", 1440},
+ {"savior", 1441},
+ {"sheep", 1442},
+ {"slept", 1443},
+ {"social", 1444},
+ {"sport", 1445},
+ {"tuck", 1446},
+ {"utter", 1447},
+ {"valley", 1448},
+ {"wolf", 1449},
+ {"aim", 1450},
+ {"alas", 1451},
+ {"alter", 1452},
+ {"arrow", 1453},
+ {"awaken", 1454},
+ {"beaten", 1455},
+ {"belief", 1456},
+ {"brand", 1457},
+ {"ceiling", 1458},
+ {"cheese", 1459},
+ {"clue", 1460},
+ {"confidence", 1461},
+ {"connection", 1462},
+ {"daily", 1463},
+ {"disguise", 1464},
+ {"eager", 1465},
+ {"erase", 1466},
+ {"essence", 1467},
+ {"everytime", 1468},
+ {"expression", 1469},
+ {"fan", 1470},
+ {"flag", 1471},
+ {"flirt", 1472},
+ {"foul", 1473},
+ {"fur", 1474},
+ {"giggle", 1475},
+ {"glorious", 1476},
+ {"ignorance", 1477},
+ {"law", 1478},
+ {"lifeless", 1479},
+ {"measure", 1480},
+ {"mighty", 1481},
+ {"muse", 1482},
+ {"north", 1483},
+ {"opposite", 1484},
+ {"paradise", 1485},
+ {"patience", 1486},
+ {"patient", 1487},
+ {"pencil", 1488},
+ {"petal", 1489},
+ {"plate", 1490},
+ {"ponder", 1491},
+ {"possibly", 1492},
+ {"practice", 1493},
+ {"slice", 1494},
+ {"spell", 1495},
+ {"stock", 1496},
+ {"strife", 1497},
+ {"strip", 1498},
+ {"suffocate", 1499},
+ {"suit", 1500},
+ {"tender", 1501},
+ {"tool", 1502},
+ {"trade", 1503},
+ {"velvet", 1504},
+ {"verse", 1505},
+ {"waist", 1506},
+ {"witch", 1507},
+ {"aunt", 1508},
+ {"bench", 1509},
+ {"bold", 1510},
+ {"cap", 1511},
+ {"certainly", 1512},
+ {"click", 1513},
+ {"companion", 1514},
+ {"creator", 1515},
+ {"dart", 1516},
+ {"delicate", 1517},
+ {"determine", 1518},
+ {"dish", 1519},
+ {"dragon", 1520},
+ {"drama", 1521},
+ {"drum", 1522},
+ {"dude", 1523},
+ {"everybody", 1524},
+ {"feast", 1525},
+ {"forehead", 1526},
+ {"former", 1527},
+ {"fright", 1528},
+ {"fully", 1529},
+ {"gas", 1530},
+ {"hook", 1531},
+ {"hurl", 1532},
+ {"invite", 1533},
+ {"juice", 1534},
+ {"manage", 1535},
+ {"moral", 1536},
+ {"possess", 1537},
+ {"raw", 1538},
+ {"rebel", 1539},
+ {"royal", 1540},
+ {"scale", 1541},
+ {"scary", 1542},
+ {"several", 1543},
+ {"slight", 1544},
+ {"stubborn", 1545},
+ {"swell", 1546},
+ {"talent", 1547},
+ {"tea", 1548},
+ {"terrible", 1549},
+ {"thread", 1550},
+ {"torment", 1551},
+ {"trickle", 1552},
+ {"usually", 1553},
+ {"vast", 1554},
+ {"violence", 1555},
+ {"weave", 1556},
+ {"acid", 1557},
+ {"agony", 1558},
+ {"ashamed", 1559},
+ {"awe", 1560},
+ {"belly", 1561},
+ {"blend", 1562},
+ {"blush", 1563},
+ {"character", 1564},
+ {"cheat", 1565},
+ {"common", 1566},
+ {"company", 1567},
+ {"coward", 1568},
+ {"creak", 1569},
+ {"danger", 1570},
+ {"deadly", 1571},
+ {"defense", 1572},
+ {"define", 1573},
+ {"depend", 1574},
+ {"desperate", 1575},
+ {"destination", 1576},
+ {"dew", 1577},
+ {"duck", 1578},
+ {"dusty", 1579},
+ {"embarrass", 1580},
+ {"engine", 1581},
+ {"example", 1582},
+ {"explore", 1583},
+ {"foe", 1584},
+ {"freely", 1585},
+ {"frustrate", 1586},
+ {"generation", 1587},
+ {"glove", 1588},
+ {"guilty", 1589},
+ {"health", 1590},
+ {"hurry", 1591},
+ {"idiot", 1592},
+ {"impossible", 1593},
+ {"inhale", 1594},
+ {"jaw", 1595},
+ {"kingdom", 1596},
+ {"mention", 1597},
+ {"mist", 1598},
+ {"moan", 1599},
+ {"mumble", 1600},
+ {"mutter", 1601},
+ {"observe", 1602},
+ {"ode", 1603},
+ {"pathetic", 1604},
+ {"pattern", 1605},
+ {"pie", 1606},
+ {"prefer", 1607},
+ {"puff", 1608},
+ {"rape", 1609},
+ {"rare", 1610},
+ {"revenge", 1611},
+ {"rude", 1612},
+ {"scrape", 1613},
+ {"spiral", 1614},
+ {"squeeze", 1615},
+ {"strain", 1616},
+ {"sunset", 1617},
+ {"suspend", 1618},
+ {"sympathy", 1619},
+ {"thigh", 1620},
+ {"throne", 1621},
+ {"total", 1622},
+ {"unseen", 1623},
+ {"weapon", 1624},
+ {"weary", 1625}
+ };
+
+ const std::string wordsArray[] = {
+ "like",
+ "just",
+ "love",
+ "know",
+ "never",
+ "want",
+ "time",
+ "out",
+ "there",
+ "make",
+ "look",
+ "eye",
+ "down",
+ "only",
+ "think",
+ "heart",
+ "back",
+ "then",
+ "into",
+ "about",
+ "more",
+ "away",
+ "still",
+ "them",
+ "take",
+ "thing",
+ "even",
+ "through",
+ "long",
+ "always",
+ "world",
+ "too",
+ "friend",
+ "tell",
+ "try",
+ "hand",
+ "thought",
+ "over",
+ "here",
+ "other",
+ "need",
+ "smile",
+ "again",
+ "much",
+ "cry",
+ "been",
+ "night",
+ "ever",
+ "little",
+ "said",
+ "end",
+ "some",
+ "those",
+ "around",
+ "mind",
+ "people",
+ "girl",
+ "leave",
+ "dream",
+ "left",
+ "turn",
+ "myself",
+ "give",
+ "nothing",
+ "really",
+ "off",
+ "before",
+ "something",
+ "find",
+ "walk",
+ "wish",
+ "good",
+ "once",
+ "place",
+ "ask",
+ "stop",
+ "keep",
+ "watch",
+ "seem",
+ "everything",
+ "wait",
+ "got",
+ "yet",
+ "made",
+ "remember",
+ "start",
+ "alone",
+ "run",
+ "hope",
+ "maybe",
+ "believe",
+ "body",
+ "hate",
+ "after",
+ "close",
+ "talk",
+ "stand",
+ "own",
+ "each",
+ "hurt",
+ "help",
+ "home",
+ "god",
+ "soul",
+ "new",
+ "many",
+ "two",
+ "inside",
+ "should",
+ "true",
+ "first",
+ "fear",
+ "mean",
+ "better",
+ "play",
+ "another",
+ "gone",
+ "change",
+ "use",
+ "wonder",
+ "someone",
+ "hair",
+ "cold",
+ "open",
+ "best",
+ "any",
+ "behind",
+ "happen",
+ "water",
+ "dark",
+ "laugh",
+ "stay",
+ "forever",
+ "name",
+ "work",
+ "show",
+ "sky",
+ "break",
+ "came",
+ "deep",
+ "door",
+ "put",
+ "black",
+ "together",
+ "upon",
+ "happy",
+ "such",
+ "great",
+ "white",
+ "matter",
+ "fill",
+ "past",
+ "please",
+ "burn",
+ "cause",
+ "enough",
+ "touch",
+ "moment",
+ "soon",
+ "voice",
+ "scream",
+ "anything",
+ "stare",
+ "sound",
+ "red",
+ "everyone",
+ "hide",
+ "kiss",
+ "truth",
+ "death",
+ "beautiful",
+ "mine",
+ "blood",
+ "broken",
+ "very",
+ "pass",
+ "next",
+ "forget",
+ "tree",
+ "wrong",
+ "air",
+ "mother",
+ "understand",
+ "lip",
+ "hit",
+ "wall",
+ "memory",
+ "sleep",
+ "free",
+ "high",
+ "realize",
+ "school",
+ "might",
+ "skin",
+ "sweet",
+ "perfect",
+ "blue",
+ "kill",
+ "breath",
+ "dance",
+ "against",
+ "fly",
+ "between",
+ "grow",
+ "strong",
+ "under",
+ "listen",
+ "bring",
+ "sometimes",
+ "speak",
+ "pull",
+ "person",
+ "become",
+ "family",
+ "begin",
+ "ground",
+ "real",
+ "small",
+ "father",
+ "sure",
+ "feet",
+ "rest",
+ "young",
+ "finally",
+ "land",
+ "across",
+ "today",
+ "different",
+ "guy",
+ "line",
+ "fire",
+ "reason",
+ "reach",
+ "second",
+ "slowly",
+ "write",
+ "eat",
+ "smell",
+ "mouth",
+ "step",
+ "learn",
+ "three",
+ "floor",
+ "promise",
+ "breathe",
+ "darkness",
+ "push",
+ "earth",
+ "guess",
+ "save",
+ "song",
+ "above",
+ "along",
+ "both",
+ "color",
+ "house",
+ "almost",
+ "sorry",
+ "anymore",
+ "brother",
+ "okay",
+ "dear",
+ "game",
+ "fade",
+ "already",
+ "apart",
+ "warm",
+ "beauty",
+ "heard",
+ "notice",
+ "question",
+ "shine",
+ "began",
+ "piece",
+ "whole",
+ "shadow",
+ "secret",
+ "street",
+ "within",
+ "finger",
+ "point",
+ "morning",
+ "whisper",
+ "child",
+ "moon",
+ "green",
+ "story",
+ "glass",
+ "kid",
+ "silence",
+ "since",
+ "soft",
+ "yourself",
+ "empty",
+ "shall",
+ "angel",
+ "answer",
+ "baby",
+ "bright",
+ "dad",
+ "path",
+ "worry",
+ "hour",
+ "drop",
+ "follow",
+ "power",
+ "war",
+ "half",
+ "flow",
+ "heaven",
+ "act",
+ "chance",
+ "fact",
+ "least",
+ "tired",
+ "children",
+ "near",
+ "quite",
+ "afraid",
+ "rise",
+ "sea",
+ "taste",
+ "window",
+ "cover",
+ "nice",
+ "trust",
+ "lot",
+ "sad",
+ "cool",
+ "force",
+ "peace",
+ "return",
+ "blind",
+ "easy",
+ "ready",
+ "roll",
+ "rose",
+ "drive",
+ "held",
+ "music",
+ "beneath",
+ "hang",
+ "mom",
+ "paint",
+ "emotion",
+ "quiet",
+ "clear",
+ "cloud",
+ "few",
+ "pretty",
+ "bird",
+ "outside",
+ "paper",
+ "picture",
+ "front",
+ "rock",
+ "simple",
+ "anyone",
+ "meant",
+ "reality",
+ "road",
+ "sense",
+ "waste",
+ "bit",
+ "leaf",
+ "thank",
+ "happiness",
+ "meet",
+ "men",
+ "smoke",
+ "truly",
+ "decide",
+ "self",
+ "age",
+ "book",
+ "form",
+ "alive",
+ "carry",
+ "escape",
+ "damn",
+ "instead",
+ "able",
+ "ice",
+ "minute",
+ "throw",
+ "catch",
+ "leg",
+ "ring",
+ "course",
+ "goodbye",
+ "lead",
+ "poem",
+ "sick",
+ "corner",
+ "desire",
+ "known",
+ "problem",
+ "remind",
+ "shoulder",
+ "suppose",
+ "toward",
+ "wave",
+ "drink",
+ "jump",
+ "woman",
+ "pretend",
+ "sister",
+ "week",
+ "human",
+ "joy",
+ "crack",
+ "grey",
+ "pray",
+ "surprise",
+ "dry",
+ "knee",
+ "less",
+ "search",
+ "bleed",
+ "caught",
+ "clean",
+ "embrace",
+ "future",
+ "king",
+ "son",
+ "sorrow",
+ "chest",
+ "hug",
+ "remain",
+ "sat",
+ "worth",
+ "blow",
+ "daddy",
+ "final",
+ "parent",
+ "tight",
+ "also",
+ "create",
+ "lonely",
+ "safe",
+ "cross",
+ "dress",
+ "evil",
+ "silent",
+ "bone",
+ "fate",
+ "perhaps",
+ "anger",
+ "class",
+ "scar",
+ "snow",
+ "tiny",
+ "tonight",
+ "continue",
+ "control",
+ "dog",
+ "edge",
+ "mirror",
+ "month",
+ "suddenly",
+ "comfort",
+ "given",
+ "loud",
+ "quickly",
+ "gaze",
+ "plan",
+ "rush",
+ "stone",
+ "town",
+ "battle",
+ "ignore",
+ "spirit",
+ "stood",
+ "stupid",
+ "yours",
+ "brown",
+ "build",
+ "dust",
+ "hey",
+ "kept",
+ "pay",
+ "phone",
+ "twist",
+ "although",
+ "ball",
+ "beyond",
+ "hidden",
+ "nose",
+ "taken",
+ "fail",
+ "float",
+ "pure",
+ "somehow",
+ "wash",
+ "wrap",
+ "angry",
+ "cheek",
+ "creature",
+ "forgotten",
+ "heat",
+ "rip",
+ "single",
+ "space",
+ "special",
+ "weak",
+ "whatever",
+ "yell",
+ "anyway",
+ "blame",
+ "job",
+ "choose",
+ "country",
+ "curse",
+ "drift",
+ "echo",
+ "figure",
+ "grew",
+ "laughter",
+ "neck",
+ "suffer",
+ "worse",
+ "yeah",
+ "disappear",
+ "foot",
+ "forward",
+ "knife",
+ "mess",
+ "somewhere",
+ "stomach",
+ "storm",
+ "beg",
+ "idea",
+ "lift",
+ "offer",
+ "breeze",
+ "field",
+ "five",
+ "often",
+ "simply",
+ "stuck",
+ "win",
+ "allow",
+ "confuse",
+ "enjoy",
+ "except",
+ "flower",
+ "seek",
+ "strength",
+ "calm",
+ "grin",
+ "gun",
+ "heavy",
+ "hill",
+ "large",
+ "ocean",
+ "shoe",
+ "sigh",
+ "straight",
+ "summer",
+ "tongue",
+ "accept",
+ "crazy",
+ "everyday",
+ "exist",
+ "grass",
+ "mistake",
+ "sent",
+ "shut",
+ "surround",
+ "table",
+ "ache",
+ "brain",
+ "destroy",
+ "heal",
+ "nature",
+ "shout",
+ "sign",
+ "stain",
+ "choice",
+ "doubt",
+ "glance",
+ "glow",
+ "mountain",
+ "queen",
+ "stranger",
+ "throat",
+ "tomorrow",
+ "city",
+ "either",
+ "fish",
+ "flame",
+ "rather",
+ "shape",
+ "spin",
+ "spread",
+ "ash",
+ "distance",
+ "finish",
+ "image",
+ "imagine",
+ "important",
+ "nobody",
+ "shatter",
+ "warmth",
+ "became",
+ "feed",
+ "flesh",
+ "funny",
+ "lust",
+ "shirt",
+ "trouble",
+ "yellow",
+ "attention",
+ "bare",
+ "bite",
+ "money",
+ "protect",
+ "amaze",
+ "appear",
+ "born",
+ "choke",
+ "completely",
+ "daughter",
+ "fresh",
+ "friendship",
+ "gentle",
+ "probably",
+ "six",
+ "deserve",
+ "expect",
+ "grab",
+ "middle",
+ "nightmare",
+ "river",
+ "thousand",
+ "weight",
+ "worst",
+ "wound",
+ "barely",
+ "bottle",
+ "cream",
+ "regret",
+ "relationship",
+ "stick",
+ "test",
+ "crush",
+ "endless",
+ "fault",
+ "itself",
+ "rule",
+ "spill",
+ "art",
+ "circle",
+ "join",
+ "kick",
+ "mask",
+ "master",
+ "passion",
+ "quick",
+ "raise",
+ "smooth",
+ "unless",
+ "wander",
+ "actually",
+ "broke",
+ "chair",
+ "deal",
+ "favorite",
+ "gift",
+ "note",
+ "number",
+ "sweat",
+ "box",
+ "chill",
+ "clothes",
+ "lady",
+ "mark",
+ "park",
+ "poor",
+ "sadness",
+ "tie",
+ "animal",
+ "belong",
+ "brush",
+ "consume",
+ "dawn",
+ "forest",
+ "innocent",
+ "pen",
+ "pride",
+ "stream",
+ "thick",
+ "clay",
+ "complete",
+ "count",
+ "draw",
+ "faith",
+ "press",
+ "silver",
+ "struggle",
+ "surface",
+ "taught",
+ "teach",
+ "wet",
+ "bless",
+ "chase",
+ "climb",
+ "enter",
+ "letter",
+ "melt",
+ "metal",
+ "movie",
+ "stretch",
+ "swing",
+ "vision",
+ "wife",
+ "beside",
+ "crash",
+ "forgot",
+ "guide",
+ "haunt",
+ "joke",
+ "knock",
+ "plant",
+ "pour",
+ "prove",
+ "reveal",
+ "steal",
+ "stuff",
+ "trip",
+ "wood",
+ "wrist",
+ "bother",
+ "bottom",
+ "crawl",
+ "crowd",
+ "fix",
+ "forgive",
+ "frown",
+ "grace",
+ "loose",
+ "lucky",
+ "party",
+ "release",
+ "surely",
+ "survive",
+ "teacher",
+ "gently",
+ "grip",
+ "speed",
+ "suicide",
+ "travel",
+ "treat",
+ "vein",
+ "written",
+ "cage",
+ "chain",
+ "conversation",
+ "date",
+ "enemy",
+ "however",
+ "interest",
+ "million",
+ "page",
+ "pink",
+ "proud",
+ "sway",
+ "themselves",
+ "winter",
+ "church",
+ "cruel",
+ "cup",
+ "demon",
+ "experience",
+ "freedom",
+ "pair",
+ "pop",
+ "purpose",
+ "respect",
+ "shoot",
+ "softly",
+ "state",
+ "strange",
+ "bar",
+ "birth",
+ "curl",
+ "dirt",
+ "excuse",
+ "lord",
+ "lovely",
+ "monster",
+ "order",
+ "pack",
+ "pants",
+ "pool",
+ "scene",
+ "seven",
+ "shame",
+ "slide",
+ "ugly",
+ "among",
+ "blade",
+ "blonde",
+ "closet",
+ "creek",
+ "deny",
+ "drug",
+ "eternity",
+ "gain",
+ "grade",
+ "handle",
+ "key",
+ "linger",
+ "pale",
+ "prepare",
+ "swallow",
+ "swim",
+ "tremble",
+ "wheel",
+ "won",
+ "cast",
+ "cigarette",
+ "claim",
+ "college",
+ "direction",
+ "dirty",
+ "gather",
+ "ghost",
+ "hundred",
+ "loss",
+ "lung",
+ "orange",
+ "present",
+ "swear",
+ "swirl",
+ "twice",
+ "wild",
+ "bitter",
+ "blanket",
+ "doctor",
+ "everywhere",
+ "flash",
+ "grown",
+ "knowledge",
+ "numb",
+ "pressure",
+ "radio",
+ "repeat",
+ "ruin",
+ "spend",
+ "unknown",
+ "buy",
+ "clock",
+ "devil",
+ "early",
+ "false",
+ "fantasy",
+ "pound",
+ "precious",
+ "refuse",
+ "sheet",
+ "teeth",
+ "welcome",
+ "add",
+ "ahead",
+ "block",
+ "bury",
+ "caress",
+ "content",
+ "depth",
+ "despite",
+ "distant",
+ "marry",
+ "purple",
+ "threw",
+ "whenever",
+ "bomb",
+ "dull",
+ "easily",
+ "grasp",
+ "hospital",
+ "innocence",
+ "normal",
+ "receive",
+ "reply",
+ "rhyme",
+ "shade",
+ "someday",
+ "sword",
+ "toe",
+ "visit",
+ "asleep",
+ "bought",
+ "center",
+ "consider",
+ "flat",
+ "hero",
+ "history",
+ "ink",
+ "insane",
+ "muscle",
+ "mystery",
+ "pocket",
+ "reflection",
+ "shove",
+ "silently",
+ "smart",
+ "soldier",
+ "spot",
+ "stress",
+ "train",
+ "type",
+ "view",
+ "whether",
+ "bus",
+ "energy",
+ "explain",
+ "holy",
+ "hunger",
+ "inch",
+ "magic",
+ "mix",
+ "noise",
+ "nowhere",
+ "prayer",
+ "presence",
+ "shock",
+ "snap",
+ "spider",
+ "study",
+ "thunder",
+ "trail",
+ "admit",
+ "agree",
+ "bag",
+ "bang",
+ "bound",
+ "butterfly",
+ "cute",
+ "exactly",
+ "explode",
+ "familiar",
+ "fold",
+ "further",
+ "pierce",
+ "reflect",
+ "scent",
+ "selfish",
+ "sharp",
+ "sink",
+ "spring",
+ "stumble",
+ "universe",
+ "weep",
+ "women",
+ "wonderful",
+ "action",
+ "ancient",
+ "attempt",
+ "avoid",
+ "birthday",
+ "branch",
+ "chocolate",
+ "core",
+ "depress",
+ "drunk",
+ "especially",
+ "focus",
+ "fruit",
+ "honest",
+ "match",
+ "palm",
+ "perfectly",
+ "pillow",
+ "pity",
+ "poison",
+ "roar",
+ "shift",
+ "slightly",
+ "thump",
+ "truck",
+ "tune",
+ "twenty",
+ "unable",
+ "wipe",
+ "wrote",
+ "coat",
+ "constant",
+ "dinner",
+ "drove",
+ "egg",
+ "eternal",
+ "flight",
+ "flood",
+ "frame",
+ "freak",
+ "gasp",
+ "glad",
+ "hollow",
+ "motion",
+ "peer",
+ "plastic",
+ "root",
+ "screen",
+ "season",
+ "sting",
+ "strike",
+ "team",
+ "unlike",
+ "victim",
+ "volume",
+ "warn",
+ "weird",
+ "attack",
+ "await",
+ "awake",
+ "built",
+ "charm",
+ "crave",
+ "despair",
+ "fought",
+ "grant",
+ "grief",
+ "horse",
+ "limit",
+ "message",
+ "ripple",
+ "sanity",
+ "scatter",
+ "serve",
+ "split",
+ "string",
+ "trick",
+ "annoy",
+ "blur",
+ "boat",
+ "brave",
+ "clearly",
+ "cling",
+ "connect",
+ "fist",
+ "forth",
+ "imagination",
+ "iron",
+ "jock",
+ "judge",
+ "lesson",
+ "milk",
+ "misery",
+ "nail",
+ "naked",
+ "ourselves",
+ "poet",
+ "possible",
+ "princess",
+ "sail",
+ "size",
+ "snake",
+ "society",
+ "stroke",
+ "torture",
+ "toss",
+ "trace",
+ "wise",
+ "bloom",
+ "bullet",
+ "cell",
+ "check",
+ "cost",
+ "darling",
+ "during",
+ "footstep",
+ "fragile",
+ "hallway",
+ "hardly",
+ "horizon",
+ "invisible",
+ "journey",
+ "midnight",
+ "mud",
+ "nod",
+ "pause",
+ "relax",
+ "shiver",
+ "sudden",
+ "value",
+ "youth",
+ "abuse",
+ "admire",
+ "blink",
+ "breast",
+ "bruise",
+ "constantly",
+ "couple",
+ "creep",
+ "curve",
+ "difference",
+ "dumb",
+ "emptiness",
+ "gotta",
+ "honor",
+ "plain",
+ "planet",
+ "recall",
+ "rub",
+ "ship",
+ "slam",
+ "soar",
+ "somebody",
+ "tightly",
+ "weather",
+ "adore",
+ "approach",
+ "bond",
+ "bread",
+ "burst",
+ "candle",
+ "coffee",
+ "cousin",
+ "crime",
+ "desert",
+ "flutter",
+ "frozen",
+ "grand",
+ "heel",
+ "hello",
+ "language",
+ "level",
+ "movement",
+ "pleasure",
+ "powerful",
+ "random",
+ "rhythm",
+ "settle",
+ "silly",
+ "slap",
+ "sort",
+ "spoken",
+ "steel",
+ "threaten",
+ "tumble",
+ "upset",
+ "aside",
+ "awkward",
+ "bee",
+ "blank",
+ "board",
+ "button",
+ "card",
+ "carefully",
+ "complain",
+ "crap",
+ "deeply",
+ "discover",
+ "drag",
+ "dread",
+ "effort",
+ "entire",
+ "fairy",
+ "giant",
+ "gotten",
+ "greet",
+ "illusion",
+ "jeans",
+ "leap",
+ "liquid",
+ "march",
+ "mend",
+ "nervous",
+ "nine",
+ "replace",
+ "rope",
+ "spine",
+ "stole",
+ "terror",
+ "accident",
+ "apple",
+ "balance",
+ "boom",
+ "childhood",
+ "collect",
+ "demand",
+ "depression",
+ "eventually",
+ "faint",
+ "glare",
+ "goal",
+ "group",
+ "honey",
+ "kitchen",
+ "laid",
+ "limb",
+ "machine",
+ "mere",
+ "mold",
+ "murder",
+ "nerve",
+ "painful",
+ "poetry",
+ "prince",
+ "rabbit",
+ "shelter",
+ "shore",
+ "shower",
+ "soothe",
+ "stair",
+ "steady",
+ "sunlight",
+ "tangle",
+ "tease",
+ "treasure",
+ "uncle",
+ "begun",
+ "bliss",
+ "canvas",
+ "cheer",
+ "claw",
+ "clutch",
+ "commit",
+ "crimson",
+ "crystal",
+ "delight",
+ "doll",
+ "existence",
+ "express",
+ "fog",
+ "football",
+ "gay",
+ "goose",
+ "guard",
+ "hatred",
+ "illuminate",
+ "mass",
+ "math",
+ "mourn",
+ "rich",
+ "rough",
+ "skip",
+ "stir",
+ "student",
+ "style",
+ "support",
+ "thorn",
+ "tough",
+ "yard",
+ "yearn",
+ "yesterday",
+ "advice",
+ "appreciate",
+ "autumn",
+ "bank",
+ "beam",
+ "bowl",
+ "capture",
+ "carve",
+ "collapse",
+ "confusion",
+ "creation",
+ "dove",
+ "feather",
+ "girlfriend",
+ "glory",
+ "government",
+ "harsh",
+ "hop",
+ "inner",
+ "loser",
+ "moonlight",
+ "neighbor",
+ "neither",
+ "peach",
+ "pig",
+ "praise",
+ "screw",
+ "shield",
+ "shimmer",
+ "sneak",
+ "stab",
+ "subject",
+ "throughout",
+ "thrown",
+ "tower",
+ "twirl",
+ "wow",
+ "army",
+ "arrive",
+ "bathroom",
+ "bump",
+ "cease",
+ "cookie",
+ "couch",
+ "courage",
+ "dim",
+ "guilt",
+ "howl",
+ "hum",
+ "husband",
+ "insult",
+ "led",
+ "lunch",
+ "mock",
+ "mostly",
+ "natural",
+ "nearly",
+ "needle",
+ "nerd",
+ "peaceful",
+ "perfection",
+ "pile",
+ "price",
+ "remove",
+ "roam",
+ "sanctuary",
+ "serious",
+ "shiny",
+ "shook",
+ "sob",
+ "stolen",
+ "tap",
+ "vain",
+ "void",
+ "warrior",
+ "wrinkle",
+ "affection",
+ "apologize",
+ "blossom",
+ "bounce",
+ "bridge",
+ "cheap",
+ "crumble",
+ "decision",
+ "descend",
+ "desperately",
+ "dig",
+ "dot",
+ "flip",
+ "frighten",
+ "heartbeat",
+ "huge",
+ "lazy",
+ "lick",
+ "odd",
+ "opinion",
+ "process",
+ "puzzle",
+ "quietly",
+ "retreat",
+ "score",
+ "sentence",
+ "separate",
+ "situation",
+ "skill",
+ "soak",
+ "square",
+ "stray",
+ "taint",
+ "task",
+ "tide",
+ "underneath",
+ "veil",
+ "whistle",
+ "anywhere",
+ "bedroom",
+ "bid",
+ "bloody",
+ "burden",
+ "careful",
+ "compare",
+ "concern",
+ "curtain",
+ "decay",
+ "defeat",
+ "describe",
+ "double",
+ "dreamer",
+ "driver",
+ "dwell",
+ "evening",
+ "flare",
+ "flicker",
+ "grandma",
+ "guitar",
+ "harm",
+ "horrible",
+ "hungry",
+ "indeed",
+ "lace",
+ "melody",
+ "monkey",
+ "nation",
+ "object",
+ "obviously",
+ "rainbow",
+ "salt",
+ "scratch",
+ "shown",
+ "shy",
+ "stage",
+ "stun",
+ "third",
+ "tickle",
+ "useless",
+ "weakness",
+ "worship",
+ "worthless",
+ "afternoon",
+ "beard",
+ "boyfriend",
+ "bubble",
+ "busy",
+ "certain",
+ "chin",
+ "concrete",
+ "desk",
+ "diamond",
+ "doom",
+ "drawn",
+ "due",
+ "felicity",
+ "freeze",
+ "frost",
+ "garden",
+ "glide",
+ "harmony",
+ "hopefully",
+ "hunt",
+ "jealous",
+ "lightning",
+ "mama",
+ "mercy",
+ "peel",
+ "physical",
+ "position",
+ "pulse",
+ "punch",
+ "quit",
+ "rant",
+ "respond",
+ "salty",
+ "sane",
+ "satisfy",
+ "savior",
+ "sheep",
+ "slept",
+ "social",
+ "sport",
+ "tuck",
+ "utter",
+ "valley",
+ "wolf",
+ "aim",
+ "alas",
+ "alter",
+ "arrow",
+ "awaken",
+ "beaten",
+ "belief",
+ "brand",
+ "ceiling",
+ "cheese",
+ "clue",
+ "confidence",
+ "connection",
+ "daily",
+ "disguise",
+ "eager",
+ "erase",
+ "essence",
+ "everytime",
+ "expression",
+ "fan",
+ "flag",
+ "flirt",
+ "foul",
+ "fur",
+ "giggle",
+ "glorious",
+ "ignorance",
+ "law",
+ "lifeless",
+ "measure",
+ "mighty",
+ "muse",
+ "north",
+ "opposite",
+ "paradise",
+ "patience",
+ "patient",
+ "pencil",
+ "petal",
+ "plate",
+ "ponder",
+ "possibly",
+ "practice",
+ "slice",
+ "spell",
+ "stock",
+ "strife",
+ "strip",
+ "suffocate",
+ "suit",
+ "tender",
+ "tool",
+ "trade",
+ "velvet",
+ "verse",
+ "waist",
+ "witch",
+ "aunt",
+ "bench",
+ "bold",
+ "cap",
+ "certainly",
+ "click",
+ "companion",
+ "creator",
+ "dart",
+ "delicate",
+ "determine",
+ "dish",
+ "dragon",
+ "drama",
+ "drum",
+ "dude",
+ "everybody",
+ "feast",
+ "forehead",
+ "former",
+ "fright",
+ "fully",
+ "gas",
+ "hook",
+ "hurl",
+ "invite",
+ "juice",
+ "manage",
+ "moral",
+ "possess",
+ "raw",
+ "rebel",
+ "royal",
+ "scale",
+ "scary",
+ "several",
+ "slight",
+ "stubborn",
+ "swell",
+ "talent",
+ "tea",
+ "terrible",
+ "thread",
+ "torment",
+ "trickle",
+ "usually",
+ "vast",
+ "violence",
+ "weave",
+ "acid",
+ "agony",
+ "ashamed",
+ "awe",
+ "belly",
+ "blend",
+ "blush",
+ "character",
+ "cheat",
+ "common",
+ "company",
+ "coward",
+ "creak",
+ "danger",
+ "deadly",
+ "defense",
+ "define",
+ "depend",
+ "desperate",
+ "destination",
+ "dew",
+ "duck",
+ "dusty",
+ "embarrass",
+ "engine",
+ "example",
+ "explore",
+ "foe",
+ "freely",
+ "frustrate",
+ "generation",
+ "glove",
+ "guilty",
+ "health",
+ "hurry",
+ "idiot",
+ "impossible",
+ "inhale",
+ "jaw",
+ "kingdom",
+ "mention",
+ "mist",
+ "moan",
+ "mumble",
+ "mutter",
+ "observe",
+ "ode",
+ "pathetic",
+ "pattern",
+ "pie",
+ "prefer",
+ "puff",
+ "rape",
+ "rare",
+ "revenge",
+ "rude",
+ "scrape",
+ "spiral",
+ "squeeze",
+ "strain",
+ "sunset",
+ "suspend",
+ "sympathy",
+ "thigh",
+ "throne",
+ "total",
+ "unseen",
+ "weapon",
+ "weary"
+ };
+ }
+}
diff --git a/src/crypto/oaes_config.h b/src/crypto/oaes_config.h
index 8a58c3cfc..3fc0e1be5 100644
--- a/src/crypto/oaes_config.h
+++ b/src/crypto/oaes_config.h
@@ -39,9 +39,9 @@ extern "C" {
//#define OAES_HAVE_ISAAC 1
//#endif // OAES_HAVE_ISAAC
-#ifndef OAES_DEBUG
-#define OAES_DEBUG 0
-#endif // OAES_DEBUG
+//#ifndef OAES_DEBUG
+//#define OAES_DEBUG 0
+//#endif // OAES_DEBUG
#ifdef __cplusplus
}
diff --git a/src/crypto/oaes_lib.c b/src/crypto/oaes_lib.c
index 126f0a2f6..f3f2aac8c 100644
--- a/src/crypto/oaes_lib.c
+++ b/src/crypto/oaes_lib.c
@@ -64,31 +64,6 @@ static const char _NR[] = {
# define min(a,b) (((a)<(b)) ? (a) : (b))
#endif /* min */
-typedef struct _oaes_key
-{
- size_t data_len;
- uint8_t *data;
- size_t exp_data_len;
- uint8_t *exp_data;
- size_t num_keys;
- size_t key_base;
-} oaes_key;
-
-typedef struct _oaes_ctx
-{
-#ifdef OAES_HAVE_ISAAC
- randctx * rctx;
-#endif // OAES_HAVE_ISAAC
-
-#ifdef OAES_DEBUG
- oaes_step_cb step_cb;
-#endif // OAES_DEBUG
-
- oaes_key * key;
- OAES_OPTION options;
- uint8_t iv[OAES_BLOCK_SIZE];
-} oaes_ctx;
-
// "OAES<8-bit header version><8-bit type><16-bit options><8-bit flags><56-bit reserved>"
static uint8_t oaes_header[OAES_BLOCK_SIZE] = {
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
diff --git a/src/crypto/oaes_lib.h b/src/crypto/oaes_lib.h
index 9155bce02..fd1942822 100644
--- a/src/crypto/oaes_lib.h
+++ b/src/crypto/oaes_lib.h
@@ -32,6 +32,7 @@
#define _OAES_LIB_H
#include <stdint.h>
+#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
@@ -101,6 +102,30 @@ typedef int ( * oaes_step_cb ) (
typedef uint16_t OAES_OPTION;
+typedef struct _oaes_key
+{
+ size_t data_len;
+ uint8_t *data;
+ size_t exp_data_len;
+ uint8_t *exp_data;
+ size_t num_keys;
+ size_t key_base;
+} oaes_key;
+
+typedef struct _oaes_ctx
+{
+#ifdef OAES_HAVE_ISAAC
+ randctx * rctx;
+#endif // OAES_HAVE_ISAAC
+
+#ifdef OAES_DEBUG
+ oaes_step_cb step_cb;
+#endif // OAES_DEBUG
+
+ oaes_key * key;
+ OAES_OPTION options;
+ uint8_t iv[OAES_BLOCK_SIZE];
+} oaes_ctx;
/*
* // usage:
*
diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c
index c7264bd96..35438dcab 100644
--- a/src/crypto/slow-hash.c
+++ b/src/crypto/slow-hash.c
@@ -11,143 +11,251 @@
#include "hash-ops.h"
#include "oaes_lib.h"
-static void (*const extra_hashes[4])(const void *, size_t, char *) = {
- hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
-};
+#include <emmintrin.h>
+
+#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
+#include <intrin.h>
+#define STATIC
+#define INLINE __inline
+#if !defined(RDATA_ALIGN16)
+#define RDATA_ALIGN16 __declspec(align(16))
+#endif
+#else
+#include <wmmintrin.h>
+#define STATIC static
+#define INLINE inline
+#if !defined(RDATA_ALIGN16)
+#define RDATA_ALIGN16 __attribute__ ((aligned(16)))
+#endif
+#endif
-#define MEMORY (1 << 21) /* 2 MiB */
+#define MEMORY (1 << 21) // 2MB scratchpad
#define ITER (1 << 20)
#define AES_BLOCK_SIZE 16
-#define AES_KEY_SIZE 32 /*16*/
+#define AES_KEY_SIZE 32
#define INIT_SIZE_BLK 8
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
-static size_t e2i(const uint8_t* a, size_t count) { return (*((uint64_t*)a) / AES_BLOCK_SIZE) & (count - 1); }
+#define U64(x) ((uint64_t *) (x))
+#define R128(x) ((__m128i *) (x))
-static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) {
- uint64_t a0, b0;
- uint64_t hi, lo;
+extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
+extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
- a0 = SWAP64LE(((uint64_t*)a)[0]);
- b0 = SWAP64LE(((uint64_t*)b)[0]);
- lo = mul128(a0, b0, &hi);
- ((uint64_t*)res)[0] = SWAP64LE(hi);
- ((uint64_t*)res)[1] = SWAP64LE(lo);
+#pragma pack(push, 1)
+union cn_slow_hash_state
+{
+ union hash_state hs;
+ struct
+ {
+ uint8_t k[64];
+ uint8_t init[INIT_SIZE_BYTE];
+ };
+};
+#pragma pack(pop)
+
+#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
+#define cpuid(info,x) __cpuidex(info,x,0)
+#else
+void cpuid(int CPUInfo[4], int InfoType)
+{
+ __asm__ __volatile__
+ (
+ "cpuid":
+ "=a" (CPUInfo[0]),
+ "=b" (CPUInfo[1]),
+ "=c" (CPUInfo[2]),
+ "=d" (CPUInfo[3]) :
+ "a" (InfoType), "c" (0)
+ );
}
+#endif
+
+STATIC INLINE void mul(const uint8_t *a, const uint8_t *b, uint8_t *res)
+{
+ uint64_t a0, b0;
+ uint64_t hi, lo;
-static void sum_half_blocks(uint8_t* a, const uint8_t* b) {
- uint64_t a0, a1, b0, b1;
-
- a0 = SWAP64LE(((uint64_t*)a)[0]);
- a1 = SWAP64LE(((uint64_t*)a)[1]);
- b0 = SWAP64LE(((uint64_t*)b)[0]);
- b1 = SWAP64LE(((uint64_t*)b)[1]);
- a0 += b0;
- a1 += b1;
- ((uint64_t*)a)[0] = SWAP64LE(a0);
- ((uint64_t*)a)[1] = SWAP64LE(a1);
+ a0 = U64(a)[0];
+ b0 = U64(b)[0];
+ lo = mul128(a0, b0, &hi);
+ U64(res)[0] = hi;
+ U64(res)[1] = lo;
}
-static void copy_block(uint8_t* dst, const uint8_t* src) {
- memcpy(dst, src, AES_BLOCK_SIZE);
+STATIC INLINE void sum_half_blocks(uint8_t *a, const uint8_t *b)
+{
+ uint64_t a0, a1, b0, b1;
+ a0 = U64(a)[0];
+ a1 = U64(a)[1];
+ b0 = U64(b)[0];
+ b1 = U64(b)[1];
+ a0 += b0;
+ a1 += b1;
+ U64(a)[0] = a0;
+ U64(a)[1] = a1;
}
-static void swap_blocks(uint8_t* a, uint8_t* b) {
- size_t i;
- uint8_t t;
- for (i = 0; i < AES_BLOCK_SIZE; i++) {
- t = a[i];
- a[i] = b[i];
- b[i] = t;
- }
+STATIC INLINE void swap_blocks(uint8_t *a, uint8_t *b)
+{
+ uint64_t t[2];
+ U64(t)[0] = U64(a)[0];
+ U64(t)[1] = U64(a)[1];
+ U64(a)[0] = U64(b)[0];
+ U64(a)[1] = U64(b)[1];
+ U64(b)[0] = U64(t)[0];
+ U64(b)[1] = U64(t)[1];
}
-static void xor_blocks(uint8_t* a, const uint8_t* b) {
- size_t i;
- for (i = 0; i < AES_BLOCK_SIZE; i++) {
- a[i] ^= b[i];
- }
+STATIC INLINE void xor_blocks(uint8_t *a, const uint8_t *b)
+{
+ U64(a)[0] ^= U64(b)[0];
+ U64(a)[1] ^= U64(b)[1];
}
-#pragma pack(push, 1)
-union cn_slow_hash_state {
- union hash_state hs;
- struct {
- uint8_t k[64];
- uint8_t init[INIT_SIZE_BYTE];
- };
-};
-#pragma pack(pop)
+STATIC INLINE int check_aes_hw(void)
+{
+ int cpuid_results[4];
+ static int supported = -1;
+
+ if(supported >= 0)
+ return supported;
+
+ cpuid(cpuid_results,1);
+ return supported = cpuid_results[2] & (1 << 25);
+}
+
+STATIC INLINE void aesni_pseudo_round(const uint8_t *in, uint8_t *out,
+ const uint8_t *expandedKey)
+{
+ __m128i *k = R128(expandedKey);
+ __m128i d;
+
+ d = _mm_loadu_si128(R128(in));
+ d = _mm_aesenc_si128(d, *R128(&k[0]));
+ d = _mm_aesenc_si128(d, *R128(&k[1]));
+ d = _mm_aesenc_si128(d, *R128(&k[2]));
+ d = _mm_aesenc_si128(d, *R128(&k[3]));
+ d = _mm_aesenc_si128(d, *R128(&k[4]));
+ d = _mm_aesenc_si128(d, *R128(&k[5]));
+ d = _mm_aesenc_si128(d, *R128(&k[6]));
+ d = _mm_aesenc_si128(d, *R128(&k[7]));
+ d = _mm_aesenc_si128(d, *R128(&k[8]));
+ d = _mm_aesenc_si128(d, *R128(&k[9]));
+ _mm_storeu_si128((R128(out)), d);
+}
+
+void cn_slow_hash(const void *data, size_t length, char *hash)
+{
+ uint8_t long_state[MEMORY];
+ uint8_t text[INIT_SIZE_BYTE];
+ uint8_t a[AES_BLOCK_SIZE];
+ uint8_t b[AES_BLOCK_SIZE];
+ uint8_t d[AES_BLOCK_SIZE];
+ uint8_t aes_key[AES_KEY_SIZE];
+ RDATA_ALIGN16 uint8_t expandedKey[256];
+
+ union cn_slow_hash_state state;
-void cn_slow_hash(const void *data, size_t length, char *hash) {
- uint8_t long_state[MEMORY];
- union cn_slow_hash_state state;
- uint8_t text[INIT_SIZE_BYTE];
- uint8_t a[AES_BLOCK_SIZE];
- uint8_t b[AES_BLOCK_SIZE];
- uint8_t c[AES_BLOCK_SIZE];
- uint8_t d[AES_BLOCK_SIZE];
- size_t i, j;
- uint8_t aes_key[AES_KEY_SIZE];
- OAES_CTX* aes_ctx;
-
- hash_process(&state.hs, data, length);
- memcpy(text, state.init, INIT_SIZE_BYTE);
- memcpy(aes_key, state.hs.b, AES_KEY_SIZE);
- aes_ctx = oaes_alloc();
- for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
- for (j = 0; j < INIT_SIZE_BLK; j++) {
- oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE);
- oaes_pseudo_encrypt_ecb(aes_ctx, &text[AES_BLOCK_SIZE * j]);
- /*memcpy(aes_key, &text[AES_BLOCK_SIZE * j], AES_KEY_SIZE);*/
- memcpy(aes_key, state.hs.b, AES_KEY_SIZE);
+ size_t i, j;
+ uint8_t *p = NULL;
+ oaes_ctx *aes_ctx;
+
+ int useAes = check_aes_hw();
+ static void (*const extra_hashes[4])(const void *, size_t, char *) =
+ {
+ hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
+ };
+
+ hash_process(&state.hs, data, length);
+ memcpy(text, state.init, INIT_SIZE_BYTE);
+
+ aes_ctx = (oaes_ctx *) oaes_alloc();
+ oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE);
+
+ // use aligned data
+ memcpy(expandedKey, aes_ctx->key->exp_data, aes_ctx->key->exp_data_len);
+
+ if(useAes)
+ {
+ for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
+ {
+ for(j = 0; j < INIT_SIZE_BLK; j++)
+ aesni_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey);
+ memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
+ }
+ }
+ else
+ {
+ for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
+ {
+ for(j = 0; j < INIT_SIZE_BLK; j++)
+ aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey);
+
+ memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
+ }
+ }
+
+ U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0];
+ U64(a)[1] = U64(&state.k[0])[1] ^ U64(&state.k[32])[1];
+ U64(b)[0] = U64(&state.k[16])[0] ^ U64(&state.k[48])[0];
+ U64(b)[1] = U64(&state.k[16])[1] ^ U64(&state.k[48])[1];
+
+ for(i = 0; i < ITER / 2; i++)
+ {
+ #define TOTALBLOCKS (MEMORY / AES_BLOCK_SIZE)
+ #define state_index(x) (((*((uint64_t *)x) >> 4) & (TOTALBLOCKS - 1)) << 4)
+
+ // Iteration 1
+ p = &long_state[state_index(a)];
+
+ if(useAes)
+ _mm_storeu_si128(R128(p), _mm_aesenc_si128(_mm_loadu_si128(R128(p)), _mm_loadu_si128(R128(a))));
+ else
+ aesb_single_round(p, p, a);
+
+ xor_blocks(b, p);
+ swap_blocks(b, p);
+ swap_blocks(a, b);
+
+ // Iteration 2
+ p = &long_state[state_index(a)];
+
+ mul(a, p, d);
+ sum_half_blocks(b, d);
+ swap_blocks(b, p);
+ xor_blocks(b, p);
+ swap_blocks(a, b);
+ }
+
+ memcpy(text, state.init, INIT_SIZE_BYTE);
+ oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE);
+ memcpy(expandedKey, aes_ctx->key->exp_data, aes_ctx->key->exp_data_len);
+ if(useAes)
+ {
+ for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
+ {
+ for(j = 0; j < INIT_SIZE_BLK; j++)
+ {
+ xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
+ aesni_pseudo_round(&text[j * AES_BLOCK_SIZE], &text[j * AES_BLOCK_SIZE], expandedKey);
+ }
+ }
}
- memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
- }
-
- for (i = 0; i < 16; i++) {
- a[i] = state.k[ i] ^ state.k[32 + i];
- b[i] = state.k[16 + i] ^ state.k[48 + i];
- }
-
- for (i = 0; i < ITER / 2; i++) {
- /* Dependency chain: address -> read value ------+
- * written value <-+ hard function (AES or MUL) <+
- * next address <-+
- */
- /* Iteration 1 */
- j = e2i(a, MEMORY / AES_BLOCK_SIZE);
- copy_block(c, &long_state[j * AES_BLOCK_SIZE]);
- oaes_encryption_round(a, c);
- xor_blocks(b, c);
- swap_blocks(b, c);
- copy_block(&long_state[j * AES_BLOCK_SIZE], c);
- assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE));
- swap_blocks(a, b);
- /* Iteration 2 */
- j = e2i(a, MEMORY / AES_BLOCK_SIZE);
- copy_block(c, &long_state[j * AES_BLOCK_SIZE]);
- mul(a, c, d);
- sum_half_blocks(b, d);
- swap_blocks(b, c);
- xor_blocks(b, c);
- copy_block(&long_state[j * AES_BLOCK_SIZE], c);
- assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE));
- swap_blocks(a, b);
- }
-
- memcpy(text, state.init, INIT_SIZE_BYTE);
- for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
- for (j = 0; j < INIT_SIZE_BLK; j++) {
- /*oaes_key_import_data(aes_ctx, &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE], AES_KEY_SIZE);*/
- oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE);
- xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
- oaes_pseudo_encrypt_ecb(aes_ctx, &text[j * AES_BLOCK_SIZE]);
+ else
+ {
+ for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
+ {
+ for(j = 0; j < INIT_SIZE_BLK; j++)
+ {
+ xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
+ aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey);
+ }
+ }
}
- }
- memcpy(state.init, text, INIT_SIZE_BYTE);
- hash_permutation(&state.hs);
- /*memcpy(hash, &state, 32);*/
- extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
- oaes_free(&aes_ctx);
+
+ oaes_free((OAES_CTX **) &aes_ctx);
+ memcpy(state.init, text, INIT_SIZE_BYTE);
+ hash_permutation(&state.hs);
+ extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
}
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index 34d053aa8..295f59e51 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -8,7 +8,7 @@
#define CRYPTONOTE_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used!
#define CRYPTONOTE_MAX_TX_SIZE 1000000000
#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0
-#define CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX 18 // addresses start with "2"
+#define CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX 18 // addresses start with "4"
#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60
#define CURRENT_TRANSACTION_VERSION 1
#define CURRENT_BLOCK_MAJOR_VERSION 1
@@ -26,8 +26,8 @@
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12
// COIN - number of smallest units in one coin
-#define COIN ((uint64_t)100000000) // pow(10, 8)
-#define DEFAULT_FEE ((uint64_t)1000000) // pow(10, 6)
+#define COIN ((uint64_t)1000000000000) // pow(10, 12)
+#define DEFAULT_FEE ((uint64_t)5000000000) // 5 * pow(10, 9)
#define ORPHANED_BLOCKS_MAX_COUNT 100
@@ -51,6 +51,8 @@
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 200 //by default, blocks count in blocks downloading
#define CRYPTONOTE_PROTOCOL_HOP_RELAX_COUNT 3 //value of hop, after which we use only announce of new block
+#define CRYPTONOTE_MEMPOOL_TX_LIVETIME 86400 //seconds, one day
+#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME 604800 //seconds, one week
#define P2P_DEFAULT_PORT 18080
#define RPC_DEFAULT_PORT 18081
diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_core/account.cpp
index ba39b9b77..3bedd7404 100644
--- a/src/cryptonote_core/account.cpp
+++ b/src/cryptonote_core/account.cpp
@@ -10,6 +10,10 @@
#include "account.h"
#include "warnings.h"
#include "crypto/crypto.h"
+extern "C"
+{
+#include "crypto/keccak.h"
+}
#include "cryptonote_core/cryptonote_basic_impl.h"
#include "cryptonote_core/cryptonote_format_utils.h"
using namespace std;
@@ -29,11 +33,17 @@ DISABLE_VS_WARNINGS(4244 4345)
m_keys = account_keys();
}
//-----------------------------------------------------------------
- void account_base::generate()
+ crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random)
{
- generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key);
- generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key);
+ crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover);
+
+ // rng for generating second set of keys is hash of first rng. means only one set of electrum-style words needed for recovery
+ crypto::secret_key second;
+ keccak((uint8_t *)&first, sizeof(crypto::secret_key), (uint8_t *)&second, sizeof(crypto::secret_key));
+
+ generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key, second, two_random ? false : true);
m_creation_timestamp = time(NULL);
+ return first;
}
//-----------------------------------------------------------------
const account_keys& account_base::get_keys() const
diff --git a/src/cryptonote_core/account.h b/src/cryptonote_core/account.h
index 8b525da97..cb77d7c4e 100644
--- a/src/cryptonote_core/account.h
+++ b/src/cryptonote_core/account.h
@@ -31,7 +31,7 @@ namespace cryptonote
{
public:
account_base();
- void generate();
+ crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false);
const account_keys& get_keys() const;
std::string get_public_address_str();
diff --git a/src/cryptonote_core/blockchain_storage.cpp b/src/cryptonote_core/blockchain_storage.cpp
index 0e20b454b..9e9c77e85 100644
--- a/src/cryptonote_core/blockchain_storage.cpp
+++ b/src/cryptonote_core/blockchain_storage.cpp
@@ -372,7 +372,7 @@ bool blockchain_storage::rollback_blockchain_switching(std::list<block>& origina
return true;
}
//------------------------------------------------------------------
-bool blockchain_storage::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain)
+bool blockchain_storage::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain, bool discard_disconnected_chain)
{
CRITICAL_REGION_LOCAL(m_blockchain_lock);
CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed");
@@ -414,16 +414,19 @@ bool blockchain_storage::switch_to_alternative_blockchain(std::list<blocks_ext_b
}
}
- //pushing old chain as alternative chain
- BOOST_FOREACH(auto& old_ch_ent, disconnected_chain)
+ if(!discard_disconnected_chain)
{
- block_verification_context bvc = boost::value_initialized<block_verification_context>();
- bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc);
- if(!r)
+ //pushing old chain as alternative chain
+ BOOST_FOREACH(auto& old_ch_ent, disconnected_chain)
{
- LOG_ERROR("Failed to push ex-main chain blocks to alternative chain ");
- rollback_blockchain_switching(disconnected_chain, split_height);
- return false;
+ block_verification_context bvc = boost::value_initialized<block_verification_context>();
+ bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc);
+ if(!r)
+ {
+ LOG_ERROR("Failed to push ex-main chain blocks to alternative chain ");
+ rollback_blockchain_switching(disconnected_chain, split_height);
+ return false;
+ }
}
}
@@ -701,6 +704,22 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
{
CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ uint64_t block_height = get_block_height(b);
+ if(0 == block_height)
+ {
+ LOG_ERROR("Block with id: " << string_tools::pod_to_hex(id) << " (as alternative) have wrong miner transaction");
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
+ if (!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height))
+ {
+ LOG_PRINT_RED_L0("Block with id: " << id
+ << ENDL << " can't be accepted for alternative chain, block height: " << block_height
+ << ENDL << " blockchain height: " << get_current_blockchain_height());
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
+
//block is not related with head of main chain
//first of all - look in alternative chains container
auto it_main_prev = m_blocks_index.find(b.prev_id);
@@ -746,31 +765,28 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
block_extended_info bei = boost::value_initialized<block_extended_info>();
bei.bl = b;
bei.height = alt_chain.size() ? it_prev->second.height + 1 : it_main_prev->second + 1;
+
+ bool is_a_checkpoint;
+ if(!m_checkpoints.check_block(bei.height, id, is_a_checkpoint))
+ {
+ LOG_ERROR("CHECKPOINT VALIDATION FAILED");
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
+
+ // Always check PoW for alternative blocks
+ m_is_in_checkpoint_zone = false;
difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
crypto::hash proof_of_work = null_hash;
- if(!m_checkpoints.is_in_checkpoint_zone(bei.height))
+ get_block_longhash(bei.bl, proof_of_work, bei.height);
+ if(!check_hash(proof_of_work, current_diff))
{
- m_is_in_checkpoint_zone = false;
- get_block_longhash(bei.bl, proof_of_work, bei.height);
-
- if(!check_hash(proof_of_work, current_diff))
- {
- LOG_PRINT_RED_L0("Block with id: " << id
- << ENDL << " for alternative chain, have not enough proof of work: " << proof_of_work
- << ENDL << " expected difficulty: " << current_diff);
- bvc.m_verifivation_failed = true;
- return false;
- }
- }else
- {
- m_is_in_checkpoint_zone = true;
- if(!m_checkpoints.check_block(bei.height, id))
- {
- LOG_ERROR("CHECKPOINT VALIDATION FAILED");
- bvc.m_verifivation_failed = true;
- return false;
- }
+ LOG_PRINT_RED_L0("Block with id: " << id
+ << ENDL << " for alternative chain, have not enough proof of work: " << proof_of_work
+ << ENDL << " expected difficulty: " << current_diff);
+ bvc.m_verifivation_failed = true;
+ return false;
}
if(!prevalidate_miner_transaction(b, bei.height))
@@ -792,22 +808,33 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(id, bei));
CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist");
alt_chain.push_back(i_res.first);
- //check if difficulty bigger then in main chain
- if(m_blocks.back().cumulative_difficulty < bei.cumulative_difficulty)
+
+ if(is_a_checkpoint)
{
//do reorganize!
- LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() -1 << " with cum_difficulty " << m_blocks.back().cumulative_difficulty
+ LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() - 1 <<
+ ", checkpoint is found in alternative chain on height " << bei.height, LOG_LEVEL_0);
+ bool r = switch_to_alternative_blockchain(alt_chain, true);
+ if(r) bvc.m_added_to_main_chain = true;
+ else bvc.m_verifivation_failed = true;
+ return r;
+ }else if(m_blocks.back().cumulative_difficulty < bei.cumulative_difficulty) //check if difficulty bigger then in main chain
+ {
+ //do reorganize!
+ LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() - 1 << " with cum_difficulty " << m_blocks.back().cumulative_difficulty
<< ENDL << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty, LOG_LEVEL_0);
- bool r = switch_to_alternative_blockchain(alt_chain);
+ bool r = switch_to_alternative_blockchain(alt_chain, false);
if(r) bvc.m_added_to_main_chain = true;
else bvc.m_verifivation_failed = true;
return r;
+ }else
+ {
+ LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height
+ << ENDL << "id:\t" << id
+ << ENDL << "PoW:\t" << proof_of_work
+ << ENDL << "difficulty:\t" << current_diff, LOG_LEVEL_0);
+ return true;
}
- LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height
- << ENDL << "id:\t" << id
- << ENDL << "PoW:\t" << proof_of_work
- << ENDL << "difficulty:\t" << current_diff, LOG_LEVEL_0);
- return true;
}else
{
//block orphaned
@@ -815,7 +842,6 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
LOG_PRINT_RED_L0("Block recognized as orphaned and rejected, id = " << id);
}
-
return true;
}
//------------------------------------------------------------------
@@ -1480,19 +1506,27 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
TIME_MEASURE_FINISH(target_calculating_time);
TIME_MEASURE_START(longhash_calculating_time);
crypto::hash proof_of_work = null_hash;
- if(!m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height()))
+
+ // Formerly the code below contained an if loop with the following condition
+ // !m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height())
+ // however, this caused the daemon to not bother checking PoW for blocks
+ // before checkpoints, which is very dangerous behaviour. We moved the PoW
+ // validation out of the next chunk of code to make sure that we correctly
+ // check PoW now.
+ proof_of_work = get_block_longhash(bl, m_blocks.size());
+
+ if(!check_hash(proof_of_work, current_diffic))
{
- proof_of_work = get_block_longhash(bl, m_blocks.size());
+ LOG_PRINT_L0("Block with id: " << id << ENDL
+ << "have not enough proof of work: " << proof_of_work << ENDL
+ << "nexpected difficulty: " << current_diffic );
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
- if(!check_hash(proof_of_work, current_diffic))
- {
- LOG_PRINT_L0("Block with id: " << id << ENDL
- << "have not enough proof of work: " << proof_of_work << ENDL
- << "nexpected difficulty: " << current_diffic );
- bvc.m_verifivation_failed = true;
- return false;
- }
- }else
+ // If we're at a checkpoint, ensure that our hardcoded checkpoint hash
+ // is correct.
+ if(m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height()))
{
if(!m_checkpoints.check_block(get_current_blockchain_height(), id))
{
@@ -1501,6 +1535,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
return false;
}
}
+
TIME_MEASURE_FINISH(longhash_calculating_time);
if(!prevalidate_miner_transaction(bl, m_blocks.size()))
@@ -1648,4 +1683,4 @@ bool blockchain_storage::add_new_block(const block& bl_, block_verification_cont
}
return handle_block_to_main_chain(bl, id, bvc);
-} \ No newline at end of file
+}
diff --git a/src/cryptonote_core/blockchain_storage.h b/src/cryptonote_core/blockchain_storage.h
index 1ea5e29ea..b1fb5df41 100644
--- a/src/cryptonote_core/blockchain_storage.h
+++ b/src/cryptonote_core/blockchain_storage.h
@@ -13,6 +13,8 @@
#include <boost/foreach.hpp>
#include <atomic>
+#include "syncobj.h"
+#include "string_tools.h"
#include "tx_pool.h"
#include "cryptonote_basic.h"
#include "common/util.h"
@@ -50,7 +52,7 @@ namespace cryptonote
uint64_t already_generated_coins;
};
- blockchain_storage(tx_memory_pool& tx_pool):m_tx_pool(tx_pool), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false)
+ blockchain_storage(tx_memory_pool& tx_pool):m_tx_pool(tx_pool), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false), m_is_blockchain_storing(false)
{};
bool init() { return init(tools::get_default_data_dir()); }
@@ -119,7 +121,7 @@ namespace cryptonote
missed_bs.push_back(bl_id);
else
{
- CHECK_AND_ASSERT_MES(it->second < m_blocks.size(), false, "Internal error: bl_id=" << string_tools::pod_to_hex(bl_id)
+ CHECK_AND_ASSERT_MES(it->second < m_blocks.size(), false, "Internal error: bl_id=" << epee::string_tools::pod_to_hex(bl_id)
<< " have index record with offset="<<it->second<< ", bigger then m_blocks.size()=" << m_blocks.size());
blocks.push_back(m_blocks[it->second].bl);
}
@@ -163,7 +165,7 @@ namespace cryptonote
typedef std::map<uint64_t, std::vector<std::pair<crypto::hash, size_t>>> outputs_container; //crypto::hash - tx hash, size_t - index of out in transaction
tx_memory_pool& m_tx_pool;
- critical_section m_blockchain_lock; // TODO: add here reader/writer lock
+ epee::critical_section m_blockchain_lock; // TODO: add here reader/writer lock
// main chain
blocks_container m_blocks; // height -> block_extended_info
@@ -186,7 +188,7 @@ namespace cryptonote
std::atomic<bool> m_is_in_checkpoint_zone;
std::atomic<bool> m_is_blockchain_storing;
- bool switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain);
+ bool switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain, bool discard_disconnected_chain);
bool pop_block_from_blockchain();
bool purge_block_data_from_blockchain(const block& b, size_t processed_tx_count);
bool purge_transaction_from_blockchain(const crypto::hash& tx_id);
@@ -301,7 +303,7 @@ namespace cryptonote
return false;
}
transactions_container::iterator tx_it = m_transactions.find(amount_outs_vec[i].first);
- CHECK_AND_ASSERT_MES(tx_it != m_transactions.end(), false, "Wrong transaction id in output indexes: " <<string_tools::pod_to_hex(amount_outs_vec[i].first));
+ CHECK_AND_ASSERT_MES(tx_it != m_transactions.end(), false, "Wrong transaction id in output indexes: " << epee::string_tools::pod_to_hex(amount_outs_vec[i].first));
CHECK_AND_ASSERT_MES(amount_outs_vec[i].second < tx_it->second.tx.vout.size(), false,
"Wrong index in transaction outputs: " << amount_outs_vec[i].second << ", expected less then " << tx_it->second.tx.vout.size());
if(!vis.handle_output(tx_it->second.tx, tx_it->second.tx.vout[amount_outs_vec[i].second]))
diff --git a/src/cryptonote_core/checkpoints.cpp b/src/cryptonote_core/checkpoints.cpp
index 54c2f3a6d..33a2d2986 100644
--- a/src/cryptonote_core/checkpoints.cpp
+++ b/src/cryptonote_core/checkpoints.cpp
@@ -29,10 +29,11 @@ namespace cryptonote
return !m_points.empty() && (height <= (--m_points.end())->first);
}
//---------------------------------------------------------------------------
- bool checkpoints::check_block(uint64_t height, const crypto::hash& h) const
+ bool checkpoints::check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const
{
auto it = m_points.find(height);
- if(it == m_points.end())
+ is_a_checkpoint = it != m_points.end();
+ if(!is_a_checkpoint)
return true;
if(it->second == h)
@@ -45,4 +46,25 @@ namespace cryptonote
return false;
}
}
+ //---------------------------------------------------------------------------
+ bool checkpoints::check_block(uint64_t height, const crypto::hash& h) const
+ {
+ bool ignored;
+ return check_block(height, h, ignored);
+ }
+ //---------------------------------------------------------------------------
+ bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const
+ {
+ if (0 == block_height)
+ return false;
+
+ auto it = m_points.upper_bound(blockchain_height);
+ // Is blockchain_height before the first checkpoint?
+ if (it == m_points.begin())
+ return true;
+
+ --it;
+ uint64_t checkpoint_height = it->first;
+ return checkpoint_height < block_height;
+ }
}
diff --git a/src/cryptonote_core/checkpoints.h b/src/cryptonote_core/checkpoints.h
index 20014b1c8..1bc055d91 100644
--- a/src/cryptonote_core/checkpoints.h
+++ b/src/cryptonote_core/checkpoints.h
@@ -16,6 +16,9 @@ namespace cryptonote
bool add_checkpoint(uint64_t height, const std::string& hash_str);
bool is_in_checkpoint_zone(uint64_t height) const;
bool check_block(uint64_t height, const crypto::hash& h) const;
+ bool check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const;
+ bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const;
+
private:
std::map<uint64_t, crypto::hash> m_points;
};
diff --git a/src/cryptonote_core/checkpoints_create.h b/src/cryptonote_core/checkpoints_create.h
index 9088b092d..a92fefd3f 100644
--- a/src/cryptonote_core/checkpoints_create.h
+++ b/src/cryptonote_core/checkpoints_create.h
@@ -13,6 +13,9 @@ namespace cryptonote {
inline bool create_checkpoints(cryptonote::checkpoints& checkpoints)
{
ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25");
+ ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6");
+ ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c");
+ ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3");
return true;
}
}
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index a09f25d31..2609fc13e 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -28,7 +28,8 @@ namespace cryptonote
m_blockchain_storage(m_mempool),
m_miner(this),
m_miner_address(boost::value_initialized<account_public_address>()),
- m_starter_message_showed(false)
+ m_starter_message_showed(false),
+ m_target_blockchain_height(0)
{
set_cryptonote_protocol(pprotocol);
}
@@ -431,6 +432,18 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
+ // Used by the RPC server to check the size of an incoming
+ // block_blob
+ bool core::check_incoming_block_size(const blobdata& block_blob)
+ {
+ if(block_blob.size() > get_max_block_size())
+ {
+ LOG_PRINT_L0("WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected");
+ return false;
+ }
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------
crypto::hash core::get_tail_id()
{
return m_blockchain_storage.get_tail_id();
@@ -502,7 +515,7 @@ namespace cryptonote
LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL
<< "The daemon will start synchronizing with the network. It may take up to several hours." << ENDL
<< ENDL
- << "You can set the level of process detailization by using command \"set_log <level>\", where <level> is either 0 (no details), 1 (current block height synchronized), or 2 (all details)." << ENDL
+ << "You can set the level of process detailization* through \"set_log <level>\" command*, where <level> is between 0 (no details) and 4 (very verbose)." << ENDL
<< ENDL
<< "Use \"help\" command to see the list of available commands." << ENDL
<< ENDL
@@ -513,7 +526,15 @@ namespace cryptonote
m_store_blockchain_interval.do_call(boost::bind(&blockchain_storage::store_blockchain, &m_blockchain_storage));
m_miner.on_idle();
+ m_mempool.on_idle();
return true;
}
//-----------------------------------------------------------------------------------------------
+ void core::set_target_blockchain_height(uint64_t target_blockchain_height) {
+ m_target_blockchain_height = target_blockchain_height;
+ }
+ //-----------------------------------------------------------------------------------------------
+ uint64_t core::get_target_blockchain_height() const {
+ return m_target_blockchain_height;
+ }
}
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index c298451e8..1f1b6eec6 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -34,6 +34,7 @@ namespace cryptonote
bool on_idle();
bool handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block);
bool handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate = true);
+ bool check_incoming_block_size(const blobdata& block_blob);
i_cryptonote_protocol* get_protocol(){return m_pprotocol;}
//-------------------- i_miner_handler -----------------------
@@ -90,6 +91,9 @@ namespace cryptonote
void print_blockchain_outs(const std::string& file);
void on_synchronized();
+ void set_target_blockchain_height(uint64_t target_blockchain_height);
+ uint64_t get_target_blockchain_height() const;
+
private:
bool add_new_tx(const transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block);
bool add_new_tx(const transaction& tx, tx_verification_context& tvc, bool keeped_by_block);
@@ -115,15 +119,17 @@ namespace cryptonote
tx_memory_pool m_mempool;
blockchain_storage m_blockchain_storage;
i_cryptonote_protocol* m_pprotocol;
- critical_section m_incoming_tx_lock;
+ epee::critical_section m_incoming_tx_lock;
//m_miner and m_miner_addres are probably temporary here
miner m_miner;
account_public_address m_miner_address;
std::string m_config_folder;
cryptonote_protocol_stub m_protocol_stub;
- math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval;
+ epee::math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval;
friend class tx_validate_inputs;
std::atomic<bool> m_starter_message_showed;
+
+ uint64_t m_target_blockchain_height;
};
}
diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp
index b2eaf18a2..7b7f18844 100644
--- a/src/cryptonote_core/cryptonote_format_utils.cpp
+++ b/src/cryptonote_core/cryptonote_format_utils.cpp
@@ -80,7 +80,7 @@ namespace cryptonote
#endif
block_reward += fee;
- std::vector<size_t> out_amounts;
+ std::vector<uint64_t> out_amounts;
decompose_amount_into_digits(block_reward, DEFAULT_FEE,
[&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
[&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
@@ -92,7 +92,7 @@ namespace cryptonote
out_amounts.resize(out_amounts.size() - 1);
}
- size_t summary_amounts = 0;
+ uint64_t summary_amounts = 0;
for (size_t no = 0; no < out_amounts.size(); no++)
{
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);;
@@ -239,8 +239,7 @@ namespace cryptonote
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra)
{
std::vector<tx_extra_field> tx_extra_fields;
- if (!parse_tx_extra(tx_extra, tx_extra_fields))
- return null_pkey;
+ parse_tx_extra(tx_extra, tx_extra_fields);
tx_extra_pub_key pub_key_field;
if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field))
diff --git a/src/cryptonote_core/miner.cpp b/src/cryptonote_core/miner.cpp
index 56b459d6e..2055bb15d 100644
--- a/src/cryptonote_core/miner.cpp
+++ b/src/cryptonote_core/miner.cpp
@@ -188,10 +188,19 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------------
- bool miner::is_mining()
+ bool miner::is_mining() const
{
return !m_stop;
}
+ //-----------------------------------------------------------------------------------------------------
+ const account_public_address& miner::get_mining_address() const
+ {
+ return m_mine_address;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ uint32_t miner::get_threads_count() const {
+ return m_threads_total;
+ }
//-----------------------------------------------------------------------------------------------------
bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs)
{
@@ -226,12 +235,14 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------------
- uint64_t miner::get_speed()
+ uint64_t miner::get_speed() const
{
- if(is_mining())
+ if(is_mining()) {
return m_current_hash_rate;
- else
+ }
+ else {
return 0;
+ }
}
//-----------------------------------------------------------------------------------------------------
void miner::send_stop_signal()
diff --git a/src/cryptonote_core/miner.h b/src/cryptonote_core/miner.h
index da4578b06..d9ac5a501 100644
--- a/src/cryptonote_core/miner.h
+++ b/src/cryptonote_core/miner.h
@@ -4,7 +4,6 @@
#pragma once
-#include <boost/atomic.hpp>
#include <boost/program_options.hpp>
#include <atomic>
#include "cryptonote_basic.h"
@@ -36,10 +35,12 @@ namespace cryptonote
bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height);
bool on_block_chain_update();
bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs);
- uint64_t get_speed();
+ uint64_t get_speed() const;
+ uint32_t get_threads_count() const;
void send_stop_signal();
bool stop();
- bool is_mining();
+ bool is_mining() const;
+ const account_public_address& get_mining_address() const;
bool on_idle();
void on_synchronized();
//synchronous analog (for fast calls)
@@ -64,7 +65,7 @@ namespace cryptonote
volatile uint32_t m_stop;
- ::critical_section m_template_lock;
+ epee::critical_section m_template_lock;
block m_template;
std::atomic<uint32_t> m_template_no;
std::atomic<uint32_t> m_starter_nonce;
@@ -73,21 +74,21 @@ namespace cryptonote
volatile uint32_t m_thread_index;
volatile uint32_t m_threads_total;
std::atomic<int32_t> m_pausers_count;
- ::critical_section m_miners_count_lock;
+ epee::critical_section m_miners_count_lock;
std::list<boost::thread> m_threads;
- ::critical_section m_threads_lock;
+ epee::critical_section m_threads_lock;
i_miner_handler* m_phandler;
account_public_address m_mine_address;
- math_helper::once_a_time_seconds<5> m_update_block_template_interval;
- math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
+ epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
+ epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
std::vector<blobdata> m_extra_messages;
miner_config m_config;
std::string m_config_folder_path;
std::atomic<uint64_t> m_last_hr_merge_time;
std::atomic<uint64_t> m_hashes;
std::atomic<uint64_t> m_current_hash_rate;
- critical_section m_last_hash_rates_lock;
+ epee::critical_section m_last_hash_rates_lock;
std::list<uint64_t> m_last_hash_rates;
bool m_do_print_hashrate;
bool m_do_mining;
diff --git a/src/cryptonote_core/tx_extra.h b/src/cryptonote_core/tx_extra.h
index 8cff085dc..37a04a41e 100644
--- a/src/cryptonote_core/tx_extra.h
+++ b/src/cryptonote_core/tx_extra.h
@@ -11,6 +11,7 @@
#define TX_EXTRA_TAG_PADDING 0x00
#define TX_EXTRA_TAG_PUBKEY 0x01
#define TX_EXTRA_NONCE 0x02
+#define TX_EXTRA_MERGE_MINING_TAG 0x03
#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
@@ -82,13 +83,62 @@ namespace cryptonote
END_SERIALIZE()
};
+ struct tx_extra_merge_mining_tag
+ {
+ struct serialize_helper
+ {
+ tx_extra_merge_mining_tag& mm_tag;
+
+ serialize_helper(tx_extra_merge_mining_tag& mm_tag_) : mm_tag(mm_tag_)
+ {
+ }
+
+ BEGIN_SERIALIZE()
+ VARINT_FIELD_N("depth", mm_tag.depth)
+ FIELD_N("merkle_root", mm_tag.merkle_root)
+ END_SERIALIZE()
+ };
+
+ size_t depth;
+ crypto::hash merkle_root;
+
+ // load
+ template <template <bool> class Archive>
+ bool do_serialize(Archive<false>& ar)
+ {
+ std::string field;
+ if(!::do_serialize(ar, field))
+ return false;
+
+ std::istringstream iss(field);
+ binary_archive<false> iar(iss);
+ serialize_helper helper(*this);
+ return ::serialization::serialize(iar, helper);
+ }
+
+ // store
+ template <template <bool> class Archive>
+ bool do_serialize(Archive<true>& ar)
+ {
+ std::ostringstream oss;
+ binary_archive<true> oar(oss);
+ serialize_helper helper(*this);
+ if(!::do_serialize(oar, helper))
+ return false;
+
+ std::string field = oss.str();
+ return ::serialization::serialize(ar, field);
+ }
+ };
+
// tx_extra_field format, except tx_extra_padding and tx_extra_pub_key:
// varint tag;
// varint size;
// varint data[];
- typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce> tx_extra_field;
+ typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce, tx_extra_merge_mining_tag> tx_extra_field;
}
VARIANT_TAG(binary_archive, cryptonote::tx_extra_padding, TX_EXTRA_TAG_PADDING);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_pub_key, TX_EXTRA_TAG_PUBKEY);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_nonce, TX_EXTRA_NONCE);
+VARIANT_TAG(binary_archive, cryptonote::tx_extra_merge_mining_tag, TX_EXTRA_MERGE_MINING_TAG);
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 24e5752ad..ce1bc1ad2 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -83,6 +83,7 @@ namespace cryptonote
txd_p.first->second.max_used_block_id = null_hash;
txd_p.first->second.max_used_block_height = 0;
txd_p.first->second.kept_by_block = kept_by_block;
+ txd_p.first->second.receive_time = time(nullptr);
tvc.m_verifivation_impossible = true;
tvc.m_added_to_pool = true;
}else
@@ -104,6 +105,7 @@ namespace cryptonote
txd_p.first->second.max_used_block_height = max_used_block_height;
txd_p.first->second.last_failed_height = 0;
txd_p.first->second.last_failed_id = null_hash;
+ txd_p.first->second.receive_time = time(nullptr);
tvc.m_added_to_pool = true;
if(txd_p.first->second.fee > 0)
@@ -178,6 +180,30 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------------------------
+ void tx_memory_pool::on_idle()
+ {
+ m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();});
+ }
+ //---------------------------------------------------------------------------------
+ //proper tx_pool handling courtesy of CryptoZoidberg and Boolberry
+ bool tx_memory_pool::remove_stuck_transactions()
+ {
+ CRITICAL_REGION_LOCAL(m_transactions_lock);
+ for(auto it = m_transactions.begin(); it!= m_transactions.end();)
+ {
+ uint64_t tx_age = time(nullptr) - it->second.receive_time;
+
+ if((tx_age > CRYPTONOTE_MEMPOOL_TX_LIVETIME && !it->second.kept_by_block) ||
+ (tx_age > CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME && it->second.kept_by_block) )
+ {
+ LOG_PRINT_L0("Tx " << it->first << " removed from tx pool due to outdated, age: " << tx_age );
+ m_transactions.erase(it++);
+ }else
+ ++it;
+ }
+ return true;
+ }
+ //---------------------------------------------------------------------------------
size_t tx_memory_pool::get_transactions_count()
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
@@ -350,18 +376,69 @@ namespace cryptonote
//---------------------------------------------------------------------------------
bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee)
{
+ // Warning: This function takes already_generated_
+ // coins as an argument and appears to do nothing
+ // with it.
+
CRITICAL_REGION_LOCAL(m_transactions_lock);
total_size = 0;
fee = 0;
- size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+ size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; // Max block size
std::unordered_set<crypto::key_image> k_images;
+
+ // Tx size limit as in wallet2.h
+ // tx_pool.cpp uses size_t for tx sizes, whereas
+ // wallet2.h uses uint64_t; just use size_t here
+ // for now
+ size_t upper_transaction_size_limit = ((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+
+ // Calculate size limit based on median too; useful
+ // for when we actually fix wallet2.h's maximum
+ // allowable tx size
+ //
+ // Can be removed when wallet2.h calculates max
+ // tx size based on the median too; just use
+ // upper_transaction_size_limit_median in all cases
+ size_t upper_transaction_size_limit_median = ((median_size * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+ if (upper_transaction_size_limit_median > upper_transaction_size_limit)
+ upper_transaction_size_limit = upper_transaction_size_limit_median;
+
BOOST_FOREACH(transactions_container::value_type& tx, m_transactions)
{
+ // Can not exceed maximum block size
if (max_total_size < total_size + tx.second.blob_size)
continue;
+ // Check to see if the minimum fee is included;
+ // exclude tx missing minimum fee
+ if (tx.second.fee < DEFAULT_FEE)
+ continue;
+
+ // Skip transactions that are too large
+ // TODO: Correct upper_transactions_size_limit
+ // such that it is based on median block size;
+ // We need to make a similar patch for
+ // wallet2.h
+ if (tx.second.blob_size > upper_transaction_size_limit)
+ continue;
+
+ // If adding this tx will make the block size
+ // greater than 130% of the median, reject the
+ // tx; this will keep down largely punitive tx
+ // from being included
+ if ( (total_size + tx.second.blob_size) > ((130 * median_size) / 100) )
+ continue;
+
+ // If we've exceeded the penalty free size,
+ // stop including more tx
+ if (total_size > median_size)
+ break;
+
+ // Skip transactions that are not ready to be
+ // included into the blockchain or that are
+ // missing key images
if (!is_transaction_ready_to_go(tx.second) || have_key_images(k_images, tx.second.tx))
continue;
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 3978dfb96..649af41a3 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -4,8 +4,6 @@
#pragma once
#include "include_base_utils.h"
-using namespace epee;
-
#include <set>
#include <unordered_map>
@@ -15,6 +13,7 @@ using namespace epee;
#include "string_tools.h"
#include "syncobj.h"
+#include "math_helper.h"
#include "cryptonote_basic_impl.h"
#include "verification_context.h"
#include "crypto/hash.h"
@@ -42,6 +41,7 @@ namespace cryptonote
bool on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id);
bool on_blockchain_dec(uint64_t new_block_height, const crypto::hash& top_block_id);
+ void on_idle();
void lock();
void unlock();
@@ -61,7 +61,7 @@ namespace cryptonote
/*bool flush_pool(const std::strig& folder);
bool inflate_pool(const std::strig& folder);*/
-#define CURRENT_MEMPOOL_ARCHIVE_VER 7
+#define CURRENT_MEMPOOL_ARCHIVE_VER 8
template<class archive_t>
void serialize(archive_t & a, const unsigned int version)
@@ -84,9 +84,11 @@ namespace cryptonote
//
uint64_t last_failed_height;
crypto::hash last_failed_id;
+ time_t receive_time;
};
private:
+ bool remove_stuck_transactions();
bool is_transaction_ready_to_go(tx_details& txd);
typedef std::unordered_map<crypto::hash, tx_details > transactions_container;
typedef std::unordered_map<crypto::key_image, std::unordered_set<crypto::hash> > key_images_container;
@@ -94,6 +96,7 @@ namespace cryptonote
epee::critical_section m_transactions_lock;
transactions_container m_transactions;
key_images_container m_spent_key_images;
+ epee::math_helper::once_a_time_seconds<30> m_remove_stuck_tx_interval;
//transactions_container m_alternative_transactions;
@@ -161,6 +164,7 @@ namespace boost
ar & td.max_used_block_id;
ar & td.last_failed_height;
ar & td.last_failed_id;
+ ar & td.receive_time;
}
}
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index 178ec2eb1..80538677c 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -81,7 +81,7 @@ namespace cryptonote
template<class t_parametr>
bool post_notify(typename t_parametr::request& arg, cryptonote_connection_context& context)
{
- LOG_PRINT_L2("[" << net_utils::print_connection_context_short(context) << "] post " << typeid(t_parametr).name() << " -->");
+ LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(context) << "] post " << typeid(t_parametr).name() << " -->");
std::string blob;
epee::serialization::store_t_to_binary(arg, blob);
return m_p2p->invoke_notify_to_peer(t_parametr::ID, blob, context);
@@ -90,7 +90,7 @@ namespace cryptonote
template<class t_parametr>
bool relay_post_notify(typename t_parametr::request& arg, cryptonote_connection_context& exlude_context)
{
- LOG_PRINT_L2("[" << net_utils::print_connection_context_short(exlude_context) << "] post relay " << typeid(t_parametr).name() << " -->");
+ LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(exlude_context) << "] post relay " << typeid(t_parametr).name() << " -->");
std::string arg_buff;
epee::serialization::store_t_to_binary(arg, arg_buff);
return m_p2p->relay_notify_to_all(t_parametr::ID, arg_buff, exlude_context);
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index a0838e690..a2f0bb3ad 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -81,7 +81,7 @@ namespace cryptonote
m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id)
{
ss << std::setw(25) << std::left << std::string(cntxt.m_is_income ? " [INC]":"[OUT]") +
- string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port)
+ epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port)
<< std::setw(20) << std::hex << peer_id
<< std::setw(25) << std::to_string(cntxt.m_recv_cnt)+ "(" + std::to_string(time(NULL) - cntxt.m_last_recv) + ")" + "/" + std::to_string(cntxt.m_send_cnt) + "(" + std::to_string(time(NULL) - cntxt.m_last_send) + ")"
<< std::setw(25) << get_protocol_state_string(cntxt.m_state)
@@ -108,9 +108,17 @@ namespace cryptonote
return true;
}
- LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << "->" << hshd.current_height
- << "[" << static_cast<int64_t>(hshd.current_height - m_core.get_current_blockchain_height()) << " blocks(" << (hshd.current_height - m_core.get_current_blockchain_height()) /1440 << " days) behind] " << ENDL
- << "remote top: " << hshd.top_id << "[" << hshd.current_height << "]" << ", set SYNCHRONIZATION mode", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1));
+ /* As I don't know if accessing hshd from core could be a good practice,
+ I prefer pushing target height to the core at the same time it is pushed to the user.
+ Nz. */
+ m_core.set_target_blockchain_height(static_cast<int64_t>(hshd.current_height));
+
+ int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height());
+ LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
+ << " [" << std::abs(diff) << " blocks (" << diff / (24 * 60 * 60 / DIFFICULTY_TARGET) << " days) "
+ << (0 <= diff ? std::string("behind") : std::string("ahead"))
+ << "] " << ENDL << "SYNCHRONIZATION started", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1));
+ LOG_PRINT_L1("Remote top block height: " << hshd.current_height << ", id: " << hshd.top_id);
context.m_state = cryptonote_connection_context::state_synchronizing;
context.m_remote_blockchain_height = hshd.current_height;
//let the socket to send response to handshake, but request callback, to let send request data after response
@@ -254,7 +262,7 @@ namespace cryptonote
if(!parse_and_validate_block_from_blob(block_entry.block, b))
{
LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n"
- << string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection");
+ << epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection");
m_p2p->drop_connection(context);
return 1;
}
@@ -274,14 +282,14 @@ namespace cryptonote
auto req_it = context.m_requested_objects.find(get_block_hash(b));
if(req_it == context.m_requested_objects.end())
{
- LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block))
+ LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
<< " wasn't requested, dropping connection");
m_p2p->drop_connection(context);
return 1;
}
if(b.tx_hashes.size() != block_entry.txs.size())
{
- LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block))
+ LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
<< ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection");
m_p2p->drop_connection(context);
return 1;
@@ -300,7 +308,7 @@ namespace cryptonote
{
m_core.pause_mine();
- misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
+ epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler(
boost::bind(&t_core::resume_mine, &m_core));
BOOST_FOREACH(const block_complete_entry& block_entry, arg.blocks)
@@ -314,7 +322,7 @@ namespace cryptonote
if(tvc.m_verifivation_failed)
{
LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = "
- << string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
+ << epee::string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
m_p2p->drop_connection(context);
return 1;
}
@@ -408,7 +416,7 @@ namespace cryptonote
<< "\r\nm_remote_blockchain_height=" << context.m_remote_blockchain_height
<< "\r\nm_needed_objects.size()=" << context.m_needed_objects.size()
<< "\r\nm_requested_objects.size()=" << context.m_requested_objects.size()
- << "\r\non connection [" << net_utils::print_connection_context_short(context)<< "]");
+ << "\r\non connection [" << epee::net_utils::print_connection_context_short(context)<< "]");
context.m_state = cryptonote_connection_context::state_normal;
LOG_PRINT_CCONTEXT_GREEN(" SYNCHRONIZED OK", LOG_LEVEL_0);
@@ -464,7 +472,7 @@ namespace cryptonote
if(!m_core.have_block(arg.m_block_ids.front()))
{
LOG_ERROR_CCONTEXT("sent m_block_ids starting from unknown id: "
- << string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection");
+ << epee::string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection");
m_p2p->drop_connection(context);
return 1;
}